agent-switchboard 2.1.0__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/CONTRIBUTING.md +2 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/PKG-INFO +2 -1
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/README.md +1 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/claude-code.md +154 -1
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/concepts.md +6 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/quickstart.md +2 -2
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/upgrading.md +13 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/extras/session-capsule/README.md +12 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/pyproject.toml +1 -1
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/__init__.py +1 -1
- agent_switchboard-2.2.0/src/switchboard/claude_session.py +658 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/cli.py +294 -2
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/client.py +5 -1
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/crypto.py +19 -0
- agent_switchboard-2.2.0/src/switchboard/handoff.py +599 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/mcp_server.py +126 -2
- agent_switchboard-2.2.0/src/switchboard/skill/history/025-SKILL.md +283 -0
- agent_switchboard-2.2.0/src/switchboard/skill/switchboard-coordinate/SKILL.md +311 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/store.py +19 -1
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/conftest.py +4 -0
- agent_switchboard-2.2.0/tests/test_claude_session.py +430 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_cli_global_flags.py +3 -0
- agent_switchboard-2.2.0/tests/test_cli_session.py +318 -0
- agent_switchboard-2.2.0/tests/test_handoff.py +591 -0
- agent_switchboard-2.2.0/tests/test_mcp_session.py +228 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/.dockerignore +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/.github/workflows/ci.yml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/.github/workflows/deploy.yml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/.github/workflows/pages.yml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/.github/workflows/publish-viewer.yml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/.github/workflows/publish.yml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/.github/workflows/roadmap.yml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/.gitignore +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/AGENTS.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/ARCS.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/Dockerfile +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/LICENSE +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/demo/README.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/demo/chess.sh +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/demo/run.sh +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docker-compose.yml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/adaptive-timing.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/api.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/codex-cli.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/deployment.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/drills.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/encryption.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/environments.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/images/viewer.png +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/layers.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/managed-hub.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/model.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/seam.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/testing.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/viewer.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/docs/why-this-exists.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/examples/coordinated_worker.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/extras/session-capsule/cc.sh +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/extras/session-capsule/claude_session_capsule.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/extras/viewer/README.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/extras/viewer/pyproject.toml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/extras/viewer/switchboard_viewer/__init__.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/extras/viewer/switchboard_viewer/__main__.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/extras/viewer/switchboard_viewer/viewer.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/extras/viewer/switchboard_viewer/web/index.html +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/extras/viewer/switchboard_viewer/web/render.js +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/extras/viewer/switchboard_viewer/web/switchboard-open.js +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/extras/viewer/switchboard_viewer/web/switchboard-room.js +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/README.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/ROADMAP.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/arcs/distribution.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/arcs/hub-boundary.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/arcs/setup-and-first-run.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/arcs/ttl-ceilings.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/a-lobby-derived-from-the-key.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/abuse-control-after-authorization.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/board-ttl-ceiling.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/ci-workspace-is-public.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/clients-that-cannot-post.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/connect-failure-message.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/cross-key-rendezvous.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/every-silent-failure-looks-like-a-quiet-room.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/hooks-warning-false-positive.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/hub-origin-reachable-bypassing-the-edge.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/identity-rebinds-on-branch-change.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/init-writes-rooms-file.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/intermittent-suite-failure.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/joining-agent-sees-empty-inbox.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/known-rooms-address-book.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/one-resolved-context-across-surfaces.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/presence-ttl-is-not-one-size.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/provisioned-token-is-stale-and-nothing-says-so.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/publish-hub-container-image.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/read-only-rooms.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/robots-policy-for-public-hosts.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/roles-and-authority-between-agents.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/seal-agent-meta.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/selective-wake-for-the-listener.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/stale-resolver-references.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/stale-token-in-session-env.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/standing-checks-that-nothing-runs.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/timing-cold-start-in-ephemeral-environments.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/ttl-clamped-silently.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/unread-dms-not-shown-outside-mcp.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/roadmap/items/write-parity-across-surfaces.yaml +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/scripts/deploy.sh +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/auth.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/config.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/drill.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/guidance.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/holds.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/invite.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/knownrooms.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/load.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/notify.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/peers.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/rendezvous.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/rooms.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/scripts/wake-on-message.sh +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/server.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/signing.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/001-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/002-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/003-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/004-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/005-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/006-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/007-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/008-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/009-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/010-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/011-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/012-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/013-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/014-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/015-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/016-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/017-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/018-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/019-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/020-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/021-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/022-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/skill/history/023-SKILL.md +0 -0
- /agent_switchboard-2.1.0/src/switchboard/skill/switchboard-coordinate/SKILL.md → /agent_switchboard-2.2.0/src/switchboard/skill/history/024-SKILL.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/spec.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/testing.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/timing.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/src/switchboard/writekey.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/README.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/__init__.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/analysis.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/economy.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/flow.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/llm.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/manager.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/report.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/run.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/tier1.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/tier1_labour.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/tier1_rounds.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/tier2_seed1_bound.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/tier2_seed1_built.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/tier2_seed1_free.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/tier2_seed1_paid.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/tier2_seed1_spend.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/tier2_seed1_told.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/tier2_seed41_bound.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter/traders.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter_experiment.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/barter_llm_experiment.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_harness.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/RESULTS.md +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/prompt_A_s31337.txt +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/prompt_A_s4242.txt +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/prompt_A_s7777.txt +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/prompt_B_s31337.txt +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/prompt_B_s4242.txt +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/prompt_B_s7777.txt +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/prompt_C_s31337.txt +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/prompt_C_s4242.txt +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/prompt_C_s7777.txt +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_haiku_A_s31337.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_haiku_A_s4242.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_haiku_A_s7777.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_haiku_B_s31337.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_haiku_B_s4242.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_haiku_B_s7777.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_haiku_C_s31337.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_haiku_C_s4242.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_haiku_C_s7777.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_opus_A_s31337.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_opus_A_s4242.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_opus_A_s7777.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_opus_B_s31337.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_opus_B_s4242.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_opus_B_s7777.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_opus_C_s31337.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_opus_C_s4242.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_opus_C_s7777.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_sonnet_A_s31337.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_sonnet_A_s4242.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_sonnet_A_s7777.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_sonnet_B_s31337.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_sonnet_B_s4242.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_sonnet_B_s7777.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_sonnet_C_s31337.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_sonnet_C_s4242.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_pilot/response_sonnet_C_s7777.json +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/tier2_run.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/experiments/timing_experiment.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_api.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_arrive.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_auth.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_barter.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_barter_llm.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_cli_board.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_cli_checkin.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_cli_config.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_cli_init.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_cli_serve.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_cli_timing.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_client_invite.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_config.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_cors_write_headers.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_crypto.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_dash_ids.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_declare.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_deployment.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_drill.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_evening_replayed.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_example_viewer.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_failure_messages.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_help.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_invite.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_isolated_hub.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_known_rooms.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_leave_a_ghost.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_load.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_lobby.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_mcp.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_notify.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_rendezvous.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_rooms.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_spec.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_store.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_surface_parity.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_testing.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_tier2_harness.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_timing.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_timing_experiment.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_transient_failures.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_version.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_wake_listener.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_web_invite.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_web_page.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_web_reader.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_web_snapshot.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_whisper.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_workflow_token.py +0 -0
- {agent_switchboard-2.1.0 → agent_switchboard-2.2.0}/tests/test_write_keys.py +0 -0
|
@@ -22,6 +22,8 @@ no service to run for the tests — they spin the app up in-process.
|
|
|
22
22
|
| `cli.py` | The `switchboard` command. |
|
|
23
23
|
| `mcp_server.py` | MCP stdio bridge — speaks JSON-RPC directly, no SDK. |
|
|
24
24
|
| `config.py` | Env-driven settings and the TTL defaults/ceilings. |
|
|
25
|
+
| `claude_session.py` | Claude Code harness adapter: locate, package, install, resume a session's transcript; stdlib only. |
|
|
26
|
+
| `handoff.py` | Session capsules over the hub: board value + signed pointer; hub-neutral. |
|
|
25
27
|
|
|
26
28
|
The dependency direction is one-way: `store` knows nothing about HTTP,
|
|
27
29
|
`server` knows nothing about the CLI, and `cli`/`mcp_server` both go through
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: agent-switchboard
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: An ephemeral orchestration hub for AI coding agents: presence, leases, messaging and a shared blackboard, all with TTLs.
|
|
5
5
|
Project-URL: Homepage, https://github.com/gald33/switchboard
|
|
6
6
|
Project-URL: Issues, https://github.com/gald33/switchboard/issues
|
|
@@ -306,6 +306,7 @@ Agents then get these as native tools:
|
|
|
306
306
|
| `say` / `dm` / `inbox` / `history` | channel and direct messaging |
|
|
307
307
|
| `board_set` / `board_get` / `board_list` | shared scratch space |
|
|
308
308
|
| `checkin` | heartbeat + renew leases + drain inbox, in one call |
|
|
309
|
+
| `session_handoff` / `session_import` / `session_resume` | move a whole Claude Code session to another environment |
|
|
309
310
|
|
|
310
311
|
`checkin` is the one that matters most in practice: a single tool call that
|
|
311
312
|
keeps the agent alive, renews everything it holds, and hands back anything
|
|
@@ -268,6 +268,7 @@ Agents then get these as native tools:
|
|
|
268
268
|
| `say` / `dm` / `inbox` / `history` | channel and direct messaging |
|
|
269
269
|
| `board_set` / `board_get` / `board_list` | shared scratch space |
|
|
270
270
|
| `checkin` | heartbeat + renew leases + drain inbox, in one call |
|
|
271
|
+
| `session_handoff` / `session_import` / `session_resume` | move a whole Claude Code session to another environment |
|
|
271
272
|
|
|
272
273
|
`checkin` is the one that matters most in practice: a single tool call that
|
|
273
274
|
keeps the agent alive, renews everything it holds, and hands back anything
|
|
@@ -104,7 +104,7 @@ claude mcp add switchboard \
|
|
|
104
104
|
```
|
|
105
105
|
|
|
106
106
|
Verify with `/mcp` inside Claude Code — you should see `switchboard` connected
|
|
107
|
-
with
|
|
107
|
+
with 26 tools.
|
|
108
108
|
|
|
109
109
|
## 4. Tell the agent to use it
|
|
110
110
|
|
|
@@ -383,6 +383,156 @@ filled in. One implementation, reachable two ways. The command is the one to
|
|
|
383
383
|
reach for otherwise: the shim bakes in a single room and cannot leave it, which
|
|
384
384
|
is right for a repo's own agents and wrong for anything crossing repos.
|
|
385
385
|
|
|
386
|
+
## 7. Hand a whole session to another environment
|
|
387
|
+
|
|
388
|
+
Everything above moves *facts* between sessions — a claim, a message, a
|
|
389
|
+
payload on the board. Sometimes what should move is the session itself: the
|
|
390
|
+
conversation a laptop started is the one a cloud runner should continue,
|
|
391
|
+
tool results and all, rather than a summary of it the next agent re-derives
|
|
392
|
+
at cold-start prices. A Claude Code session turns out to be portable as one
|
|
393
|
+
file, and Switchboard carries that file the way it carries any other handoff
|
|
394
|
+
— payload on the blackboard, pointer in a message — with nothing added to
|
|
395
|
+
the hub: no endpoint, no schema, no fifth primitive.
|
|
396
|
+
|
|
397
|
+
The facts this rests on were established empirically and are logged in
|
|
398
|
+
[`extras/session-capsule/README.md`](../extras/session-capsule/README.md);
|
|
399
|
+
the short version is what the code relies on. Claude Code writes every turn,
|
|
400
|
+
tool call and tool result of a session to
|
|
401
|
+
`<config-dir>/projects/<project-key>/<id>.jsonl` — `<config-dir>` is
|
|
402
|
+
`$CLAUDE_CONFIG_DIR`, else `~/.claude`; `<project-key>` is the working
|
|
403
|
+
directory with every character outside `[A-Za-z0-9]` replaced by `-` — plus
|
|
404
|
+
an optional `<id>/` sidecar directory when the session spawned subagents.
|
|
405
|
+
Copy that file under any project key on another machine and `claude --resume
|
|
406
|
+
<id>` continues the conversation there, from a different directory, with no
|
|
407
|
+
path rewriting and no other state. `claude --bg --resume <id>` does the same
|
|
408
|
+
as a background session that `claude attach <short-id>` opens later. The
|
|
409
|
+
transcript is carried byte for byte and never interpreted.
|
|
410
|
+
|
|
411
|
+
### The flow
|
|
412
|
+
|
|
413
|
+
On the side handing off — inside the session, where Claude Code exports
|
|
414
|
+
`CLAUDE_CODE_SESSION_ID` and the MCP bridge and hook commands inherit it:
|
|
415
|
+
|
|
416
|
+
```
|
|
417
|
+
session_handoff to="<agent id from roster>"
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
or from a shell, `switchboard session handoff <agent>`, with `<agent>`
|
|
421
|
+
resolved the way `dm` resolves it: a roster id, or a unique name or branch.
|
|
422
|
+
One call exports the session, publishes it on the board under
|
|
423
|
+
`sessions/<session-id>` with a ten-minute TTL (`--ttl` / `ttl` changes it,
|
|
424
|
+
never past the hub's board ceiling), and sends the recipient a signed
|
|
425
|
+
pointer as a direct message. The result says how many bytes went, when the
|
|
426
|
+
capsule expires, and which leases you still hold. Those are listed in the
|
|
427
|
+
pointer and *kept* unless you pass `--release-leases` / `release_leases`:
|
|
428
|
+
the sender is still running when it hands off, the receiver may never
|
|
429
|
+
appear, and a lease nobody holds is exactly the window a third agent walks
|
|
430
|
+
into.
|
|
431
|
+
|
|
432
|
+
On the side receiving:
|
|
433
|
+
|
|
434
|
+
```
|
|
435
|
+
session_import → installed: [{session_id, resume, …}]
|
|
436
|
+
session_resume session_id="<id>" → attach: "claude attach <short-id>"
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
or `switchboard session receive`, then `switchboard session resume <id>`
|
|
440
|
+
(`--bg` for a background session, `--command` to print the line instead of
|
|
441
|
+
running it). `receive` reads this agent's own inbox — a committed read, so
|
|
442
|
+
the pointer is consumed rather than collected again on every read for ten
|
|
443
|
+
minutes — verifies the pointer's signature against the roster and the
|
|
444
|
+
capsule's sha256 against what the pointer announced, deletes the board
|
|
445
|
+
entry, and only then installs the files. The delete is the claim: the hub
|
|
446
|
+
answers it inside one transaction, so of two receivers exactly one installs
|
|
447
|
+
and the other is told the capsule was taken. Then it sends the sender a
|
|
448
|
+
receipt. On the CLI the files land where the session already lives on this
|
|
449
|
+
machine if it does (the return leg of a round trip), else under the capsule's
|
|
450
|
+
original project key, unless `--cwd` names the directory you will resume
|
|
451
|
+
from; the MCP tool defaults to this session's project directory. Either way
|
|
452
|
+
the id ends up
|
|
453
|
+
under exactly one key, because `claude --resume` refuses to choose between
|
|
454
|
+
duplicates. Other direct messages the read consumed come back as `other`
|
|
455
|
+
rather than being lost.
|
|
456
|
+
|
|
457
|
+
Local → cloud → local is then three commands and no hub change: `session
|
|
458
|
+
handoff` on the laptop, `session receive` in the cloud session followed by
|
|
459
|
+
`claude --resume`, and the same pair back when the cloud side is done. The
|
|
460
|
+
hub saw two sealed values it cannot name — the pointer's discriminator
|
|
461
|
+
travels inside the sealed body and the message type stays `note`, so not
|
|
462
|
+
even the row type says what moved.
|
|
463
|
+
|
|
464
|
+
`switchboard session export -o FILE` and `switchboard session import FILE`
|
|
465
|
+
are the two halves with no hub between them: a capsule file, created `0600`
|
|
466
|
+
because it is as private as the transcript it carries, that you move however
|
|
467
|
+
you like.
|
|
468
|
+
|
|
469
|
+
### What is trusted, and what is not
|
|
470
|
+
|
|
471
|
+
A transcript is instructions. Whoever resumes it runs a conversation
|
|
472
|
+
somebody else wrote, with their own credentials and their own repo, so the
|
|
473
|
+
rules here are stricter than for any other payload, and each is a refusal
|
|
474
|
+
rather than a warning:
|
|
475
|
+
|
|
476
|
+
- **Nothing installs from a pointer nobody vouches for.** The sender must be
|
|
477
|
+
on the roster and the pointer's signature must verify, and the capsule
|
|
478
|
+
must be the bytes that pointer announced. A pointer that fails either
|
|
479
|
+
comes back as not installed, with the reason; `--unverified` /
|
|
480
|
+
`unverified` overrides that, on your own say-so.
|
|
481
|
+
- **Nothing resumes on its own.** `session_import` installs; `session_resume`
|
|
482
|
+
is a separate call. On the CLI, `session receive --resume` runs `claude
|
|
483
|
+
--resume` afterwards only for senders named with `--from <agent-id>` (or
|
|
484
|
+
`--any-sender`), and `--bg` makes that a background session.
|
|
485
|
+
- **A plaintext room is refused.** The hub would hold everything the session
|
|
486
|
+
read — every file and secret in a tool result — in the clear. Hand off
|
|
487
|
+
inside a keyed room, or pass `--allow-plaintext` / `allow_plaintext` when
|
|
488
|
+
the hub is yours and local.
|
|
489
|
+
- **A checkpoint has no sender.** `switchboard session publish` (or
|
|
490
|
+
`session_handoff` with no `to`) puts the capsule on the board with nobody
|
|
491
|
+
pointed at it; anyone holding the key can collect it by id — `switchboard
|
|
492
|
+
session receive <id>`, `session_import(session_id=…)` — while it lasts.
|
|
493
|
+
That is trusting the room, and the result says so: `verified: null`.
|
|
494
|
+
|
|
495
|
+
What the design does not protect against, stated plainly. Any holder of the
|
|
496
|
+
room key can delete or replace a board entry — the hub has no owners — so a
|
|
497
|
+
handoff can be made to vanish in transit, though the signature check means
|
|
498
|
+
it cannot be *substituted* without the receiver noticing. In a keyed room
|
|
499
|
+
every `board_list` fetches every value, because keys are blinded and a
|
|
500
|
+
prefix cannot hide one; the ten-minute TTL and the delete-on-claim are what
|
|
501
|
+
bound that cost, and a handoff nobody collected is re-sent, not recovered.
|
|
502
|
+
Version skew between Claude Code releases, and the interactive trust prompt
|
|
503
|
+
on a first resume, are untested. And a session resumed on another host
|
|
504
|
+
derives a different Switchboard agent id unless `SWITCHBOARD_AGENT_ID` is
|
|
505
|
+
pinned: the same conversation, but not, to the roster, the same agent.
|
|
506
|
+
|
|
507
|
+
### Without a model in the loop
|
|
508
|
+
|
|
509
|
+
Every step is a plain function, so none of this needs an LLM to drive it. A
|
|
510
|
+
Claude Code `Stop` hook can run `switchboard session handoff <agent>` or
|
|
511
|
+
`switchboard session publish` so a session checkpoints itself — opt-in, and
|
|
512
|
+
deliberately not among the hooks `init` installs, which stay runner-agnostic.
|
|
513
|
+
Know what `Stop` means here: it fires at the end of every response, not once
|
|
514
|
+
when the session ends (the installed Stop hook releases leases on the same
|
|
515
|
+
cadence), so a checkpoint hook publishes a capsule per turn. Give it a short
|
|
516
|
+
`--ttl`; in a keyed room every board listing pays for the capsule until it
|
|
517
|
+
expires. And a parked receiver can loop:
|
|
518
|
+
|
|
519
|
+
```bash
|
|
520
|
+
export SWITCHBOARD_AGENT_ID=cloud-receiver
|
|
521
|
+
while true; do
|
|
522
|
+
switchboard session receive --wait 25 --resume --bg --from <sender-id>
|
|
523
|
+
done
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
`receive` prints `listening as <agent id>` so the sender knows whom to hand
|
|
527
|
+
off to. Pin `SWITCHBOARD_AGENT_ID` for that loop: an unpinned id is derived
|
|
528
|
+
per process, so each iteration would listen somewhere new and a pointer sent
|
|
529
|
+
to the last one is read by nobody. The exit code is what the loop branches
|
|
530
|
+
on — `0` when something was installed (or nothing was pending, without
|
|
531
|
+
`--wait`), `2` when `--wait` elapsed with nothing, and `1` when a pointer or
|
|
532
|
+
an id named a capsule that could not be installed: expired, claimed by
|
|
533
|
+
another receiver, unverified, or not what was announced. That last one is
|
|
534
|
+
the case to log.
|
|
535
|
+
|
|
386
536
|
## Tool reference
|
|
387
537
|
|
|
388
538
|
| Tool | Use it when |
|
|
@@ -401,6 +551,9 @@ is right for a repo's own agents and wrong for anything crossing repos.
|
|
|
401
551
|
| `board_set` / `board_get` / `board_list` | Hand off structured context |
|
|
402
552
|
| `keygen` | Starting a private side-conversation with specific peers — see below |
|
|
403
553
|
| `join_room` | Enter a room somebody sent an invite for — see below |
|
|
554
|
+
| `session_handoff` | Move this whole session to another agent, or with no `to` checkpoint it on the board for anyone holding the key — see section 7 |
|
|
555
|
+
| `session_import` | Collect a session handed to you (or one capsule by id) into this machine's Claude config dir; installs, never resumes |
|
|
556
|
+
| `session_resume` | Start `claude --bg --resume` for an installed session and get the `claude attach` line back. Local; never touches the hub |
|
|
404
557
|
|
|
405
558
|
### A room somebody sent you
|
|
406
559
|
|
|
@@ -134,6 +134,12 @@ which is how you do leader election without a lease.
|
|
|
134
134
|
Default TTL is 24 hours, the longest in the system, because a handoff has to
|
|
135
135
|
survive the gap between one session ending and the next starting.
|
|
136
136
|
|
|
137
|
+
A whole Claude Code session can travel the same way, as an opaque capsule
|
|
138
|
+
under `sessions/<session-id>` with a TTL of minutes rather than a day, since
|
|
139
|
+
a transcript is everything the session read; the receiver's tool collects and
|
|
140
|
+
deletes it rather than reading it as text — see
|
|
141
|
+
[claude-code.md](claude-code.md#7-hand-a-whole-session-to-another-environment).
|
|
142
|
+
|
|
137
143
|
## Putting it together
|
|
138
144
|
|
|
139
145
|
The intended shape of an agent's life on a hub:
|
|
@@ -19,7 +19,7 @@ switchboard serve --port 8787
|
|
|
19
19
|
You should see:
|
|
20
20
|
|
|
21
21
|
```
|
|
22
|
-
switchboard 2.
|
|
22
|
+
switchboard 2.2.0 → http://127.0.0.1:8787 db=switchboard.db
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
Leave it running.
|
|
@@ -47,7 +47,7 @@ export SWITCHBOARD_AGENT_ID=beta
|
|
|
47
47
|
|
|
48
48
|
```bash
|
|
49
49
|
$ switchboard health
|
|
50
|
-
{ "ok": true, "version": "2.
|
|
50
|
+
{ "ok": true, "version": "2.2.0", "auth": true }
|
|
51
51
|
|
|
52
52
|
$ switchboard register -c build
|
|
53
53
|
registered local-main-yourhost (local) in demo
|
|
@@ -3,6 +3,19 @@
|
|
|
3
3
|
What changes for you between releases that are not backwards compatible, in
|
|
4
4
|
the order you will hit them. Everything not listed here kept its behaviour.
|
|
5
5
|
|
|
6
|
+
## 2.1.0 → 2.2.0
|
|
7
|
+
|
|
8
|
+
Additive. A whole Claude Code session can be moved between environments
|
|
9
|
+
through the hub: `switchboard session handoff <agent>` publishes the
|
|
10
|
+
conversation as a capsule sealed to the room, and `switchboard session
|
|
11
|
+
receive` collects it and installs it for `claude --resume`. `export` and
|
|
12
|
+
`import` do the two halves against a file instead. The capsule is a
|
|
13
|
+
blackboard entry that expires on its own and is deleted the moment it is
|
|
14
|
+
collected; the hub never opens it. Nothing that worked in 2.1.0 changed.
|
|
15
|
+
|
|
16
|
+
The commands are new, so a peer running 2.1.0 or earlier cannot collect a
|
|
17
|
+
capsule you publish and will not recognise the pointer. Both ends need 2.2.0.
|
|
18
|
+
|
|
6
19
|
## 2.0.1 → 2.1.0
|
|
7
20
|
|
|
8
21
|
**The whisper envelope says `whisper` on the wire.** From 0.11.0 to 2.0.1 it
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Claude Code session capsule (prototype)
|
|
2
2
|
|
|
3
|
+
> **This experiment graduated.** What it established now lives in the
|
|
4
|
+
> package:
|
|
5
|
+
> [`switchboard.claude_session`](../../src/switchboard/claude_session.py)
|
|
6
|
+
> locates, packages, installs and resumes a session, and
|
|
7
|
+
> [`switchboard.handoff`](../../src/switchboard/handoff.py) carries the
|
|
8
|
+
> capsule through the hub as a board value with a signed pointer. Both are
|
|
9
|
+
> driven by the `switchboard session` commands and the `session_handoff` /
|
|
10
|
+
> `session_import` / `session_resume` MCP tools — see
|
|
11
|
+
> [docs/claude-code.md](../../docs/claude-code.md). This directory remains
|
|
12
|
+
> the experiment log: the observations below are the facts the code relies
|
|
13
|
+
> on, and the prototype is kept as it ran them.
|
|
14
|
+
|
|
3
15
|
Experiment log and disposable tooling for carrying a **native Claude Code
|
|
4
16
|
session** between environments and resuming it there by its original session
|
|
5
17
|
id. This is the "native handoff" mode (Claude Code -> Claude Code). It does
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "agent-switchboard"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.2.0"
|
|
4
4
|
description = "An ephemeral orchestration hub for AI coding agents: presence, leases, messaging and a shared blackboard, all with TTLs."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|