# CoWorker Protocol

> MCP connects agents to tools. A2A connects agents in enterprises. **CoWorker connects agents across the open internet.**

<p align="center">
  <a href="https://pypi.org/project/coworker-protocol/"><img src="https://img.shields.io/pypi/v/coworker-protocol?style=flat-square" alt="PyPI"></a>
  <a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.10%2B-blue?style=flat-square" alt="Python 3.10+"></a>
  <img src="https://img.shields.io/badge/tests-509%20passing-brightgreen?style=flat-square" alt="Tests">
  <img src="https://img.shields.io/badge/dependencies-zero-black?style=flat-square" alt="Zero deps">
  <a href="./LICENSE"><img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="MIT"></a>
</p>

<p align="center">
  <img src="https://raw.githubusercontent.com/anthropic-ai/coworker-protocol/main/docs/assets/coworker-demo.gif" alt="CoWorker cross-network demo" width="800" />
  <br />
  <sub>Beijing agent discovers and calls a San Francisco agent's skill over XMTP — E2E encrypted, no IP needed.</sub>
</p>

---

## Install

```bash
pip install coworker-protocol
```

Requires Python 3.10+ and Node.js 18+ (for the XMTP bridge).

## Quickstart

**1. Create an agent with a skill:**

```python
from coworker import Agent

agent = Agent("my-bot")

@agent.skill("summarize", description="Summarize text",
             input_schema={"text": "str", "max_words": "int"},
             output_schema={"summary": "str", "word_count": "int"})
def summarize(text: str, max_words: int = 50) -> dict:
    return {"summary": text[:100], "word_count": len(text.split())}

agent.serve()  # XMTP listener + monitor dashboard on :8090
```

**2. Call it from another agent — anywhere on the internet:**

```python
agent2 = Agent("caller")

# Discover peer skills via XMTP (no IP, no DNS, just a wallet)
peer = agent2.connect("0xB0B_WALLET_ADDRESS")
print(peer["skills"])  # ["summarize"]

# Call a remote skill — encrypted end-to-end
result = agent2.call("0xB0B_WALLET_ADDRESS", "summarize", {"text": "Hello from Beijing!"})

# Or collaborate on a complex task
agent2.collaborate("0xB0B_WALLET_ADDRESS", "Research AI agents and write a report")
```

That's it. Two agents, different machines, different networks, encrypted collaboration.

## Why CoWorker?

| | CoWorker | MCP | A2A | CrewAI / AutoGen |
|---|---|---|---|---|
| **Connects** | Agent ↔ Agent | Agent ↔ Tool | Agent ↔ Agent | Agent ↔ Agent |
| **Network** | Open internet | Local / client-server | Enterprise HTTP | Single process |
| **Identity** | Wallet address | N/A | Service cards | In-memory |
| **Encryption** | E2E (XMTP MLS) | Transport-dependent | Enterprise TLS | None |
| **NAT traversal** | Yes (XMTP relay) | No | Infra-dependent | No |
| **Central broker** | None | MCP server | Discovery service | Runtime host |
| **Dependencies** | Zero (stdlib) | Varies | HTTP stack | Heavy |

**In one line:** CoWorker is the missing protocol for agents that don't share a process, a network, or an owner.

## How It Works

```mermaid
flowchart LR
    subgraph "Network A (e.g. Beijing)"
        A["Python Agent<br/><code>agent.serve()</code>"] <-->|HTTP localhost| B["XMTP Bridge<br/>(Node.js)"]
    end

    B <-->|"Wallet-to-wallet<br/>E2E encrypted"| D["XMTP Network"]

    subgraph "Network B (e.g. San Francisco)"
        E["XMTP Bridge<br/>(Node.js)"] <-->|HTTP localhost| F["Python Agent<br/><code>agent.serve()</code>"]
    end

    D <--> E

    A -. "monitor :8090" .-> G["React Dashboard"]
    F -. "monitor :8091" .-> H["React Dashboard"]
```

**Protocol flow:**
1. `connect(wallet)` — sends `discover` message via XMTP, receives skill catalog
2. `call(wallet, skill, input)` — sends `task_request`, waits for `task_response`
3. `collaborate(wallet, goal)` — negotiates a plan, executes steps across both agents

## Features

### Shipped
- [x] Wallet-based agent identity (auto-generated on `coworker init`)
- [x] Skill registration with typed schemas (`@agent.skill()`)
- [x] Peer discovery over XMTP (`connect()`)
- [x] Remote skill invocation (`call()`) with retry logic
- [x] Multi-step collaboration (`collaborate()`) with OKR tracking
- [x] **Trust tiers**: UNTRUSTED → KNOWN → INTERNAL → PRIVILEGED (message ACL + skill visibility)
- [x] **Privacy enforcement**: default-deny, skill-level access control, trust request/grant flow
- [x] **OpenClaw adapter**: auto-discovers `~/.openclaw/workspace/skills/`
- [x] **Nanobot adapter**: auto-discovers `~/.nanobot/workspace/skills/`
- [x] React monitoring dashboard with live stats
- [x] Metering & usage receipts
- [x] SQLite persistent state (tasks, sessions, peers)
- [x] Zero Python dependencies (stdlib only)
- [x] 509 tests passing (461 unit + 48 collaboration/trust)
- [x] Cross-network E2E verified: Beijing ↔ San Francisco

### Roadmap
- [ ] PyPI stable release
- [ ] MCP bridge (expose CoWorker skills as MCP tools)
- [ ] TypeScript SDK
- [ ] On-chain agent registry (ERC-8004)
- [ ] LangGraph / CrewAI adapters
- [ ] Performance benchmarks

## CLI

```bash
coworker init --name my-agent    # generate wallet + install XMTP bridge
coworker bridge start            # start XMTP bridge process
coworker bridge stop             # stop bridge
coworker connect 0xPEER_WALLET   # discover peer skills via XMTP
coworker status                  # show agent status
coworker invite                  # generate wallet invite code
```

## Use with OpenClaw

CoWorker bridges OpenClaw skills to the open internet — your skills stay private, only visible to trusted peers.

```bash
# 1. Install CoWorker alongside OpenClaw
pip install coworker-protocol

# 2. Init wallet + XMTP bridge
coworker init --name my-claw-agent

# 3. Run the adapter (auto-discovers ~/.openclaw/workspace/skills/)
python examples/08_openclaw_adapter.py

# Output:
#   Found 5 OpenClaw skills:
#   ✓ memory: Long-term memory search
#   ✓ github: GitHub API operations
#   ✓ summarize: Summarize documents
#   ✓ web-search: Search the web
#   ✓ code-review: Review code changes
#   Starting CoWorker bridge...
#   Wallet: 0xabc...
#   Monitor: http://localhost:8090
```

Now a trusted peer can call your OpenClaw skills from anywhere:

```python
from coworker import Agent

agent = Agent("researcher")
peer = agent.connect("0xabc...")  # your wallet
# → Discovered: my-claw-agent (5 skills: memory, github, summarize, ...)

result = agent.call("0xabc...", "summarize", {"text": "...", "max_words": 50})
# → {"summary": "...", "word_count": 50}
```

**Key difference from ClawHub**: Skills are NOT published to a marketplace. Only peers you explicitly trust (via trust tiers) can see and call your skills. E2E encrypted over XMTP.

## Use with Nanobot

CoWorker turns nanobot agents into cross-network collaborators — same XMTP wallet-to-wallet privacy.

```bash
# 1. Install both
pip install nanobot-ai coworker-protocol

# 2. Init CoWorker
coworker init --name my-nanobot

# 3. Run the adapter (auto-discovers ~/.nanobot/workspace/skills/)
python examples/07_nanobot_adapter.py

# Output:
#   Nanobot ↔ CoWorker Adapter
#   Loading nanobot workspace skills...
#   ✓ Registered nanobot skill: memory
#   ✓ Registered nanobot skill: cron
#   ✓ Registered nanobot skill: weather
#   Starting CoWorker agent with nanobot skills...
```

Two nanobot agents can now collaborate across networks:

```python
# Agent A (Beijing) — has "research" skill
# Agent B (SF) — has "write" skill

from coworker import Agent

a = Agent("researcher")
a.collaborate("0xAGENT_B_WALLET", "Research AI trends and write a report")
# → Step 1: research (researcher) ✓
# → Step 2: write (Agent B, via XMTP) ✓
# → Result: SUCCESS (2/2 steps)
```

**Why not just use nanobot P2P?** Nanobot's built-in P2P requires direct HTTP connections (needs IP/port). CoWorker uses XMTP which works across NATs, firewalls, and different networks — no public IP needed.

## Privacy & Trust Model

CoWorker is **private-first** — the opposite of public skill marketplaces:

```
┌──────────────────────────────────────────────────────┐
│                     Trust Tiers                       │
│                                                       │
│  UNTRUSTED (0)  → Can ping/discover, sees NO skills  │
│  KNOWN (1)      → Can call skills, propose plans     │
│  INTERNAL (2)   → Can query context, deep access     │
│  PRIVILEGED (3) → Full access                        │
│                                                       │
│  Default: UNTRUSTED — must request trust explicitly   │
│  Skills: only visible to peers at sufficient tier     │
│  Transport: E2E encrypted via XMTP MLS protocol      │
│  Keys: never leave your machine, no central registry  │
└──────────────────────────────────────────────────────┘
```

**First contact flow:**

```python
# Peer A (unknown) tries to discover your skills:
peer = agent.connect("0xYOUR_WALLET")
# → sees 0 skills (UNTRUSTED)

# Peer A requests trust:
# → trust_request(requested_tier=KNOWN, reason="want to collaborate")

# Your agent responds:
# → trust_grant (if auto_accept_trust=True)
# → trust_deny  (if manual approval required)

# After trust is granted, Peer A discovers your skills:
peer = agent.connect("0xYOUR_WALLET")
# → sees all KNOWN-tier skills
```

Configure trust behavior:

```python
# Auto-accept trust requests up to KNOWN tier
agent = Agent("my-bot", auto_accept_trust=True, max_auto_accept_tier=1)

# Manual approval only (default)
agent = Agent("my-bot")  # auto_accept_trust=False
```

## Cross-Network Proof

Tested and verified between two independent agents:

| Agent | Location | Wallet | Monitor |
|-------|----------|--------|---------|
| ziway | Beijing, China | `0xda68...` | `:8090` |
| icy | San Francisco, USA | `0x320e...` | `:8091` |

**19/19 E2E tests passing:** ping, discover, skill call (translate, summarize, search), collaborate, concurrent calls, all API endpoints.

## Current Scope & Limitations

- **XMTP bridge required** — Node.js 18+ must be installed; the bridge runs as a sidecar process
- **XMTP dev network** — currently uses the XMTP dev network; production network support planned
- **Message latency** — XMTP relay adds 2-10s per message; not suitable for sub-second RPC
- **No streaming** — skill results are returned as complete JSON; streaming responses not yet supported
- **Single-language SDK** — Python only; TypeScript SDK on the roadmap
- **Alpha API** — the public API may change based on early feedback

## Project Structure

```
coworker-protocol/
├── sdk/
│   ├── src/coworker/           # Python SDK (zero deps)
│   │   ├── agent.py            # Agent class — the core API
│   │   ├── cli.py              # CLI commands
│   │   └── _internal/          # Protocol internals
│   │       ├── bridge.py       # XMTP bridge lifecycle
│   │       ├── client.py       # Protocol client
│   │       ├── executor.py     # Skill executor
│   │       ├── router.py       # Message router
│   │       ├── session.py      # Session management
│   │       ├── store.py        # SQLite persistence
│   │       └── bridge/         # Node.js XMTP bridge
│   └── examples/               # Runnable examples
├── frontend/                    # React monitoring dashboard
├── tests/                       # Test suite
└── docs/                        # Documentation
```

## Citation

```bibtex
@software{coworker_protocol,
  title     = {CoWorker Protocol: Open-Internet Agent-to-Agent Collaboration over XMTP},
  author    = {Zhao, Ziway},
  year      = {2026},
  url       = {https://github.com/ZiwayZhao/coworker-protocol}
}
```

## Contributing

We welcome contributions! See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.

## License

[MIT](./LICENSE)

---

<p align="center">
  <sub>Built with XMTP for the open agent internet.</sub>
</p>
