AgToAgP — Agent-to-Agent Protocol
AgToAgP is a zero-setup, framework-agnostic, peer-to-peer protocol that lets AI agents discover each other and exchange tasks over a local network — with zero API keys, zero cloud servers, and zero configuration.
Think of it as HTTP for the AI era — an open, un-ownable standard that keeps artificial intelligence decentralized, private, and peer-to-peer.
✨ Features
- Zero Setup —
pip install agtoagpand run. No config files, no cloud accounts, no API keys. - Automatic Discovery — Agents find each other via mDNS (multicast DNS). Plug in and they appear.
- Framework Agnostic — Native adapters for LangGraph, CrewAI, and AutoGen. Your framework, your tools.
- MCP Bridge — Translates Anthropic's Model Context Protocol (MCP) on the fly. No rewrites needed.
- Cryptographic Identity — Every node gets an Ed25519 key pair and a
did:keyidentifier. Requests are signed and verified. - Secure Sandbox — Peer-submitted code executes in an isolated subprocess with restricted filesystem access and timeouts.
- Auto-Healing — Background heartbeat pings peers and prunes offline nodes. Exponential-backoff retry for resilient calls.
- Strict JSON-RPC 2.0 — All messages are validated against Pydantic v2 schemas. Parse errors, invalid requests, and internal errors return standard JSON-RPC error codes.
📦 Install
pip install agtoagp
With framework adapters:
pip install agtoagp[langraph] # LangGraph support
pip install agtoagp[crewai] # CrewAI support
pip install agtoagp[autogen] # AutoGen support
pip install agtoagp[all] # Everything
🚀 Quickstart (3 Minutes)
1. Start a node
from agtoagp import A2ALibraryNode, run_a2a_node
async def my_runner(method, params):
return {"status": "completed", "result": f"Echo: {params}"}
node = A2ALibraryNode(
agent_id="did:a2a:my-node-001",
name="MyAgent",
port=8765,
runner_callback=my_runner,
)
run_a2a_node(node) # Blocks. Ctrl+C to stop.
2. Start a second node
# Same file, different port
node2 = A2ALibraryNode(
agent_id="did:a2a:my-node-002",
name="MyAgent2",
port=8766,
runner_callback=my_runner,
)
run_a2a_node(node2)
3. Watch them discover each other
Run both terminals. Each node automatically broadcasts itself via mDNS and discovers the other. You'll see logs like:
Peer discovered: did:a2a:my-node-002 -> http://192.168.1.34:8766
4. Call a peer
# From any node:
result = await node.call_peer("did:a2a:my-node-002", "ping", {"msg": "hello"})
print(result)
# {"jsonrpc": "2.0", "result": {"status": "completed", "result": "Echo: {'msg': 'hello'}"}, "id": null}
That's it. Zero cloud, zero config, zero API keys.
🔌 Framework Adapters
LangGraph
from agtoagp.adapters.langraph import langraph_adapter
# graph = CompiledGraph(...) # your LangGraph graph
node = langraph_adapter(graph, agent_id="did:a2a:lg", name="LangGraph-Node", port=9001)
run_a2a_node(node)
CrewAI
from agtoagp.adapters.crewai import crewai_adapter
# crew = Crew(...) # your CrewAI crew
node = crewai_adapter(crew, agent_id="did:a2a:crew", name="CrewAI-Node", port=9002)
run_a2a_node(node)
AutoGen
from agtoagp.adapters.autogen import autogen_adapter
# agent = ConversableAgent(...) # your AutoGen agent
node = autogen_adapter(agent, agent_id="did:a2a:ag", name="AutoGen-Node", port=9003)
run_a2a_node(node)
🔐 Cryptographic Identity
Every node can generate an Ed25519 key pair and derive a did:key identifier:
from agtoagp import CryptoIdentity
crypto = CryptoIdentity()
print(crypto.did) # did:key:z6MkrJRy5EoWh1VBszoCwmebpYmEn3JmmcBGFDtqnougVjB9
node = A2ALibraryNode(
agent_id=crypto.did,
name="SecureNode",
port=8765,
runner_callback=my_runner,
crypto=crypto,
enable_signing=True, # Signs all outgoing requests
)
Incoming requests with invalid signatures are rejected with HTTP 401.
🌉 MCP Bridge
AgToAgP automatically translates Anthropic's Model Context Protocol (MCP) requests on the fly. Send an MCP tools/call and get an MCP-formatted response back — no adapter code needed.
# Send an MCP request (e.g., via httpx)
mcp_request = {
"jsonrpc": "2.0",
"method": "tools/call",
"params": {"name": "audit", "arguments": {"target": "10.0.0.0/8"}},
"id": 1,
}
# Response comes back in MCP format:
# {"jsonrpc": "2.0", "result": {"content": [...], "isError": false}, "id": 1}
🏖️ Secure Sandbox
Execute untrusted peer code in isolation:
from agtoagp import SecureSandbox
sandbox = SecureSandbox()
result = await sandbox.run_code("""
async def main(params):
return {"sum": params["a"] + params["b"]}
""", params={"a": 40, "b": 2})
print(result) # {"sum": 42}
sandbox.cleanup()
The sandbox:
- Runs code in a subprocess with a dedicated temp directory
- Restricts filesystem access to that directory
- Removes dangerous builtins (
eval,exec,compile,__import__) - Enforces a 30-second timeout
📚 API Reference
| Class / Function | Description |
|---|---|
A2ALibraryNode(agent_id, name, port, runner_callback) |
Core A2A node with discovery, heartbeat, crypto, and MCP bridge |
run_a2a_node(node, host, log_level) |
Blocking runner that starts mDNS, discovery, and FastAPI |
node.call_peer(peer_name, method, params) |
Call a discovered peer with exponential-backoff retry |
node.discovered_agents |
Dict of currently discovered peers |
node.start_heartbeat() |
Begin background peer health monitoring |
CryptoIdentity() |
Ed25519 key pair + did:key derivation + request signing |
SecureSandbox(work_dir) |
Isolated execution environment for untrusted code |
MCPTranslator |
Static methods for MCP ↔ A2A translation |
langraph_adapter(graph, ...) |
Wrap a LangGraph graph as an A2A node |
crewai_adapter(crew, ...) |
Wrap a CrewAI crew as an A2A node |
autogen_adapter(agent, ...) |
Wrap an AutoGen agent as an A2A node |
📡 Protocol Spec
See spec/rfc-001-a2a-protocol.md for the full specification.
🤝 Contributing
Pull requests are welcome. See our issues page for roadmap items.
📄 License
Apache 2.0. AgToAgP is free, open, and un-ownable by design.
AgToAgP — The HTTP of the AI Era.
Metadata
Release files for agtoagp 7.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| agtoagp-7.0.0.tar.gz | 49.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| agtoagp-7.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 94.3 kB
Release files / agtoagp-7.0.0.tar.gz
| Download URL | agtoagp-7.0.0.tar.gz |
|---|---|
| Size | 49.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ae0d8c302db3c550f0b3c323531a400f194272df42bb2e34f4ebe47a03607451
|
|
BLAKE2b-256 checksum How to use checksums |
476e7c0fe75abeaa26ef27eaf26b3ffb398c03d2010cd490f4fe609ed36089d1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|
Release files / agtoagp-7.0.0-py3-none-any.whl
| Download URL | agtoagp-7.0.0-py3-none-any.whl |
|---|---|
| Size | 45.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b8b13638c27ade93a58d5e151607b01583576c04ddb221b009f9c9a21c9e8f9b
|
|
BLAKE2b-256 checksum How to use checksums |
fb068617800620b4bec46029d4d264135e51c8055d403f2d418df0673af48c14
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|