
Security News
pnpm 12’s Rust Rewrite Cuts Install Times by Up to 90%
pnpm 12 rewrites the package manager in Rust, cutting install times by up to 90% while preserving pnpm 11 workflows and lockfiles.
a2acalling
Advanced tools
Agent-to-Agent calling with OpenClaw support. "I'll have my people call your people!"
Your AI agent can now call other AI agents — across instances, with scoped permissions, strategic summaries, and owner notifications. Think of it as a comms stream system for agents to communicate via text as effeciently as possible.
trace_id, error_code, and hintsa2a create --name "My Agent" --owner "Your Name" --permissions friends
# Output:
# 🤝 Your Name is inviting you to connect agents!
# Your agent can reach My Agent for: chat, web, files
# a2a://your-host.com/fed_abc123xyz
# Add them as a contact
a2a add "a2a://their-host.com/fed_xyz789" "Alice's Agent"
# Make a call
a2a call "Alice's Agent" "Hey! Want to collaborate on the a2a protocol?"
# Or call directly
a2a call "a2a://their-host.com/fed_xyz789" "Hello!"
A2A Callbook is also available as a native macOS app that wraps the dashboard in a proper macOS window with native integrations.
Features:
a2a:// URLs open in the app)Auto-installed on macOS when you run npm install -g a2acalling. The app is placed in ~/Applications/.
Manual install: Download the .dmg from GitHub Releases.
Build from source:
# Requires Rust: https://rustup.rs
cargo install tauri-cli --version "^2"
cd native/macos/src-tauri
cargo tauri build --target universal-apple-darwin
To open the app via CLI: a2a gui (prefers native app; use --browser to force browser).
# Global CLI
npm install -g a2acalling
# As a library
npm install a2acalling
# Stop pm2 server (name: a2a) and remove local config/DB (prompts unless --force)
a2a uninstall
# Keep config/DB for reinstall
a2a uninstall --keep-config --force
# Remove the global package
npm uninstall -g a2acalling
# Auto setup (detects OpenClaw gateway/runtime or configures standalone mode)
npx a2acalling setup
# Or clone and install
git clone https://github.com/onthegonow/a2a_calling.git
cd a2a_calling
npm install
node scripts/install-openclaw.js setup
Setup behavior:
/a2a and A2A API at /api/a2a/* (proxied to A2A backend)./dashboard.Before the first a2a call, the owner must complete onboarding (install location, permission tiers, and server ingress verification). Run:
/a2a quickstart
CLI equivalents:
# Local machine (local-only invites)
a2a quickstart --port 3001
# Server / public hostname (recommended: terminate at 443 via reverse proxy)
a2a quickstart --hostname YOUR_DOMAIN:443 --port 3001
| Tier | What They Can Access |
|---|---|
public | Conversation only |
friends | Most read-only tools (calendar/email/search) |
family | Full tool access (careful!) |
Customize tiers in ~/.config/openclaw/a2a-config.json:
{
"tiers": {
"friends": {
"topics": ["chat", "web", "files", "calendar"],
"allowed_tools": ["Bash(readonly)", "Read", "Grep", "Glob", "WebSearch", "WebFetch"],
"disclosure": "minimal"
}
}
}
# Add a contact
a2a add "a2a://host/token" "Alice"
# View contact details (shows trust level from YOUR token to them)
a2a show "Alice"
# Ping to check availability
a2a ping "Alice"
# Link a token you created FOR them
a2a link "Alice" tok_abc123
# List all contacts
a2a contacts
# Remove a contact
a2a rm "Alice"
Every call generates an owner-context summary that tracks the exchange:
{
"exchange": {
"weGot": ["learned about their developer tools project"],
"weGave": ["shared our A2A work"],
"balance": "even",
"fair": true
},
"mutualValue": {
"found": true,
"opportunities": ["potential integration partnership"],
"alignment": "connects to owner's interest in agent collaboration"
},
"trust": {
"assessment": "appropriate",
"recommendation": "maintain",
"pattern": "genuine partner, collaborative tone"
}
}
Summaries are private — never shared with the caller.
a2a create [options] # Create an invite token
--name, -n <name> # Token/contact name
--owner, -o <name> # Your name (for invite)
--tier, -t <tier> # public|friends|family
--topics <list> # Custom topic list
--expires, -e <duration> # 1h|1d|7d|30d|never (default: never)
--max-calls <n> # Limit total calls (default: unlimited)
--notify <level> # all|summary|none
a2a list # List your tokens
a2a revoke <id> # Revoke a token
a2a quickstart # Deterministic onboarding
a2a call <target> <message> # Call an agent
--timeout <seconds> # Response timeout (default: 60)
--context <text> # Add context for the call
a2a ping <target> # Check if agent is available
a2a server [options] # Start A2A server
--port, -p <port> # Port (default: 3001)
a2a setup # Auto setup via installer (gateway-aware dashboard)
Dashboard paths:
http://<host>:<port>/dashboardhttp://<gateway>/a2aIf the owner wants to manage A2A from a different machine (ex: their MacBook), you can pair a browser session using a one-time install link:
http://127.0.0.1:<port>/dashboard/Settings -> Remote CallbookCreate Install Link (24h) and copy the URLNotes:
Settings -> Remote Callbook.~/.config/openclaw/a2a-callbook.db (or $A2A_CONFIG_DIR/a2a-callbook.db).All runtime logs are persisted in SQLite and also emitted to stdout:
~/.config/openclaw/a2a-logs.db (or $A2A_CONFIG_DIR/a2a-logs.db)trace_id, conversation_id, token_id, error_code, status_code, hintDashboard/API log routes:
GET /api/a2a/dashboard/logsGET /api/a2a/dashboard/logs/trace/:traceIdGET /api/a2a/dashboard/logs/statsGET /api/a2a/dashboard/debug/call?trace_id=<id> (or conversation_id=<id>)Useful filters for /api/a2a/dashboard/logs:
trace_id, conversation_id, token_iderror_code, status_codecomponent, event, level, search, from, to, limitExample:
curl "http://localhost:3001/api/a2a/dashboard/logs?trace_id=trace_abc123&error_code=TOKEN_INVALID_OR_EXPIRED"
Every /api/a2a/invoke and /api/a2a/end response now returns:
trace_id (generated when caller does not send one)request_id (generated when caller does not send one)To inspect one call, use the dashboard debug endpoint:
curl -H "x-admin-token: $A2A_ADMIN_TOKEN" \
"http://localhost:3001/api/a2a/dashboard/debug/call?trace_id=<trace_id>"
For each call you get:
summary (event count, first/last seen, duration, and IDs involved)errors and error_codes for fast triagelogs (ordered timeline events from that trace)Tokens use the a2a:// URI scheme:
a2a://<hostname>[:port]/<token>
| Method | Path | Description |
|---|---|---|
GET | /api/a2a/status | Check A2A support |
GET | /api/a2a/ping | Health check with auth |
POST | /api/a2a/invoke | Call the agent |
POST | /api/a2a/end | End a conversation and return summary data |
{
"message": "Hello!",
"caller": { "name": "Agent Name", "owner": "Owner Name" },
"conversation_id": "optional-for-continuation",
"timeout_seconds": 60
}
{
"success": true,
"conversation_id": "conv_123",
"response": "Agent's response",
"can_continue": true,
"tokens_remaining": null
}
{
"conversation_id": "conv_123"
}
{
"success": true,
"conversation_id": "conv_123",
"status": "concluded",
"summary": "Optional call summary"
}
const { A2AClient } = require('a2acalling');
const client = new A2AClient({
caller: { name: 'My Agent', owner: 'My Name' }
});
// Call via invite URL
const response = await client.call(
'a2a://their-host.com/fed_token123',
'Can you help me with something?'
);
// Continue the conversation
const followUp = await client.call(
'a2a://their-host.com/fed_token123',
'Thanks! One more question...',
{ conversationId: response.conversation_id }
);
// Explicitly end the call when done
const ended = await client.end(
'a2a://their-host.com/fed_token123',
response.conversation_id
);
const { createRoutes, TokenStore } = require('a2acalling');
const express = require('express');
const app = express();
app.use(express.json());
app.use('/api/a2a', createRoutes({
tokenStore: new TokenStore(),
async handleMessage(message, context) {
// context.permissions, context.caller, context.conversationId
return {
text: await yourAgent.respond(message, context),
canContinue: true
};
},
async notifyOwner({ caller, message }) {
await notify(`🤝 ${caller.name} called your agent`);
}
}));
app.listen(3001);
a2a revoke| Variable | Description |
|---|---|
A2A_HOSTNAME | Hostname for invite URLs (required for internet-facing invites) |
A2A_PORT | Server port (default: 3001) |
A2A_CONFIG_DIR | Config directory (default: ~/.config/openclaw) |
A2A_WORKSPACE | Workspace root for context files like USER.md (default: current directory) |
A2A_RUNTIME | Runtime mode: auto (default), openclaw, or claude |
A2A_AGENT_NAME | Override local agent display name |
A2A_OWNER_NAME | Override owner display name |
A2A_COLLAB_MODE | Conversation style: adaptive (default) or deep_dive |
A2A_ADMIN_TOKEN | Protect dashboard/conversation admin routes for non-local access |
A2A_LOG_LEVEL | Minimum persisted/stdout log level: trace, debug, info, warn, error (default: info) |
A2A_LOG_STACKS | Include stack traces in log DB error payloads (true by default outside production) |
A2A is cooperative AND adversarial. Each agent maximizes value for their owner — but the best outcomes are mutual wins.
Your agent should:
MIT — go build something cool.
I'll have my people call your people. 🤝
FAQs
Agent-to-agent calling for OpenClaw - A2A agent communication
The npm package a2acalling receives a total of 563 weekly downloads. As such, a2acalling popularity was classified as not popular.
We found that a2acalling demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
pnpm 12 rewrites the package manager in Rust, cutting install times by up to 90% while preserving pnpm 11 workflows and lockfiles.

Security News
Socket CTO Ahmad Nassri joins AppSec leaders at Black Hat to discuss active malware, package manager risks, and software supply chain defense.

Research
/Security News
Thirteen malicious Packagist themes expose visitors on unpatched iPhones to a WebKit-to-kernel exploit chain that steals device data and wallet seeds.