# AgentAnycast Python SDK

> Python SDK for AgentAnycast — the decentralized P2P runtime for the A2A (Agent-to-Agent) protocol. Async/await API, framework adapters (CrewAI, LangGraph, Google ADK, OpenAI Agents, Claude Agent SDK, AWS Strands), MCP Server + bridging, CLI.

## Install

```bash
pip install agentanycast               # Core SDK
pip install agentanycast[crewai]       # + CrewAI adapter
pip install agentanycast[langgraph]    # + LangGraph adapter
pip install agentanycast[adk]          # + Google ADK adapter
pip install agentanycast[openai-agents] # + OpenAI Agents adapter
pip install agentanycast[claude]       # + Claude Agent SDK adapter
pip install agentanycast[strands]      # + AWS Strands adapter
pip install agentanycast[mcp]          # + MCP Server
pip install agentanycast[adapters]     # All adapters
pip install -e ".[dev]"               # Development (pytest, ruff, mypy)
```

The Go daemon binary is auto-downloaded on first run. Override with `daemon_bin=` or `daemon_path=`.

## Node — Core API

```python
from agentanycast import Node, AgentCard, Skill

card = AgentCard(
    name="MyAgent",
    description="Helpful assistant",
    skills=[Skill(id="qa", description="Answer questions")],
)

async with Node(card=card, relay="/ip4/.../p2p/12D3KooW...") as node:
    print(f"PeerID: {node.peer_id}")
    print(f"DID: {node.did_key}")

    # Register task handler
    @node.on_task
    async def handle(task):
        text = task.messages[-1].parts[0].text
        await task.update_status("working")
        await task.complete(artifacts=[{"parts": [{"text": f"Answer: {text}"}]}])

    await node.serve_forever()
```

Node constructor parameters: `card`, `relay`, `key_path`, `daemon_addr`, `daemon_bin`, `daemon_path`, `home`.

## AgentCard and Skill

```python
from agentanycast import AgentCard, Skill

skill = Skill(
    id="translate",
    description="Translate text between languages",
    input_schema='{"type": "object", "properties": {"text": {"type": "string"}}}',
    output_schema='{"type": "object", "properties": {"result": {"type": "string"}}}',
)
card = AgentCard(name="Translator", version="1.0.0", skills=[skill])
```

## IncomingTask — Server-Side API

Methods available on the `task` object received in `@node.on_task`:
- `task.task_id` — unique task identifier
- `task.peer_id` — originator PeerID
- `task.messages` — list of Message objects
- `task.target_skill_id` — which skill was requested
- `task.sender_card` — AgentCard of the sender (if available)
- `await task.update_status("working")` — update status
- `await task.complete(artifacts=[...])` — mark completed with results
- `await task.fail("error message")` — mark failed
- `await task.request_input(message=...)` — request additional input

## Three send_task Modes

```python
msg = {"role": "user", "parts": [{"text": "Hello"}]}

# Direct — known peer
handle = await node.send_task(msg, peer_id="12D3KooW...")

# Anycast — skill-based routing via relay registry
handle = await node.send_task(msg, skill="translate")

# HTTP Bridge — standard HTTP A2A endpoint
handle = await node.send_task(msg, url="https://agent.example.com")
```

## TaskHandle — Client-Side API

```python
handle = await node.send_task(msg, skill="translate")
result = await handle.wait()             # Block until terminal status
print(handle.status)                     # TaskStatus enum
print(handle.artifacts[0].parts[0].text) # Access result text
await handle.cancel()                    # Cancel the task
```

## Discovery

```python
agents = await node.discover("translate", tags={"lang": "en"}, limit=10)
for agent in agents:
    print(agent["peer_id"], agent["agent_name"])
```

## Framework Adapters

### CrewAI

```python
from crewai import Crew
from agentanycast import AgentCard, Skill
from agentanycast.adapters.crewai import serve_crew

crew = Crew(agents=[...], tasks=[...])
card = AgentCard(name="Research Crew", skills=[Skill(id="research", description="Research any topic")])
await serve_crew(crew, card=card, relay="/ip4/.../p2p/12D3KooW...")
```

### LangGraph

```python
from langgraph.graph import StateGraph
from agentanycast.adapters.langgraph import serve_graph

compiled = StateGraph(...).compile()
card = AgentCard(name="QA Agent", skills=[Skill(id="qa", description="Answer questions")])
await serve_graph(compiled, card=card, relay="/ip4/.../p2p/12D3KooW...")
```

### Google ADK

```python
from google.adk.agents import Agent
from agentanycast.adapters.adk import serve_adk_agent

agent = Agent(name="helper", model="gemini-2.0-flash", instruction="You are a helpful assistant.")
card = AgentCard(name="Helper", skills=[Skill(id="help", description="General help")])
await serve_adk_agent(agent, card=card, relay="/ip4/.../p2p/12D3KooW...")
```

### OpenAI Agents

```python
from agents import Agent
from agentanycast.adapters.openai_agents import serve_openai_agent

agent = Agent(name="helper", instructions="You are a helpful assistant.", model="gpt-4o")
card = AgentCard(name="Helper", skills=[Skill(id="help", description="General help")])
await serve_openai_agent(agent, card=card, relay="/ip4/.../p2p/12D3KooW...")
```

### Claude Agent SDK

```python
from agentanycast import AgentCard, Skill
from agentanycast.adapters.claude_agent import serve_claude_agent

card = AgentCard(name="Code Reviewer", skills=[Skill(id="review", description="Review code")])
await serve_claude_agent(
    prompt_template="You are a code review assistant.",
    card=card,
    relay="/ip4/.../p2p/12D3KooW...",
)
```

### AWS Strands

```python
from strands import Agent
from agentanycast.adapters.strands import serve_strands_agent

agent = Agent(system_prompt="You are a helpful assistant.")
card = AgentCard(name="Helper", skills=[Skill(id="help", description="General help")])
await serve_strands_agent(agent, card=card, relay="/ip4/.../p2p/12D3KooW...")
```

## MCP Server

Start the built-in MCP server for AI tool integration (Claude Desktop, Cursor, VS Code, etc.):

```bash
agentanycast mcp                     # stdio mode (Claude Desktop, Cursor)
agentanycast mcp --transport http    # HTTP mode (ChatGPT, remote)
```

Claude Desktop configuration (`claude_desktop_config.json`):
```json
{"mcpServers": {"agentanycast": {"command": "agentanycast", "args": ["mcp"]}}}
```

Available MCP tools: `discover_agents`, `send_task`, `send_task_by_skill`, `get_task_status`, `get_agent_card`, `list_connected_peers`, `get_node_info`.

## MCP Bridging

```python
from agentanycast import MCPTool, mcp_tool_to_skill, skill_to_mcp_tool, mcp_tools_to_agent_card

# MCP Tool -> A2A Skill
tool = MCPTool(name="get_weather", description="Get weather", input_schema={"type": "object"})
skill = mcp_tool_to_skill(tool)

# A2A Skill -> MCP Tool
tool = skill_to_mcp_tool(skill)

# Wrap all MCP tools as a single AgentCard
card = mcp_tools_to_agent_card("WeatherServer", [tool1, tool2], description="Weather tools")
```

## DID Identity

```python
from agentanycast import peer_id_to_did_key, did_key_to_peer_id

did = peer_id_to_did_key("12D3KooW...")          # -> "did:key:z6Mk..."
peer_id = did_key_to_peer_id("did:key:z6Mk...")  # -> "12D3KooW..."
```

## CLI

```bash
agentanycast demo                    # Start echo agent
agentanycast discover <skill>        # Find agents by skill
agentanycast send <target> "msg"     # Send task (peer_id, skill, or URL)
agentanycast status                  # Daemon status
agentanycast info                    # Node info (PeerID, DID, addresses)
```

## Key Concepts

- **Sidecar daemon**: Go binary auto-downloaded on first run; SDK communicates via gRPC over Unix socket
- **AgentCard**: A2A-standard agent identity with name, skills, and P2P extensions (peer_id, did_key)
- **Offline queue**: Messages queued when peer is offline, delivered on reconnection
- **Streaming**: Chunked artifact delivery for large payloads via `send_artifact()`
- **Noise_XX**: All peer connections are end-to-end encrypted; no plaintext transport path

## Related Repositories

- [agentanycast](https://github.com/AgentAnycast/agentanycast) — Docs and issue tracker
- [agentanycast-ts](https://github.com/AgentAnycast/agentanycast-ts) — TypeScript SDK
- [agentanycast-node](https://github.com/AgentAnycast/agentanycast-node) — Go daemon
- [agentanycast-relay](https://github.com/AgentAnycast/agentanycast-relay) — Relay server
- [agentanycast-proto](https://github.com/AgentAnycast/agentanycast-proto) — Protobuf definitions
