Repository navigation
Architecture
The mental model in one line: a Cordis plugin container where every capability is a replaceable seam, and every agent turn is a durable, replayable event log.
┌──────────────────────────────────────────────────────────────┐
│ dsh CLI launcher │
│ profile = ordered bundle patch layers + your patch │
└──────────────────────────────┬───────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────────┐
│ Cordis context (ctx) │
│ │
│ ctx.llm ──── adapters ──► OpenAI / Anthropic / DeepSeek │
│ ctx.tools ── registry ──► bash, fs, web, subagent, … │
│ ctx.shell ──────────────► bash-local / pwsh-local │
│ ctx.fs ─────────────────► fs-local (audit + policy) │
│ ctx.web ────────────────► fetch/search backends │
│ ctx.sessions ───────────► JSONL / SQLite persistence │
│ ctx.subagents ──────────► delegation, teams, jobs │
│ ctx.sandbox ────────────► read-only / workspace-write │
│ ctx.credentials ────────► owner-only secret store │
│ ctx.settings ───────────► settings.yaml + revision gates │
└──────────────────────────────┬───────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────────┐
│ The Agent Loop │
│ system prompt ─► model stream ─► tool calls ─► results ─► │
│ … until finish reason. Every step = durable session event. │
└──────────────────────────────────────────────────────────────┘
1. Capability seams, never implementations. A tool calls ctx.shell, not "spawn
bash". The executor behind the seam is a separate plugin (bash-local, pwsh-local,
your own). Swap the executor → the model-facing schema is unchanged. This is the single
most important property; every layer obeys it.
2. Every turn is an event log. The agent loop appends typed events (tool/call,
tool/result, llm/retry, todo/write, team/message/queued, …) to a durable session.
Persistence (JSONL or SQLite) is itself a seam. Sessions replay: a restart folds the log
back into live state — mailboxes, goals, schedules, todos all survive.
3. Failures are coded, not vibes. Provider errors arrive as a serializable
LlmFailure (RATE_LIMIT, TIMEOUT, TRANSPORT, CONTEXT_WINDOW_EXCEEDED, …) that
policy routes on — retries, backoff, and escalation are decisions made from codes, not
regex archaeology on error text.
4. Containment is a layer, not a suggestion. Sandbox policy travels with the execution spec; executors confine before spawning; escalation is an explicit, validated, human-approved transition. Approval and permission policy gate every mutating call.
| Layer | Mechanism |
|---|---|
| Framework | Vendored Cordis (plugin container, HMR, fibers) |
| Config validation |
Schemastery schemas behind every plugin's Config
|
| Session persistence | JSONL (default) or SQLite; semantic checkpoint policy |
| Retry | Per-provider bounded policies (codes + jittered backoff) or unbounded always
|
| Context pressure | Token metering → compaction → tool-result pruning; overflow detection against declared windows |
| Watchdogs | Idle-timeout watchdogs on streams, deadlines on every exec, timer disposal on teardown |
Model streaming is translated into a normalized chunk vocabulary —
block-start / text-delta / tool-call-delta / usage / finish — so every adapter
(OpenAI SSE, Anthropic Messages, pi-ai protocols) feeds the same renderer and the same
finish-reason semantics (stop, tool-calls, max-tokens, aborted, error kinds).
| Topic | In-repo doc |
|---|---|
| Capability seams | docs/capability-seams.md |
| Agent lifecycle | docs/agent-lifecycle.md |
| API gateway | docs/api-gateway.md |
| The plugin container |
docs/cordis-primer.md + docs/cordis-tutorial/
|
| Full tool schemas |
docs/tool-catalog.md (generated, exact) |