Skip to main content

Baton Python SDK

Drive Baton, the multi-agent coding daemon, from Python. It is a small, standard-library-only client for the Baton control protocol (JSON-RPC 2.0 over the project's Unix socket), the same API the TUI uses.

  • Python 3.9 or newer, with no dependencies. Works on macOS and Linux (Unix sockets).
  • Import name baton, distribution name batonsh.
pip install ./sdk-python        # or just put sdk-python/ on PYTHONPATH

Quick start

import baton

with baton.connect() as client:                 # finds the project, starts `baton daemon` if needed
    run = client.run_state()                    # self-updating view of the run
    seq = run.last_seq
    client.submit("migrate the tests to pytest")   # same as typing it in the TUI
    run.wait_idle(timeout=900, since_seq=seq)      # until every agent is idle again
    for a in run.agents.values():
        print(a.name, a.status, a.diff, "$%.3f" % a.cost, a.last_message)

Connecting

client = baton.connect(
    cwd=None,              # any directory inside the project (default: os.getcwd())
    socket_path=None,      # explicit socket (skips discovery)
    autostart=True,        # launch a detached daemon when nothing answers
    client_name="python",
    daemon_command=None,   # ["baton", "daemon", "--root", "{root}"] or lambda root: [...]
    start_timeout=15.0,
    env=None,              # extra env vars for a started daemon
)

connect() walks up from cwd to the project root (the first directory with .baton/config.toml, otherwise the nearest .git). It connects to .baton/run/baton.sock, or to the path stored in .baton/run/socket-path for deeply nested projects. Without a running daemon it starts baton daemon --root <root> using $BATON_BIN (shell-split, e.g. BATON_BIN="bun packages/cli/src/main.ts") or baton on PATH, waits for the socket, and raises BatonError if the daemon exits first. The hello handshake is done for you: client.project_root, client.run_id, client.daemon_pid.

Calls

Each control method has a wrapper. Results are plain dicts with the protocol's camelCase keys.

client.snapshot()                                  # agents, tasks, approvals, totals, autonomy, lastSeq
info = client.spawn("codex", label="review", approval="auto-edit", options={"speed": 0})
client.prompt(info["agentId"], "review the latest diff", delivery="steer")
client.submit("@codex-2 verify codex-1's fix")     # @mentions, /commands, or a task for the orchestrator
client.send("*", "freeze: release in 10 minutes", delivery="interrupt")
client.respond(agent_id, request_id, option_id)    # answer a permission request (None cancels)
client.interrupt(agent_id); client.kill(agent_id)
client.set_autonomy("auto")                        # normal | ask | auto | yolo
client.merge(agent_id); print(client.diff(agent_id))
client.query_events(types=["tool.*"], limit=50)
client.call("runs.list", {"limit": 5})             # anything else, by method name
client.shutdown()                                  # stop the daemon

Errors raise baton.BatonError, which carries .code, .message and .data. A closed connection raises baton.ConnectionClosed, and a timeout= on call() raises baton.BatonTimeoutError, which is also a TimeoutError.

Events

Every event is a dict {id, seq, ts, runId, agentId?, type, data} (see the BEP table in docs/sdk.md).

# iterator: subscribes immediately; breaking out of the loop unsubscribes; ends when the connection closes
for e in client.events(types=["tool.*", "bus.message"], from_seq=0):
    print(e["seq"], e["type"], e["data"])

# callback on a worker thread (it may call the client)
def approve_reads(e):
    d = e["data"]
    if d.get("kind") == "read":
        allow = next(o["optionId"] for o in d["options"] if o["kind"] == "allow_once")
        client.respond(e["agentId"], d["requestId"], allow)

sub = client.on_event(approve_reads, types=["permission.requested"])
...
sub.close()

events(timeout=…) raises TimeoutError when nothing arrives for that long. client.subscribe(handler) is the low-level form. Its handler runs on the socket reader thread, so it must be fast and must not call the client.

Run state

client.run_state() replays the whole run, then follows it live, and gives you:

  • agents: {agentId: Agent}, where each Agent has name adapter status label role model cost usage diff tool_calls turns last_message busy alive
  • approvals: {requestId: Approval}
  • tasks, workspaces, bus, autonomy, mode, totals, last_seq
  • wait_for(predicate, timeout), wait_idle(timeout, since_seq=None, settle=0.3), is_idle(), find_agent(name_or_id)
run = client.run_state()
coder = run.wait_for(lambda s: s.find_agent("codex-1"), timeout=30)
run.wait_for(lambda s: not s.approvals and coder.status == "ready", timeout=600)

Pass since_seq=run.last_seq (captured before you submit work) to wait_idle so it does not return before the work starts. settle requires the run to stay quiet for that long, which covers short idle gaps when agents hand off to each other.

Examples

  • examples/watch.py prints a live one-line-per-event feed (--replay, --types 'tool.*', --agent NAME).
  • examples/run_task.py "task" --approve reads submits a task, waits until every agent is idle, and prints cost, per-agent changes and the files touched.

Tests

python3 -m unittest discover -s sdk-python/tests -v

The integration tests start a throwaway daemon with bun packages/cli/src/main.ts daemon in a temporary git repo, using mock agents and temporary BATON_CONFIG_DIR/BATON_STATE_DIR. They are skipped when bun is not installed.

Metadata

Release files for batonsh 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for batonsh 0.2.0
File Size Uploaded
batonsh-0.2.0.tar.gz 23.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for batonsh 0.2.0
File Interpreter ABI Platform
batonsh-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 42.3 kB

Release files / batonsh-0.2.0.tar.gz

Download URL batonsh-0.2.0.tar.gz
Size 23.6 kB
Tags Source
SHA-256 checksum
How to use checksums
3ef2fcdb1a64860cf7594f6d2b155ad8554b0f7855a70183bf3af2d14f4fc247
BLAKE2b-256 checksum
How to use checksums
907e3cc78c4e1759a98ba04bf04be3d33ca5ad800c80f0131b2a59837dee1715
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / batonsh-0.2.0-py3-none-any.whl

Download URL batonsh-0.2.0-py3-none-any.whl
Size 18.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e43cb98000c31532ef6f870a1cc8f95cd2f875754ac880126b3d04a41b690820
BLAKE2b-256 checksum
How to use checksums
e62117ab02f4c63fa83bc9759647f0196bfe0f8bb49635842e13cf8b6dce081d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page