Demo: form a SLIM group by discovering members in the Agent Directory¶
This walkthrough forms a SLIM group where the moderator doesn't start out knowing who's in it — it discovers members by capability (skill) or by an already-known DID via the AGNTCY Agent Directory (DIR), and can pull a newly-discovered agent into an already-running group later, without ever losing the option to add someone by hand.
This is a separate, additive demo from
Secure Agent Group Demo — that one still works exactly
as written; nothing here changes it. /slim create, /slim invite <name>,
and /slim join are untouched by any of this.
What this shows¶
- Real, connectable AgentCards in DIR —
agentbridge register --dir-publishpublishes a real A2AAgentCard(real skills, real SLIM endpoint) wrapped in DIR'sintegration/a2aOASF module, with the agent'sdid:keyas the record'sauthorsentry — not a disconnected placeholder record. - Discovery by skill —
agentbridge listandshadictl slim create-group --members skill:<skill>resolve real{name, did, slim_endpoint}triples from a Directory search, not raw CLI output. - Discovery by already-known DID —
--members did:<did>resolves an agent's current name/endpoint from Directory when the moderator already trusts a specific DID but not necessarily anything else about it. - The fully-manual technique, formalized —
--members explicit:<name>=<did>[@<endpoint>]names an agent directly, no Directory round-trip at all, as a peer to the two discovery techniques above. - A live audit trail for the trust set —
--write-configpersists the resolved DID trust superset as aslim_masGroupConfigTOML, soshadictl slim-mas list-members/validatecan inspect it later. - Dynamic growth —
/slim invite-from <spec>re-resolves a member source live, inside an already-running group session, and invites whichever matches are already in the group's trust set.
Prerequisites¶
# 1. Build the CLIs
cargo build -p agntcy-shadi-cli -p agntcy-agentbridge-cli
# 2. Generate mTLS material for the SLIM transport (one CA + client/server certs)
export DEMO=/tmp/shadi-dir-demo
bash tools/generate_slim_mtls_certs.sh "$DEMO/shadi-slim-mtls"
# 3. Install dirctl if you don't already have it
brew tap agntcy/dir https://github.com/agntcy/dir/ && brew install dirctl
Start a local Agent Directory node¶
dirctl daemon start runs a complete local DIR node in one process — API
server, reconciler, SQLite database, and a local content store — with no
Docker, Postgres, or external OCI registry required:
dirctl daemon start
dirctl daemon status # "Daemon is running"
macOS: port 5000 conflicts with AirPlay Receiver
The daemon's embedded content store defaults to localhost:5000 for its
OCI-compatible registry, which on macOS is claimed by AirPlay Receiver by
default — pushes fail with a 403 Forbidden that has nothing to do with
SHADI or DIR permissions. Either turn off AirPlay Receiver (System
Settings → General → AirDrop & Handoff), or point the daemon at a
different port with a custom config:
cp $(brew --prefix dirctl 2>/dev/null || echo .)/../share/dirctl/daemon.config.yaml \
~/.agntcy/dir/daemon.config.yaml 2>/dev/null || \
curl -s https://raw.githubusercontent.com/agntcy/dir/main/cli/cmd/daemon/daemon.config.yaml \
-o ~/.agntcy/dir/daemon.config.yaml
sed -i '' 's/registry_address: "localhost:5555"/registry_address: "localhost:5556"/' ~/.agntcy/dir/daemon.config.yaml
dirctl daemon start --config ~/.agntcy/dir/daemon.config.yaml
Stop it later with dirctl daemon stop.
1. Shared environment (every terminal)¶
source docs/content/demos/demo-env-dir.sh
Unlike demo-env.sh, this deliberately doesn't set
SLIM_MEMBER_DIDS for the moderator — that's the whole point: the
moderator's trust set gets built from Directory discovery, not a
hand-written list.
2. Start the SLIM node¶
Terminal M (moderator):
source docs/content/demos/demo-env-dir.sh
target/debug/shadictl slim start-node
started SLIM node on 127.0.0.1:47660
Leave this running for the rest of the demo.
3. Register two agents, publishing real AgentCards to DIR¶
Each agent terminal needs the moderator's DID in its own SLIM_MEMBER_DIDS
(to admit the moderator's future invite) — get it once with /slim whoami:
source docs/content/demos/demo-env-dir.sh
printf '/slim whoami\n/exit\n' | SHADI_AGENT_ID=avatar target/debug/shadictl shell | grep did:
# did: did:key:z6MkwE1Y6L4KLgaQMACssnKN9LSEGTJpgdJxATgvRJAgkF76
Terminal copilot and Terminal codex — register a real listener and
publish its AgentCard to the local DIR node. agentbridge register
--slim-endpoint refuses to start unless it's running under a SHADI sandbox with
network blocked by default — wrapping it in shadictl is enough to constrain
whatever CLI tool the adapter spawns to run a task, with no extra code:
source docs/content/demos/demo-env-dir.sh
export SLIM_MEMBER_DIDS="did:key:z6MkwE1Y6L4KLgaQMACssnKN9LSEGTJpgdJxATgvRJAgkF76"
SHADI_AGENT_ID=copilot target/debug/shadictl --net-block \
--net-allow "$SLIM_ENDPOINT" --net-allow "$SHADI_DIR_SERVER" \
--read "$SHADI_TMP_DIR" -- \
target/debug/agentbridge register --tool copilot \
--command "$(pwd)" --slim-endpoint "$SLIM_ENDPOINT" \
--dir-publish --dir-server "$SHADI_DIR_SERVER"
Registered Copilot adapter (agent id: copilot)
Starting SLIM A2A listener on 127.0.0.1:47660 as agntcy/shadi/copilot-a2a ...
Publishing AgentCard for 'copilot' to 127.0.0.1:8888...
Published. CID: baeareiccmurazht4fdrmlcl3optjab7qvybnejojjappzfgjhmgqx6dd5u
[agentbridge] ready — listening on agntcy/shadi/copilot-a2a
Repeat in Terminal codex with --tool codex. Both adapters advertise the
standard agentbridge skill set — agent_orchestration/task_decomposition,
agent_orchestration/agent_coordination, and
natural_language_processing/natural_language_generation/text_completion —
real OASF skill taxonomy classes, confirmed
against a live Directory's schema validator (arbitrary skill strings are
rejected by dirctl push).
4. Discover them with agentbridge list¶
Any terminal:
source docs/content/demos/demo-env-dir.sh
target/debug/agentbridge list --dir-server "$SHADI_DIR_SERVER"
Searching Agent Directory (127.0.0.1:8888) for agentbridge adapters...
codex did=did:key:z6MkjFJX8CHfgsZKWpS2FfQz38KyzHkf2mDo1vKJ9rMfSUvg slim://127.0.0.1:47660
copilot did=did:key:z6MkfGB4nkEoDvT6KgdPbobdXqnWh5K8jQSy3Ho5Ga6CdJFb slim://127.0.0.1:47660
Both entries are real, resolved from Directory records agentbridge list
pulled and parsed — not raw dirctl stdout.
5. Moderator: create a group by discovering its members¶
Terminal M:
target/debug/shadictl slim create-group \
--members "skill:agent_orchestration/agent_coordination" \
--dir-server "$SHADI_DIR_SERVER" \
--write-config /tmp/shadi-dir-demo/mas.toml \
agntcy/shadi/dir-room
Resolved 2 candidate member(s):
codex did=did:key:z6MkjFJX8CHfgsZKWpS2FfQz38KyzHkf2mDo1vKJ9rMfSUvg slim://127.0.0.1:47660
copilot did=did:key:z6MkfGB4nkEoDvT6KgdPbobdXqnWh5K8jQSy3Ho5Ga6CdJFb slim://127.0.0.1:47660
wrote group config to /tmp/shadi-dir-demo/mas.toml
shadi> /slim create agntcy/shadi/dir-room
created channel agntcy/shadi/dir-room as moderator agntcy/shadi/avatar (did:key:z6MkwE1Y6L4KLgaQMACssnKN9LSEGTJpgdJxATgvRJAgkF76)
create-group resolved both adapters' DIDs from the skill search, folded
them into SLIM_MEMBER_DIDS for this process, created the channel, and
handed off into the same interactive shell shadictl shell gives you —
/slim invite <name>, /slim status, /slim whoami, etc. all work here
exactly as in the other demo, because they're the same
commands, unmodified.
The written config is a real slim_mas GroupConfig:
[mas]
default_group = "agntcy/shadi/dir-room"
[groups."agntcy/shadi/dir-room"]
moderator_did = "did:key:z6MkwE1Y6L4KLgaQMACssnKN9LSEGTJpgdJxATgvRJAgkF76"
[[groups."agntcy/shadi/dir-room".members]]
did = "did:key:z6MkfGB4nkEoDvT6KgdPbobdXqnWh5K8jQSy3Ho5Ga6CdJFb"
[[groups."agntcy/shadi/dir-room".members]]
did = "did:key:z6MkjFJX8CHfgsZKWpS2FfQz38KyzHkf2mDo1vKJ9rMfSUvg"
Audit it independently at any time:
target/debug/shadictl slim-mas --config /tmp/shadi-dir-demo/mas.toml list-members
did:key:z6MkfGB4nkEoDvT6KgdPbobdXqnWh5K8jQSy3Ho5Ga6CdJFb
did:key:z6MkjFJX8CHfgsZKWpS2FfQz38KyzHkf2mDo1vKJ9rMfSUvg
6. Members join, moderator invites¶
Same choreography as the other demo steps 4–5 — each
discovered agent runs /slim join agntcy/shadi/dir-room --timeout 120 in its
own terminal (Terminal copilot, Terminal codex), then Terminal M
invites each by name:
/slim invite agntcy/shadi/copilot
/slim invite agntcy/shadi/codex
This is the exact invite_participant call manual /slim invite always
used — create-group only changed how the trust set that makes these DIDs
admittable in the first place got built.
7. Dynamic growth: discover and invite a new agent mid-session¶
This is the part that isn't possible with a static allow-list: register one more matching adapter after the group already exists, and pull it in without recreating anything.
Terminal claude-code (opened now, after step 5):
source docs/content/demos/demo-env-dir.sh
export SLIM_MEMBER_DIDS="did:key:z6MkwE1Y6L4KLgaQMACssnKN9LSEGTJpgdJxATgvRJAgkF76"
SHADI_AGENT_ID=claude-code target/debug/shadictl --net-block \
--net-allow "$SLIM_ENDPOINT" --net-allow "$SHADI_DIR_SERVER" \
--read "$SHADI_TMP_DIR" -- \
target/debug/agentbridge register --tool claude-code \
--command "$(pwd)" --slim-endpoint "$SLIM_ENDPOINT" \
--dir-publish --dir-server "$SHADI_DIR_SERVER"
Then join the already-running channel, same as step 6:
/slim join agntcy/shadi/dir-room --timeout 120
Back in Terminal M (still the same session from step 5 — this is the
important part, /slim invite-from operates on the live in-process trust
set create-group built):
/slim invite-from skill:agent_orchestration/agent_coordination
invite-from re-runs the skill search live. It finds claude-code — but
claude-code's DID was never in this session's trust set (it wasn't a
candidate when create-group first resolved members), so it's reported and
skipped rather than silently failing:
skipping claude-code (did:key:z6MkkYR1mqCHqEutWUM6bKoqPsPj2diDu8ykXk3cZMGxeQV9): not in this group's trust set — recreate the group with a broader --members set to include it
To actually admit a DID discovered after the group's App was created, that
App's JWKS would need to change live — SLIM has no mutation API for that
today (see Notes / limitations). The fix isn't to
retroactively trust it; it's to have included it in the trust superset up
front. did:<did> can't do that before the agent has published anything —
there's nothing yet for a Directory search to find — but explicit: can,
since it names a DID directly with no Directory round trip at all. If the
moderator already knows claude-code's DID is coming (e.g. from a prior run,
or communicated out of band), creating the group with one extra spec:
target/debug/shadictl slim create-group \
--members "skill:agent_orchestration/agent_coordination" \
--members "explicit:claude-code=did:key:z6MkkYR1mqCHqEutWUM6bKoqPsPj2diDu8ykXk3cZMGxeQV9" \
--dir-server "$SHADI_DIR_SERVER" \
agntcy/shadi/dir-room
puts that DID in the trust superset immediately, before claude-code even
exists in the Directory. Once it later registers, publishes, and joins, the
exact same live command from this section:
/slim invite-from did:did:key:z6MkkYR1mqCHqEutWUM6bKoqPsPj2diDu8ykXk3cZMGxeQV9
now resolves it from Directory (this time the record exists) and invites it successfully — no skip, no restart — because the DID was already trusted.
8. The other member-source techniques¶
--members/invite-from accept three interchangeable spec forms, freely
combinable in one --members list:
| Spec | Technique |
|---|---|
skill:<skill> |
Discover by capability — dirctl search --skill under the hood |
did:<did> |
Discover by an already-known DID — dirctl search --author |
explicit:<name>=<did>[@<endpoint>] |
Fully manual, no Directory round-trip |
target/debug/shadictl slim create-group \
--members "skill:agent_orchestration/agent_coordination" \
--members "did:did:key:z6MkkYR1mqCHqEutWUM6bKoqPsPj2diDu8ykXk3cZMGxeQV9" \
--members "explicit:trusted-bot=did:key:z6Mk...@10.0.0.5:47560" \
--dir-server "$SHADI_DIR_SERVER" \
agntcy/shadi/multi-source-room
Notes / limitations¶
/slim create,/slim invite <name>,/slim joinare unchanged. Every command in this demo that isn'tcreate-group/invite-fromis the exact, unmodified code path the other demo exercises.- Membership vs. admission. Inviting a discovered agent into a running
session (
Session::invite_and_wait) is fully dynamic — no restart needed. Admission — whose DID is cryptographically allowed to even connect — is fixed for the life of the moderator'sApp; SLIM builds that JWKS once, with no live mutation API.create-groupresolves a deliberately broad trust superset up front for exactly this reason;invite-fromoperates within it, not around it. - Real OASF skill names are required.
dirctl pushvalidates records against a live OASF schema server — invented skill strings are rejected. Browse valid classes at github.com/agntcy/oasf if you adapt this demo to different capabilities. /slim joinblocks (listening for the moderator's invite) until invited or its--timeoutelapses — give it a generous window, same as the other demo.- This demo hasn't been captured as a single scripted run (unlike
run-demo.shfor the other one) — the discovery/resolution steps (2–5, 7's registration+invite-fromskip path) were verified live against a real localdirctl daemon; the final join/invite handshake in step 6/7 follows the same manual, multi-terminal choreography the other demo documents and recommends generous timeouts for.
Next steps¶
- Read the design rationale in the plan this demo exercises, or see AgentBridge for the full CLI coding-agent interconnect.
- See Secure Agent Group Demo for the DID-identity and A2A-messaging half of this picture — unaffected by anything here.
- Look up exact
shadictl/agentbridgeflags in the CLI Reference.