MAC Agent Terminal Timeout
When to use
Apply this skill when:
- A task report shows
tool_errorwith signatureterminal:timeout. - You are about to call
terminal()for any of the following in a MAC repo worktree:scripts/run-contract-tests.sh— the full suite can take 4-5 minutes.python3 scripts/bootstrap-project.py— downloads and installs deps.git cloneof a large repository.- Any
pip install,uv sync, or heavy build step.
Root cause
The Hermes terminal() tool defaults to a 180-second timeout. MAC contract
tests can exceed 30 minutes on a heterogeneous fleet (a recent Darwin run
reached 29% after ten minutes without a failing test). With the default timeout,
the terminal call is cancelled mid-suite,
leaving no test results and causing the task to be blocked with a
terminal:timeout error.
Fix: always pass explicit timeout for long operations
Set timeout high enough for the slowest plausible run. Conservative values
for MAC repo work:
| Operation | Recommended timeout (seconds) |
|---|---|
scripts/run-contract-tests.sh |
3600 |
python3 scripts/bootstrap-project.py |
300 |
git clone --depth 1 <repo> |
240 |
Any pip install / uv sync |
300 |
Example — running the contract test suite:
terminal(command="scripts/run-contract-tests.sh", timeout=3600, workdir=worktree)
Never use the default timeout for any of the operations above. The contract suite timeout is deliberately finite: it allows a slow, healthy suite to finish, while still surfacing a genuine hang with enough time for diagnostic output to identify the stalled phase.
Recovery when a timeout has already occurred
- Re-run the failing operation with the explicit timeout above.
- If the suite still exceeds the budget, decompose the task: post child tasks
via the MAC API (
POST /tasks/<id>/children) so each child covers one deliverable and can be verified independently. - Record the explicit timeout used under
verification.environment_deltainmac-evidence.jsonso reviewers can confirm it was intentional.
Checked-in docs / skills identity rule
When adding or updating skills in the skills/ directory, docs in docs/,
or deploy markdown, use only generic role names and placeholders:
- Roles:
hub,worker-1,worker-2,gpu-worker - Placeholders:
<user>,<host>,<mesh-ip>,<fleet-name>
Never embed real agent names, usernames, hostnames, or IP addresses.
The test test_docs_carry_no_operator_identity enforces this and will fail
the contract suite if any fleet-specific identity token is found.
Diagnostic checklist
- Does the task evidence show
"timed out"orexit_code: 124? - Was
terminal()called without an explicittimeoutparameter? - Is the operation in the long-lived category above?
- Did the previous attempt add a skill/doc with operator identity tokens?
Check with:
grep -rn "agent_\|worker[0-9]" skills/ docs/ - Does the failure mention
CARGO_HOME,cargo/bin,rustup, orrust-toolchain? These indicate a Rust toolchain provisioning gap —cargolives in~/.cargo/bin, which is outsideMAC_SANDBOX_BASE_PATH. The task executor symlinks it intoMAC_TOOLCHAIN_BINon demand; if that step failed or was skipped,cargowill not be found even on agents with Rust installed. Verify with:echo $CARGO_HOME; ls ${CARGO_HOME:-$HOME/.cargo}/bin/cargo 2>/dev/null - Did the task declare
cargo,rustc, orrustupintoolchain.required_commands? If yes and the toolchain setup shell did not run, the symlink intoMAC_TOOLCHAIN_BINwas never created. Re-run bootstrap or inspectmac_sandbox_toolchain_setupoutput.
Pitfall: cargo not found even when Rust is installed
Symptom: A task with cargo, rustc, or rustup in
toolchain.required_commands fails with command not found: cargo (or similar)
even though Rust is installed on the worker.
Root cause: Cargo's binaries live in ~/.cargo/bin (or $CARGO_HOME/bin).
That directory is intentionally outside MAC_SANDBOX_BASE_PATH, so cargo is not
visible inside the task sandbox by default.
How it is handled automatically: mac_sandbox_toolchain_setup (injected into
every task sandbox before agent or test work runs) iterates over
toolchain.required_commands. When it encounters cargo, rustc, or rustup, it
creates symlinks from $CARGO_HOME/bin/<binary> (defaulting to ~/.cargo/bin)
into MAC_TOOLCHAIN_BIN, then calls mac_refresh_sandbox_path so the updated
PATH takes effect. If no local Rust installation exists, it runs the upstream
rustup installer and links the freshly installed binaries into MAC_TOOLCHAIN_BIN.
What can go wrong:
mac_sandbox_toolchain_setupwas never called (e.g., the sandbox shell script was skipped or the task used a rawterminal()call without sourcing the setup).cargois not listed intoolchain.required_commands, so the symlink step is never triggered.CARGO_HOMEpoints to an unexpected location and~/.cargo/bin/cargodoes not exist; the installer then has no network access to fetch Rust.
Fix checklist:
- Declare
cargo(orrustc/rustup) intoolchain.required_commandsinside the repository's.mac/project.yaml.mac_sandbox_toolchain_setupruns automatically for every task that uses the repository contract and will symlink the Cargo binaries intoMAC_TOOLCHAIN_BIN. - If you are running a
terminal()call manually (outside the normal sandbox boot), source the toolchain setup first or prependmac_sandbox_toolchain_setup &&to the command. - Verify the symlink is present before the failing command:
ls -la $MAC_TOOLCHAIN_BIN/cargo. - If the binary is still missing, inspect
$MAC_TASK_WORKSPACE/mac-toolchain.logfor errors from the install step.