Custom subagents
A subagent works on a task in its own fresh context and reports back, keeping the main conversation clean.
Define one with a Markdown file at .houston/agents/<name>.md: frontmatter description plus a system-prompt body. The main agent dispatches it by name with dispatch_agent.
Frontmatter options
| Key | Effect |
|---|---|
description | what the agent is for (required) |
tools: | narrows which tools it may use |
model: | pins it to a (usually cheaper) sibling model from the current provider; unknown ids fall back to the chat's model |
max_turns: | a hard limit on its steps (a whole number up to 500) that never extends |
write: true | gives it the writable tier (see below) |
Read-only and writable
- Read-only by default. A subagent can't edit files or run commands.
- Writable (
write: true) subagents are dispatched withdispatch_writable_agent, which asks for approval because it grants write access. One approval covers the whole delegated task's local actions, confined to the project.
Permissions still apply
Inside either tier, your permission rules work exactly as for the main agent:
- a
denyrule (including a managed-policy or project guardrail one) refuses the subagent's call outright - an
askrule, a credential-file read (a.env, a private key), or a shell command naming a path outside the project asks you first
Network. Either tier can use web_fetch and web_search, and every network request asks you for approval per destination, like the main agent's own calls. A denial comes back to the subagent as its tool result. A subagent's shell commands never get network access.
Unsandboxed hosts. On a host without an OS-enforced sandbox (such as Windows), each shell command a writable subagent runs would run unconfined, so each asks for its own approval too.
Cost. Tokens a subagent spends roll into the conversation's usage meter, priced at the model it actually ran on.
Seeing what a subagent did
While it works, its row in the desktop app lists each step as it happens (what it read, searched, edited, or ran, with the outcome: lines read, matches found, a command's exit code, an edit's line counts) and shows its model, step count, time, and tokens. A nested agent gets its own indented block.
When it finishes, the row collapses to a summary: model, steps, time, cost, and its id (like ag1). Expand it for three tabs:
- Report: the agent's report, rendered.
- Steps: each step expands to its result, or an edit's real diff.
- Prompt & setup: the exact task the main agent wrote, which agent and model ran it and who chose the model, its tools, step budget, usage, and system prompt.
Open transcript shows the whole run in order in a side panel, with a Copy as Markdown button. A review's row links to the same view for each of its reviewers.
Saved with the chat, so it's there after a restart. Settings > Agent Behavior > Loop control sets how much a chat keeps (4 MB by default). Past that, the oldest subagents keep their task, steps, and report but drop step results and diffs.
In the terminal, a line is printed per step under the dispatch (a review's reviewers only with /verbose), then the report. --json emits subagent_start, subagent_step, and subagent_end.
Step budget
A subagent works under the same step budget as the main agent:
- the "Steps per turn" setting, extended in the same chunks while it's still finding things out or making edits, up to the same hard limit, with the same loop detection
- near the end it's told to wrap up, and its last step can't run tools, so it always ends with a report of what it has
- a custom agent's
max_turnsreplaces all of this with a fixed limit - a review's agents keep the base budget without extending, since a review runs many at once
Follow-ups and nesting
- Resume. The main agent can pass a subagent's id back as
resumeto send a follow-up into that subagent's context instead of starting over. Ids last for the app session; the saved record doesn't make an agent resumable after a restart. - Cheaper legwork. A dispatch can pass
modelto run one-off work on a cheaper sibling model. - One level of nesting. A dispatched agent may dispatch its own nested read-only researchers (never writable, and no deeper).
Running one yourself
/agent <name> <task> hands a job to one of your agents directly, instead of describing it and hoping the right one gets picked. It works in the desktop app and the terminal. /agent alone (or /agents) lists them.