Skip to content

About

Minimal composable Python agent harness built on Cordis principles — plugin-first, auditable, self-extensible.

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Cordis Python

A fast, minimal Python microkernel for composable agent harnesses.

Experimental, community-oriented implementation inspired by the public Cordis / DeepSeek Harness architecture. This project is not affiliated with or endorsed by DeepSeek or the Cordis maintainers, and does not claim API compatibility.

Cordis-Python keeps the core generic and small. LLM providers, tools, sessions, context management, agent loops, skills, workers and the web UI are plugins that communicate through stable services and scoped events.

Supported platforms: Windows, macOS and Linux. Python 3.10–3.13.

Why Cordis is different

Cordis does not try to be one monolithic harness containing chat, tools, memory, browser, code, UI and telemetry.

It provides a small, working kernel—contexts, services, events, dependency reconciliation—and just enough base plugins to run a real agent. The agent can then read its own architecture skill and add specialized plugins through the same plugin boundary, instead of forcing every future capability into the core.

Quickstart: least-privilege user profile

python -m venv .venv

Activate the environment:

# Windows PowerShell
.venv\Scripts\Activate.ps1
# macOS / Linux
source .venv/bin/activate

Install the full user extras and start the harness:

pip install -e ".[full]"
cordis run --profile profiles/user.yml --workspace .

Open:

http://127.0.0.1:8000

The default provider is a fake offline provider, so the UI starts without any API key.

With profiles/user.yml, the UI starts even if SearXNG or Lightpanda are not running. Web tool calls that require a missing backend return a structured error until that backend is available.

profiles/user.yml is the recommended normal-user harness:

  • the main agent sees only runtime_status, list_skills, read_skill, worker_web_research and worker_code
  • the main agent cannot directly call shell, file, raw web or raw code tools
  • web research runs in an isolated worker:web context
  • code work runs in an isolated worker:code context
  • capability policy is deny-by-default

Use a workspace you are comfortable letting the code worker inspect. For real self-extension work, the workspace should be a clean Git repository.

Inspect the effective configuration

cordis run --profile profiles/user.yml --dump-config
cordis run --profile profiles/user.yml --explain-config

OpenAI-compatible provider

Cordis-Python can connect to OpenAI-compatible endpoints such as LM Studio, llama.cpp, vLLM, Ollama and compatible servers:

cordis run \
  --profile profiles/user.yml \
  --workspace . \
  --provider openai \
  --base-url http://127.0.0.1:1234/v1 \
  --model local-model \
  --api-key lm-studio \
  --context-window 131072

On Windows PowerShell, use one line or PowerShell backticks instead of \ line continuations.

profiles/user.yml is provider-agnostic: it does not hard-code a provider, model, endpoint or API key.

Profiles

Profile Intended use
profiles/user.yml Recommended interactive user harness: UI, skills, isolated web/code workers, least-privilege main agent
profiles/self-coding.yml Stricter code-worker composition: deny-by-default, no UI/shell/files/network by default
profiles/research.yml Web-research-focused harness with a deny-by-default web capability gate
profiles/coding.yml Developer file/shell harness without web UI
profiles/minimal.yml Minimal agent loop + provider + conversation state

Important distinction:

  • Use --profile profiles/user.yml for normal user work.
  • Running cordis run without a profile is the developer/bootstrap harness. It mounts broader development plugins such as shell, developer-tools and filesystem-local. Treat it as a development configuration, not as the least-privilege user profile.
  • Only profiles/user.yml keeps ui-fastapi enabled among the shipped profiles. research.yml, self-coding.yml, coding.yml and minimal.yml disable the UI; with the current cordis run CLI, re-enable ui-fastapi with a patch or use a custom entrypoint.

Real runtime UI

The FastAPI dashboard is a real runtime inspector, not only a chat page:

  • Chat — real tool-calling agent loop
  • Runtime — services, fibers, effects and reconciliation diagnostics
  • Plugins — plugin/fiber state, dependencies, provided services and enable/disable controls
  • Skills — inspect skills callable by the agent
  • Tools — inspect the tools currently exposed to the model
  • Events — live lifecycle, agent and tool events

The UI does not depend on the agent service. If the provider disappears and the agent loop becomes pending, the dashboard remains alive so the user can inspect and repair the runtime.

Durable session log

Cordis-Python keeps an append-only SQLite record of every model-visible step:

  • default path: <workspace>/.cordis/session.sqlite
  • override: --session-log PATH
  • storage: stdlib sqlite3, WAL mode, no extra dependency
  • invariant: anything the model can see has a durable, ordered representation
  • worker activity is logged in child sessions such as web-<uuid> and code-<uuid>
  • replay/fork/export APIs are available: read, sessions, fork, derive_messages, export_jsonl

See docs/SESSION_LOG.md for schema, event mapping and replay semantics.

Context manager and token budgeting

The context-manager plugin budgets every LLMRequest before dispatch:

  • provider-owned token counting
  • output and reasoning reserves
  • context/budget emitted for prepared requests
  • deterministic compaction bands for prune / compress / checkpoint
  • compaction bands never call the model
  • the append-only session log is never mutated by compaction

See docs/ARCHITECTURE.md for the budgeting and compaction contract.

Capability policies

Cordis-Python separates visibility from authority:

  • unauthorized tools are hidden from the LLM schema
  • the same capability policy is checked again immediately before dispatch
  • configuration layers control plugin composition only; they cannot bypass the dispatch-time permission gate
  • shipped user/research/self-coding profiles use default_allow: false
  • deny rules win over allow rules
  • principals such as main, worker:web and worker:code are scoped separately

Minimal policy shape:

default_allow: false
principals:
  main:
    allow:
      - "runtime_status"
      - "list_skills"
      - "read_skill"
      - "worker_web.research"
      - "worker_code.task"
  "worker:web":
    allow:
      - "web.search"
      - "web.fetch"
      - "web.browser"
  "worker:code":
    allow:
      - "code.search"
      - "code.read"
      - "code.write"
      - "code.git.status"
      - "code.git.diff"
      - "code.test.run"
      - "code.lint.run"
      - "skill.read"
      - "worker_web.research"

Isolated web worker

The main agent sees one public web tool:

worker_web_research(task, sources=6, depth="low")

The web worker owns a private tool registry. Its internal tools are not exposed to the main agent:

web_search
web_fetch
web_browser
web_crawl

Web worker setup

cordis run --profile profiles/user.yml starts the UI and runtime even if SearXNG or Lightpanda are not running.

Capability Required backend Requirement
web_search SearXNG accessible SearXNG instance; default endpoint http://127.0.0.1:8080
web_fetch HTTPX included by pip install -e ".[full]"; no Lightpanda required
web_browser Lightpanda lightpanda on PATH, or configure lightpanda_binary
web_crawl Firecrawl optional; configure firecrawl_url and enable Firecrawl explicitly
  • web_search currently uses SearXNG through the network-web seam.
  • web_fetch uses HTTPX for direct public page fetches and does not require Lightpanda.
  • web_browser requires Lightpanda for JavaScript rendering/navigation.
  • web_crawl / Firecrawl is optional and explicitly configured; profiles/user.yml denies web.crawl by default.
  • Missing backends do not prevent startup; they cause the corresponding web tool call to return a structured error.

Untrusted target URLs are validated against SSRF-style abuse, including redirects. Point network-web.searxng_url at your own SearXNG instance if needed.

See docs/WORKER_WEB.md for depth modes, seams, backend behavior, configuration and isolation limits.

Isolated code worker

The main agent sees one public code tool:

worker_code(task, on_success="leave_dirty", on_failure="rollback",
            commit_message="", fail_on_lint=true, max_steps=8)

The worker:code principal sees a private registry of code tools:

code_search
code_read
code_create_file
code_delete_file
code_apply_patch
code_git_status
code_git_diff
code_run_tests
code_run_lint
read_skill
research_web   (only when the worker-web plugin is mounted)

When the web worker is mounted, research_web is the code worker's only web access: one narrow delegation to the isolated worker:web, never the raw web tools.

The worker does not receive the general shell plugin and cannot supply arbitrary shell argv. It runs only fixed, Cordis-built command operations:

  • git for checkpoint / status / diff / commit / rollback
  • python -m pytest -q for tests
  • python -m ruff check . for lint
  • Python compile() for syntax checks

Each attempt:

  1. checkpoints on a cordis/attempt-* branch
  2. edits files inside the configured workspace
  3. runs syntax, test and lint validation
  4. emits a code/manifest event in a child code-<uuid> session
  5. leaves changes dirty, commits, or rolls back according to the harness
  6. reports structured failure semantics and retry guidance

The retry budget is bounded per user request.

See docs/CODE_WORKER.md for the full manifest, Git workflow and profile details.

Isolation principle: risky work behind narrow worker boundaries

Cordis-Python's default answer to "the agent must do something risky" is not to expose more low-level tools to the main agent, but to isolate the work behind a specialized worker with a narrow boundary. This is a Cordis architectural choice, not a generic multi-agent framework:

  • the main agent receives small, intentional high-level capabilities (worker_code, worker_web_research), never the underlying tools
  • each specialized worker owns a private tool registry and a restricted capability scope
  • worker:code performs filesystem/code/test/git operations inside its isolated code capability boundary
  • when code work needs external information, worker:code does not receive raw web_search, web_fetch, web_browser, web_crawl; it receives the narrow research_web delegation, which invokes the isolated worker:web
  • web research results cross the boundary as untrusted reference data, never instructions
  • delegation is deliberately asymmetric: worker:code → worker:web exists, but worker:web → worker:code does not
  • the asymmetry prevents an accidental generic recursive worker graph: delegation stays bounded to depth 1 and remains auditable
  • the session log preserves the hierarchy main → code-* → web-*

The rule: isolate risky capabilities behind narrow worker boundaries, compose those capabilities explicitly through the capability policy, and keep the microkernel unaware of application-specific worker orchestration.

The bundled worker-web, worker-code, browser, memory and other reference plugins are not claimed to be the best possible implementations. They are functional reference plugins intended to show that the Cordis model works end-to-end, and that implementations can be replaced without moving their complexity into the microkernel.

See docs/ARCHITECTURE.md, docs/CODE_WORKER.md and docs/WORKER_WEB.md for implementation details.

Self-extension example

Conceptual flow for:

User: Add a weather plugin.
main:
  1. read_skill("cordis-architecture")
  2. worker_code(
       task="Add a weather plugin",
       on_success="leave_dirty",
       on_failure="rollback"
     )

worker:code:
  3. code_search / code_read to inspect existing plugin patterns
  4. code_create_file / code_apply_patch to add the weather plugin
  5. code_run_tests
  6. code_run_lint
  7. success → code/manifest + leave dirty or commit
     failure → rollback + code/manifest with retry guidance

The point is not that the core understands weather plugins. The point is that the agent can extend the harness through the same plugin, permission, test and audit boundaries already exposed by Cordis.

Architecture skill

Cordis-Python ships a built-in skill:

cordis_py/skills/cordis-architecture/SKILL.md

The skills plugin exposes it through ordinary tools:

list_skills
read_skill

Before modifying Cordis-Python itself, the agent is instructed to read cordis-architecture, inspect the relevant source/runtime state, preserve the core/plugin boundary, make minimal edits and run tests.

Project skills can also be loaded:

my-skills/
└── my-project/
    └── SKILL.md
cordis run --profile profiles/user.yml --skills ./my-skills

Security: real protections and explicit limits

Real protections:

  • deny-by-default capability profiles
  • private tool registries for workers
  • tool schema hiding plus dispatch-time permission re-check
  • workspace confinement for file tools and code tools
  • no arbitrary shell argv in the code worker
  • fixed pytest / ruff / git command surface for code attempts
  • SSRF validation for untrusted web targets
  • append-only session log for model-visible steps
  • structured code/manifest audit data for code attempts

Explicit limits:

  • Cordis-Python is not an OS security sandbox.
  • Plugins run inside the Cordis Python process.
  • The shell plugin, when enabled, is an allow-listed subprocess helper, not an OS sandbox.
  • The network guard is an SSRF/URL validation layer, not a full egress proxy.
  • For untrusted workloads, run Cordis inside a container, VM, micro-VM or dedicated OS sandbox.

Architecture

                          CORDIS-PY CORE

          Context / scope / isolation / services
                            │
       events: emit / serial / parallel / waterfall
                            │
                          Runtime
                 dependency reconciliation
                            │
                  reversible Effect cleanup
                            │
                            ↓
                          PLUGINS

      provider ─────────────┐
      tools ────────────────┤
      sessions ─────────────┼──→ agent-loop
      context-manager ──────┤
      skills ───────────────┘
         │
         └── read_skill("cordis-architecture")

      developer-tools ──→ workspace file tools
      shell ────────────→ allow-listed subprocess helper
      worker-web ───────→ isolated web research
      worker-code ──────→ isolated code worker
      session-log ──────→ append-only SQLite audit
      ui-fastapi ───────→ live runtime inspection + chat

The core remains ignorant of LLMs, tools, skills, agents, browsers, code workers and UI.

The most important plugin rule

Plugins depend on capabilities and contracts, not on plugin implementations.

Good:

class ContextManagerPlugin:
    inject = ("provider",)

Bad:

from cordis_py.plugins.provider_openai import OpenAIProviderPlugin

A provider owns model transport, token counting and context-window knowledge. Context compaction remains separate because its strategy can change independently.

Repository map

cordis_py/
├── context.py
├── composition.py
├── contracts.py
├── errors.py
├── events.py
├── fiber.py
├── loader.py
├── netguard.py
├── permissions.py
├── runtime.py
├── textutils.py
├── tooling.py
├── cli.py
│
├── plugins/
│   ├── provider_fake.py
│   ├── provider_openai.py
│   ├── tools.py
│   ├── agent_loop.py
│   ├── session.py
│   ├── session_log.py
│   ├── context_manager.py
│   ├── skills.py
│   ├── developer_tools.py
│   ├── shell.py
│   ├── filesystem_local.py
│   ├── network_httpx.py
│   ├── browser_lightpanda.py
│   ├── worker_web.py
│   ├── code_tools.py
│   ├── worker_code.py
│   ├── subagents.py
│   ├── capabilities.py
│   └── ui_fastapi.py
│
└── skills/
    └── cordis-architecture/
        └── SKILL.md

Development

pip install -e ".[full,dev]"
pytest -q
ruff check .

On current main (v0.11.0), the suite reports:

177 passed

Benchmarks are regression signals, not scientific measurements:

python bench.py
python bench_stress.py

Documentation

Deep details live in docs/:

  • docs/ARCHITECTURE.md
  • docs/CONFIGURATION.md
  • docs/SESSION_LOG.md
  • docs/WORKER_WEB.md
  • docs/CODE_WORKER.md
  • docs/PLUGIN_CONFIG.md

License

MIT.

About

Minimal composable Python agent harness built on Cordis principles — plugin-first, auditable, self-extensible.

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages