本文档面向开发者,介绍 OpenClaw-Py 的整体架构、核心组件和设计决策。
OpenClaw-Py 是一个多通道 AI 网关,将 AI Agent 连接到 25+ 消息平台。核心设计目标:
ChannelPlugin 接口┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Flet UI │ │ CLI (Typer) │ │ ACP Bridge │
└──────┬──────┘ └──────┬───────┘ └──────┬──────┘
│ │ │
└─────────┬───────┘───────────────────┘
│ WebSocket v3 / HTTP
┌─────────▼─────────┐
│ Gateway (FastAPI) │
│ ┌───────────────┐ │
│ │ RPC Handlers │ │
│ │ OpenAI Compat │ │
│ └───────┬───────┘ │
└──────────┼─────────┘
│
┌──────────▼─────────┐
│ Agent Runtime │
│ ┌──────────────┐ │
│ │ Runner Loop │ │ prompt → LLM stream → tool exec → loop
│ │ Session DAG │ │
│ │ Sub-agents │ │
│ └──────────────┘ │
└──────────┬─────────┘
┌──────┼──────┐
▼ ▼ ▼
┌──────┐ ┌────┐ ┌──────┐
│Tools │ │MCP │ │Skills│
└──────┘ └────┘ └──────┘
src/pyclaw/gateway/server.py
/ws) 和 HTTP 端点method 字段路由到 methods/ 下的处理函数_load_plugins) 和配置监控 (_start_config_watcher)class GatewayServer:
def register_handler(self, method: str, handler: MethodHandler) -> None: ...
async def _dispatch(self, method: str, params: dict, conn: GatewayConnection) -> Any: ...
src/pyclaw/agents/runner.py
核心执行循环:
while not done:
response = await llm.stream(messages, tools)
for chunk in response:
if chunk.is_tool_call:
result = await tool_registry.execute(chunk.tool, chunk.args)
messages.append(tool_result(result))
elif chunk.is_text:
yield chunk.text
if no_tool_calls:
done = True
设计特点:
stream.py 将 OpenAI / Anthropic / Gemini / Ollama 的流式 API 归一化为相同的 chunk 格式tool_guards.py 控制危险操作审批subagents/ 管理 spawn / steer / kill 生命周期src/pyclaw/channels/
每个通道是一个独立目录,包含 channel.py 实现 ChannelPlugin 基类:
class ChannelPlugin(ABC):
async def start(self) -> None: ...
async def stop(self) -> None: ...
async def send_reply(self, reply: ChannelReply) -> None: ...
def on_message(self, callback) -> None: ...
通道管理器 (manager.py) 统一管理所有通道的生命周期。
Plugin SDK (plugin_sdk/) 定义了 20 个 Protocol 接口:
| Protocol | 用途 |
|---|---|
ConfigAdapter |
配置 schema + 验证 |
AuthAdapter |
认证 |
OutboundAdapter |
消息发送 |
ActionsAdapter |
反应、置顶 |
StreamingAdapter |
草稿/流式消息 |
HeartbeatAdapter |
连接心跳 |
DirectoryAdapter |
用户目录 |
| … | 共 20 个 |
运行时通过 detect_capabilities(plugin) 探测通道支持哪些能力。
src/pyclaw/config/
schema.py):强类型配置模型,30+ 配置节env_substitution.py):${VAR} / ${VAR:-default} 语法includes.py):大配置文件可拆分为多个 JSON5migrations.py):v1 → v2 → v3 自动迁移runtime_overrides.py):后台轮询检测文件变更,触发回调backup.py):先写临时文件再原子重命名,保留备份src/pyclaw/mcp/
实现 MCP (Model Context Protocol) 客户端,连接外部工具服务器:
src/pyclaw/memory/
双引擎记忆系统:
┌─────────────┐ ┌─────────────┐
│ SQLite FTS5 │ │ LanceDB │
│ (关键词搜索) │ │ (向量搜索) │
└──────┬──────┘ └──────┬──────┘
└────────┬────────┘
┌─────▼─────┐
│ Hybrid │ MMR + 时间衰减
│ Ranker │
└───────────┘
src/pyclaw/ui/
基于 Flet 的跨平台 UI:
| 模块 | 功能 |
|---|---|
app.py |
主应用 + ChatView + NavigationRail |
theme.py |
Light/Dark 主题 |
agents_panel.py |
Agent 管理面板 |
toolbar.py |
聊天工具栏 |
menubar.py |
桌面菜单栏 |
voice.py |
语音交互 (TTS + STT) |
onboarding.py |
4 步设置向导 |
tray.py |
系统托盘 |
i18n.py |
多语言 (en/zh-CN/ja) |
permissions.py |
移动端权限管理 |
User (Flet/CLI/Channel)
│
▼
Gateway.chat.send(sessionId, message)
│
▼
AgentRunner.run(session, message)
│
├─ append user message to session
│
├─ build system prompt (AGENTS.md + skills + context)
│
├─ LLM.stream(messages, tools)
│ │
│ ├─ text delta → push chat.delta event
│ │
│ └─ tool_call → ToolRegistry.execute()
│ │
│ ├─ built-in tool
│ ├─ MCP tool (stdio/HTTP)
│ └─ approval gate (if exec/patch)
│
├─ append assistant message to session
│
└─ push chat.done event
Channel (Telegram/Discord/...)
│
▼
ChannelPlugin.on_message(callback)
│
▼
ChannelManager → Routing (7-tier priority)
│
▼
AgentRunner.run(...) ← 选定的 Agent
│
▼
Channel.send_reply(response)
路由优先级:
Agent 请求执行命令
│
▼
ToolGuards.check_policy(command)
│
├─ allow_list → 直接执行
├─ deny_list → 拒绝
└─ approval_required → 推送审批请求到 UI/CLI
│
▼
用户审批/拒绝
127.0.0.1,防止未授权访问通过 Python entry_points 机制自动发现第三方插件:
# 第三方包的 pyproject.toml
[project.entry-points."pyclaw.plugins"]
my_plugin = "my_package.plugin:MyPlugin"
Gateway 启动时自动加载所有已安装的插件。
Agent 能力注入:
~/.pyclaw/workspace/skills/
├── my-skill/
│ └── SKILL.md # 包含系统提示和工具定义
└── ...
技能在 Agent 系统提示中被注入,可通过 ClawHub marketplace 安装。
事件钩子 (HOOK.md):
# HOOK.md
## on_message_received
Run sentiment analysis before processing.
支持 before_send / after_send / on_error 等生命周期钩子。
| 决策 | 选择 | 理由 |
|---|---|---|
| Web 框架 | FastAPI | 原生 async,WebSocket 支持好 |
| CLI 框架 | Typer + Rich | 类型安全 + 丰富输出 |
| 配置格式 | JSON5 | 支持注释,兼容 JSON |
| 会话存储 | JSONL (文件) | 无需数据库,便于调试 |
| 向量引擎 | LanceDB | 零配置,嵌入式 |
| UI 框架 | Flet | 单一 Python 代码库跨平台 |
| LLM 流式 | 统一 chunk 格式 | 屏蔽 Provider 差异 |
| 进程管理 | asyncio subprocess | 与 async 架构一致 |
| 日志 | stdlib logging | 无额外依赖 |
| 类型系统 | Pydantic v2 | 验证 + 序列化 |
src/pyclaw/
├── __init__.py
├── main.py # 入口
│
├── agents/ # Agent 运行时
│ ├── runner.py # 核心循环
│ ├── stream.py # 多 Provider 流式
│ ├── session.py # 会话存储
│ ├── system_prompt.py # 系统提示构建
│ ├── tokens.py # Token 计数
│ ├── embedded_runner/ # 嵌入式运行器
│ ├── providers/ # LLM Provider 适配
│ ├── subagents/ # 子 Agent 管理
│ ├── skills/ # SKILL.md 系统
│ ├── tools/ # 20+ 内置工具
│ ├── progress.py # 进度事件
│ └── types.py # 共享类型
│
├── gateway/ # Gateway 服务
│ ├── server.py # FastAPI + WebSocket
│ ├── openai_compat.py # OpenAI API 兼容层
│ ├── protocol/ # 帧定义
│ ├── methods/ # RPC 方法处理器
│ └── events.py # 事件广播
│
├── channels/ # 25 个消息通道
│ ├── base.py # ChannelPlugin 基类
│ ├── manager.py # 通道管理器
│ ├── plugin_sdk/ # 20 个 Protocol 接口
│ ├── plugins/ # 通道增强 (onboarding/outbound/actions/normalize)
│ └── <channel>/ # 各通道实现
│
├── config/ # 配置管理
├── mcp/ # MCP 客户端
├── memory/ # 记忆系统
├── security/ # 安全策略
├── secrets/ # 密钥管理
├── hooks/ # 事件钩子
├── plugins/ # 扩展系统
├── routing/ # 消息路由
├── media/ # 媒体处理
├── social/ # Agent 社交网络
├── infra/ # 基础设施
├── cli/ # CLI 命令
├── ui/ # Flet UI
└── web/ # Web API