Savant-Code is an engineering agent framework built on the ECHO Protocol v0.2.0. The framework enforces a separation-of-duties agent model where each phase of the Perfection Loop is handled by a specialized agent. Code is never written until a FID (Feature Implementation Document) has converged through the Perfection Loop.
Two products ship from this monorepo: Savant-Code (paid CLI + SDK) and Savant-Free (ad-supported variant). Both share one runtime, one SDK, and one set of engineering laws (ECHO).
Hybrid Mode exception: the overview rule below applies to complex tasks.
For simple tasks the Orchestrator writes code directly without a FID (ECHO.md
Hybrid Mode; runtime path idle → green), then verifies immediately.
FID-2026-0803-001 ECHO-4.
| # | Agent | Phase | Responsibility | Tools |
|---|---|---|---|---|
| 1 | Orchestrator | ALL | Routes work through Perfection Loop, enforces protocol compliance, spawns all agents | spawn_agents, read_files, read_subtree, run_readonly_command, write_todos, suggest_followups, ask_user, read_url, skill, set_output, list_directory, glob, render_ui, gravity_index, update_goal, get_goal (durable goal mode, FID-2026-0814-002), transition_phase, write_file, str_replace, apply_patch (phase-gated), set_scaffold_complete (scaffold mode) |
| 2 | Detective | RED | Codebase analysis, grep call-graphs, find issues, catalog evidence with file paths | code_search, set_output, list_directory, glob, read_files, read_subtree, query_blast_radius, query_node_edges, query_domain_clusters |
| 3 | Forge | GREEN | Implementation only. Writes code following the converged FID spec. Cannot self-verify. | read_files, write_file, str_replace, set_output (FID-2026-0824-031) |
| 4 | Verifier | AUDIT | Double-audit, run tests, check call-graph reachability, reject hallucinated claims | (no tools — reads only via message history) |
| 5 | Recorder | FID | Create, track, archive FIDs. Update CHANGELOG. Ensure no FID closes without AUDIT evidence | write_file, read_files, glob, code_search, set_output |
| 6 | Thinker | Planning | Deep reasoning via sequential thinking engine. Critiques specs, plans, implementations | sequentialthinking, end_turn |
| 7 | Scout | Explore | File/code search, glob, read subtrees, context gathering | glob, list_directory, read_files, read_subtree, set_output, query_blast_radius, query_node_edges, query_domain_clusters |
| 8 | Researcher | Research | Web search, documentation lookup, external API research | web_search, read_url (web); read_docs (docs); deep_research (FID-2026-0804-002) |
| 9 | Scribe | Docs | Session summaries, LESSONS.md, knowledge files, end-of-session capture | read_files, write_file, glob, code_search, set_output |
| 10 | Adversary | ADVERSARIAL | Meta-verification: refutes every Verifier FAIL, re-audits every unevidenced PASS, resolves citations, re-rates severities; verdicts override the Verifier's (FID-2026-0805-004) | read_files, code_search, glob, list_directory, set_output |
Note on Orchestrator write tools: Per FID-2026-0718-008, the Orchestrator has
write_file+str_replacein its toolName list, but they are GATED to exempt paths only (dev/fids/,dev/scratchpad/,dev/nova/) bytool-executor.ts. For all non-exempt paths, these tools are blocked unless FSM phase isgreenorself_correct(see Tool Gating). This satisfies ECHO separation-of-duties for production code while allowing FIDs/scratchpad without ceremony. FID-2026-0803-001 ECHO-5 reconciled this table withagents/savant/savant.ts(run_readonly_command,gravity_index,apply_patch,set_scaffold_completeare model-visible for the Orchestrator).
Note on Recorder archive ownership: the Recorder has no filesystem move/archive tool; the CLI/orchestrator executes the
dev/fids/ → dev/fids/archive/move while the Recorder authors the FID + CHANGELOG content and evidence. FID-2026-0803-001 ECHO-6.
The Perfection Loop runs on the FID document, not on the code. Code implementation begins only after the FID converges to COMPLETE.
┌──────────────────────────────────────────────────────────┐
│ FID PERFECTION LOOP │
│ (iterates on the FID document until convergence) │
│ │
│ ┌─────────┐ ┌──────────┐ ┌─────────┐ ┌──────────────┐ │
│ │ RED │──>│ GREEN │──>│ AUDIT │──>│ ADVERSARIAL │ │
│ │ PHASE │ │ PHASE │ │ PHASE │ │ PHASE │ │
│ └─────────┘ └────┬─────┘ └─────────┘ └───┬──────┬────┘ │
│ ^ │ │ │ │ │
│ │ │ ┌───────┴───────┐ │ │ │
│ │ │ │ SELF-CORRECT │<───┘ │ │
│ │ │ │ (findings) │ │ │
│ │ │ └───────┬───────┘ │ │
│ │ │ │ ┌──────────────┘ │
│ │ │ ▼ ▼ │
│ │ │ ┌──────────────┐ │
│ │ │ │ COMPLETE │ │
│ │ │ │ (converged) │ │
│ │ │ └──────────────┘ │
│ └──────────────┘ (new issues → re-enter RED) │
└────────────────────────────────────────────────────────────────┘
│
┌──────────────────────────────────────┘
▼
┌─────────────────┐
│ IMPLEMENTATION │ Only after FID converges
│ (Forge agent) │
└─────────────────┘
│
▼
┌─────────────────┐
│ VERIFICATION │ Verifier validates the code matches FID
│ (Verifier) │
└─────────────────┘
| FID Phase | Agent | What Gets Produced |
|---|---|---|
| RED | Detective | Issue catalog with evidence: file paths, line numbers, grep output, call-graph |
| GREEN | Thinker + Recorder | Proposed fix in FID, all questions answered, most robust defaults chosen |
| AUDIT | Verifier + Recorder | Verification output pasted into FID, call-graph grep results, double-audit evidence, per-finding file:line citations (FID-2026-0805-004) |
| ADVERSARIAL | Adversary | Meta-verification: refuted/evaluated Verifier findings (CONFIRMED/REFUTED/ADJUSTED), resolved citations, re-rated severities; verdicts override (FID-2026-0805-004) |
| SELF-CORRECT | Thinker + Recorder | Revised fix, updated FID sections |
| COMPLETE | Recorder | FID closed, archived to dev/fids/archive/, CHANGELOG.md updated |
| Post-FID: Forge | Forge | Code implementation matching the FID spec |
| Post-FID: Verify | Verifier | Code verified: typecheck, tests, lint, call-graph check |
The Thinker agent uses the sequentialthinking tool for all non-trivial reasoning.
This is a direct copy+integration of the SequentialThinkingServer class from
the MCP reference implementation, stripped of MCP transport.
The Thinker calls sequentialthinking iteratively in a loop:
thought 1: "Analyze the problem... what exactly needs to be solved?"
thought 2: "Identify constraints... boundaries, requirements, non-negotiables
..."
thought 3: "Wait, that approach has a flaw — revising thought 2"
(isRevision: true, revisesThought: 2)
thought 4: "Alternative approach branching from thought 1"
(branchFromThought: 1, branchId: "approach-b")
thought 5: "Compare approach A vs approach B..."
...
thought N: "Final recommendation. nextThoughtNeeded: false"
The SequentialThinkingServer instance lives in the Thinker agent's state,
persisting across steps within a single think session:
thoughtHistory[]— every thought step, in orderbranches{}— branching thoughts keyed by branchId- Each call returns: current thought number, total thoughts, branch list, thought history length
{
thought: string, // Current thinking step
nextThoughtNeeded: boolean, // true unless fully converged
thoughtNumber: number, // Current position in sequence
totalThoughts: number, // Current estimate (auto-adjusts)
isRevision?: boolean, // Revising a previous thought
revisesThought?: number, // Which thought is being revised
branchFromThought?: number,// Branching from this thought number
branchId?: string, // Branch identifier
needsMoreThoughts?: boolean// Need to extend beyond initial estimate
}agents/thinker/thinker.ts— getsuseSequentialThinkingTool: truecommon/src/tools/constants.ts— new tool namesequentialthinking- Tool handler in
packages/agent-runtime/src/tools/— wrapsSequentialThinkingServer
The Orchestrator tracks current Perfection Loop phase in AgentState:
type PerfectionLoopPhase =
| 'idle'
| 'red'
| 'green'
| 'audit'
| 'adversarial'
| 'self_correct'
| 'complete'- Phase transitions are explicit via the
transition_phasetool - The runtime validates that transitions follow the FSM legal paths
- Invalid transitions (e.g., idle → audit) are rejected
Tracked in AgentState:
{
charChangeTotal: number, // Running total for 10% cap
iterationCount: number, // Current loop iteration
oscillationDetections: number, // Same issue reappearing
lastIssueIds: string[], // Last 3 issues for oscillation detection
}Tools are gated by FSM phase in tool-executor.ts:
| Tool | Allowed Phases | Status |
|---|---|---|
| write_file, str_replace, apply_patch | GREEN + SELF_CORRECT (exempt paths: dev/fids/, dev/nova/, dev/scratchpad/) | ✅ Active |
| run_terminal_command (bash) | AUDIT + GREEN + SELF_CORRECT | ✅ Active (FID-2026-0806-016 F4) |
| sequentialthinking | Thinker only (id starts with thinker) |
✅ Active |
| code_search, read_files, glob, list_directory | ALL | ✅ Active (no gating needed) |
| spawn_agents | ALL | ✅ Active (template-level only) |
| bash (destructive) | Never | ⏭️ Future phase (command classification not yet implemented) |
| create_fid, update_fid, archive_fid | Recorder only | ⏭️ Future phase (these are conceptual roles, not registered tools) |
The tool executor exposes a project-scoped hook system declared in
protocol.config.yaml under hooks:. Hooks fire at lifecycle points
(PreToolUse/PostToolUse/PostToolUseFailure + session/subagent events) and
compose with the EHEL beforeToolCall gate — an additional gate, never a
bypass. Hooks are fail-open: only exit code 2 or a JSON
"permissionDecision": "deny" blocks a tool. See
docs/design/hook-system.md.
The Orchestrator owns a durable, budgeted goal record on agentState
(active | paused | blocked | complete) driven by a continuation driver and
the update_goal/get_goal tools. See docs/design/goal-mode.md.
Every write records a per-role Ed25519-signed receipt into an append-only
hash-only session ledger (provenance.mode: off | record | enforce). See
docs/design/zero-trust-agentic-provenance.md.
- Load ECHO.md — establish identity
- Load
protocol.config.yaml— get project commands - Review
dev/fids/— flag open FIDs - Create session summary at
dev/session-summaries/ - Enter IDLE phase — wait for user input
The 10-agent roster above represents ECHO runtime roles — the conversational agents that the Orchestrator spawns through the Perfection Loop.
The filesystem under agents/ may also contain helper tool libraries which are consumed by the canonical 10 roles
but do NOT constitute independent conversational agents:
| Helper Dir | Consumed By | Notes |
|---|---|---|
browser-use/ |
agents/savant/savant.ts:132, agents/context-pruner.ts, common/src/constants/free-agents.ts, common/src/__tests__/free-agents.test.ts |
Browser automation helper used by Orchestrator + context-pruner |
database/ |
agents/savant/savant.ts, common/src/constants/free-agents.ts, common/src/__tests__/free-agents.test.ts |
SQLite schema inspection + safe queries (FID-2026-0804-004) — native handlers with adapter-enforced read-only/write-approval guardrails |
(package) knowledge-graph/ |
agents/detective/detective.ts, agents/scout/scout.ts, packages/agent-runtime/src/tools/handlers/tool/graph/*, packages/agent-runtime/src/util/graph-injection.ts |
Deterministic codebase knowledge graph (FID-2026-0806-002) — query_blast_radius/query_node_edges/query_domain_clusters read-only native tools; Verifier/Thinker reachability evidence injected via message history (zero-tool contracts unchanged) |
github/ |
agents/savant/savant.ts, common/src/constants/free-agents.ts, common/src/__tests__/free-agents.test.ts, agents/github/github.test.ts |
GitHub PR/issue/CI/code-search via the official MCP server (FID-2026-0804-003) — remote HTTP route, read-only default |
editor/ |
cli/src/utils/implementor-helpers.ts, agents/editor/best-of-n/* |
Editor scaffolding/best-of-N helper agents used by the CLI implementor flow |
file-explorer/ |
common/src/constants/agents.ts, agents/file-explorer/* |
File listing helpers (directory-lister, glob-matcher) |
librarian/ |
agents/context-pruner.ts |
Knowledge/context helper used by context-pruner |
types/ |
agents/base-chat.ts, agents/savant/savant.ts, agents/basher.ts, agents/browser-use/browser-use.ts |
Type-only shared imports across all agents + basher |
debug/ |
(none — transient output) | Browser-agent trace output dir (agents/debug/browser-agent-traces/); not a helper library |
Hierarchy:
- 10 canonical ECHO runtime roles (Orchestrator + 9 specialists)
-
- 8 helper tool libraries (above;
debug/is a transient trace-output dir;database/+github/added per FID-2026-0804-006)
- 8 helper tool libraries (above;
- = 19 directories in
agents/(FID-2026-0803-001 ECHO-9 reconciled the count after thesavant-deep/e2e/__tests__removals; FID-2026-0804-006 addeddatabase/+github/; FID-2026-0805-004 addedadversary/)
These two counts are NOT in conflict: the 10-agent roster represents runtime conversation entities; the 19-dir count represents filesystem entries. Future checklists/audits should not confuse them.
Current state: The repository uses the @savant-code/* workspace names and import paths at version 0.0.26.
Historical rebrand and checkpoint decisions remain in the archived session records and release history; this architecture
document tracks the current repository state.