Shikanime Org Agent Swarm
Distribute one task across a cluster of agents over the Hermes A2A protocol
(https://hermes-agent.nousresearch.com/docs/user-guide/messaging/a2a). Route
each unit by the capability it needs, the machine it should run on, and the live
resource pressure on the runner — then optionally run the whole swarm inside a
disposable sks-adversarial sandbox so a misroute costs nothing.
This skill is a router, not a transport. It decides what goes where; A2A and
delegate_task do the delivery. It does NOT replace them.
When to Use
- One task fragments into units that need different capabilities (model, tool,
permission) or different machines (GPU vs CPU, isolated vs shared).
- The runner is under resource pressure and units must be spread, not stacked.
- A fan-out result is uncertain → wrap the swarm in
sks-adversarial first.
When NOT to Use
- A few sibling PRs in one repo →
sks-async (jj workspaces, no cluster).
- One unit, one machine →
sks-stack; do not spin up a swarm.
- Root cause only →
sks-investigate; this skill executes, not analyzes.
Procedure
Enable A2A on every host that will run a unit. In config.yaml:
gateway.platforms.a2a.enabled: true and a port via extra.port; list peers
under a2a_agents. Then hermes tools enable a2a on each host. Inbound
serves the Agent Card at GET /.well-known/agent-card.json and JSON-RPC 2.0
at POST / (SendMessage, SendStreamingMessage over SSE, GetTask,
ListTasks, CancelTask, SubscribeToTask, plus push-notification config
CRUD). Tasks inject into the live gateway session (same agent/memory/ tools),
keyed by contextId for multi-turn.
Enumerate units with their requirements — capability tag (model/tool/
permission), target machine, and a rough resource weight (cpu/mem/io). Record
the list in the linked issue before dispatching.
Probe runner pressure before assigning. Read live load on candidate
machines; a unit whose weight exceeds a host's headroom must move or wait.
Never co-locate two heavy units on a pressured runner. Re-probe before each
(re)dispatch, not once at the start — pressure re-checks are cheap, a
misroute onto a loaded runner is not.
Route each unit by capability match → resource fit → least-loaded
eligible host. The target host must be A2A-callable (verify its card with
a2a_discover(url)). Override the default host only with an explicit reason
(# ponytail: manual placement — <reason>).
Dispatch over A2A. Fan one task to every peer advertising a capability
with a2a_orchestrate(capability, message, mode?) — modes all (every
reply), first (first success), best (longest successful reply; an
all-error fan-out reports the failures instead of picking one). For a single
targeted unit use a2a_call(agent, message, context_id?) (multi-turn via
context_id); a2a_history(context_id, limit?) recalls a prior exchange.
Parent re-verifies every child's gate via terminal before trusting the
aggregate — child reports are not proof. If sandboxed, pass the unit its
promote/discard contract from sks-adversarial.
Reconcile. Collect results, surface a blocked child as a BLOCKED:
report with evidence, and merge only units that passed. Reclaim idle agents /
workspaces with sks-gc.
Pitfalls
- Routing purely by capability and ignoring live pressure stacks heavy units on
a hot runner — measure headroom, then place.
- Treating a child's "done" self-report as verified — re-run its gate in the
parent before promoting.
- Spinning a swarm for one unit —
sks-stack is the smaller, correct tool.
- A sandboxed swarm that merges un-reviewed skips the
sks-adversarial promote
gate; the sandbox is a trial, not an approved change.
- Unauthenticated A2A binds
127.0.0.1 only. Remote needs a bearer token and
A2A_HOST. A2A_PEER_TOKENS="name:token,…" sets per-peer identity. Inbound
text is injection-filtered and cannot reach operator slash commands;
credential-shaped replies are redacted; every exchange logs to
~/.hermes/a2a_audit.jsonl. Per-context turn cap (A2A_MAX_PINGPONG_TURNS,
default 5) stops agent↔agent ping-pong. Stdlib only — no a2a-sdk.
Verification
# after dispatch: every unit has a host + capability tag recorded
# pressure: re-probe candidate hosts before each (re)dispatch
# reconcile: gh issue view <N> --repo <org>/<repo> # units + gates listed
# sks-gc reclaims idle agents/workspaces once reconciled
# host reachable: a2a_discover(url) returns a parsed Agent Card
curl --fail --silent --show-error http://<host>:9900/.well-known/agent-card.json
Use a2a_discover to validate the Agent Card; curl is a quick replacement when
A2A tooling is unavailable.
A2A API (Hermes Agent-to-Agent, v1.0)
Swarm delivery rides the Hermes a2a toolset / inbound JSON-RPC server. Enable
in config.yaml (gateway.platforms.a2a.enabled: true, inbound port via
extra.port; peers under a2a_agents), then hermes tools enable a2a.
Outbound tools (call other agents):
a2a_discover(url) — fetch + summarize a peer's Agent Card.
a2a_call(agent, message, context_id?) — send one task, get the reply;
multi-turn via context_id.
a2a_list() — configured peers, saved conversations, metrics.
a2a_history(context_id, limit?) — recall a persisted A2A conversation.
a2a_orchestrate(capability, message, mode?) — fan one task to every peer
advertising a capability. Modes: all (every reply), first (first success),
best (longest successful reply; all-error fan-out reports the failures
instead of picking one).
Inbound (be callable): serves the v1.0 Agent Card at
GET /.well-known/agent-card.json and JSON-RPC 2.0 at POST / — canonical
methods SendMessage, SendStreamingMessage (SSE), GetTask, ListTasks,
CancelTask, SubscribeToTask, plus push-notification config CRUD. Tasks
inject into the live gateway session (same agent/memory/tools), keyed by
contextId for multi-turn.
Security: no token ⇒ bind 127.0.0.1 only (remote needs a bearer token
and A2A_HOST); A2A_PEER_TOKENS="name:token,…" gives per-peer identity;
inbound text is injection-filtered and cannot reach operator slash commands;
credential-shaped replies are redacted; every exchange logs to
~/.hermes/a2a_audit.jsonl; per-context turn cap (A2A_MAX_PINGPONG_TURNS,
default 5) stops agent↔agent ping-pong. Stdlib only — no a2a-sdk.
Quick test (from another agent/machine):
curl http://your-host:9900/.well-known/agent-card.json
curl -X POST http://your-host:9900/ -H 'Content-Type: application/json' \
-H 'Authorization: Bearer <token>' \
-d '{"jsonrpc":"2.0","id":1,"method":"SendMessage",
"params":{"message":{"messageId":"m1","role":"ROLE_USER",
"parts":[{"text":"What tools do you have?"}]}}}'
See also
sks-adversarial — wrap an uncertain swarm in a disposable sandbox.
sks-async — in-repo parallel streams when no agent cluster is needed.
sks-investigate — root-cause discipline before executing a swarm.
sks-gc — reclaim idle agents / workspaces after reconcile.
1---2name: sks-swarm3description: Use when distributing a task across a cluster of agents over A2A — route by capability need, machine resource, and runner pressure, optionally in a disposable sks-adversarial sandbox.4license: Apache-2.05---67# Shikanime Org Agent Swarm89Distribute one task across a cluster of agents over the Hermes A2A protocol10(<https://hermes-agent.nousresearch.com/docs/user-guide/messaging/a2a>). Route11each unit by the capability it needs, the machine it should run on, and the live12resource pressure on the runner — then optionally run the whole swarm inside a13disposable `sks-adversarial` sandbox so a misroute costs nothing.1415This skill is a router, not a transport. It decides _what goes where_; A2A and16`delegate_task` do the delivery. It does NOT replace them.1718## When to Use1920- One task fragments into units that need different capabilities (model, tool,21 permission) or different machines (GPU vs CPU, isolated vs shared).22- The runner is under resource pressure and units must be spread, not stacked.23- A fan-out result is uncertain → wrap the swarm in `sks-adversarial` first.2425## When NOT to Use2627- A few sibling PRs in one repo → `sks-async` (jj workspaces, no cluster).28- One unit, one machine → `sks-stack`; do not spin up a swarm.29- Root cause only → `sks-investigate`; this skill executes, not analyzes.3031## Procedure32331. **Enable A2A on every host that will run a unit.** In `config.yaml`:34 `gateway.platforms.a2a.enabled: true` and a port via `extra.port`; list peers35 under `a2a_agents`. Then `hermes tools enable a2a` on each host. Inbound36 serves the Agent Card at `GET /.well-known/agent-card.json` and JSON-RPC 2.037 at `POST /` (`SendMessage`, `SendStreamingMessage` over SSE, `GetTask`,38 `ListTasks`, `CancelTask`, `SubscribeToTask`, plus push-notification config39 CRUD). Tasks inject into the live gateway session (same agent/memory/ tools),40 keyed by `contextId` for multi-turn.41422. **Enumerate units** with their requirements — capability tag (model/tool/43 permission), target machine, and a rough resource weight (cpu/mem/io). Record44 the list in the linked issue before dispatching.45463. **Probe runner pressure** before assigning. Read live load on candidate47 machines; a unit whose weight exceeds a host's headroom must move or wait.48 Never co-locate two heavy units on a pressured runner. Re-probe before each49 (re)dispatch, not once at the start — pressure re-checks are cheap, a50 misroute onto a loaded runner is not.51524. **Route each unit** by capability match → resource fit → least-loaded53 eligible host. The target host must be A2A-callable (verify its card with54 `a2a_discover(url)`). Override the default host only with an explicit reason55 (`# ponytail: manual placement — <reason>`).56575. **Dispatch over A2A.** Fan one task to every peer advertising a capability58 with `a2a_orchestrate(capability, message, mode?)` — modes `all` (every59 reply), `first` (first success), `best` (longest successful reply; an60 all-error fan-out reports the failures instead of picking one). For a single61 targeted unit use `a2a_call(agent, message, context_id?)` (multi-turn via62 `context_id`); `a2a_history(context_id, limit?)` recalls a prior exchange.63 Parent re-verifies every child's gate via `terminal` before trusting the64 aggregate — child reports are not proof. If sandboxed, pass the unit its65 promote/discard contract from `sks-adversarial`.66676. **Reconcile.** Collect results, surface a blocked child as a `BLOCKED:`68 report with evidence, and merge only units that passed. Reclaim idle agents /69 workspaces with `sks-gc`.7071## Pitfalls7273- Routing purely by capability and ignoring live pressure stacks heavy units on74 a hot runner — measure headroom, then place.75- Treating a child's "done" self-report as verified — re-run its gate in the76 parent before promoting.77- Spinning a swarm for one unit — `sks-stack` is the smaller, correct tool.78- A sandboxed swarm that merges un-reviewed skips the `sks-adversarial` promote79 gate; the sandbox is a trial, not an approved change.80- Unauthenticated A2A binds `127.0.0.1` only. Remote needs a bearer token _and_81 `A2A_HOST`. `A2A_PEER_TOKENS="name:token,…"` sets per-peer identity. Inbound82 text is injection-filtered and cannot reach operator slash commands;83 credential-shaped replies are redacted; every exchange logs to84 `~/.hermes/a2a_audit.jsonl`. Per-context turn cap (`A2A_MAX_PINGPONG_TURNS`,85 default 5) stops agent↔agent ping-pong. Stdlib only — no `a2a-sdk`.8687## Verification8889```bash90# after dispatch: every unit has a host + capability tag recorded91# pressure: re-probe candidate hosts before each (re)dispatch92# reconcile: gh issue view <N> --repo <org>/<repo> # units + gates listed93# sks-gc reclaims idle agents/workspaces once reconciled94# host reachable: a2a_discover(url) returns a parsed Agent Card95curl --fail --silent --show-error http://<host>:9900/.well-known/agent-card.json96```9798Use `a2a_discover` to validate the Agent Card; curl is a quick replacement when99A2A tooling is unavailable.100101## A2A API (Hermes Agent-to-Agent, v1.0)102103Swarm delivery rides the Hermes `a2a` toolset / inbound JSON-RPC server. Enable104in `config.yaml` (`gateway.platforms.a2a.enabled: true`, inbound port via105`extra.port`; peers under `a2a_agents`), then `hermes tools enable a2a`.106107**Outbound tools (call other agents):**108109- `a2a_discover(url)` — fetch + summarize a peer's Agent Card.110- `a2a_call(agent, message, context_id?)` — send one task, get the reply;111 multi-turn via `context_id`.112- `a2a_list()` — configured peers, saved conversations, metrics.113- `a2a_history(context_id, limit?)` — recall a persisted A2A conversation.114- `a2a_orchestrate(capability, message, mode?)` — fan one task to every peer115 advertising a capability. Modes: `all` (every reply), `first` (first success),116 `best` (longest successful reply; all-error fan-out reports the failures117 instead of picking one).118119**Inbound (be callable):** serves the v1.0 Agent Card at120`GET /.well-known/agent-card.json` and JSON-RPC 2.0 at `POST /` — canonical121methods `SendMessage`, `SendStreamingMessage` (SSE), `GetTask`, `ListTasks`,122`CancelTask`, `SubscribeToTask`, plus push-notification config CRUD. Tasks123inject into the live gateway session (same agent/memory/tools), keyed by124`contextId` for multi-turn.125126**Security:** no token ⇒ bind `127.0.0.1` only (remote needs a bearer token127_and_ `A2A_HOST`); `A2A_PEER_TOKENS="name:token,…"` gives per-peer identity;128inbound text is injection-filtered and cannot reach operator slash commands;129credential-shaped replies are redacted; every exchange logs to130`~/.hermes/a2a_audit.jsonl`; per-context turn cap (`A2A_MAX_PINGPONG_TURNS`,131default 5) stops agent↔agent ping-pong. Stdlib only — no `a2a-sdk`.132133**Quick test (from another agent/machine):**134135```bash136curl http://your-host:9900/.well-known/agent-card.json137curl -X POST http://your-host:9900/ -H 'Content-Type: application/json' \138 -H 'Authorization: Bearer <token>' \139 -d '{"jsonrpc":"2.0","id":1,"method":"SendMessage",140 "params":{"message":{"messageId":"m1","role":"ROLE_USER",141 "parts":[{"text":"What tools do you have?"}]}}}'142```143144## See also145146- `sks-adversarial` — wrap an uncertain swarm in a disposable sandbox.147- `sks-async` — in-repo parallel streams when no agent cluster is needed.148- `sks-investigate` — root-cause discipline before executing a swarm.149- `sks-gc` — reclaim idle agents / workspaces after reconcile.