Skip to main content

taut-summon

Summon extension for Taut: host an existing agent harness (Claude Code and friends) as an ordinary member of a taut workspace.

This package is intentionally separate from the core taut-chat distribution. The summon driver is the agent's terminal, not its runtime: it injects chat into the harness's own live session (its ears), and the agent speaks through the ordinary taut CLI selected by its continuity token (its mouth). The full contract lives in the core repository at docs/specs/04-summon.md.

Status

Functional. The CLI surface (taut-summon run|stop|status) and the installed root verbs (taut summon, taut dismiss), the foreground driver (bootstrap, chat injection, event pump, crash-resume, clean shutdown), the session ledger with a single-driver guard and PTY wired flag, the control plane (STOP/STATUS/PING) with a rate backstop, the default persona, and the provider adapters are implemented. pty is the default adapter for the interactive harnesses (claude, codex, coder, grok, qwen, kimi, opencode, pi); claude-stream remains available for Claude Code's structured stream-json mode. See docs/plans/2026-07-06-taut-summon-plan.md, docs/plans/2026-07-07-taut-summon-pty-harness-adapter-plan.md, and docs/implementation/05-taut-summon-architecture.md for the driver design. Command registration and rich-host composition are documented in docs/implementation/06-command-extensions.md.

Requirements

  • Python 3.11+
  • Core distribution taut-chat and extension taut-summon installed in the same environment
  • A SQL-sidecar backend (SQLite or Postgres) — summon state rides sidecar tables

Installation

The core distribution is taut-chat; it still installs the taut command and import package. The extension remains taut-summon. Once the first coordinated PyPI release is published:

pipx install taut-chat
pipx inject --include-apps taut-chat taut-summon

The tag gate reuses the exact wheel and sdist built by canonical Test. It stages them in a draft GitHub Release, publishes them through the taut-summon top-level PyPI Trusted Publisher, verifies filenames and SHA-256 digests, and only then publishes the GitHub Release as immutable.

Usage

taut summon claude              # summon a claude into #general
taut summon reviewer --provider claude dev
taut summon reviewer --provider claude-stream dev
taut dismiss reviewer
taut-summon status

When the workspace is discoverable from the current directory, --db is not required. The quickstart above exercises the same discovery path for the driver, control loop, and recovered broker handles.

taut-summon --help lists the three verbs and their exit classes; each verb's own --help documents every positional and flag. Exit 0 is success, 1 is an invocation, adapter, storage, or unresponsive-driver error, and 2 means nothing is currently summoned. With no verb, help goes to stderr and exits 1.

Installing this package registers native taut summon and taut dismiss command adapters through Taut's command-extension interface. The root and standalone consoles use the same parser configuration and controller adapters; neither console invokes the other. taut-summon status remains the standalone control-plane listing and inspection command.

On first PTY use, summon attaches your terminal so you can answer trust, login, or model prompts in the real harness UI. Detach with Ctrl-\ Ctrl-\. After detach the member is marked wired and future summons run detached. Use taut summon --attach NAME to re-enter setup, or --detach for an explicit detached run. PTY output is never parsed as speech; the agent speaks by running taut say.

Summon command records, standalone status/errors, and Summon-owned non-interactive logs use core's public taut.escape_terminal_text policy. This reduces the chance that prompt-injected chat or provider text is relayed as a live terminal command sequence. It is a safe default, not a sandbox boundary. The explicit PTY attach is intentionally exempt and copies provider terminal bytes unchanged because those bytes are the attached terminal protocol. Provider-owned stderr inherited directly by an external adapter is also outside Taut-owned text rendering and may contain controls. Constrain or redirect that provider stream when its output is not trusted; mediating it would require a separately drained pipe rather than this text-display policy.

The PTY orientation is the first injected user turn, not a privileged system message. Chat continuation lines are indented to keep attribution visible, but chat remains untrusted user-role workspace input. Notification injection is at most once because inbox records are consumable pointers; the source chat is durable. The rate backstop limits posting volume and does not detect a low-rate semantic loop.

Trust boundary

Anyone who can write the configured Taut storage can feed user-role input and storage-backed control requests to the summoned harness. For SQLite this is the local file-access boundary. For shared Postgres, a remote database writer can therefore influence tools on the harness host. Restrict storage writers to principals authorized for that effect, or constrain the harness tools separately. Names, personas, message framing, driver evidence, and continuity tokens preserve attribution or lifecycle state; they are not authorization.

Control requests carry driver evidence as a stale-generation fence. That evidence prevents an old queued command from acting on a replacement driver; it does not authenticate the requester.

Testing

From the repository root:

uv run pytest extensions/taut_summon/tests

Local runs attempt the live PTY harness smoke matrix by default. A provider skips with an explicit reason when its binary is absent, the fresh test database has not been onboarded with a real attach/detach cycle, or status cannot reach a usable detached session. CI skips the real-harness matrix unless TAUT_SUMMON_LIVE_HARNESS=1 is set. For a fast local loop, use:

TAUT_SUMMON_LIVE_HARNESS=0 uv run pytest extensions/taut_summon/tests

Run taut summon --attach <name> once for a provider that still needs trust, login, or model setup before expecting its detached live smoke to pass. For a hard local external-provider smoke, use strict mode. It prewires the temporary test session to model an already-onboarded provider and fails on missing binaries, readiness gaps, status timeouts, unanswered terminal queries, or injection catch-up failures. The external-provider lane does not require hosted CLIs to auto-execute shell commands; the local LLM lane below owns the deterministic sentinel-posting proof.

TAUT_SUMMON_LIVE_HARNESS_STRICT=1 uv run pytest extensions/taut_summon/tests/test_live_harness.py

The local LLM smoke runs locally by default when a loopback OpenAI-compatible endpoint lists the served model, and it runs in CI through the dedicated Ollama-backed workflow job. Defaults:

TAUT_SUMMON_LOCAL_LLM_ENDPOINT=http://127.0.0.1:11434/v1
TAUT_SUMMON_LOCAL_LLM_MODEL=taut-summon-local-model:latest

To run it locally with Ollama:

ollama pull qwen2.5:0.5b
cat > /tmp/TautSummonModelfile <<'EOF'
FROM qwen2.5:0.5b
PARAMETER num_ctx 2048
PARAMETER num_predict 64
PARAMETER temperature 0
EOF
ollama create taut-summon-local-model:latest -f /tmp/TautSummonModelfile
uv run pytest extensions/taut_summon/tests/test_live_local_llm.py

Use TAUT_SUMMON_LOCAL_LLM=0 to skip the local LLM smoke locally, or TAUT_SUMMON_LOCAL_LLM=1 to make missing endpoint/model setup fail instead of skip.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

taut_summon-0.9.1.tar.gz (78.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

taut_summon-0.9.1-py3-none-any.whl (94.4 kB view details)

Uploaded Python 3

File details

Details for the file taut_summon-0.9.1.tar.gz.

File metadata

  • Download URL: taut_summon-0.9.1.tar.gz
  • Upload date:
  • Size: 78.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for taut_summon-0.9.1.tar.gz
Algorithm Hash digest
SHA256 c496a44d7a55f055d6543d57e36b9b2a55b9794cdbccc5f86c133b837fec2580
MD5 0d90a79de64c34861cd82443602e8c42
BLAKE2b-256 c1a1ef047ca0693933073d51367174255a2c5bfb6328b11523d99e69c5b1128b

See more details on using hashes here.

Provenance

The following attestation bundles were made for taut_summon-0.9.1.tar.gz:

Publisher: release-gate-summon.yml on VanL/taut

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file taut_summon-0.9.1-py3-none-any.whl.

File metadata

  • Download URL: taut_summon-0.9.1-py3-none-any.whl
  • Upload date:
  • Size: 94.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for taut_summon-0.9.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9af3aa1d141af6649038aa2ae5b341694dc3271ce41c190396d17d93b8713d0b
MD5 38c5821e7b954cf20b291faf1403b1d7
BLAKE2b-256 abeddbb600ccb314c6bd77bd94f8a43695380fee8967c095a7dd341f26c8574a

See more details on using hashes here.

Provenance

The following attestation bundles were made for taut_summon-0.9.1-py3-none-any.whl:

Publisher: release-gate-summon.yml on VanL/taut

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.9.5

2 files

0.9.4

2 files

0.9.3

2 files

0.9.2

2 files

This release

0.9.1 This release

2 files

0.9.0

2 files

0.8.7

2 files

0.8.6

2 files

0.8.5

2 files

0.8.2

2 files

0.8.1

2 files

0.8.0

2 files

0.7.1

2 files

0.7.0

2 files

0.6.7

2 files

0.6.6

2 files

0.6.5

2 files

0.6.4

2 files

0.6.2

2 files

0.6.1

2 files

0.6.0

2 files

0.5.4

2 files

0.5.3

2 files

0.5.2

2 files

0.5.1

2 files

0.5.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page