Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Custom agents

Place JSON files in .koda/agents/ (project-local) or ~/.config/koda/agents/ (global):

{
  "name": "testgen",
  "system_prompt": "You are a test generation specialist. When asked to write tests, always use the project's existing test patterns.",
  "model": "gemini-2.5-flash",
  "trust": "safe",
  "allowed_tools": ["Read", "Write", "Edit", "Bash", "Grep", "Glob"]
}

Agent fields

FieldRequiredDescription
nameIdentifier used with /agent <name> and InvokeAgent
system_promptThe agent’s persona and instructions
trust"plan" (read-only), "safe" (write-capable, default), or "auto" (auto-approve mutations within sandbox). See Trust modes.
modelModel alias or ID (defaults to current saved model)
allowed_toolsSubset of tools the agent can call (defaults to all)
disallowed_toolsTools to deny even if allowed_tools is empty
max_iterationsPer-sub-agent turn cap (default: 30 for sub-agents, 200 for top-level). See Sub-agent budget.
skip_memorySkip injecting project/global memory into the prompt (saves tokens for read-only agents)
write_accessDeprecated — use trust instead. Pre-existing JSONs still work; a warning is logged at load. See Migration from write_access.

Three example shapes

The trust field is the primary mechanism. Most custom agents fall into one of three shapes:

Read-only investigator (Plan trust)

For agents that should only investigate, never modify state:

{
  "name": "auditor",
  "system_prompt": "You audit code for security issues. Read, grep, and report — never modify files.",
  "trust": "plan",
  "skip_memory": true
}

trust: "plan" makes the kernel sandbox enforce read-only at the syscall level — strictly stronger than soft-denying Write/Edit/Delete in disallowed_tools. (Soft-denying still works as a behavioral floor for tools the matrix can’t gate, like InvokeAgent or AskUser.)

Write-capable worker (Safe trust)

The default shape for agents that need to make changes:

{
  "name": "testgen",
  "system_prompt": "You write tests. Match the project's existing patterns.",
  "trust": "safe",
  "allowed_tools": ["Read", "Write", "Edit", "Bash", "Grep", "Glob"]
}

In Safe trust, the sub-agent matrix auto-approves mutating ops (Write/Edit/MemoryWrite) and blocks destructive ops (rm -rf, git reset --hard, Delete). No human prompt needed because there’s no UI for the sub-agent to prompt into.

Read-only with execution escape valve (Safe trust + denied writes)

For agents that need to run tests / inspect runtime state but should never modify code (e.g. the built-in verify agent):

{
  "name": "verify",
  "system_prompt": "You verify behavior by running tests. Never edit source.",
  "trust": "safe",
  "disallowed_tools": ["Write", "Edit", "Delete"]
}

This is strictly different from trust: "plan": the agent can still call Bash (run cargo test, pytest, etc.) but the trust matrix’s auto-approve for mutating tools is overridden by the soft denylist. Plan would deny Bash outright as a mutation.

Migration from write_access

The legacy write_access: bool field is deprecated. The mapping:

Old shapeNew shape
{ "write_access": true }{ "trust": "safe" }
{ "write_access": false }{ "trust": "plan" }
{ "write_access": false, "disallowed_tools": [...] }{ "trust": "plan", "disallowed_tools": [...] }

Pre-existing JSONs without trust still work via a back-compat default-deny: write_access: false (or absent) injects Write/Edit/Delete into disallowed_tools at load. Adding trust explicitly skips the legacy default-deny so an explicit trust: "safe" declaration works cleanly without surprise denials.

A deprecation warning is logged at load when both trust and write_access: true appear in the same JSON.

Sub-agent budget

Sub-agents are bounded by a per-invocation turn cap to prevent runaway exploration (#1135). The default is 30 turns — empirically enough for any reasonable read-only investigation on a moderate codebase, and matching gemini-cli’s DEFAULT_MAX_TURNS. Long-running write agents that legitimately need more can opt up:

{
  "name": "big-refactor",
  "trust": "safe",
  "max_iterations": 100,
  "...": "..."
}

When a sub-agent hits its budget without producing a final answer, Koda runs one grace turn with this system reminder appended:

You have reached the maximum number of turns. You have ONE final chance to complete the task. You MUST respond with your best answer NOW as plain text. DO NOT call any more tools — any tool calls in this response will be ignored.

If the model complies, its grace-turn text becomes the sub-agent’s result. If the model defies the reminder and emits more tool calls, those calls are dropped and the sub-agent returns a [max_turns reached: ...] marker so the parent (and user) can see what happened.

The top-level Koda agent still uses the larger 200-turn cap with an interactive extension prompt (LoopCapReached) — the budget pattern is sub-agent-only.

Using agents

/agent testgen     ← switch to a named agent for the current session

The main model dispatches to sub-agents via the InvokeAgent tool. Each sub-agent runs in its own worktree with its own model, tools, and session.

Built-in agents

AgentTrustPurpose
defaultsafeGeneral-purpose coding assistant — the master agent shape
tasksafeGeneric write-capable sub-agent for InvokeAgent dispatch
exploreplanRead-only investigation sub-agent — code review, dependency tracing, audit trails
planplanRead-only planning sub-agent — proposes changes without making them
verifysafeExecution-only sub-agent — runs tests/scripts but Write/Edit/Delete are denied as a behavioral floor