Skip to content

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": "…"}
  • result is the deliverable, or the pending question when WAITING_INPUT. It is null on failure.
  • failure is {"kind": "gate|stopped|worker_error", "gate": "<cmd>|output-schema|null", "message": "…"}.
  • approval is {"command": "…", "prefix": "…"} only while a WAITING_INPUT session waits on [APPROVAL NEEDED] (#59); the key is absent otherwise. Answer with tether send <id> approve (or tether allow <id>, MCP tether_send approve); 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 ends FAILED as Stopped by user.

  • tether run --result-file <path>: write the deliverable to a file, print nothing on stdout.

  • tether run --output-schema <schema.json>: done is 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 --follow streams 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.