Type @<agent> at the start of a prompt:
@claude please review the changes in src/core/agent.ts
@opencode how many .ts files are in this repo?
Always triggered by you
Delegation is explicitly triggered by you. Titah’s model never decides on its own to call another agent.
The reason is cost: one turn could call Claude Code repeatedly and blow up the bill without anyone noticing. A mention is a decision you made; an autonomous call is one you did not.
What happens
| Working directory | The same as your session. The external agent sees the code you are working on |
| What enters context | Only the final answer. The full transcript goes to tool-output/ and is referenced by path — injecting it whole would blow out the context window within two or three delegations |
| Continuity | The external session id is mapped to yours, so the second @claude resumes the same conversation |
| Cost | Shown separately in the footer (ext 1.2k/45 ≈$0.093). Summing it with Titah’s own tokens would make the number a lie |
The $ figure | Passed through from the external agent (Claude Code’s total_cost_usd). It is an API-price equivalent, not a bill — on a subscription, what you spend is rate-limit quota |
| Credentials | Its own. Titah never forwards its provider keys into the subprocess |
| Write access | Read-only by default. External agents answer; if a change is needed, Titah applies it through its own permission model |
An agent whose CLI is not installed is still listed as unavailable rather
than silently hidden. Check with titah doctor.
The mechanism
Subprocess plus JSON streaming, uniform across both targets:
claude | opencode | |
|---|---|---|
| Command | claude -p "<prompt>" --output-format stream-json --verbose | opencode run "<msg>" --format json |
| Continuity | --session-id <uuid> to create, --resume <uuid> to continue | --session <id> |
| Other protocol | — | opencode acp (ACP) available |
The internal adapter interface is deliberately shaped like ACP (prompt,
sessionUpdate, requestPermission, cancel), so adding an ACP transport later
means writing one new adapter rather than rebuilding the core.
!!! note “Two things that are easy to get wrong”
Both were verified directly against the installed CLIs rather than guessed
from documentation: Claude Code rejects --output-format stream-json
without --verbose, and passing the same --session-id twice is not how
you resume.
Adding a third agent
One config block, no code:
{
"externalAgent": {
"aider": {
"command": "aider",
"args": ["--message", "{prompt}", "--no-stream"],
"format": "text",
"timeout": 600000
}
}
}
| Key | Meaning |
|---|---|
command | The executable, found on PATH |
args | Argument template. {prompt} is substituted |
format | text or json — how to read the output |
timeout | Milliseconds. Default 600000 (10 minutes) |
sessionMode | generate or discover — see below |
enabled | false removes it from /consensus and from the @ popup |
sessionMode
Who owns the session id:
generate— Titah creates a UUID and hands it to the CLI. This is Claude Code’s way:--session-id <uuid>to create,--resume <uuid>to continue.discover— the id is read from the first call’s output and sent back afterwards. This is opencode’s way.
Failure handling
| Failure | Behaviour |
|---|---|
| CLI not installed | Detected via which at startup. Shown as unavailable, with the command that is missing — never hidden |
| Timeout | 10-minute default, configurable per adapter, with progress pulses so you can see the agent is alive. A silent timeout is the worst possible experience |
| Output does not match the schema | Tolerant parsing plus a known-good minimum version. Raw stderr is saved to tool-output/ when parsing fails |
| Non-zero exit | Reported as a failed delegation with the exit code and the saved stderr path, not as an empty answer |
Delegation from a sub-agent
An agent with delegate set routes its work through an external CLI instead of
Titah’s own loop — the same engine, reached from task / /tim rather than a
mention. It is mutually exclusive with model, and it is always treated as a
writer for concurrency purposes.
See Sub-agents.
Asking everyone at once
/consensus fans one question out to every available agent in parallel. See
Consensus mode.