On this page
Execution budgets
Budgets are the limits that stop one command, script or batch of child agents from running forever or taking over your machine. By default a shell command has two minutes, four child agents run at once, and a child agent cannot start its own. Change them when a build needs longer, or when you want fewer things running at once.
A budget is not a security boundary. It bounds a command that hangs or loops; it does not stop code that is trying to do harm.
Change a budget
Put the settings under execution in haarness.json: ~/.config/haarness/haarness.json for all
projects, or haarness.json or .haarness/haarness.json in one project. A project value replaces
only the settings it names.
{
"execution": {
"shell_timeout_ms": 600000,
"subagent_concurrency": 2
}
}In config.toml, the same keys go under [execution]. Unknown keys are an error.
Why did my command stop after two minutes?
A shell command the agent runs has two minutes by default. The agent can set a different limit
on a single command. To change the default, set shell_timeout_ms; 0 removes the limit.
When the limit is reached, the command and every process it started are stopped. Without a limit, Esc Esc in the terminal UI, or stopping the turn in Desktop, still stops it.
Where did the rest of the output go?
When a command prints more than 50 KiB or 2,000 lines, the full output is saved to a file. The agent sees the end of it and the file's path, and can read the rest.
How many child agents run at once?
Four at a time, at each level. By default a child agent cannot start children of its own.
| To | Set |
|---|---|
| Run fewer child agents at once | subagent_concurrency to a smaller number |
| Let child agents start their own children | subagent_depth to 2 |
| Stop the agent from starting child agents | subagent_depth to 0 |
Stopping a turn stops all of its child agents too.
What runs at the same time?
Reads, file listings, searches and web fetches run together, up to read_parallelism at a time.
Child agents started together run side by side, up to subagent_concurrency. Edits, shell
commands, MCP tools and everything else run one at a time, in the order the agent asked for them.
All settings
| Setting | Default | Means |
|---|---|---|
shell_timeout_ms |
120000 | Shell command limit; 0 means none |
subagent_concurrency |
4 | Child agents running at once, per level |
subagent_depth |
1 | How many levels of child agents; 0 turns them off |
read_parallelism |
8 | Reads and searches run together |
media_max_bytes |
20971520 | Largest image, PDF, audio or video the agent reads (20 MiB) |
code_timeout_ms |
60000 | Time limit for a script the agent writes; 0 means none |
code_max_calls |
100 | Tool calls one such script may make; 0 means no limit |
code_max_source_bytes |
262144 | Largest such script; 0 turns the check off |
plan_read_tools |
[] |
Extension tools the plan agent may use |
subagent_concurrency, read_parallelism and media_max_bytes must be greater than zero.
The code_* settings apply to the execute tool, where the agent writes a short JavaScript
program that calls MCP and browser tools. It needs bun on your PATH.
plan_read_tools lists exact extension tool names, such as ext__code_search__query, that you
have checked only read. Wildcards are refused. The plan agent can then use them.
Limit the number of tool rounds
A turn can call tools as many times as it needs. To cap it:
{
"tools": { "max_rounds": 64 }
}When a turn reaches the cap, its tools are switched off and the model is asked to sum up. A custom agent's own step limit takes precedence.
Extension limits
Extensions have their own limits, in extensions.json next to your other configuration (or
.haarness/extensions.json in a project):
{
"enabled": true,
"timeout_ms": 30000,
"tool_timeout_ms": 120000,
"payload_max_bytes": 2097152,
"entries": []
}| Setting | Default | Means |
|---|---|---|
timeout_ms |
30000 | Default limit for every step; 0 means none |
init_timeout_ms |
timeout_ms |
Loading the extension |
hook_timeout_ms |
timeout_ms |
Each hook it runs |
tool_timeout_ms |
timeout_ms |
Each tool call |
payload_max_bytes |
2097152 | Largest message to or from it (2 MiB) |
When a call times out or you stop it, the extension is stopped and the call is not retried. Its tools fail until you reload or restart Haarness. Return large results as files instead of in the message.
Hook limits
A command hook has 60 seconds by default. Set timeout (in seconds,
1 to 600) on the hook to change it.
Related
- Permissions — what the agent may do, rather than for how long
- Reasoning and ultracode — watching child agents