Metadata-Version: 2.4
Name: agtoagp
Version: 2.0.0
Summary: Zero-setup P2P Agent-to-Agent Protocol with vectorized intent matching and sub-50ms latency
Author-email: AgToAgP Contributors <core@agtoagp.dev>
License: Apache-2.0
Project-URL: Homepage, https://github.com/agtoagp/agtoagp-core
Project-URL: Documentation, https://github.com/agtoagp/agtoagp-core
Project-URL: Source, https://github.com/agtoagp/agtoagp-core
Project-URL: Issues, https://github.com/agtoagp/agtoagp-core/issues
Keywords: a2a,agent,p2p,zeroconf,decentralized,ai,vector
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: System :: Networking
Classifier: Topic :: Communications
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastapi>=0.110.0
Requires-Dist: uvicorn>=0.27.0
Requires-Dist: zeroconf>=0.130.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: cryptography>=41.0.0
Dynamic: license-file

# 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 agtoagp` and 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:key` identifier. 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

```bash
pip install agtoagp
```

With framework adapters:

```bash
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

```python
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

```python
# 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

```python
# 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

```python
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

```python
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

```python
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:

```python
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.

```python
# 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:

```python
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](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.**
