Providers and adapters¶
OpenCode is the default engine. Codex: --engine codex. Claude Code: --engine claude
(built in). Any other tool registers with one TOML file.
Provider process ownership¶
Supervised task-stage providers, including core TaskRun conversations and
autocode ui, require a native little-endian Linux x86_64 or aarch64
runtime, matching /proc PID namespace, and working seccomp user notifications
with syscall continuation. A Linux host without them, and any other unsupported
host except macOS, refuses the launch before provider spawn. The refusal
identifies the unavailable boundary; it does not send a model request. There is
no CLI opt-out.
macOS has no seccomp, so providers there run without this boundary (#1195):
the keeper's lifeline and sampled process-group and session ownership, as for
runner commands, with no kernel proof that every descendant exited. The run
prints one notice on stderr, and the supervision receipt carries no
session_boundary. A provider child that calls setsid() and reparents
between samples can outlive the run there; use Linux when that matters.
Automatic model-access probes started by a task use the same provider boundary and retain attempt-local admission and cleanup receipts. Admission or cleanup failure pauses the task. A probe timeout remains uncertain and can be retried; it does not become a cached access pass.
Each automatic probe counts toward the run's recorded spend and active time. The runner checks the remaining money/time allowance and pending human input before each request, limits its timeout to the remaining active time, and saves its usage before admitting another probe or workflow stage. Stop is acknowledged only after the previous probe's cleanup is verified. Interrupted attempts retain their evidence and usage; they require verified cleanup before a retry. Older marker-only access passes remain readable, but their historical probe usage cannot be reconstructed from the marker.
The dashboard's separate conversation/intake transports and explicitly invoked standalone provider probes use other launch paths; this task-owned boundary does not qualify them.
The owner chose this macOS fallback in #1195 (delivered by #1204). #1265 replaced it with strict refusal on 2026-10-14; the owner restored the fallback on 2026-10-15, so local live qualification can run on macOS.
Normal detached shell tools remain allowed: the independent keeper records a
prospective session before permitting setsid(). Its receipt preserves that
ownership through controller or keeper loss. Cleanup is verified only when the
kernel reports that no task retains the inherited boundary. Permission errors,
missing receipts and unverified cleanup remain failures.
Providers inherit no_new_privs, so privilege elevation through exec is
unavailable. Additional ordinary seccomp filters remain allowed, but installing
a replacement notification listener is refused. Launches with permitted or
effective CAP_SYS_PTRACE or CAP_SYS_ADMIN are also refused. The keeper is
non-dumpable to protect its listener from same-user descriptor access. This is
a process ownership boundary, not a filesystem or network sandbox.
Offline native tests cover detached spawning, thread callers, double forks, descriptor closure, owner loss and keeper loss. They do not establish live-model or provider-version conformance. This policy changes no role models or routes.
Runner-owned verification commands use their existing portable lifeline and sampled SID guard, including nested preparation workers. They do not install a provider listener or claim its kernel family-extinction proof. Commands already inside a provider family continue to inherit that family's filter. The model adapters always use the mandatory provider boundary; there is no CLI opt-out.
OpenCode adapter¶
The Requirements Gatherer, Planner and default Builder use the connections already configured in OpenCode. --engine opencode
is accepted but is optional for new runs:
python3 tools/autocode.py "Your rough idea" --workspace /path/to/project
Override the planning roles with --requirements-model, --glm-model, and
--plan-reviewer-model (plus their reasoning-effort flags). For a new task without
a conversation-handoff profile, --glm-model also selects the initial Requirements
model unless --requirements-model selects it separately. Conversation handoffs
apply an independent profile: Requirements keeps that profile's default unless
--requirements-model selects it explicitly. Resuming keeps the saved Requirements
model unless --requirements-model explicitly changes it.
Override execution roles with --astra-model, --terra-model,
--sol-model, or --completion-model using a provider/model ID from opencode models, including
openai/… with an OpenCode ChatGPT OAuth connection. Saved runs retain their original role
engines and sessions; no existing run is migrated by a dashboard selection.
If an account offers only one model, --single-model MODEL assigns it to all
roles and permits same-model verification. The roles still run in separate
sessions and all normal evidence, approval and completion gates remain active,
but model-family independence is intentionally unavailable in this mode.
OpenCode reasoning variants can be selected in the browser or with the existing
role-specific reasoning-effort flags. New joint runs start with separate GLM requirements
and planner sessions, GPT-6 Sol High for the Plan Reviewer, GLM Medium for the Builder, GPT-6
Sol High for the Validator, and a separate GPT-6 Sol Medium session for the Completion Owner.
Escalation then follows the ladders and Builder retry policy documented in
Models. Provider
credentials remain with OpenCode: Autocode does
not read its auth file or change your global configuration.
The same approval, task, independent-evidence and completion gates apply. The adapter
uses OpenCode's non-interactive JSON event interface,
validates the final report against the stage schema, and verifies command evidence
against actual completed bash events; the runner then re-runs a passing Validator's
checks itself in a clean copy (Execution). Raw events, session IDs and stage-local
permission overrides are saved alongside the checkpoint. Token limits include cache
reads/writes and reasoning tokens. Malformed or uncertain results pause; the runner
does not automatically replay an ambiguous provider request. An explicitly retryable
native APIError with ECONNRESET, ETIMEDOUT, EPIPE, or HTTP 500/502/503/504 may
receive one fresh same-stage, same-model retry when its entire event stream contains
only that error, its collected failed process exited normally with verified owned
cleanup, and its source, Git index, task, settings and route are unchanged. The
failed attempt, raw events and usage remain charged and retained. The existing
run-wide automatic-recovery limit still applies; restarts, abandonment and route
changes do not renew a failed chain's allowance. Session continuations, partial
turns/tools/reports, uncertain cleanup, human gates, quota/auth failures and output
limits keep their ordinary recovery policy. Saved attempts without the launch
binding and non-native transports remain unsupported by this automatic retry.
The supported native error fields follow OpenCode 1.18.33's conversion
and HTTP error metadata;
unknown metadata keeps the ordinary hold.
When a Validator or Completion Owner response is cut off by the output-token limit and the process exited cleanly with the source unchanged, the runner archives the attempt and queues a bounded report-only repair from the saved partial response and check evidence rather than replaying the provider request.
OpenCode has a different isolation boundary: Requirements Planner sessions and other
read-only OpenCode roles have edit tools denied and their workspace snapshots
checked, but OpenCode tool permissions are not an OS sandbox. Shell commands
and configured external tools retain OpenCode's native permission policy. Autocode
also rejects a read-only report when native OpenCode step snapshots record a
workspace change during the attempt, even if the final files were restored. This
check applies when loading saved reports and when reusing review evidence for
report repair. Before a native OpenCode launch, the runner adds local Git
exclusions for .autocode/, .autocode-ui/, __pycache__/ and *.pyc, matching
its existing source-snapshot boundary and preserving other exclusion rules.
This prevents runtime evidence writes from looking like source drift. The check
cannot detect writes outside the workspace, ignored files, or
transient changes between snapshots, and is unavailable when the transport omits
snapshots. Use an OS sandbox when filesystem prevention is required.
The built-in OpenCode adapter does not enable --auto or override user-level
permission rules with blanket allows.
A denied required operation is reported back as a blocker.
See OpenCode's permission documentation.
Output cap¶
OpenCode derives a requested response limit from the model's listed output limit
and OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX, with a 32000-token default. Provider routes
can override it. On routes that honor the setting, reasoning counts against the same
limit; a planning report can exceed it and stop with finish reason length and
truncated JSON. AutoCode therefore launches OpenCode with
OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX=64000 unless you set a positive whole number
yourself, which wins:
OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX=100000 autocode "..."
The setting is a request, not a verified provider limit. For example, OpenCode 1.18.33's
OpenAI Codex plugin clears maxOutputTokens
after OpenCode derives it from this setting.
A real Codex check returned responses exceeding the requested setting. Increasing this
variable cannot be assumed to fix truncation on that route.
AutoCode does not default to the model's whole listed limit: OpenCode's context planning
uses this setting, and some APIs refuse a request whose input plus maximum output
exceeds the window. Each stage record keeps the requested setting (or OpenCode's default
when absent) under output_token_cap (tokens, and set_by:
operator, autocode, or opencode when the variable did not reach it). A length stop's
pause distinguishes that setting from how many tokens the last response used. A collected, terminal
length stop offers a route-ROLE question (PAUSED_OUTPUT_CAP): answer it with a
different model on the same engine, then resume. The answer retains the incomplete
attempt, work and usage; it never launches a provider. Workflow jobs also require
the displayed job retry token and issue a new token for the explicit retry.
On a route that honors the setting, another recovery option is to request a larger limit,
set the attempt aside with --abandon-stage, and --resume-paused. Model and provider
limits still apply. Automatic report repair remains bounded to the existing read-only
Tester and Completion Reviewer stages; Builder and Requirements never retry
an output-limit stop automatically. Ambiguous or interrupted output remains uncertain.
The cap-setting rules are in tools/autocode_output_cap.py; they do not alter configured
command providers' environment or token limits.
For an isolated native run paused before plan approval, an OpenCode authentication
failure can also be set aside explicitly with the displayed --abandon-stage
attempt. This requires a collected nonzero exit containing only one terminal
401/403 APIError, no response or report, and the original stopped supervisor,
unchanged source, settings and runtime. Other uncertain output remains refused.
The command preserves the failed attempt and pauses without launching a model.
Refresh the provider credential before --resume-paused; resume retains the
same models, review gates and time limits. An older run cannot adopt a changed
runtime to gain this recovery operation.
Environment variables agents see¶
Every provider process, and every test command the runner executes itself, gets
the runner's environment minus variables that look like credentials: a name word
such as TOKEN, SECRET, PASSWORD, KEY or AUTH (GITHUB_TOKEN,
AWS_SECRET_ACCESS_KEY, SSH_AUTH_SOCK, OPENAI_API_KEY), or a URL value with
an embedded password. Proxy variables and AutoCode's ordinary AUTOCODE_* settings are
kept. The nine controller token variables
are always withheld, including when named in AUTOCODE_PASS_ENV. Token counts are kept:
a TOKEN word followed by MAX, LIMIT, COUNT or
BUDGET, or after MAX, holding a whole number
(OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX=100000). Each stage record lists the withheld
names (never values) under withheld_env. The rules are in tools/autocode_agent_env.py.
Providers sign in from their own stored logins (OpenCode, Codex and Kilo auth files, and the Claude Code login), so the default routes need none of these. If your provider or your project's tests genuinely need one, name it:
AUTOCODE_PASS_ENV=ZHIPU_API_KEY,DATABASE_URL autocode "..."
Configured providers' version, model and authentication preflights use the same
filtered ambient environment as their stage processes. A check that needs an
explicitly named variable therefore needs the same AUTOCODE_PASS_ENV opt-in.
An authentication listing can still describe a stored route without proving the
request will authenticate. When a configured stage returns a native HTTP 401 or
403 API error, AutoCode names any withheld candidates and points to the opt-in;
those names do not establish which variable the provider requires. Pass only
variables you intend to expose to that provider and its agents. Private controller
tokens remain withheld even when listed.
Withholding variables is not a sandbox: an agent with shell access can still read
files such as ~/.aws/credentials or ~/.config/gh/hosts.yml.
Resuming preserves the saved engine, models and separate role sessions. Start a new
run when switching between Codex, OpenCode and Claude Code; their session IDs cannot be reused
across engines. A response with an unexpected session ID pauses the run.
OpenCode version or configuration drift pauses the saved run, including changes to
custom config-directory files, agent definitions and local plugin/tool definitions.
This adapter was live-checked with OpenCode 1.18.31. OpenCode 2.x is accepted: the stage runs in the workspace directory with --standalone, and reasoning effort is provider/model#effort rather than --variant. A saved run records the OpenCode version, so resume refuses a silent major-version change. Strict tool containment and verified visual delivery stay qualified only for OpenCode 1.18.33.
Check provider compatibility¶
Before relying on a new tool/model combination, run the shared provider conformance probe. It checks the same workspace, JSON report, command evidence, usage and session rules through Codex, OpenCode, KiloCode and Claude Code. Passing applies to that recorded tool/model/configuration combination.
Codex provider overrides¶
Pass --engine codex to start a Codex-engine run. Roles can use different
Responses-compatible Codex providers in one run, e.g. planning on the ChatGPT
subscription while the Validator audits and the Builder codes via another compatible provider:
python3 tools/autocode.py "Build a greeting CLI" --workspace /path/to/project \
--engine codex \
--astra-model gpt-6-astra \
--sol-model audit-model --sol-provider other_provider \
--terra-model implementation-model --terra-provider other_provider --reasoning-effort high
Each role can also have its own reasoning effort. For example, use the Astra route at
extra-high (xhigh) for read-only discovery and planning:
python3 tools/autocode.py "Build a greeting CLI" --workspace /path/to/project \
--engine codex --astra-model gpt-6-astra --astra-reasoning-effort xhigh
Role-specific effort overrides the shared --reasoning-effort value. All selected
models and providers are saved in the run checkpoint, so resumed runs retain this
assignment.
An interactive terminal starts in chat mode by default. The Requirements Gatherer presents a few material
questions at a time; type replies directly or /default to accept a proposed default.
When the build brief is displayed, type feedback to revise it, y to approve that exact
revision, or /pause to save and exit. After approval the implementation, validation
and review loop runs automatically within the configured limits. During questions,
/feedback TEXT sends a broader correction to the Requirements Gatherer.
Use --chat to select this mode explicitly, or --no-chat for one command per turn.
Non-interactive invocations default to the command-per-turn interface.
--<role>-provider is saved per role like models and is passed to Codex as a
model_provider override; roles without a provider keep the local Codex login
(ChatGPT auth). The named provider must implement the OpenAI Responses API.
For the connected Z.ai Coding Plan, use the OpenCode engine above. Changing the global
provider/auth in local Codex config still pauses a saved Codex-engine run.
A final message that is only a shell command¶
Some models served through a Codex transport sometimes end a stage with the arguments of a shell tool call instead of the stage's JSON report (#512):
{"cmd": "ls docs/ && wc -l docs/*.md"}
AutoCode treats this as a known provider defect, never as a report, and never
runs the command. A final message counts as only a command when its keys are
cmd or command (holding a command) and, at most, the other arguments of a
Codex shell call (workdir, timeout_ms, yield_time_ms, max_output_tokens,
shell, login, with_escalated_permissions, justification), and none of
them is a field of the stage's schema. A command whose text embeds a JSON report
is still a command: AutoCode does not unwrap it, though a wrapper in your
provider command may before AutoCode reads the report. The stage is rejected
with Provider final message is a shell command ({"cmd": ...}) instead of the
JSON report; ... and then:
- On a transport that keeps sessions (
--engine codex, OpenCode, or a tool withoutput = "opencode_events"andresume), the runner resumes the stage's own session once and asks for the report alone, with no command. This correction spends no report-repair attempt. It applies to every stage, planning stages included, but only when it would run on the route (engine, provider, model, effort) that started the session: a Plan Reviewer attempt that ran on its one-use fallback route goes straight to step 2. - Otherwise, or when that correction fails, the usual report-only repairs run
(
report_repair.max_attempts, two by default), told that the rejected report is a command with nothing to repair. - A stage that keeps doing it stops there, usually at
PAUSED_REPEATED_FAILURE, with that reason instop_reason. As for any stuck stage, the Investigator looks at it first.
Roles affected. Every stage's final message is checked, so every role is
covered. The defect was seen (2026-10-05) on the roles one profile ran through
Codex with the gocode provider: the Plan Reviewer (astra_challenge,
astra_finalize) and the Tester (sol). Its Builder and Requirements ran
through another tool and did not show it. No role is qualified on a route that
shows the defect: if a role keeps stopping this way, run it on another model,
and check a new tool/model pair with the
conformance probe first.
GoCode¶
Register GoCode as ~/.config/autocode/providers/gocode.toml (the command wraps
gocode env then codex exec). The provider sets API credentials for its own
child process. Keep OPENAI_API_KEY, CODEX_API_KEY, and OPENAI_BASE_URL out
of the AutoCode process itself: ambient keys trip joint-planning's billing-route
gate (PAUSED_BILLING_ROUTE) even when GoCode would have supplied the right
route for the child. Unset them in the shell that launches autocode or
scenarios/run.py, or put them in the provider's forbid_env so AutoCode
strips them before the stage.
Put -o {report} (or --output-last-message {report}) in the command list
as its own argv slot, not only inside a sh -c string. When Autocode sees that
slot, the stage prompt asks the model to return the JSON report as its final
response (Codex persists it). If the flag is buried in a shell string, Autocode
asks the model to write the report with a tool, which fails under
--sandbox read-only and yields empty Requirements contracts with
REPORT_WRITE blockers (docs/bugs/2026-10-12-gocode-cross-product-fixes.md).
name = "gocode"
command = [
"sh", "-c", "eval \"$(gocode env --shell bash)\" && exec \"$@\"", "gocode",
"codex", "exec",
"-C", "{workspace}",
"--sandbox", "{sandbox}",
"--model", "{model}",
"-c", "model_reasoning_effort=\"{effort}\"",
"--output-schema", "{schema}",
"-o", "{report}",
"-",
]
prompt = "stdin"
models_command = ["gocode", "models"]
version_command = ["gocode", "--version"]
[roles]
astra = { model = "gpt-5.6-luna", effort = "high" }
terra = { model = "gpt-5.6-luna", effort = "low" }
sol = { model = "gpt-5.6-luna", effort = "high" }
completion = { model = "gpt-5.6-luna", effort = "high" }
glm = { model = "gpt-5.6-luna", effort = "low" }
plan_reviewer = { model = "gpt-5.6-luna", effort = "high" }
In ~/.codex/config.toml, under [model_providers.gocode.auth], set
timeout_ms = 45000 so a slow gocode api-key-helper refresh does not end the
stage as a bare exit 1. Autocode names that stop as a provider auth-helper
timeout when the trailing log lines match.
The scenario harness profile gocode-cross (scenarios/harness/profiles.py) is
the reliability scorecard route: Luna for requirements and planning, Terra for
the Builder, Sol for the Plan Reviewer, Validator and Completion Reviewer, Astra
for the Resolver. Batch the three RELIABILITY.md cases with three repeats each:
unset OPENAI_API_KEY CODEX_API_KEY OPENAI_BASE_URL
for scenario in bugfix-iso-weeks greenfield-todo-cli feature-timesheet-by-project; do
for n in 1 2 3; do
.venv/bin/python scenarios/run.py run "$scenario" --profile gocode-cross \
--i-authorize-live-model-spend --out .scenario-runs/gocode-cross-scorecard
done
done
.venv/bin/python scenarios/run.py stats --out .scenario-runs/gocode-cross-scorecard
Any FALSE_COMPLETE blocks the change under test. A drop in pass rate is
investigated by re-running the same case on origin/master.
Claude Code provider¶
--engine claude (or --provider claude, or engine = "claude" in the project
settings) runs every role through Claude Code (claude -p) with your
Claude Code login: no OpenCode or Codex install, no API key. It is built in
(tools/providers/claude.py); --engine claude is the OpenCode engine's facade with the provider
claude, so the status view shows provider: "claude" and every route's engine opencode.
claude auth login # once, with a Claude subscription
autocode doctor --engine claude # claude on PATH and logged in, in the agents' environment
autocode --engine claude "Add a --json flag to the export command"
Default routes: Sonnet (claude-sonnet-5-5) drafts requirements and plans and tests, Opus
(claude-opus-5-5) reviews plans, resolves and completes, Haiku (claude-haiku-4-5-20251001) builds;
every role at effort medium. A stuck Builder's stronger attempt runs Sonnet and its checkers move
to Opus. The usual --*-model and --*-reasoning-effort flags take these bare ids and the efforts
low, medium, high, xhigh and max.
How a stage runs. Each stage is one process:
python -I tools/providers/claude_stream.py … -- claude -p --output-format stream-json … with the
stage prompt on standard input. The translator inserts the report schema (--json-schema), reads
Claude's stream and writes Codex-shaped events to the stage log, so sessions, usage, cost, command
evidence, the idle watchdog and the output cap work as for any stage. Claude's raw rows (stream deltas
left out) are kept beside the log as <stage>.claude.jsonl.
- Sessions. Every stage starts a fresh Claude session: its stage record has
expected_session: nulland its command no--resume. When a role's earlier session is set aside for this, the record says so (fresh_session_reason); a role's first stage and every joint-planning stage have no earlier session to set aside. Only a same-stage correction (a report that did not parse, or a shell command returned as the report) resumes the stage's own session. - Reports. The report is the JSON object Claude Code's StructuredOutput tool accepted. A stage that ends without one gets the same-session format correction, then the bounded report repair. A report Claude Code rejected is never used.
- Evidence. Every Bash call is a
command_executionevent with Claude Code's real exit code, cited asevent:item_N; capture receipts work too. A command whose exit code Claude Code did not report (moved to the background, interrupted, timed out, denied, or an unrecognized result) has exit codenulland is never evidence: run it again in the foreground. - Tools and permissions. The same
--tools Bash,Read,Edit,Write,Glob,Grepon every stage, no MCP servers (--strict-mcp-config), no skills (--disable-slash-commands), project settings only (--setting-sources project). Edit and Write are pre-approved unless the stage's sandbox is read-only (planning stages); judging stages keep them, and the after-stage snapshot catches a judge's source edit.git commit,push,checkout,reset,stash,branch,rebaseandmergeare denied. - Login. Before every stage of a joint-planning run, after
--accept-transport-change, and in doctor,claude auth status --jsonruns in the agents' environment and must report a first-party Claude subscription login (claude.aioroauth_token). An API key (ANTHROPIC_API_KEY,ANTHROPIC_AUTH_TOKEN, anapiKeyHelper), Bedrock or Vertex is refused (PAUSED_BILLING_ROUTE); a variable only in your own shell is fine, because the agent scrub withholds it.auth statusdoes not apply an untrusted project's settings, whileclaude -ptrusts them, so before every stage, at run start and in doctor the project's.claude/settings.jsonis read too: one that setsapiKeyHelper,awsAuthRefresh,awsCredentialExportorgcpAuthRefresh, or anenventry for an Anthropic API key, auth token or base URL,CLAUDE_CODE_USE_*orCLAUDE_CODE_OAUTH_TOKEN, is refused, and so is one that is not valid JSON. A stage whose Claude Code still reports an API key source (apiKeySourcein its first row) is stopped at once and pausesPAUSED_BILLING_ROUTE. A setup token reaches Claude Code only throughAUTOCODE_PASS_ENV=CLAUDE_CODE_OAUTH_TOKEN. The account's email and organization are never stored or printed.auth statusis necessary, not sufficient: the stage's own call proves it authenticates. - Environment. The agent environment, minus ten variables that would tie the child to a parent
Claude Code session (
CLAUDE_CODE_SESSION_ID,CLAUDE_CODE_REMOTE_SESSION_ID,CLAUDE_CODE_CHILD_SESSION,CLAUDE_CODE_DEBUG,CLAUDE_CODE_DIAGNOSTICS_FILE,CLAUDE_CODE_TEE_SDK_STDOUT,CLAUDE_CODE_MESSAGING_SOCKET,CLAUDE_EFFORT,CLAUDE_AUTO_BACKGROUND_TASKS,CLAUDE_CODE_ENTRYPOINT), plusDISABLE_AUTOUPDATER=1. - Identity. A saved run records the launch policy (hashed), the resolved
claude, its version, a hash of<workspace>/.claude/settings.jsonand hashes ofANTHROPIC_BASE_URLandCLAUDE_CONFIG_DIR. A change pauses it withPAUSED_TRANSPORT_CHANGED; after aclaudeupdate,autocode resume --accept-transport-changere-checks the login and continues.CLAUDE_CODE_MAX_OUTPUT_TOKENSis not part of it. - Cost. Each stage's reported cost is that call's share of Claude Code's
total_cost_usd(list price, not your subscription's spend). Claude reports a session's total, so a resumed call subtracts what the session had already cost (a ledger under the run'sclaude-sessions/); when that is unknown the stage falls back to the dated price estimate.
Stops.
| Claude Code says | The run |
|---|---|
Output token limit (max_output_tokens) |
PAUSED_OUTPUT_CAP; a truncated Tester or Completion report is repaired automatically. Raise CLAUDE_CODE_MAX_OUTPUT_TOKENS or name another model. |
| Context window limit | PAUSED_PROVIDER_UNCERTAIN (never an output cap) |
| Subscription usage limit, spend limit, billing | PAUSED_BUDGET (with the reset time when Claude gave one) |
| Rate limit (429) | PAUSED_RATE_LIMIT |
| Overloaded (529) | PAUSED_PROVIDER_CAPACITY |
| Refusal | PAUSED_CONTENT_FILTER |
| Authentication (401/403) | PAUSED_PROVIDER_UNCERTAIN, naming any withheld variables; run claude auth login |
An API key source in its first row (apiKeySource) |
PAUSED_BILLING_ROUTE; Claude Code is stopped before the stage runs |
| Anything else, a cut stream, a start failure | PAUSED_PROVIDER_UNCERTAIN, no automatic replay |
The model's own words never classify a stop, and nothing is retried automatically (Claude Code retries API errors itself). Rejections of a report that did not parse read "OpenCode final message is not a JSON report" for every event-mode provider.
The name claude is reserved. --provider claude always selects the built-in provider; a user
~/.config/autocode/providers/claude.toml (the retired example) is ignored and doctor names it. A run
started with that example resolves to the built-in on resume and pauses PAUSED_TRANSPORT_CHANGED at
its next stage; resume it with --accept-transport-change.
Limits. No kernel tool containment (Claude Code's permission flags and the workspace snapshot
checks apply); no verified visual evidence; no --task-preflight; no hybrid split by stage; no replay
of recorded Claude runs; no Investigator report adoption; autocode models lists nothing for the bare
ids. program, components and verify take --provider claude rather than --engine claude;
tasks has neither and runs its lanes on Claude Code through AUTOCODE_PROVIDER=claude,
default_provider = "claude" or the project's engine = "claude". Claude Code loads CLAUDE.md files of the workspace and its ancestors, so keep a
scenario's --out outside this repository. In a root cloud container, prefix runs with
setpriv --bounding-set=-sys_admin,-sys_ptrace (cloud sessions).
Add a tool¶
OpenCode and Claude Code are built in. Any other tool registers with one TOML file, not a Python
package. --provider <name> loads ~/.config/autocode/providers/<name>.toml and,
if that file is absent, the bundled example at tools/providers/configs/<name>.toml.
Configs inside a project are not loaded. The names opencode and claude are reserved for the built-in
providers; a user config with either name is never read. KiloCode is a worked example.
name = "kilocode"
command = ["kilo", "run", "--auto", "--dir", "{workspace}", "--model", "{model}", "--variant", "{effort}", "--format", "json"]
prompt = "stdin" # or "file" (uses {prompt_file})
output = "opencode_events" # or "report_file"; see below
resume = ["--session", "{session}"] # optional; enables saved sessions
models_command = ["kilo", "models"] # optional; or a static list: models = [...]
version_command = ["kilo", "--version"]
[roles]
astra = { model = "openai/gpt-5.6-sol", effort = "high" }
terra = { model = "openai/gpt-5.6-terra", effort = "medium" }
sol = { model = "openai/gpt-5.6-sol", effort = "high" }
completion = { model = "openai/gpt-5.6-sol", effort = "medium" }
glm = { model = "zhipuai-coding-plan/glm-5.3", effort = "medium" }
plan_reviewer = { model = "openai/gpt-6-sol", effort = "high", light_effort = "medium" }
For clear, small tasks the Plan Reviewer may use light_effort (or one lower
standard effort tier) only when a new run used an automatic/default effort.
An explicit reviewer effort, including a project effort setting, wins. Saved
runs without effort provenance retain their existing effort on upgrade; model
pins alone do not establish effort provenance. The review-call allowance still
applies independently of this effort choice.
[roles] must keep each verifier on a different model family from what it checks
(Planner/Plan Reviewer, Builder/Validator, Builder/Completion Owner); a run whose
roles break that pauses with PAUSED_CROSS_MODEL before any agent is launched.
Placeholders are {model}, {effort}, {workspace}, {report}, {schema},
{prompt_file}, {run_dir}, {role}, and {sandbox}. The opt-in Codex
artifact adapter below adds the standalone {sandbox_args} argv splice. {sandbox} is
read-only for planning, workspace-write for the builder, and
workspace-write for the judging stages (Validator, Completion Owner,
milestone checkpoint): their contract requires writing runner-owned
operational files under .autocode/ (capture receipts, reports), which
read-only forbids. Their source contract stays enforced by the runner's
after-stage workspace snapshot, not by the sandbox.
{effort} reaches the tool only if the command uses it.
Use {{ and }} for literal braces in a command argument, such as
${{VAR}} or {{"key":1}}; single braces are reserved for placeholders.
Changing the config file or the tool version pauses a saved run.
A different tool for one role¶
For a new run on --engine opencode --provider opencode, repeat
--role-transport ROLE=PROVIDER to select an external configured tool for only
those roles. ROLE is the existing CLI code name, such as sol or completion;
PROVIDER names its registered TOML config, such as kilocode. Each selection
requires an explicit corresponding model flag. Select its exact model ID from
that tool's catalogue, including a bare ID when the tool publishes one:
autocode models --provider opencode
autocode models --provider kilocode
# Replace the placeholder with an ID actually offered by the second catalogue.
autocode "Your task" --engine opencode --provider opencode \
--role-transport sol=kilocode --sol-model '<MODEL_FROM_KILO_CATALOGUE>' \
--sol-reasoning-effort high
The other roles retain their routes selected by the ordinary model flags and
OpenCode defaults. Roles derived mid-run (such as Analyst, Investigator, Architect,
Acceptance Tester, Resolver, Stuck Investigator, or Utility) inherit the external
tool transport identity bound to their source role when their own route is on that
tool. A derived role whose own route stays on the run's tool, such as a Resolver
given its own --resolver-model on OpenCode, inherits nothing and runs there. Keep the GLM and MiMo role flags when using a profile that
assigns them requirements, planning, building, plan review or resolution; a
role selection does not assign every role to the new tool. Each tool checks
only its own selected models and auth routes. At build start, the model-access
probe covers every tool whose config declares [auth] billing routes, including
a selected tool when the run's own tool declares none. It sends each role's model
only through the tool that runs that role. Before the first request, it checks
the login of each of those tools that still has a model to probe; a tool whose
models all passed earlier in the run is not probed again. A pass on one tool
never counts for the same model on another. Independent verification and all
ordinary approval, evidence and completion gates still apply.
The binding is immutable once the run starts. Do not repeat --role-transport
when advancing or reattaching with TaskRun; pass it in start_options only.
A missing or mismatched saved identity cannot fall back to the default tool.
Changes to a bound config fingerprint, executable path or version pause rather than move its
session to another tool; --accept-transport-change does not replace these
bindings. This selection cannot combine with --single-model or recorded
replay.
Ordinary transport compatibility does not qualify a tool for native role isolation or image acceptance. Those flows still require their exact supported native owner and independently verified containment/image transport. Registered Kilo roles remain refused by those guards until such qualification exists; a model appearing in its catalogue is insufficient. Check the concrete tool/model pair with provider conformance before relying on it.
Builder retry on a tool¶
A Builder that keeps failing a milestone gets one ordinary retry and then one stronger
attempt (Models). By default that attempt runs GPT-6 Sol,
and a checker on GPT-6 Sol moves to GLM; a tool whose model list (models or models_command)
lacks GPT-6 Sol, or lacks GLM while a checker would move to it, gets only one more ordinary retry
instead. A tool that serves other models names its own in an optional
[builder_retry] table (the built-in claude provider uses the same policy: Sonnet, checked by Opus):
[builder_retry]
strong_model = "claude-sonnet-5-5" # the Builder's stronger attempt
checker_model = "claude-opus-5-5" # a Tester or Completion Reviewer on strong_model moves here
strong_effort = "xhigh" # optional; xhigh when left out
Both models are the tool's own spelling. When the config lists models, both must be in
it. strong_model must differ from the [roles] Builder's model, and checker_model must be
neither strong_model nor another model of its GLM or MiMo family; a config that breaks either
is refused when it loads. A new run takes the
table when it is created (--builder-strong-model still wins). A Builder that already runs
the strong model makes its stronger attempt on that model at strong_effort. When the stronger attempt
starts, a Tester or Completion Reviewer that runs the strong model moves to checker_model
until the next milestone, as does one on another model of the strong model's GLM or MiMo family.
When the Builder's model has no provider/ prefix it moves only when it runs the strong model
in the tool's spelling (or such a family member), is neither pinned nor on another provider, and
checker_model is a model the run already routes a role to; otherwise the run pauses with
PAUSED_BUILDER_RETRY_LIMIT before changing any route. A config without the table keeps the
default models, and provider/model names such as KiloCode's keep the earlier rule (a checker
that cannot move is left for the cross-model guard). Adding or changing the table
changes the config file, so saved runs on that tool stop with PAUSED_TRANSPORT_CHANGED at
their next stage: change it between runs.
Output modes¶
output says how the result comes back:
output = "report_file"(the default): the tool writes exactly one JSON object to{report}, ascodex exec -odoes. Every stage starts fresh. Command evidence is acapture_commandreceipt file, not anevent:id. These tools need supported usage events for token accounting; otherwise those counts remain unknown in the usage ledger.output = "opencode_events": the tool prints OpenCode-format JSON events, asopencode run --format jsonandkilo run --format jsondo. Autocode reads the final report, token usage and command exit codes from those events, and resumes each role's session with the requiredresumetemplate, for exampleresume = ["--session", "{session}"].
Every structured handoff for these output modes includes an executable
capture_command, including standalone review, design, discuss and investigation
jobs. Models append --output .autocode/evidence/<unique-name>.json -- <command>
to that value. It uses the public autocode.py capture entry point; the
autocode_capture_command.py implementation module is not a standalone command.
An existing handoff command and its explicit output mode are preserved; the
supplied default inherits the runner's output-mode environment. This supplies
tool context without granting additional filesystem permissions.
The runner can fill an omitted check exit code from a unique executed event or
the cited, verified capture receipt before checking the unchanged report schema.
It never replaces a supplied exit code, guesses from output text, or resolves
ambiguous executions. The original report is retained as .reported.json, and
the stage records the derived metadata. Nonzero exits remain failures.
For report_file tools, capture commands must inherit AUTOCODE_CAPTURE_CONTEXT
from the tool process: the capture helper records it automatically and the
validator checks it against the saved attempt. Receipts from another attempt,
missing capture context, or changed output hashes are rejected. Event providers
continue to require their independent tool-event attestation.
A stage log holds the tool's stdout and stderr. When a tool exits with an error,
AutoCode reads the provider's reason from its error and turn.failed JSON
events and from the plain-text error lines (ERROR: …, Error: …) that end the
log, as codex exec without --json prints them. So
ERROR: exceeded retry limit, last status: 429 Too Many Requests stops the stage
as a rate limit, and a used-up plan or a busy model as a quota or capacity stop
(Models). Tool output earlier in the log
is never read as the provider's error, even when it mentions 429.
Codex commands that write capture receipts¶
A registered report_file command that passes --sandbox read-only to Codex
cannot create AutoCode's required capture receipts. For that command, opt in to
sandbox_adapter = "codex_artifacts" and replace the legacy sandbox flag and
{sandbox} value with the standalone {sandbox_args} argument:
This adapter permits -C/--cd only with the exact {workspace} binding; literal
or derived destinations and other sandbox/worktree overrides are refused before
launch. Config arguments must use a valid key=value override, with policy and
project-trust keys reserved for the adapter. JSON blobs are not config overrides.
name = "codex_receipts"
sandbox_adapter = "codex_artifacts"
command = ["codex", "exec", "--ephemeral", "{sandbox_args}", "-C", "{workspace}", "--model", "{model}", "-c", "model_reasoning_effort=\"{effort}\"", "-c", "approval_policy=\"never\"", "-c", "forced_login_method=\"chatgpt\"", "--output-schema", "{schema}", "-o", "{report}", "--json", "-"]
prompt = "stdin"
output = "report_file"
version_command = ["codex", "--version"]
[roles]
astra = { model = "gpt-6-sol", effort = "medium" }
terra = { model = "gpt-6-luna", effort = "medium" }
sol = { model = "gpt-6-sol", effort = "medium" }
completion = { model = "gpt-6-sol", effort = "medium" }
glm = { model = "gpt-6-luna", effort = "medium" }
plan_reviewer = { model = "gpt-6-sol", effort = "medium" }
[auth]
command = ["codex", "login", "status"]
forbid_env = ["OPENAI_API_KEY", "CODEX_API_KEY", "OPENAI_BASE_URL"]
[[auth.routes]]
models = "gpt-"
pattern = "(?m)^Logged in using (ChatGPT)$"
expect = "ChatGPT"
Save this as ~/.config/autocode/providers/codex_receipts.toml, then select it
with autocode "Your task" --provider codex_receipts. Choose models available
to your login. Registered command providers synthesize Requirements defaults
from the config's own glm model and effort. For a new provider-configured task,
--glm-model overrides the model for both Planner and Requirements;
--requirements-model wins for Requirements when given. The provider's Requirements reasoning default stays
independent of --glm-reasoning-effort; use --requirements-reasoning-effort to
change it. OpenCode keeps its separately defined Requirements defaults when
neither model override is given.
An existing Requirements route keeps its saved model when --glm-model changes
the Planner. Enabling joint planning at a supported migration boundary uses the
same fallback only when creating a missing Requirements route. Pass
--requirements-model to explicitly change that role, or --single-model on a
new run to move every role.
This adapter requires Codex CLI 0.160.0 or later, checked before a model
request. For planning and review it selects a named permission profile derived
from :read-only, adding writes only to the workspace's .autocode/evidence/,
.autocode/output/, and the exact assigned stage JSON report. The Builder keeps
workspace-write. Codex's -o option saves the final JSON response; the model
still runs actual capture commands to produce independently checked receipts.
No permission answer automatically changes this profile.
Opting in passes --ignore-user-config to each Codex invocation. Global files
are untouched and the stored login is reused, but user-level configuration,
plugins, MCP servers and provider defaults are omitted. Supply any required,
compatible options explicitly in the command. Managed requirements still apply.
Do not combine the adapter with legacy sandbox flags, additional writable roots,
configuration profiles or permission-policy overrides. The adapter rejects those
combinations instead of silently overriding a policy.
Operational paths must be canonical and unaliased. Pre-existing symlinks,
hard-linked files and special files in the writable operational directories are
rejected before launch; AutoCode does not delete or rewrite them. A stage report
must be a JSON file under the run's iterations/ directory. Existing source
snapshot, receipt identity, hash, regression-proof and completion checks still
apply. Language tools that need additional caches must use an allowed operational
path or a separately configured provider; this adapter does not grant arbitrary
cache directories.
Existing provider configs and --engine codex keep their configuration semantics.
Changing a saved run's provider config triggers its existing transport-change
pause; inspect and accept that change through the public recovery command.
Permission-profile behavior has been exercised on macOS with Codex 0.160.0;
other platform/version combinations need their own conformance check.
Auth checks¶
A tool can declare how its subscription login is checked. Without an [auth]
table Autocode does not inspect the tool's login. With one, before an OpenAI
role starts, Autocode runs command, strips terminal color codes, and requires
every match of pattern to equal expect. A mismatch, a failed listing, or a
variable in forbid_env pauses the run with PAUSED_BILLING_ROUTE before any
model is called:
[auth]
command = ["kilo", "auth", "list"]
forbid_env = ["OPENAI_API_KEY", "CODEX_API_KEY", "OPENAI_BASE_URL"]
[[auth.routes]]
models = "openai/"
name = "OpenAI"
billing = "subscription"
pattern = "^\\s*[●•]\\s+OpenAI\\s+(\\S+)\\s*$"
expect = "oauth"
A route may also carry name (the login name the tool itself prints; defaults to
the prefix) and billing ("subscription" or "pay per token"; unknown when
unset). These feed automatic route selection (#1426): the discovery step reads the
same listing to learn which accounts are connected and which models each one can
bill, so a model no connected login serves is never offered to the selector. A
command template whose {effort} arguments (like Kilo's --variant {effort}) get
no reasoning level omits those arguments instead of passing an empty value, and the
model uses its own default level.
A tool that reports a subscription usage limit or runs out of pay-as-you-go
credit pauses the run with PAUSED_BUDGET.
KiloCode¶
tools/providers/configs/kilocode.toml is bundled. It runs kilo run --auto.
Its default routes use ChatGPT OAuth for openai/..., Zhipu AI Coding Plan for
zhipuai-coding-plan/..., and Alibaba Token Plan for alibaba-token-plan/....
Optional zai-coding-plan/... and kilo/... routes require their separate
Z.AI Coding Plan api and Kilo Gateway oauth logins. Check kilo models and
kilo auth list for your installed version and configured account; distinct
provider names are not credential aliases. Connect the routes you select with
kilo auth first. The plan reviewer is GPT-5.6 Sol here because Kilo has no
Cursor ACP route:
name = "kilocode"
command = ["kilo", "run", "--auto", "--dir", "{workspace}", "--model", "{model}", "--variant", "{effort}", "--format", "json"]
prompt = "stdin"
output = "opencode_events"
resume = ["--session", "{session}"]
models_command = ["kilo", "models"]
version_command = ["kilo", "--version"]
[roles]
astra = { model = "openai/gpt-5.6-sol", effort = "high" }
terra = { model = "openai/gpt-5.6-terra", effort = "medium" }
sol = { model = "openai/gpt-5.6-sol", effort = "high" }
completion = { model = "openai/gpt-5.6-sol", effort = "medium" }
glm = { model = "zhipuai-coding-plan/glm-5.3", effort = "medium" }
plan_reviewer = { model = "openai/gpt-5.6-sol", effort = "high" }
[auth]
command = ["kilo", "auth", "list"]
forbid_env = ["OPENAI_API_KEY", "CODEX_API_KEY", "OPENAI_BASE_URL"]
[[auth.routes]]
models = "openai/"
pattern = "^\\s*[●•]\\s+OpenAI\\s+(\\S+)\\s*$"
expect = "oauth"
[[auth.routes]]
models = "alibaba-token-plan/"
pattern = "^\\s*[●•]\\s+Alibaba Token Plan\\s+(\\S+)\\s*$"
expect = "api"
# Each coding plan keeps its own login and quota; the gateway is an explicit paid route.
[[auth.routes]]
models = "zai-coding-plan/"
pattern = "^\\s*[●•]\\s+Z\\.AI Coding Plan\\s+(\\S+)\\s*$"
expect = "api"
[[auth.routes]]
models = "zhipuai-coding-plan/"
pattern = "^\\s*[●•]\\s+Zhipu AI Coding Plan\\s+(\\S+)\\s*$"
expect = "api"
[[auth.routes]]
models = "kilo/"
pattern = "^\\s*[●•]\\s+Kilo Gateway\\s+(\\S+)\\s*$"
expect = "oauth"
Copy it to ~/.config/autocode/providers/kilocode.toml to change models or
reasoning levels. Select an ID published by your kilo models whose prefix is
declared in [auth] and whose login passes the check. Available model prefixes
and login rows depend on your Kilo installation and configured account.
If a selected model matches no configured route, PAUSED_BILLING_ROUTE lists
those routed prefixes before running the login check. Choose a published model
with one of those prefixes; add a route only when you intend to configure it.
The message lists your loaded configuration, including user-defined routes.
kilo/... IDs bill the Kilo Gateway pay-as-you-go account instead of a
subscription. The [auth] table above runs kilo auth list before a role on any declared route and pauses with
PAUSED_BILLING_ROUTE if its own login is absent or has the wrong mode:
| Model prefix | Kilo login | Required mode |
|---|---|---|
openai/ |
OpenAI | oauth |
alibaba-token-plan/ |
Alibaba Token Plan | api |
zai-coding-plan/ |
Z.AI Coding Plan | api |
zhipuai-coding-plan/ |
Zhipu AI Coding Plan | api |
kilo/ |
Kilo Gateway | oauth |
Each coding plan uses its separate login; a gateway login does not satisfy a
coding-plan route. A missing Kilo Gateway oauth row refuses Gateway calls.
For these routes the check also refuses a set
OPENAI_API_KEY, CODEX_API_KEY, or OPENAI_BASE_URL. When [auth] declares
routes, every selected model must match a declared prefix; add an
[[auth.routes]] entry for another vendor before using it.
The bundled command uses Kilo's --auto for noninteractive stages: ordinary
permission requests are approved once; effective explicit deny rules in
Kilo's configuration and selected agent still block the tool. AutoCode does
not replace that permission configuration or enable Kilo's permission-bypass
flags. Without --auto, Kilo rejects the first request and exits with an
auto-rejected-permission error. If you copied an older provider config to
~/.config/autocode/providers/kilocode.toml, add --auto to its command too;
the bundled update does not replace your custom file. AutoCode's plan approvals,
human reviews and recovery choices still require their own user input.
This command does not establish an OS sandbox or native read-only planning policy. A read-only stage that edits source is caught afterwards by AutoCode's workspace snapshot check and pauses; use explicit Kilo permission restrictions for operations that must be blocked before execution. See Kilo's permission reference.
The alibaba-token-plan/ route serves that login's own plan rather than the
Gateway: Qwen (qwen3.8-max, qwen3.7-plus, qwen3.6-flash and the rest of
kilo models' alibaba-token-plan/ list), and on the same login DeepSeek, GLM,
Kimi and MiniMax. Because one login reaches several vendors, a Builder and the
Tester that checks it can be different model families, which is what the
cross-model guard is for.
Default provider¶
New runs use OpenCode unless you choose otherwise. --provider <name> picks the
tool for one run. To change the default for every new run and for the dashboard,
set AUTOCODE_PROVIDER=kilocode or add this to ~/.config/autocode/config.toml:
default_provider = "kilocode"
A saved run keeps the provider it started with, and --engine codex runs still
use Codex. autocode-dashboard --provider <name> overrides the default for the
dashboard; its model pickers list that tool's models.
See also: Models · Install · CLI
Conformance matrix¶
Generated by python tools/provider_matrix.py --write from
tools/provider-matrix.json. Do not edit by hand.
A version the offline conformance suite has not been run against is
untested — never guess. Run the suite with
python tools/provider_conformance.py --fake (no model calls).
| Engine | Version | Transport | Containment | Visual | Result | Date | Commit | Note |
|---|---|---|---|---|---|---|---|---|
| opencode | 1.18.33 | opencode | qualified | qualified | known-good | 2026-10-08 | a8852cf4 |
The version the glm53-mimo three-case reliability sweep ran on (docs/bugs/2026-10-06-opencode-2.md). |
| opencode | 1.18.31 | opencode | untested | untested | known-good | 2026-10-01 | 68e89aa4 |
Live-checked in the 2026-10-01 glm53-openai sweep; containment/visual stay qualified only for 1.18.33. |
| opencode | 2.0.20 | opencode-standalone | refused | refused | accepted-for-ordinary-runs | 2026-10-06 | 9a31a8e8 |
Uses --standalone and a provider/model#effort id. A 2.x binary fails the containment and visual checks closed until it has its own conformance pass (docs/bugs/2026-10-06-opencode-2.md). |
| codex | native | codex | n/a | n/a | known-good | 2026-10-03 | b96a633e |
Native Codex probes in docs/provider-conformance.md; ChatGPT login required. |
| kilocode | registered-adapter | kilocode | n/a | n/a | known-good | 2026-10-03 | b96a633e |
Registered KiloCode adapter; see docs/provider-conformance.md. |
Connection setup and company backends¶
autocode connections list --json lists built-in Kilo, OpenCode and Claude Code
and user-registered providers. connections check --provider NAME --json checks
credentials without model traffic. connections login --provider NAME opens the
backend's own interactive sign-in. AutoCode does not store a second copy of keys,
SSO sessions, or AWS credentials. Kilo/OpenCode login lets the backend choose its
supported API-key or browser flow; existing route/billing checks still apply
before a task launches.
A company GoCode adapter can keep its corporate authentication and Bedrock routing. AutoCode does not require it to go through Kilo or OpenCode. In a registered provider's user-level TOML, optionally add:
[connection]
login_command = ["your-company-cli", "its-documented-login-command"]
status_command = ["your-company-cli", "its-documented-login-status-command"]
These are argument arrays executed without a shell. Use the company's documented commands; the names above are placeholders, not GoCode commands. The status command must make no inference requests: exit 0 for credentials present, 1 for sign-in required, and another code for a failed check. Its stdout/stderr is withheld from clients. The interactive login command owns its terminal output. Without these optional commands AutoCode reports login as unchecked and offers no guessed sign-in command. Provider files are trusted user configuration; files in a project are never discovered as connection definitions.
AutoCode direct connections (issue #1493)¶
AutoCode includes its own text/tool runtime. It does not require Kilo, OpenCode, Codex, Claude Code, or another coding-agent executable. In VS Code open Connections → AutoCode · Direct connection → Set up AutoCode, or run:
autocode connections setup
autocode connections check --provider autocode --json
autocode "hi" --provider autocode --joint-planning --spec-first
Setup is interactive in a terminal and launches no model. Choose mimo, zai, openai, claude, or a custom compatible API. One direct provider/endpoint is selected for a connection; mixed-provider routing remains available through the existing Kilo backend.
| API choice | Protocol | Authentication | Response limit field |
|---|---|---|---|
| MiMo | Chat Completions | api-key |
max_completion_tokens |
| Z.ai | Chat Completions | Bearer key | max_tokens |
| OpenAI / custom compatible | Chat Completions | Bearer key | max_completion_tokens |
| Claude | Anthropic Messages | x-api-key, version 2023-06-01 |
max_tokens |
MiMo and Z.ai require an explicit base URL, including its version path. Use the
exact endpoint and matching key for your billing route: ordinary API access and
Token/Coding Plan subscriptions have separate endpoints. Setup shows the API
examples and requires you to choose; it never falls back to another billing
route. OpenAI defaults to https://api.openai.com/v1; Claude defaults to
https://api.anthropic.com/v1. Endpoint overrides require HTTPS (HTTP is allowed
only for loopback fixtures). This setup accepts API keys, not ChatGPT or Claude
subscription logins. Kilo continues to own its separate sign-in and routes.
MiMo/Z.ai assistant messages retain reasoning_content across tool turns.
Claude uses native tool_use/tool_result blocks and replays signed thinking
blocks in order. Unsupported content and incomplete responses fail closed.
Nonempty Chat Completions effort overrides are sent as reasoning_effort and
must be supported by that model. Claude effort overrides are currently refused;
its default reasoning is used. Redirects are refused, with no automatic
parameter change, retry or provider fallback. Bedrock is outside this scope.
Model IDs are those the endpoint accepts, not Kilo/OpenCode routing aliases.
Setup groups Planner/Builder/Requirements and independent reviewers/testers; the
existing verifier-independence rules still apply. Reopening setup with blank
model answers preserves every saved role assignment. models --provider autocode
lists the configured roster; unconfigured model escalation is refused.
The API key lives in a separate auth.json file, mode 0600, under
$XDG_CONFIG_HOME/autocode/direct/ (default ~/.config/autocode/direct/), whose
mode is 0700. This is a private local file, not an OS keychain. The credential
is bound to the API endpoint: changing the endpoint requires an explicit key for
that destination. Status and launch arguments never contain key values. Listing
connections reads metadata only; Check setup validates local setup, not live
model access. configured and setup_required are distinct.
Key rotation for the same endpoint preserves transport identity; changes to the
API provider, endpoint, models or runtime change it and trigger the saved
run's existing drift checks. Configuration is never read from project files.
Select Use for new chats after setup. This does not replace an existing
Kilo/GoCode connection or change its model routes. CLI callers explicitly pass
--provider autocode; setup does not silently change the global default.
The existing supported-Linux provider supervisor owns each launch and cleanup. Model-requested commands run only through AutoCode's existing kernel shell boundary, with credentials removed, no network, protected run files, and the stage's read/write authority. Read-only execution uses the existing verification copy mechanism. There are at most 32 model responses per stage and eight tool calls per response, an 8192-token requested response cap, a 60-second HTTP read bound, and a 90-second tool bound; outer task/stage/spend limits still apply. Tool output is bounded at 65536 bytes and explicitly marked when truncated. Actual tool output and exit codes supply evidence; model prose cannot manufacture command events. Reported input/output usage is retained across requests, including failed turns; output counts include reasoning. A separate reasoning-token breakdown is not yet reported by this runtime. Missing token fields and prices remain unknown.
This initial runtime supports text and shell tools with a fresh context per stage. It does not provide native image qualification, in-process file tools, MCP tools, or external-agent session resumption. Local HTTP fixtures and supported-Linux task tests verify protocol and safety behavior; they do not establish live model access. The implementation stays draft pending live qualification with an explicitly configured connection.
Protocol references: OpenAI Chat Completions, MiMo API and Token Plan setup, MiMo Chat Completions, Z.ai Chat Completions, Z.ai thinking replay, and Claude Messages.
Automatic routes for new runs¶
New runs automatically select qualified models from the chosen tool's connected
accounts, preferring subscriptions and preserving independent checking. No per-role
model flags are needed, including with TaskRun.start(workspace, brief).
Explicit model, effort and tool overrides win; saved runs keep their choices.
--no-auto-select retains fixed defaults. --auto-select requires selection to
succeed instead of falling back when discovery or an independent checker is unavailable.
See automatic model selection for discovery,
reasoning levels, bounded preflight, recovery and the read-only selection preview.