Demo: round-robin Rust, two lines per turn¶
Five coding-agent CLIs — claude-code, copilot, codex,
cursor-agent, goose — write a small Rust library. The moderator (avatar) owns
the file and starts the first hop. Each turn an agent may output at most two
lines of code; a third line is discarded by the orchestrator, even if the
model dumps a whole file. The same reply names the next peer (NEXT
<id> or DONE). That finishing agent is the A2A client for the handoff —
avatar does not pick the order.
The default problem is a Vec-backed LRU cache with many stubs. get and
put cannot finish in one two-line hop, so a live run typically needs
on the order of twenty turns (default cap: MAX_CYCLES × N = 40 hops
for five agents). Optional fifo is a shorter queue if you only want to
smoke-test the token path.
| Problem | Goal | Starting stub |
|---|---|---|
lru (default) |
Lru<K, V> — items[0] is LRU, last is MRU; scan the Vec only |
None / 0 / false / empty put |
fifo |
Fifo<T> with push / pop / len / is_empty |
no-op methods |
One command¶
From the repo root:
bash docs/content/demos/run-collab-demo.sh
In a second terminal:
bash docs/content/demos/watch-collab-demo.sh
Only one problem, or a shorter agent set:
PROBLEM=lru bash docs/content/demos/run-collab-demo.sh
PROBLEM=fifo MAX_CYCLES=6 bash docs/content/demos/run-collab-demo.sh
PROBLEM=both MAX_CYCLES=10 bash docs/content/demos/run-collab-demo.sh
COLLAB_AGENTS=goose,claude-code PROBLEM=lru MAX_CYCLES=12 bash docs/content/demos/run-collab-demo.sh
TRANSPORT=grpc PROBLEM=fifo bash docs/content/demos/run-collab-demo.sh
--net-allow includes cisco.com:443 and *.cisco.com:443; without
--watch-policy that opens port 443 to any host. Add more with
COLLAB_NET_ALLOW=host.example.com:443 (comma-separated).
The script starts a SLIM node (unless TRANSPORT=grpc), registers the adapters under
shadictl --net-block (DID-signed A2A, list --local leases), then
token-passes: avatar delegates the coding prompt → the finishing
listener A2A-dispatches NEXT to the chosen peer → apply-capped-edit →
cargo test → avatar follows that choice for the next coding hop.
TRANSPORT=grpc (or jsonrpc / http+json) skips the SLIM node and uses
register --a2a-listen --a2a-binding plus DID→locator lookup for the same
fifo/lru finishing condition. A no-CLI loopback run that reproduces that
fifo cargo test outcome is A2A unicast
(sample run).
Against a remote SLIM node¶
If SLIM_ENDPOINT names a host other than loopback, the script starts no
local node and generates no certificates. If the node checks a bearer token
on the connection, give the token file. For example, slimctl login writes
~/.slimctl/token:
SLIM_ENDPOINT=node.example.com:443 SLIM_AUTH_TOKEN_FILE=~/.slimctl/token \
COLLAB_AGENTS=goose,claude-code PROBLEM=fifo MAX_CYCLES=6 \
bash docs/content/demos/run-collab-demo.sh
With a token, no client certificate is sent, and the node's certificate is
checked against the system roots. To use a CA file instead, set
SLIM_TLS_CA; to also send a certificate, set SLIM_TLS_CERT and
SLIM_TLS_KEY. Run the cheap fifo smoke test above first, then drop
COLLAB_AGENTS and PROBLEM for the full five-agent LRU run. Each new
connection presents the token, so log in again before a run that could
outlast it. An expired token shows up as a link negotiation error right
after connecting.
The agent names (agntcy/shadi/<tool>-a2a) and the DID seed in
demo-env.sh are fixed and public. On a node shared with others, run one
demo at a time, and expect that anyone else who can connect can also reach
your listeners.
What this shows¶
- Token-passing collaboration — the same listeners as the
DID agent-group demo, plus goose.
avatarstarts hop 1; each agent chooses who codes next. A missing or invalidNEXTfalls back to the next name in the list.MAX_CYCLES(default 8) caps hops atMAX_CYCLES × N(N is the agent count). Narrow the set withCOLLAB_AGENTS=goose,claude-code. - Agents are A2A servers and clients — the coding prompt is an A2A
SendMessagefromavatartoagntcy/shadi/<tool>-a2a. After the CLI replies withNEXT <peer>, that sameregisterprocess sends the turn (lastREPLACE/NEXT, goal,src/lib.rs, lastcargo test) asHANDOFF from …(…/<tool>-a2a-client→…/<peer>-a2a). The receiver stores that packet and does not run the coding CLI on it.avatardoes not runhandoff. The client name is distinct so the listener does notSendMessageto itself. - Hard two-line cap —
collab-apply.pyacceptsREPLACE/INSERT/APPENDplus at most two Rust lines.NEXT/DONEare routing and are not written into the crate. - Host still owns the file — apply and
cargo teststay in the orchestrator. The prompt forbids replacing signatures or tests. The LRU crate asserts the impl does not useHashMap,BTreeMap,HashSet,BTreeSet,VecDeque, orLinkedList. - DID + sandbox — same admission and
register --slim-endpointrules as the other live demos (--writeon$SHADI_TMP_DIRso leases and the workspace can be written, plus~/.cursor,~/.codex,~/.claude, and the login keychain so Claude/Copilot/Codex/Cursor can refresh tokens and bind app-server sockets, plus Goose's existing config and state dirs). Goose keeps its own provider settings; this demo does not set a model or endpoint. HostGOOSE_PROVIDER/GOOSE_MODELare passed asgoose run --provider/--model. HostGOOSE_*,OPENAI_*,*_API_KEY, and Goose providerapi_key_envnames are forwarded.--net-allowincludescisco.com:443and*.cisco.com:443(plus anyCOLLAB_NET_ALLOWoverrides). A hop only produces Rust if that CLI already works on the host. Network or tool errors are not applied to the file.
Turn protocol¶
The prompt forbids markdown and explanation. A legal reply is:
REPLACE 22
self.cap
NEXT copilot
or
INSERT 48
self.items.push((key, value));
NEXT cursor-agent
or
APPEND
pub fn is_empty(&self) -> bool { self.items.is_empty() }
DONE
REPLACE n swaps the single line n for one or two lines (it does not
eat the neighbor). INSERT n splices before that line. APPEND adds at
the end. In every case the apply step keeps two code lines max.
NEXT / DONE are stripped before the file is written.
Prerequisites¶
Same as the DID demo: build shadictl and agentbridge, have the CLIs
on PATH and authenticated (claude OAuth, cursor-agent login /
CURSOR_API_KEY, Copilot/Codex already signed in, Goose already
configured). A failed delegate is
logged and that turn is skipped — no handoff is attempted, so a dead CLI
does not stall the cycle. The apply cap only runs on a successful reply.
After a run¶
The summary prints each turn's apply note and diff, the final src/lib.rs,
and the last cargo test. Logs live under /tmp/shadi-collab-demo.*/logs
(lru-turns.log, fifo-turns.log, per-turn .prompt / .reply / .apply).
A live 17-hop PROBLEM=lru transcript (and a shorter fifo run) is in
Sample run: round-robin Rust. Hop counts and
peer choices vary on every live run.
Next steps¶
- The identity and roll-call that precede this loop: Secure Agent Group Demo.
- Autonomous propose/vote (no two-line cap):
agentbridge coordinate. - Flags: CLI Reference, AgentBridge.
- Call the same CLI from inside a harness (no new Rust): the
agentbridge skill
(
list --local/delegate/handoff). See Use from a harness.