Skip to content

How Anode Works

Anode is a loop. You prompt, the model asks for tools, Anode runs approved tools, and the results go back into the next model turn.

You do not need this page to use Anode. Read it when you want to understand why profiles, permissions, context, subagents, and review mode behave the way they do.

Every Anode session is a loop. You send a prompt. The model thinks. It calls tools. Anode executes them and returns results. The model decides what to do next. The loop continues until the model produces a final answer or hits a turn limit.

user prompt
-> model response
-> approved tool call
-> tool result
-> next model turn or final answer

Each turn, Anode sends the full conversation - your messages, model responses, and every tool result - to the LLM. The model has complete context to decide its next action. It either emits a text answer or requests another tool call.

Turn limits prevent runaway loops. The default profile (craft) caps at 20 turns. The study profile allows 40.

Anode also records local harness evidence for runs and diagnostics. Harness artifacts live under .anode-harness/ in the workspace and are ignored by git. They include run ledgers, raw event traces, tool receipts, best-effort diffs, validation reports, smoke reports, benchmark reports, and model usage summaries when providers emit token accounting.

Use these commands when you need to verify or inspect what happened:

anode doctor
anode harness check
anode harness smoke
anode harness bench --dry-run
anode harness inspect <run-id>
anode harness ledger <run-id>

anode harness replay <run-id> does not execute tools by default. It classifies recorded steps so you can see which calls were read-only candidates and which calls require manual inspection. --execute-read-only reruns only successful read-only receipts with raw call arguments; everything else remains skipped or inspect-only. Executed read-only replays save a replay artifact back into the run ledger and fail if replayed output no longer matches the original receipt summary. The replay header also shows recorded run timing so slow or interrupted sessions are obvious before opening the ledger JSON.

The model doesn’t run tools directly. It emits a structured response indicating what it wants to do. Anode parses that response and executes the corresponding tool.

The model can emit four kinds of responses:

KindPrefixWhat Happens
ANSWERPlain text or ANSWER:Anode displays the response to you
BASHBASH:Anode runs a shell command in your workspace
TOOLTOOL:Anode calls a named tool with JSON arguments
PATCHPATCH:TUI mode presents a unified diff for approval. Headless mode emits an approval-required event instead of applying it.

A TOOL response contains a JSON payload with the tool name and arguments:

{"name": "edit_file", "args": {"path": "main.go", "edits": [{"old": "foo", "new": "bar"}]}}

Anode parses the payload, runs the tool, captures the result, and appends it to the conversation. The model sees the result on its next turn and decides whether to continue or stop.

Anode ships with a core set of tools. Each tool has a permission level controlling whether it runs automatically or requires your confirmation.

ToolPurposePermission
bashRun a shell command (also handles the OpenAI shell_command request shape via canonical-name aliasing)Requires confirmation
readRead a fileAuto-allowed
multi_readRead up to 10 files in one round-tripAuto-allowed
edit_fileEdit an existing fileRequires confirmation
create_fileCreate a new fileRequires confirmation
apply_patchApply a unified diffRequires confirmation
finderSearch files, text, or symbolsAuto-allowed
globMatch workspace files by globAuto-allowed
grepFast text search using ripgrep or grepAuto-allowed
chartRender small terminal chartsAuto-allowed
taskSpawn a subagentDelegated
oracleConsult a second-opinion modelExternal read
code_reviewRun a structured read-only review passExternal read
web_searchSearch the web. The only external-fetch primitive; raw page bodies fall back to bash + curl.External read
lspCode intelligence via language servers, registered only when a server is configured or auto-detectedAuto-allowed
get_diagnosticsRead LSP diagnostics when LSP is activeAuto-allowed
ask_userAsk you a questionInteractive
todo_read / todo_writeManage agent task listAuto-allowed / State write
task_listPersistent task tracker with dependenciesState write
handoffCreate a structured handoffDelegated
look_atInspect visual artifactsAuto-allowed
skillLoad a predefined skillDelegated
find_thread / read_threadSearch and inspect local Anode sessions/runsAuto-allowed

Additional tools come from MCP servers, toolbox executables, and process plugins.

Anode connects to any LLM provider. It doesn’t lock you into one vendor. You set an API key, and Anode handles the rest.

ProviderEnv VarDefault Model
AnthropicANTHROPIC_API_KEYclaude-sonnet-4-6
OpenAIOPENAI_API_KEYgpt-5.5
Z.aiZAI_API_KEYglm-5.1
Z.ai CodingZAI_CODING_API_KEYGLM-5.1

Anode supports Gemini, Groq, DeepSeek, Mistral, Fireworks, Ollama, xAI, OpenRouter, Together, Cerebras, DeepInfra, Hugging Face, Azure OpenAI, Bedrock, and any OpenAI-compatible endpoint. See Providers for the full list and configuration.

All providers implement the same streaming interface. Anode sends a request and receives tokens back one at a time. The TUI renders tokens as they arrive. Headless mode emits them as JSON events.

Provider configuration lives in your config file:

{
"model": "anthropic/claude-sonnet-4-6",
"providers": {
"deepseek": {
"type": "deepseek",
"apiKey": "{env:DEEPSEEK_API_KEY}"
}
}
}

Every model has a context window - a limit on how much text it can process at once. Anode tracks token usage across the conversation and manages that budget for you.

The default context window is 200,000 tokens if you don’t set one. To use a different window for a specific model, set maxContextTokens under providers[*].modelDefaults; that value wins over the global context.window whenever that model is active.

By default Anode auto-compacts at 85% of the effective context window (so ~170k tokens on a 200k model, ~850k on a 1M model). When the threshold is crossed, older turns are summarized into a structured note while preserving:

  • Your original goal
  • Files read and modified
  • Recent errors and their resolutions
  • A log of actions already taken

The most recent 20,000 tokens are never summarized. This keeps the model’s short-term memory intact while freeing space for new work.

Compaction is transparent. You don’t need to manage it. If you want to tune the behavior, adjust the context section in your config file:

{
"context": {
"window": 200000,
"reserveTokens": 16384,
"keepRecent": 20000,
"compactPercent": 0.85,
"compactEnabled": true
}
}

compactPercent accepts (0, 0.99]; pass -1 to fall back to the legacy window - reserveTokens cutoff. See Configuration → Per-model context windows for the BYOK / proxy model setup.

A profile combines a model, system prompt, tool access, and behavior into a single preset. Profiles route work to the right model with the right constraints.

ProfilePurposeToolsRead-OnlyMax TurnsEffort
craftGeneral-purpose codingBroad coding toolsNo203
quickFast, small tasksFocused subsetNo102
studyComplex architecture and debuggingBroad plus coordination toolsNo404
reviewRead-only code reviewRead-onlyYes123
oracleSecond-opinion reasoningRead-onlyYes84
findRepository and manual/project-note discoveryRead-onlyYes82
aggmanMulti-agent aggregationThread, web, receive_messages, todo_readYes62

Switch profiles in the TUI with /mode or on the CLI with --profile. Define custom profiles in your config file, and see Profiles for aliases and built-in profile details.

The main agent can spawn child agents using the task tool. Each subagent gets its own context window, runs independently, and returns a summary when done.

Subagents are useful for:

  • Isolated work. Child runs can focus on distinct files or questions without carrying all intermediate context back into the parent. Streaming review checks use child runs and can run with bounded concurrency.
  • Large-output tasks. A subagent can process a huge file without bloating the parent’s context.
  • Context isolation. Exploratory work stays in the child. Only the summary comes back.
{
"name": "task",
"args": {
"title": "Add input validation",
"goal": "Add email validation to the signup handler in auth.go",
"max_steps": 20,
"read_only": false
}
}

The parent tracks child runs via child_run.started and child_run.result events. Subagent permissions inherit from the parent’s permission policy with a child_run context.

The oracle tool consults a second-opinion model. It’s a read-only child run scoped to reasoning - no file mutations, no shell commands.

Use oracle for:

  • Complex debugging where a fresh perspective helps
  • Architectural review of a proposed approach
  • Evaluating trade-offs between alternatives
{
"name": "oracle",
"args": {
"question": "Is this migration safe to run in production?",
"files": ["migrations/003_add_index.sql"],
"focus": "data safety and locking behavior"
}
}

Oracle uses the oracle profile by default (high reasoning effort, read-only tools). You can override the model with the model argument.

On startup, Anode scans your repository and builds a context pack. This context is included in the first model request so the model understands your project from turn one.

The context pack includes:

  • Repository structure. Top-level files and directories (up to 80 entries).
  • Git state. Current branch, working tree status, and a bounded changed-file list extracted from git status --short, with an explicit truncation marker when the list is capped.
  • Agent instructions. Contents of AGENTS.md, AGENT.md, or CLAUDE.md files at the repo root and in subdirectories. These files let you give the model project-specific instructions.
  • Available skills. Skills discovered in ~/.config/anode/skills/, .agents/skills/, and .claude/skills/.

Agent instruction files support @file includes for pulling in additional context. See Agents and Skills for the full format.

Anode doesn’t blindly execute whatever the model asks for. Every tool call passes through a permission system before execution.

Tools that modify files (edit_file, create_file) or run shell commands (bash) require your confirmation by default. Read-only tools like read and finder run automatically.

A JSON-based policy controls what’s auto-allowed, what requires confirmation, and what’s blocked entirely. Rules match on tool name, arguments, and context (main run vs child run).

[
{"tool": "bash", "matches": {"command": "go test *"}, "action": "allow"},
{"tool": "bash", "matches": {"command": "rm -rf *"}, "action": "reject"}
]

Three presets provide starting points:

PresetBehavior
unrestrictedAllow everything (yolo is an alias for unrestricted)
carefulReject destructive commands, allow safe reads
strictAsk for everything

See Permissions for rule syntax and precedence.

Anode records every file modification in a change ledger. Each entry tracks the file path, before/after content hashes, diffs, risk level, and validation status. Use /changes in the TUI to review what Anode has modified. Use /commit to prepare a git commit from tracked changes.