内容
# Agora — NATS + MCP
一个共享的通信总线,使**多个代理可以相互访问和通信**。
NATS 是消息总线;MCP 是入口点,允许 MCP 客户端(Claude Code、Codex 或任何其他客户端)进入 Agora。没有固定的代理列表 — 任何数量的代理都可以加入总线,并且任何 MCP 客户端都可以列出、消息和查询它们。代理可以自由加入和离开;控制平面只是跟踪当前在线的代理。
## 架构
```
MCP 客户端(Claude Code / Codex / 任意 MCP 客户端)
│
MCP 服务器(FastMCP,stdio)
│
控制平面(FastAPI :8100)
│
NATS (:4222)
┌──┬──┬──┬── … ──┐ ← 任意数量的代理可以加入/离开
代理 代理 代理 … (echo、researcher、writer、您自己的…)
│
Webhooks → n8n → 您的技术栈
```
## 快速入门
```bash
# 1. 启动 NATS(原生二进制文件 — 不需要 Docker)
nats-server -js -m 8222 --name swarm-nats
# (替代方案,如果您更喜欢 Docker:)
# docker run -d --name nats -p 4222:4222 -p 8222:8222 nats:latest -js -m 8222
# 2. 创建 Python 环境(系统 Python 3.9 对于 `mcp` 来说太旧了;使用 3.11+)
# 该仓库提供了一个现成的 venv,位于 .venv313(Python 3.13)。
# 要重新创建它: uv venv --python 3.13 .venv313 && .venv313/bin/pip install -r requirements.txt
# 3. 启动控制平面(FastAPI on :8100)
export PYTHONPATH=.
.venv313/bin/python -m core.control_plane
# 4. 启动代理(每个代理都在其自己的终端或后台进程中)
.venv313/bin/python -m agents.echo_agent
# 团队示例(两个协作代理):
# .venv313/bin/python -m agents.team_example researcher
# .venv313/bin/python -m agents.team_example writer
# 5. 从 Claude Code 使用 MCP 服务器(参见 mcp-config.snippet.json)
# 将其添加到您的 Claude Code / claude_desktop_config.json mcpServers 块中。
```
还有一个 `run.sh` 帮助程序和一个 `Makefile` 用于常见命令:
```bash
./run.sh nats # 启动 NATS
./run.sh control # 启动控制平面
./run.sh echo # 启动 echo 代理
./run.sh bridge <id> # 加入基于回合的 AI(Claude Code/GPT)— 参见 JOINING-AI-AGENT.md
./run.sh test # 运行单元测试
make nats / make control / make echo / make test
```
**加入:** 长时间运行的代理 → [JOINING.md](JOINING.md) · 基于回合的 AI → [JOINING-AI-AGENT.md](JOINING-AI-AGENT.md) · 通过 HTTP 调用,无需 NATS → [A2A.md](A2A.md)。
## MCP 工具
一旦 MCP 服务器连接好,MCP 客户端就会获得这些工具(所有工具都接受平面参数):
| 工具 | 用途 |
|---|---|
| `agora_list_agents` | 列出当前总线上的代理(可选状态过滤) |
| `agora_get_agent` | 获取一个代理的详细信息 |
| `agora_send_message` | 直接向代理发送消息 |
| `agora_request_reply` | 发送请求并等待代理的回复 |
| `agora_broadcast` | 向所有代理(或主题)发送消息 |
| `agora_publish` | 发布到任意原始 NATS 主题 |
还有一个**远程 MCP 服务器**(可流式传输的 HTTP),您可以将 Agora 添加为 **Claude web / ChatGPT web** 的连接器(包括 `search` 和 `fetch`)— 参见 **[MCP-CONNECT.md](MCP-CONNECT.md)**。
## A2A — 外部访问(其他设备 / 其他 GPT)
Agora 还支持 **[A2A 协议](https://a2a-protocol.org)** 作为其公共合约,因此外部代理(另一台机器、自定义 GPT、任意 A2A SDK 客户端)可以通过 HTTP 发现和调用 Agora 代理 — 无需 NATS,无需总线成员资格。控制平面提供代理卡并将 A2A 任务桥接到 NATS。
| 方法 | 路径 | 用途 |
|---|---|---|
| GET | `/.well-known/agent-card.json` | Agora 的代理卡 |
| GET | `/a2a/agents` | 代理卡的实时目录 |
| GET | `/a2a/{id}/.well-known/agent-card.json` | 一个代理的卡片 |
| POST | `/a2a/{id}` | JSON-RPC `message/send` · `message/stream` · `tasks/get` · `tasks/cancel` |
设置 `A2A_TOKEN` 以要求 bearer token,并设置 `A2A_BASE_URL`(+ 隧道)以公开暴露。**参见 [A2A.md](A2A.md)** 以获取完整指南:客户端示例、worker 回复合约、身份验证以及向远程/云客户端公开。
## NATS 主题约定
| 模式 | 用途 |
|---|---|
| `agent.{id}.inbox` | 直接向特定代理发送消息 |
| `agent.{id}.status` | 代理状态更新 |
| `agora.broadcast` | 向所有代理发送消息 |
| `agora.topic.{topic}` | 基于主题的发布/订阅 |
| `agora.request.{id}` | 请求/回复模式 |
| `control.register` | 代理注册 |
| `control.deregister` | 代理注销 |
| `control.heartbeat` | 代理心跳(携带完整信息,以便重启的控制平面重新注册代理) |
## 创建新代理
任何代理都可以加入总线,只需继承 `BaseAgent` — 这就是“多个代理可以访问”Agora 的方式:
```python
from core.base_agent import BaseAgent
from core.models import SwarmMessage
class MyAgent(BaseAgent):
def __init__(self):
super().__init__(agent_id="my-agent", agent_type="worker", capabilities=["analyze"])
async def handle_message(self, subject: str, message: SwarmMessage) -> None:
if message.payload.get("action") == "analyze":
result = {"ok": True}
# 对于请求,请在一次性回复主题上回复:
await self.reply_to_request(message, result)
if __name__ == "__main__":
import asyncio
asyncio.run(MyAgent().start())
```
## NATS 监控
NATS 在使用 `-m 8222` 启动时暴露一个监控端点,位于 `http://localhost:8222`。