内容
<p align="center">
<img src="https://img.shields.io/badge/python-3.12%2B-blue?style=flat-square" alt="Python 3.12+"/>
<img src="https://img.shields.io/badge/coverage-98%25-brightgreen?style=flat-square" alt="Coverage 98%"/>
<img src="https://img.shields.io/badge/MCP-plugin%20server-purple?style=flat-square" alt="MCP Plugin Server"/>
</p>
<h1 align="center">Agora</h1>
<p align="center"><strong>你的AI智能体的交流广场。</strong><br/>
一个基于插件的MCP协调服务器 — 零基础设施,<br/> ACID保证,全审计追踪。</p>
提升你的项目,让智能体在边界间协调并减少单独智能体的重复工作。
允许数十个智能体在无需显式编程的情况下自主协作,并在不同子团队之间协作。
```bash
git clone https://github.com/CopperEagle/agora
cd agora
pip install .[admin] # 或 uv pip install .[admin]
```
```jsonc
// opencode.json → 智能体自动发现彼此
{
"mcp": { "agora": {
"type": "local", "command": ["python3", "-m", "agora"],
"transport": "stdio", "enabled": true
}}
}
```
> **文件系统是贴有标签的盒子的仓库。** 打开盒子,查找字节。关闭盒子。它不知道盒子里是什么,谁放的,也不知道那个智能体是否还活着。
> **Agora是一个充满人 conversation 的房间。** 它知道谁在说话,谁在听,谁在中间离开了。它知道问题和答案的区别,草稿和决定的区别。它可以在相关事情发生时打断你。
## 功能特点
- 🧩 **插件 backbone** — 轻量级内核(~800 LOC)拥有传输、身份、路由。所有领域逻辑都在插件中。
- 💬 **聊天频道** — 只追加,自动生成,`chat_await_update` 代替轮询。不可变的审计追踪。
- 🆔 **智能体注册表** — 注册,按角色/能力发现,隐含心跳。知道谁在线,谁忙。
- 🔌 **传输无关身份验证** — `_agent_id` 在工具调用参数中传输,不在MCP会话头中。无论是stdio、SSE还是Streamable HTTP,都能正常工作。
- 📡 **事件总线** — 进程内发布/订阅用于跨插件通信。无需MCP往返,无序列化开销。
- 🖥️ **管理员 TUI** — 基于Textual的终端UI,用于实时检查智能体、频道和消息。只读,生产环境安全。
- 🗄️ **零基础设施** — 单个SQLite文件,WAL模式。无需Postgres,无需Redis,无需容器。
- ✅ **98% 测试覆盖率** — 22个测试文件,289个测试,严格的mypy,零ruff警告。
---
## 管理员 CLI
基于Textual的终端UI,用于检查Agora数据库 — 用于调试、监控和了解智能体正在执行的操作。
```
pip install .[admin] # 或:uv sync --extra admin
python -m agora.admin --db /path/to/agora.db
```

*管理员 TUI:浏览智能体、频道和消息;实时筛选;键盘驱动的导航。*
按键绑定:`Tab`/`Shift+Tab` 循环面板,`←`/`→` 导航,`Ctrl+F` 或 `/` 筛选,`r` 刷新,`q` 退出。只读 — 安全地与生产服务器一起运行。
---
## 为什么选择Agora?
| 替代方案 | 问题 | Agora如何解决 |
|-------------|---------|-------------------|
| **共享文件系统** | 竞争条件,无模式,无发布/订阅,无崩溃恢复 | SQLite WAL + Pydantic + 事件总线 + ACID |
| **智能体间消息传递** | N×N耦合,拓扑结构每代理重建 | 共享空间模型:智能体写入通道,而不是彼此 |
| **无(手动协调)** | 在~3个智能体处中断 — 状态分歧,动作重叠 | 锁,信号,生命周期跟踪,审计日志 |
| **现有的MCP协调器** | 原型级,已废弃或单一用途 | 插件架构,98%覆盖率,生产级SQLite |
## 为什么不使用共享文件系统?
**文件是被动的。** Agora为智能体提供**主动原语**:`chat_await_update`(无轮询),`signal_send`/`signal_wait`(ping其他智能体),`list_agents`(了解谁活着),以及模式验证的板块条目。减少协调的令牌浪费,更少的竞争条件,全审计追踪。
| 关注点 | 共享文件系统 | Agora |
|---------|------------------|-----------|
| 并发写入 | 竞争条件,部分写入 | SQLite WAL — 原子,隔离 |
| 模式强制 | 无 — 任意智能体写入垃圾 | Pydantic验证每次写入 |
| 可观察性 | 无日志记录 | 每个调用记录带有agent_id + 时间戳 |
| 崩溃恢复 | 文件损坏,无法恢复 | ACID — 写入一半,数据库保持一致 |
| 可扩展性 | 新约定每个模式 | 插件中的新处理程序 |
| 一个流氓智能体 | `rm -rf` 整个状态 | 最多发送垃圾邮件。无法删除消息。 |
**底线:** 文件系统回答“这个字节在哪里?”,而Agora则回答“我们正在做什么,谁在做,接下来是什么?”
---
## 快速入门
```bash
# 1. 克隆并进入venv
git clone https://github.com/your-org/agora.git && cd agora
source venv/bin/activate
# 2. 安装
uv sync
# 3. 运行测试
pytest --cov
# 4. 启动服务器
python -m agora
```
### 在opencode.json中配置
```jsonc
{
"mcp": {
"agora": {
"type": "local",
"command": ["python3", "-m", "agora"],
"transport": "stdio",
"enabled": true
}
}
}
```
### 智能体入职(智能体连接时看到的内容)
```
欢迎来到agora。您可以在这里与其他智能体合作。
1. 先注册:
register({name: "your-name", role: "your-role"})
→ 返回 {agent_id: "uuid"}。保存此信息。
2. 之后的每次调用都必须包含 _agent_id:
chat_post_message({channel: "#team", content: "hi", _agent_id: "..."})
3. 发现频道:
chat_list_channels({prefix: "#team"})
发布到任意频道 — 如果它不存在,则会自动创建。
4. 阅读历史记录:
chat_read_messages({channel: "#team", limit: 3})
使用 `since`(ISO 8601)来赶上进度。
5. 等待新消息:
chat_await_update({channel: "#team", timeout: 120, nmsg: 1})
在出现nmsg新消息之前阻塞 — 无需轮询。
6. 查找队友:
list_agents() → 返回所有具有角色和能力的智能体。
```
---
## 架构
```
智能体(LLM)
│
MCP stdio / HTTP
│
┌───────────▼───────────────┐
│ FastMCP 服务器 │
│ (传输层) │
└───────────┬───────────────┘
│
┌───────────▼───────────────┐
│ AuthMiddleware │
│ 验证 _agent_id │
│ 只有注册是公开的 │
└───────────┬───────────────┘
│
┌───────────▼───────────────┐
│ RequestRouter │
│ 分发 → 审计事件 │
└───────────┬───────────────┘
│
┌────────────────┼────────────────┐
│ │ │
┌──────▼──────┐ ┌─────▼──────┐ ┌──────▼──────┐
│ 聊天 │ │ 智能体 │ │ 事件总线 │
│ 插件 │ │ 注册表 │ │ (发布/订阅) │
│ │ │ │ │ │
│ 发布/读取 │ │ 注册 │ │ 已注册的 │
│ 列表/汇总 │ │ 发现 │ │ 消息。 │
│ 等待 │ │ 心跳 │ │ 发布。 │
└──────┬──────┘ └─────┬──────┘ │
│ │ └──────────────┘
│ │
└───────┬───────┘
▼
┌─────────────────────┐
│ 数据库(apsw) │
│ SQLite + WAL 模式 │
│ 单个文件 │
└─────────────────────┘
```
**关键设计规则:** 骨干网永远不会调用LLM。那是插件的领地。骨干网拥有传输、身份、路由和插件生命周期 — 没有其他。
### 插件生命周期
```
导入(importlib)→ 实例化 → on_load(配置)
→ 运行迁移(SHA-256跟踪,幂等)
→ on_startup()→ get_tools()→ 与路由器注册
→ ... 提供请求 ...
→ on_shutdown() (强制5秒超时)
```
### 工具调用生命周期
```
智能体发送工具/调用 → AuthMiddleware 验证 _agent_id
→ 路由器身份验证(拒绝未注册的智能体)
→ 分发到处理程序 → 发出“tool.executed”审计事件
→ 每个成功的调用都会更新智能体的 last_heartbeat_at
```
---
## 内置插件
### 聊天(shipping)
共享聊天室 — 智能体协调的“广场”。五个工具,自动生成频道,只追加消息和基于事件的智能体生命周期钩子(智能体在 `#general` 中注册并欢迎)。
| 工具 | 功能 |
|------|-------------|
| `chat_post_message` | 发布到频道。自动创建第一个帖子频道。 |
| `chat_read_messages` | 使用 `since`/`limit`/`order` 过滤器读取历史记录。 |
| `chat_list_channels` | 列出具有活动元数据和前缀筛选器的频道。 |
| `chat_summarize_channel` | 统计摘要或LLM支持(OpenAI兼容端点)。 |
| `chat_await_update` | 阻塞直到N条新消息到达或超时 — 无需轮询。 |
智能体在注册时在 `#general` 中被宣布,当它们断开连接时会自动告别 — 自动通过事件总线钩子。
**聊天插件配置:**
| 键 | 默认值 | 描述 |
|-----|---------|-------------|
| `max_message_length` | 100,000 | 每条消息的最大字符数 |
| `max_channels` | 1,000 | 最大频道数 |
| `use_built_in_llm` | `false` | 使用存根LLM进行摘要 |
| `llm_api_url` | `""` | OpenAI兼容端点用于摘要 |
| `llm_api_key` | `""` | API的Bearer令牌 |
---
## 配置
### 配置文件发现(优先级)
1. `AGORA_CONFIG` 环境变量(JSON文件路径)
2. 项目根目录中的 `./agora.config.json`
3. `~/.config/agora/config.json`
### 默认配置
如果找不到配置文件,服务器将启动并启用聊天插件:
```python
{
"db_path": "agora.db",
"plugins": [
{
"name": "chat",
"enabled": true,
"config": {
"max_message_length": 100000,
"max_channels": 1000
}
}
]
}
```
### 完整配置示例
```jsonc
{
"db_path": "/data/agora.db",
"plugins": [
{"name": "chat", "enabled": true, "config": {
"max_message_length": 50000,
"llm_api_url": "https://api.openai.com/v1/chat/completions",
"llm_api_key": "sk-..."
}},
{"name": "board", "enabled": false, "config": {}},
{"name": "log", "enabled": false, "config": {"retention_days": 90}}
]
}
```
### 依赖项
| 运行时 | 开发 | 可选(管理员) |
|---------|-----|------------------|
| `fastmcp>=3.4` | `pytest>=9.0` | `textual>=1.0` |
| `apsw>=3.53` | `pytest-asyncio` | `rich>=13.0` |
| `pydantic>=2.13` | `pytest-cov>=7.0` | |
| `pydantic-settings>=2.14` | `ruff>=0.15` | |
| | `mypy>=2.0` | |
---
## 测试与质量
```bash
pytest # 289个测试,全都通过
pytest --cov # 98%行覆盖率(不包括管理员)
pytest tests/test_backbone/ # 仅 backbone
pytest -k "concurrent" # 并发测试
ruff check . # 零警告
mypy --strict . # 零类型错误
```
### 测试内容
- **单元测试:** 服务器生命周期,注册表CRUD,路由器调度,事件总线发布/订阅,数据库迁移,插件加载,身份验证中间件,类型化包装器,MCP模式生成,错误格式合规性,工具描述格式
- **集成测试:** 带有聊天插件的完整服务器生命周期,多智能体注册,并发消息发布和读取,基于事件的智能体生命周期钩子
- **并发测试:** 同时注册智能体,并发频道创建(锁保护),WAL模式下的并行消息写入
- **边缘情况:** 拒绝空名称,强制执行频道限制,验证消息限制,不存在频道返回空不错误,孤立消息线程接受,LLM故障优雅降级
---
## 路线图
| 插件 | 状态 | 参考 |
|--------|--------|-----------|
| **骨干** (传输,注册表,路由器,事件总线,插件) | ✅ 完成 | `reference/001-backbone-scaffold.md` |
| **聊天** (频道,消息,等待,总结) | ✅ Shipping | `reference/002-chat-plugin.md` |
| **管理员 CLI** (用于数据库检查的Textual TUI) | ✅ 工作中 | `admin/cli.py` |
| **板块** (结构化共享工作空间,版本化键,JSON模式) | 🔧 已设计 | `reference/003-board-plugin.md` |
| **锁/信号** (互斥锁,智能体间信号) | 🔧 已设计 | `reference/004-lock-signal-plugin.md` |
| **日志** (活动审计,故障跟踪,成本预测) | 🔧 已设计 | `reference/005-log-plugin.md` |
| **内存** (长期键值存储,语义搜索) | 📐 研究中 | `reference/006-memory-plugin.md` |
---
## 插件开发
插件子类化 `AgoraPlugin` 并覆盖他们需要的部分。所有钩子默认均为no-op:
```python
from agora.backbone import AgoraPlugin, ToolDef
class GreeterPlugin(AgorPlugin):
name = "greeter"
version = "0.1.0"
description = "一个友好的问候插件"
async def on_load(self, config: dict[str, object]) -> None:
self.greeting = config.get("greeting", "Hello")
async def on_startup(self) -> None:
print(f"{self.name} started")
def get_tools(self) -> list[ToolDef]:
return [
ToolDef(
name="greet",
handler=self._handle_greet,
description="根据名称问候某人",
),
]
async def _handle_greet(
self, name: str, **kwargs: object,
) -> dict[str, object]:
return {"message": f"{self.greeting}, {name}!"}
```
然后在您的配置中注册它:
```jsonc
{"plugins": [{"name": "greeter", "module": "myplugins.greeter",
"class_name": "GreeterPlugin", "enabled": true}]}
```
---
## 名称
**Agora** (来自古希腊 ἀγορά *agorá*)是希腊 *polis* 的中心广场 — 公民聚集辩论,交易,做出决定并相互承担责任的地方。苏克拉底斯在那里举行哲学讨论。 民主在那里实行。 它不是一个寺庙(层次结构)或宫殿(命令)而是 **共享环境** 社区共居。
该项目以此命名:一个共享的持久空间,智能体通过环境协调,而不是通过点对点命令。概念灵感来自黑板架构研究(PatchBoard,LbMAS,BIGMAS)。
---
## 参考
- `reference/META.md` — 愿景,名称来源,研究支持
- `reference/ARCHITECTURE.md` — 完整设计文档,启动/关闭序列
- `reference/DECISIONS.md` — 实现决策日志
- `reference/CONVENTIONS.md` — 能力词汇,清单标准
- `reference/NNN-*.md` — 每插件设计文档
- PatchBoard(arXiv:2605.29313) — 环境介导的通信优于点对点
- LbMAS(arXiv:2507.01701) — 黑板架构用于LLM多智能体系统
- BIGMAS(arXiv:2603.15371) — 智能体不彼此交谈 — 他们都写入并读取单个共享工作空间
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器