A framework for running agents unattended — scenes, fallbacks, adaptive variations, urgent contact escalation, and a programme at the end.
Status: v1.1.0 — production-ready, on PyPI, used in real operations at Short+Sweet International. Open source, runtime free.
The Show is an orchestration runtime for creative work. It uses a theatrical metaphor — programmes, scenes, Stage Manager, Urgent Contact — because the metaphor maps onto how creative operators already think. You write a programme. The Stage Manager runs it, persisting state after every scene. When something needs a human decision, the Urgent Contact system sends a signed, authenticated request across Telegram, email, SMS or WhatsApp. You respond. The show continues.
The specific differentiator: async cancellation mid-LLM-call across four signed-link channels with typed response schemas and per-channel authentication. When the first valid response comes in, outstanding sends are cancelled. That combination doesn't exist elsewhere as a coherent system.
The v1.0 release was built by running The Show on itself — examples/build-v1.0-release.yaml is the programme that built v1.0. It's in the repo.
Here's what a programme looks like — three scenes from the Curiosity Cat launch announcement that ran on 23 April 2026:
running-order:
- scene: draft_english
title: "Draft English announcement"
outputs:
post: {type: object}
principal:
method: sub-agent
agent: gemini
brief: "Draft a 280-char social post for the Curiosity Cat launch."
params: {model: gemini-flash}
cut: {condition: escalate, reason: "Cannot proceed without English draft"}
- scene: draft_arabic
title: "Draft Arabic announcement"
depends-on: [draft_english]
inputs:
english_post: from(draft_english.post)
outputs:
post: {type: object}
principal:
method: sub-agent
agent: gemini
brief: "Translate the English post to natural Arabic for the UAE market."
params: {model: gemini-flash}
cut: {condition: escalate}
- scene: approve_drafts
title: "Operator approval"
depends-on: [draft_english, draft_arabic]
outputs:
decision: {type: string}
principal:
method: human-approval
brief: "Reply APPROVE to publish, REJECT to abort."
cut: {condition: escalate}The full programme is at examples/curiosity-cat-launch-announcement.yaml. The operator guide explains the metaphor and the mechanics in detail — see docs/OPERATOR_GUIDE.md.
Version: v1.1.0 — 231 passing tests
- SQLite state (
~/.the-show/state/<show-id>.db, WAL mode) - Crash recovery — interrupted shows prompt for resume on next run
- Full scene state vocabulary including
cascading-dependency-failureandplayed-fallback-N - Per-strategy
success-whenoverrides (falls back to scene-level) - Basic schema validation in
meets_success(list / dict / string / number) - Markdown-fence sanitisation on untrusted output (
sanitise.py) - Field-validator hook — logs INFO, skips (real validators planned)
- Idempotency key generation for side-effectful strategies (logged to event DB)
- Urgent Contact — real dispatcher:
- Three auth methods: channel-native, reply-token (6-digit), signed-link (HMAC-SHA256)
- Strict response parsing: APPROVE / REJECT / STOP / CONTINUE only; invalid format sends a correction prompt and keeps polling
- Sequential and parallel dispatch modes;
criticalseverity forces parallel - Cancellation of pending sends on first valid response
- Exhaustion path (
blocked-no-response) when all contacts fail to reply - DAG pruning: exhausted/blocked scene cascades
cascading-dependency-failureto all transitive dependents - Frequency throttle: default 3 unplanned matters per show;
human-approvalscenes always exempt;criticalalways bypasses - Mock channel for testing (file-drop at
~/.the-show/urgent-mock/)
- Real channel adapters:
- Telegram — dedicated urgent-contact bot, polling-based, channel-native auth
- Email — SMTP send + signed action links, HMAC-SHA256 tokens, 24h expiry
- WhatsApp — skeleton with setup checklist; send() raises NotImplementedError until Meta onboarding complete
- SMS — Twilio, reply-token auth
- Signed-link server — Flask app on port 5099; handles email link clicks + WhatsApp / Twilio webhooks
load_adapters()indispatcher.py— registers only configured adapters; warns if credentials missing; mock always available- Programme reads from SQLite event log
tests/— 231 passing pytest tests
- WhatsApp
send()raisesNotImplementedErroruntil Meta Business API onboarding completes - Link server is localhost-only — needs reverse proxy or Cloudflare Tunnel for WhatsApp and Twilio webhooks
- Execution Monitor — not yet enabled
STOPkeyword — parsed and returned but does not yet abort the whole show- Field-level validators — hook exists, no real validators
- Basic schema validation only — no JSON Schema deep validation
# From PyPI
pip install the-show
# Or from source
git clone https://github.com/markscleary/the-show.git
cd the-show
pip install -e ".[dev]"See docs/QUICKSTART.md for a five-minute walkthrough.
# Validate a show file
the-show validate example_show.yaml
# Run a show (with crash-resume)
the-show run example_show.yaml
# Inspect current state
the-show peek outreach-enrichment-001
# Regenerate programme from saved state
the-show programme outreach-enrichment-001
# Print event log
the-show events outreach-enrichment-001 [--since=<ISO>] [--limit=N]
# Run tests (from a source checkout)
pytest tests/State DB: ~/.the-show/state/<show-id>.db
Programme output: ~/.the-show/state/<show-id>/programme.md and programme.json
Run a show that contains a human-approval scene. When the dispatcher raises a matter via the mock channel, drop a JSON response file to resolve it:
# 1. Start the show — it will block on the human-approval scene
the-show run example_show.yaml
# 2. In another terminal, find the matter ID from the event log
the-show events outreach-enrichment-001 --limit=5
# 3. Drop a response for that matter ID (replace <matter-id> with the real value)
mkdir -p ~/.the-show/mock_responses
echo '{"keyword": "APPROVE", "auth_token": null}' \
> ~/.the-show/mock_responses/<matter-id>.json
# 4. The dispatcher will pick it up within the next poll interval (default 5 s)
# and unblock the show.The THE_SHOW_POLL_INTERVAL environment variable controls the poll delay (seconds, default 5). Set it to 0 or 0.01 in tests for instant resolution.
models.py— core dataclasses (Strategy now hassuccess_when)loader.py— YAML loading and validationexecutor.py— scene execution loop (resume, all v0.4.1 states, real urgent contact)state.py— SQLite state layer (WAL, resume, event log, urgent matter / send tables)sanitise.py— markdown fence stripper for untrusted outputprogramme.py— reads from SQLite, generates markdown + JSONadapters.py— stub adapters + idempotency key utilitiescli.py— CLI: validate / run / peek / programme / eventsexample_show.yaml— 5-scene example covering core scene mechanicsurgent_contact/— Urgent Contact subsystemdispatcher.py— raise matters, fire sends, poll, cancel, return resolutionauth.py— channel-native / reply-token / signed-link authparser.py— strict APPROVE / REJECT / STOP / CONTINUE keyword parserthrottle.py— per-show matter frequency limitdegradation.py— DAG pruning for cascading-dependency-failurechannels/base.py— ChannelAdapter protocol and InboundResponse typechannels/config.py— env var config helpers for all channelschannels/mock.py— file-drop mock channel for testingchannels/telegram.py— polling Telegram Bot API adapterchannels/email.py— SMTP send + signed-link poll adapterchannels/whatsapp.py— WhatsApp Business API skeletonchannels/sms.py— Twilio SMS adapterlink_queue.py— shared SQLite for email/SMS/WhatsApp webhook responseslink_server.py— Flask server:/respond,/whatsapp-webhook,/twilio-webhook
tests/— pytest suite (231 tests)
Copy .env.example to .env and fill in credentials:
cp .env.example .env
# edit .envChannels activate automatically when their env vars are set. Missing vars emit a warning and the channel is skipped; the mock channel is always available.
Telegram — fastest to activate: create a bot with BotFather and set URGENT_TELEGRAM_BOT_TOKEN plus the authorised user IDs.
Email — create a Gmail App Password, set URGENT_SMTP_* vars and URGENT_EMAIL_SIGNING_SECRET.
WhatsApp — requires Meta Business API onboarding (1–7 days). See channels/whatsapp.py class docstring for the setup checklist.
SMS — Twilio account required. Trial accounts can only send to verified numbers.
The link server receives email link clicks and Twilio/WhatsApp webhooks.
# Manual (for development)
.venv/bin/python -m urgent_contact.link_server
# Via launchd (production — after filling in the plist env vars)
launchctl load ~/Library/LaunchAgents/org.shortandsweet.urgent-link-server.plistFor WhatsApp and Twilio webhooks (which require HTTPS), use ngrok:
ngrok http 5099
# Use the resulting https://*.ngrok.io URL in Meta / Twilio dashboards- Quickstart — get a programme running in 5 minutes.
- Operator Guide — the theatrical metaphor, how scenes work, approval gates, urgent contact mechanics. The starting point for anyone running The Show.
- Spec v0.4.2 — formal specification and patch notes.
- Execution Monitor — watches running scenes, triggers Urgent Contact on anomalies.
- WhatsApp send() implementation once Meta Business API onboarding lands.
- Stronger STOP semantics — parsed STOP aborts the whole show, not just the scene.