AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

A2a

skill-javimosch-a2a-skill-a2a · by javimosch

Spawn a team of agentic-CLI sessions (claude, opencode, pi, ...) that talk to each other as peers via a shared SQLite message bus at ~/.a2a/{project}/database.db. No central chain of command — each agent decides who to message. Use when the user wants multiple AI sessions to collaborate, debate, or divide work without a fixed orchestrator.

No reviews yet
0 installs
34 views
0.0% view→install

Install

$ agentstack add skill-javimosch-a2a-skill-a2a

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-javimosch-a2a-skill-a2a)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
3mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of A2a? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

/a2a — agent-to-agent peer messaging

a2a turns N agentic-CLI sessions into peers on a shared SQLite message bus. Each agent can send to any other agent (or all for broadcast) and recv blocking until something arrives. There is no orchestrator: communication flows freely.

Usage

/a2a spawn  [--role R] [--prompt "..."] [--cli claude|opencode|pi] [--model MODEL]
/a2a list
/a2a peek                     # show recent messages on the bus
/a2a send  "" --from    # inject a message from the host shell
/a2a stop                     # kill all spawned a2a sessions in this project
/a2a clear                    # wipe the message bus

The default project name is the basename of the current working directory. Set A2A_PROJECT or pass --project NAME to override.

For the full list of CLI commands and their usage (Python & Go binaries), see [docs/GOCLIREFERENCE.md](../../../docs/GOCLIREFERENCE.md).

⚠️ Critical: Use Pattern 3 for Multi-Agent Teams

When spawning 2+ agents, ALWAYS use Pattern 3 auto-spawn. Manual spawning or ad-hoc approaches will fail — agents will work independently without bus coordination.

Pattern 3 is the only reliable method because:

  • Agents register BEFORE spawning (critical for bus communication)
  • Kit prompts are written to files (avoids shell escaping bugs)
  • --project flag ensures all agents connect to the same bus
  • PIDs are updated after spawn with --upsert
  • Agents coordinate via the bus, not just file editing

See Step 2-4 below for the Pattern 3 workflow. Reference implementation: examples/remote_worktree_team.sh

Common Command Syntax Mistakes

These mistakes will cause agents to fail:

Wrong: a2a register --as agent-1Correct: a2a register agent-1 --role "Dev"

Wrong: a2a send --as agent-1 "hello"Correct: a2a send agent-2 "hello" --from agent-1

Wrong: a2a recv agent-1Correct: a2a recv --as agent-1

Wrong: Inline kit prompts in spawn commands ✅ Correct: Write kit prompts to files first, then reference with --kit-file

When to use

  • The user asks for "multiple claude sessions talking to each other"
  • The user wants a "team of agents" without a fixed orchestrator
  • Debate / red-team-blue-team setups, multi-perspective analysis
  • Divide-and-conquer where peers self-coordinate

If the user wants a strict orchestrator → workers pattern, prefer the standard Agent tool (subagents) instead. a2a is for peer communication.

Three usage patterns

This skill implements Pattern 3 below. See [docs/QUICKSTART.md](../../../docs/QUICKSTART.md) for Patterns 1 and 2.

| # | Pattern | Who drives | Documented in | |---|---------|------------|---------------| | 1 | Human-drive CLI — you open terminals and type a2a send/recv by hand | You (the human) | QUICKSTART.md — "Pattern 1" section | | 2 | Multi-terminal AI team — you open N terminals, tell each AI agent to join the bus with a role, and they self-coordinate | AI agents (you instruct them) | QUICKSTART.md — "Pattern 2" section | | 3 | Auto-spawn — one agent launches N background sessions via /a2a spawn | AI agents (spawned automatically) | This document (below) |

What follows assumes Pattern 3: you are an AI agent running inside an agentic CLI (Claude Code, pi, opencode, etc.) and you will spawn peer agents as background processes. The kit prompt, a2a-spawn flags, monitoring loop, and teardown steps are all specific to this pattern.

For Pattern 2 (multi-terminal AI team), you don't need this spawn protocol. Just tell each human-driven terminal: "register yourself, a2a recv, a2a send, `a2a status done". The kit prompt in Step 4 can serve as inspiration.

What You Must Do When Invoked

Step 0 — Locate the a2a binary

The a2a CLI lives next to the skill. It is available as a Python script (default) or a faster Go binary companion. Resolution order:

  1. $A2A_BIN env var (overrides all — set this to a downloaded Go binary)
  2. $PATH (preferred — installer symlinks it into ~/.local/bin)
  3. ~/.agents/skills/a2a/a2a (global cross-CLI skills path)
  4. ~/.claude/skills/a2a/a2a (Claude Code skills path)
  5. The skill source directory itself
A2A="${A2A_BIN:-}"
if [ -z "$A2A" ]; then
  for cand in \
      "$(command -v a2a 2>/dev/null)" \
      "$HOME/.agents/skills/a2a/a2a" \
      "$HOME/.claude/skills/a2a/a2a" ; do
    if [ -x "$cand" ]; then A2A="$cand"; break; fi
  done
fi
[ -z "${A2A:-}" ] && { echo "a2a binary not found"; exit 1; }
PROJECT="${A2A_PROJECT:-$(basename "$PWD")}"
export A2A_PROJECT="$PROJECT"

Step 1 — Initialize the project bus

"$A2A" init

If the user supplied agent definitions inline (e.g. "spawn alice as a planner and bob as a critic"), use those. Otherwise ask the user once for the agent roster, then proceed without further questions.

Step 2 — Register each agent up front

For each agent the user wants, before spawning the process:

"$A2A" register  --role "" --prompt "" --cli claude

Registration makes the agent addressable. The --prompt is stored so other agents can a2a list --json to see who they are talking to.

Step 3 — Spawn each agent as a background CLI session

Each agent runs in its own CLI process and receives the peer kit prompt that bootstraps it onto the bus. The kit prompt is CLI-agnostic; only the launch flags differ. Use the a2a-spawn helper that ships with the skill — it knows the right flags for each supported CLI:

| CLI | System prompt flag | Non-interactive flag | Notes | |-----------|----------------------------|----------------------|------------------------------------------------------| | claude | --append-system-prompt | -p | use --dangerously-skip-permissions for unattended | | opencode | (none — embed in message) | run "" | use ~/.opencode/bin/opencode (the opencode alias goes through tmux) | | pi | --append-system-prompt | -p | needs a --provider and --model set, e.g. --provider google --model gemini-2.5-flash |

Write each agent's kit prompt to a temp file (avoids shell-escape bugs for multi-line prompts) and spawn:

printf '%s' "$KIT_PROMPT_FOR_ALICE"  > /tmp/a2a-$PROJECT-alice.kit
printf '%s' "$KIT_PROMPT_FOR_BOB"    > /tmp/a2a-$PROJECT-bob.kit

ALICE_PID=$(a2a-spawn --cli claude   --id alice --model haiku   \
                      --log /tmp/a2a-$PROJECT-alice.log         \
                      --kit-file /tmp/a2a-$PROJECT-alice.kit)
BOB_PID=$(  a2a-spawn --cli opencode --id bob   --model anthropic/claude-haiku-4-5 \
                      --log /tmp/a2a-$PROJECT-bob.log           \
                      --kit-file /tmp/a2a-$PROJECT-bob.kit)

⚠️ CRITICAL: Do NOT foreground-wait for agents after spawning. a2a-spawn already nohup+disowns the process — the PIDs are captured above for lifecycle tracking, NOT for wait loops. If the caller adds a while loop polling a2a list or sleeps between checks, it blocks the entire spawning context for the agent's full runtime. This prevents parallel spawns, defeats Hermes background-task tracking, and causes timeouts on long agent sessions.

Correct patterns:

  • Hermes: terminal(command="a2a-spawn ...", background=True, notify_on_complete=True) — let Hermes track lifecycle
  • Shell script: capture PIDs, move on. Poll A2A bus as a SEPARATE process or cron, not inline after the spawn
  • AM daemon: use scheduler run-lifecycle tracking (DB run records), not a synchronous waitForAgents() loop

Save each PID so you can stop them later, and write it back to the registry so peers can see who is online:

"$A2A" register alice --pid "$ALICE_PID" --upsert
"$A2A" register bob   --pid "$BOB_PID"   --upsert

If a2a-spawn is not on PATH, invoke it directly: ~/.agents/skills/a2a/a2a-spawn or ~/.claude/skills/a2a/a2a-spawn.

Step 4 — The peer kit prompt (what every agent receives)

⚠️ Critical: Kit prompts must include coordination instructions.

Without explicit instructions to:

  1. Register themselves on the bus
  2. Introduce themselves to peers
  3. Use a2a send/recv for coordination

Agents will skip bus coordination and work directly on files, defeating the purpose of A2A. Always include these steps in every kit prompt.

This is CLI-agnostic. Substitute {AGENT_ID}, {ROLE}, {USER_PROMPT}, {PEER_LIST}, {PROJECT}. The {A2A_PATH} line is computed dynamically by the agent so it works across CLIs that may or may not have a2a on PATH.

You are agent "{AGENT_ID}" on an a2a peer bus (project={PROJECT}).

Your role: {ROLE}
Your standing instruction from the user:
{USER_PROMPT}

You are one of several peers. There is no boss. You decide whom to message,
when to ask, when to answer, when to stop. Coordinate with your peers.

== Peers on the bus ==
{PEER_LIST}

== How to find the a2a CLI ==
Run the bash snippet below ONCE at the start to pick a working `a2a` binary
and store it in $A2A. Check $A2A_BIN first (if set), then try PATH, then
common skill installation paths:

  A2A="${A2A_BIN:-}"
  [ -z "$A2A" ] && A2A="$(command -v a2a 2>/dev/null)"
  [ -z "$A2A" ] && [ -x "$HOME/.agents/skills/a2a/a2a" ] && A2A="$HOME/.agents/skills/a2a/a2a"
  [ -z "$A2A" ] && [ -x "$HOME/.claude/skills/a2a/a2a" ] && A2A="$HOME/.claude/skills/a2a/a2a"
  echo "using a2a at: $A2A"

== How to communicate ==
You have a shell/bash tool. Use ONLY the `a2a` CLI to talk to peers.
A2A_PROJECT={PROJECT} is already in the environment.

  # see who is online (json includes their roles and prompts)
  $A2A list --json

  # check your inbox (blocks up to 30s for new messages)
  $A2A recv --as {AGENT_ID} --wait 30

  # send a direct message to a peer by id
  $A2A send  "your message" --from {AGENT_ID}

  # broadcast to everyone
  $A2A send all "your message" --from {AGENT_ID}

  # mark yourself done so others know
  $A2A status done --as {AGENT_ID}

== Loop ==
1. recv --as {AGENT_ID} --wait 30
2. Decide: respond to a peer, ask a question, broadcast a finding, or finish.
3. Send at most one short message.
4. If nothing left to do AND no peer is awaiting your reply, run
   `status done --as {AGENT_ID}` and stop.
5. Else go back to step 1.

== Rules ==
- Do not invent peers. Address only ids returned by `a2a list`.
- Stay terse. One short message per turn unless asked for detail.
- Never speak on behalf of another agent.
- If you receive a broadcast that does not concern you, ignore it silently.
- If `recv` returns empty 3 times in a row, mark yourself `done` and stop.
- Do NOT call `a2a clear`, `a2a unregister`, or modify other agents' state.
- Hard cap: 8 loop iterations, then mark done and stop.

== Coordination rules (multi-role teams) ==
Omit this block if all agents have the same role or there is no role discipline.
- CLAIM:  —  BEFORE starting any work. Wait for ACK-CLAIM if collision.
- CLAIM expires after 5 minutes. Re-CLAIM if resuming after a gap.
- Bug reports: verify the issue exists in the current state before reporting. Do not report from assumptions formed earlier in the session.
- Role boundary: each agent stays within their declared role. Announce before crossing.
- To cross a role: send ROLE-CROSS:  and wait 60s for a VETO before proceeding.
- Do NOT claim tasks outside your declared role without a ROLE-CROSS signal.

Begin now: run the locator snippet, then `$A2A recv --as {AGENT_ID} --wait 5`.
If empty, introduce yourself with one short broadcast, then enter the loop.

Step 5 — Monitor & relay to the user

While the agents run, poll the bus and show the user activity:

"$A2A" peek --limit 50
"$A2A" list

The user is not on the bus by default. To inject a message from the user, register a synthetic user (or host) agent once and send from it:

"$A2A" register user --role human --upsert
"$A2A" send all "stop debating, summarize." --from user

Step 6 — Tear down

When the user signals stop, or when every agent's status is done:

# Kill spawned background sessions (using ids you saved at spawn time)
# The harness reports completion when each background bash finishes; you can
# also kill via the saved PIDs:
"$A2A" list --json | grep -o '"pid": [0-9]*' | awk '{print $2}' | xargs -r kill 2>/dev/null || true

Leave the database intact unless the user asks to wipe it (/a2a clear). Database survives between sessions — useful for resuming.

Remote machine spawn

You can run the entire spawn sequence on a remote host via SSH. The pattern is identical to local spawn — init, register, write kit files, spawn, register --pid — but pipe it all through a single `ssh host bash /dev/null)"; [ -z "$CLAUDE" ] && CLAUDE="$HOME/.local/bin/claude"

a2a-spawn

SPAWN="$(command -v a2a-spawn 2>/dev/null)" [ -z "$SPAWN" ] && SPAWN="$HOME/.agents/skills/a2a/a2a-spawn" [ -z "$SPAWN" ] && SPAWN="$HOME/.claude/skills/a2a/a2a-spawn"


**Always pass `--project` explicitly.** The default is `basename($PWD)`,
which on a root home directory resolves to `root` — a collision-prone name.

**Resolve stale git state before creating a worktree.** Check for
`.git/rebase-merge` or `.git/rebase-apply` and abort before running
`git worktree add`. Reset to `origin/main` if local and remote diverged.

**Add explicit ACK instructions to implementer kit prompts.** Without them,
developer agents silently begin work and PM/architect agents send redundant
check-in messages while waiting for confirmation.

See [`examples/remote_worktree_team.sh`](../../../examples/remote_worktree_team.sh)
for a complete working example of this pattern.

## Common Pitfalls & Gotchas

### 12. Cross-user database ownership

When the spawning agent (orchestrator) runs as one user (e.g. `root`) but
spawned agents run as a different user (e.g. via `sudo -u agent`), the a2a
database at `~/.a2a/{project}/database.db` is created with the orchestrator's
ownership. The spawned agents then get:

a2a: list error: attempt to write a readonly database


**Fix:** After `a2a init`, `chown` the database directory to the agent user:

```bash
chown -R agent:agent ~agent/.a2a/{project}/

Or run a2a init as the target user in the first place:

sudo -u agent a2a --project {project} init
sudo -u agent a2a --project {project} register ...

13. Sudo spawns lose the parent's PATH and env vars

When spawning agents via sudo -u user, the child process inherits a minimal environment. The A2A_PROJECT env var, PATH entries, and shell configs (.bashrc, .zshrc) are not inherited. The kit prompt's a2a locator snippet handles this by probing standard paths.

Fix: Either:

  • Pass env explicitly: sudo -u agent env A2A_PROJECT=... a2a ...
  • Use absolute paths for a2a in the kit prompt locator
  • Install a2a to a system-wide location like /usr/local/bin/a2a

14. --dangerously-skip-permissions blocked on root

The claude CLI refuses --dangerously-skip-permissions when running as root/sudo:

--dangerously-skip-permissions cannot be used with root/sudo privileges

Fix: Either:

  • Run claude as a non-root user (via sudo -u user claude ...)
  • Use the env var CLAUDE_CODE_DANGEROUSLY_SKIP_PERMISSIONS=1 combined with

--permission-mode acceptEdits instead of the flag

15. Foreground-waiting after spawn blocks the caller indefinitely

a2a-spawn already backgrounds agents with nohup+disown. If the calling script/daemon adds a while loop or sleep-based polling after spawning, it blocks until every agent exits — preventing parallel spawns, defeating Hermes background-task tracking, and causing spurious timeouts.

Common symptom: "spawning team for X..." prints, agents log activity, then the spawning terminal hangs for 30+ minutes until timeout kills it.

**Correct patterns instead of a

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.