Agent Interface Reference¶
For: agents and scripts calling tether. After this page you know the JSON shape, exit codes and MCP tools.
Machine-readable surface for calling Tether from another agent. Setup per harness: Use Tether Inside Your Harness. Code: tether/api.py, tether/mcp.py, tether/schema.py.
Session JSON (schema version 1)¶
{"v": 1, "id": "ses_…", "status": "COMPLETED|WAITING_INPUT|FAILED|RUNNING|PENDING",
"model": "ollama/qwen3.5:9b", "steps": 4, "max_steps": 15,
"tokens": {"prompt": 1200, "completion": 90}, "duration_ms": 8100,
"failure": null, "exit_code": 0, "result": "…"}
resultis the deliverable, or the pending question whenWAITING_INPUT. It isnullon failure.failureis{"kind": "gate|stopped|worker_error", "gate": "<cmd>|output-schema|null", "message": "…"}.approvalis{"command": "…", "prefix": "…"}only while aWAITING_INPUTsession waits on[APPROVAL NEEDED](#59); the key is absent otherwise. Answer withtether send <id> approve(ortether allow <id>, MCPtether_sendapprove); any other reply refuses.- Keys are stable; new keys may be added.
--json is available on run, pipeline, status, list, read (also --digest, --steps, --full), wait, send and stats. With --headless it prints {"v":1,"id":"ses_…"}. A foreground run (with or without --json) writes session ses_… to stderr as soon as the session exists, before the first model call, so a caller that kills it on its own timeout can still status, stop or send it; stdout is unchanged.
Exit codes¶
| Code | Meaning |
|---|---|
| 0 | completed |
| 1 | usage error (bad flag, unknown session, invalid pipeline) |
| 2 | waiting for input (done --ask), or handed back as [STUCK ...] after two restarts that did not help |
| 3 | verification gate failed or misconfigured (including --output-schema) |
| 5 | worker or provider error, or tether stop |
| 6 | wait timed out with sessions still RUNNING or PENDING (message on stderr) |
In plain mode the failure reason goes to stderr; stdout only ever holds a deliverable. wait returns the highest code among its sessions.
With tether run --worktree, the session JSON carries worktree (the worktree path), branch (tether/<id>) and commit (the full sha, or null when nothing changed) at the top level of the session JSON. The MCP run tool accepts a worktree argument to request the same isolation; it cannot pass a setup command.
Other flags¶
-
tether stop <id>: terminate a running detached session (SIGTERM to its worker); the session endsFAILEDasStopped by user. -
tether run --result-file <path>: write the deliverable to a file, print nothing on stdout. tether run --output-schema <schema.json>:doneis rejected (like a failed gate, 0 prompt tokens until it fails) unless the deliverable is JSON matching the schema. Supported subset:type,enum,required,properties,items.tether events <id> [--follow]: one JSON object per turn (turn,step,role,cmd,event,text); with--followstreams until the session ends and finishes with{"event":"status","status":"…"}.
MCP server: tether mcp [--db <path>] [--workspace <dir>]¶
Optional: pip install "tether-sdk[mcp]" (installs the official mcp SDK; core Tether never imports it). Without the extra, tether mcp prints a warning with the install command to stderr and exits 1. Transport: stdio, tools capability only. Tool results are the JSON above as text content; failures set isError.
| Tool | Arguments |
|---|---|
tether_run |
goal, model, skill, tools, verify[], max_steps, max_tokens, context_tokens, fold_after, sandbox, workspace, no_network, web_allow, allow_unsandboxed, allow, limits, output_schema, wait (default true) |
tether_status |
id |
tether_wait |
ids[], timeout |
tether_read |
id, mode = full | digest | steps |
tether_send |
id, message, wait (default false: resume in background) |
tether_list |
limit |
tether_stats |
model, skill |
tether_query |
id, query, top |
Security: sandboxes are always rooted at --workspace (default: the server's cwd). Callers can choose read-only or no_network, never widen, with two exceptions that widen what runs outside the jail: allow (a list of command prefixes that run outside the jail, see security-and-sandbox section 8) and allow_unsandboxed (boolean) lets a workspace-write session run without bwrap (command checks only). Without bwrap and without it, tether_run returns a tool error that names --allow-unsandboxed, TETHER_SANDBOX=container and how to install bubblewrap; the CLI exits 1 in the same case. A caller of a shared MCP server can opt out per call with allow_unsandboxed; the server does not set a default for it.
workspace (optional) must be an absolute existing directory inside the server workspace; anything else is rejected.
limits (optional) is an object of key to whole number, e.g. {"cpu": 60, "mem": 2048} (keys cpu seconds, mem MB, procs, fsize MB; Linux only), the same as --limit. An unknown key, a non-integer (including 1.0), a value below 1 or above 2147483647 is a tool error.