agentanycast
v0.8.1
Published
TypeScript SDK for AgentAnycast — A2A protocol over P2P
Maintainers
Readme
AgentAnycast TypeScript SDK
TypeScript/JavaScript SDK for AgentAnycast -- decentralized A2A agent-to-agent communication over P2P.
AgentAnycast is fully decentralized. On a local network, it works with zero configuration. For cross-network communication, just deploy your own relay with a single command.
Installation
npm install agentanycastThe daemon binary is automatically downloaded on install. Skip with AGENTANYCAST_SKIP_DOWNLOAD=1 if building from source.
How It Works
┌─────────────┐ mDNS / Relay ┌─────────────┐
│ Agent A │◄──────────────────────────────►│ Agent B │
│ (Node.js) │ E2E encrypted (Noise) │ (Python) │
└──────┬──────┘ └──────┬──────┘
│ gRPC │ gRPC
┌──────┴──────┐ ┌──────┴──────┐
│ Daemon A │◄──────── libp2p ──────────────►│ Daemon B │
│ (Go) │ Noise_XX + Yamux + QUIC │ (Go) │
└─────────────┘ └─────────────┘TypeScript and Python agents interoperate seamlessly -- they share the same daemon and protocol.
Quick Start
Server Agent
import { Node, type AgentCard } from "agentanycast";
const card: AgentCard = {
name: "EchoAgent",
description: "Echoes back any message",
skills: [{ id: "echo", description: "Echo the input" }],
};
const node = new Node({ card });
await node.start();
console.log(`Peer ID: ${node.peerId}`);
node.onTask(async (task) => {
const text = task.messages.at(-1)?.parts[0]?.text ?? "";
await task.complete([{ parts: [{ text: `Echo: ${text}` }] }]);
});
await node.serveForever();Client Agent
const node = new Node({ card, home: "/tmp/agentanycast-client" });
await node.start();
const handle = await node.sendTask(
{ role: "user", parts: [{ text: "Hello!" }] },
{ peerId: "12D3KooW..." },
);
const result = await handle.wait(30_000);
console.log(result.artifacts[0].parts[0].text); // "Echo: Hello!"
await node.stop();Three Ways to Send a Task
await node.sendTask(message, { peerId: "12D3KooW..." }); // direct
await node.sendTask(message, { skill: "translate" }); // by skill
await node.sendTask(message, { url: "https://agent.example.com" }); // HTTP bridgeSkill Discovery
const agents = await node.discover("translate");
const frenchAgents = await node.discover("translate", { tags: { lang: "fr" } });Features
- End-to-end encrypted — All communication uses the Noise_XX protocol
- NAT traversal — Automatic hole-punching with relay fallback
- Anycast routing — Send tasks by skill, not by address
- HTTP Bridge — Reach standard HTTP A2A agents from P2P
- DHT discovery — Decentralized agent discovery via Kademlia DHT
- DID support — W3C
did:key,did:web, anddid:dnsidentity - MCP interop — Bidirectional MCP Tool ↔ A2A Skill mapping
- Sidecar architecture — Go daemon handles networking; SDK communicates via gRPC
API Reference
Node
| Method | Description |
|---|---|
| new Node(options) | Create a node with an AgentCard and optional config |
| start() | Launch daemon, connect gRPC, register card |
| stop() | Stop daemon and clean up |
| sendTask(message, target) | Send a task (by peerId, skill, or url) |
| getCard(peerId) | Fetch a remote agent's card |
| discover(skill, options?) | Find agents by skill with optional tag filtering |
| onTask(handler) | Register handler for incoming tasks |
| serveForever() | Block until stopped, processing incoming tasks |
AgentCard
interface AgentCard {
name: string;
description?: string;
version?: string;
protocolVersion?: string;
skills: Skill[];
// Read-only (populated by daemon):
peerId?: string;
supportedTransports?: string[];
relayAddresses?: string[];
didKey?: string; // W3C did:key
didWeb?: string; // did:web identifier
didDns?: string; // did:dns identifier
verifiableCredentials?: string[]; // JSON-encoded VCs
}Interoperability
import { peerIdToDIDKey, didKeyToPeerId } from "agentanycast";
import { didWebToUrl, urlToDidWeb } from "agentanycast";
import { mcpToolsToAgentCard, mcpToolToSkill, skillToMcpTool } from "agentanycast";Development
npm install # Install deps (AGENTANYCAST_SKIP_DOWNLOAD=1 to skip daemon)
npm run build # Compile TypeScript
npm test # Run tests (vitest)
npm run lint # Lint (eslint)Requirements
- Node.js 18+
- The agentanycastd daemon (auto-downloaded on install, or build from source)
