适用版本: OpenClaw v2026.3 阅读时间: 约 30 分钟 前置知识: 阅读前两篇文章,理解 Gateway 和消息流程 源码位置:
src/agents/,src/acp/
开篇:Agent 是什么?
前两篇文章,我们了解了 Gateway 如何协调子系统、消息如何流转。今天,让我们进入最核心的问题:
Agent 是什么?它和 LLM 有什么区别?
LLM(Large Language Model)只是一个文本生成器——给它一段文本,它返回续写的文本。
Agent 则是 LLM 的"躯壳与灵魂":
- 躯壳——工具、记忆、状态管理、多模态处理
- 灵魂——规划、推理、自我反思、任务分解
用一个比喻:
LLM = 大脑(只有神经元)
Agent = 机器人(大脑 + 感知 + 行动 + 记忆)
本文将回答核心问题:
OpenClaw 如何让不同的 LLM 表现出一致的 Agent 行为?ACP 协议解决了什么问题?
Agent 架构概览
双模式运行时
OpenClaw 支持两种 Agent 运行模式:
flowchart TB
subgraph Gateway["Gateway"]
SM[Session Manager]
AR[Agent Router]
end
subgraph Embedded["Embedded 模式<br/>(Pi Agent)"]
PC[Pi Core]
PA[Pi AI]
PD[Pi Coding]
MEMORY[(Memory)]
end
subgraph ACP["ACP 模式<br/>(独立进程)"]
ASM[ACP Session Manager]
BA[Backend Adapters]
CL[Claude]
GM[Gemini]
OAI[OpenAI]
CUS[Custom]
end
subgraph LLM["LLM Providers"]
OPENAI[OpenAI]
ANTHROPIC[Anthropic]
GOOGLE[Google]
end
Gateway --> Embedded
Gateway --> ACP
Embedded --> LLM
ACP --> LLM
style Embedded fill:#e3f2fd
style ACP fill:#fff3e0
| 模式 | 特点 | 适用场景 |
|---|---|---|
| Embedded | 与 Gateway 同进程,零通信开销 | 默认模式、高性能需求 |
| ACP | 独立进程,通过 RPC 通信 | 隔离性要求、自定义后端 |
ACP 协议:统一不同后端
ACP(Agent Communication Protocol)是 OpenClaw 定义的标准接口,让不同的 LLM 后端表现一致。
// src/acp/runtime/types.ts
/**
* ACP Runtime 的核心接口
* 任何 Agent 后端都必须实现这个接口
*/
export interface AcpRuntime {
// 会话管理
ensureSession(input: AcpRuntimeEnsureInput): Promise<AcpRuntimeHandle>;
// 核心执行
runTurn(input: AcpRuntimeTurnInput): AsyncIterable<AcpRuntimeEvent>;
// 能力查询
getCapabilities?(input: { handle?: AcpRuntimeHandle }): Promise<AcpRuntimeCapabilities>;
// 状态查询
getStatus?(input: { handle: AcpRuntimeHandle }): Promise<AcpRuntimeStatus>;
// 控制
setMode?(input: { handle: AcpRuntimeHandle; mode: string }): Promise<void>;
setConfigOption?(input: { handle: AcpRuntimeHandle; key: string; value: string }): Promise<void>;
// 中断
cancel(input: { handle: AcpRuntimeHandle; reason?: string }): Promise<void>;
close(input: { handle: AcpRuntimeHandle; reason: string }): Promise<void>;
// 诊断
doctor?(): Promise<AcpRuntimeDoctorReport>;
}
设计意图: 无论底层是 Claude、GPT-4、Gemini 还是自定义模型,上层代码只看到 runTurn() 返回的事件流。
Turn 执行:一次对话的完整生命周期
什么是 Turn?
Turn 是 Agent 执行的基本单位——一个"回合":
用户发送消息 → Agent 处理 → Agent 回复
一次 Turn 可能包含:
- 多次 LLM 调用(如果需要工具调用)
- 多个流式事件
- 工具执行结果
Turn 执行流程
sequenceDiagram
autonumber
participant User as 用户
participant Agent as Agent Runtime
participant LLM as LLM Provider
participant Tools as Tool Executor
User->>Agent: runTurn(message)
Note over Agent: 1. 构建提示词
Agent->>Agent: buildPrompt(message, transcript)
Note over Agent: 2. 调用 LLM
Agent->>LLM: streamCompletion(prompt)
loop 流式输出
LLM-->>Agent: text_delta
Agent-->>User: event: text_delta
end
alt 需要工具调用
LLM-->>Agent: tool_call
Agent-->>User: event: tool_call
Note over Tools: 3. 执行工具
Agent->>Tools: execute(tool_name, params)
Tools-->>Agent: result
Agent-->>User: event: tool_result
Note over Agent: 4. 继续生成
Agent->>LLM: continue(tool_result)
loop 流式输出
LLM-->>Agent: text_delta
Agent-->>User: event: text_delta
end
end
Note over Agent: 5. 完成
LLM-->>Agent: done
Agent-->>User: event: done
Agent-->>Agent: saveTranscript()
Turn 输入输出
// 输入
interface AcpRuntimeTurnInput {
handle: AcpRuntimeHandle; // 会话句柄
text: string; // 用户消息
attachments?: Attachment[]; // 附件(图片、文件等)
mode: "prompt" | "steer"; // 模式:对话 or 引导
requestId: string; // 请求 ID
signal?: AbortSignal; // 中断信号
}
// 输出(事件流)
type AcpRuntimeEvent =
| { type: "text_delta"; text: string; stream?: "output" | "thought" }
| { type: "status"; text: string; used?: number; size?: number }
| { type: "tool_call"; name: string; args: Record<string, unknown>; id: string }
| { type: "tool_result"; id: string; result: string }
| { type: "usage_update"; input: number; output: number }
| { type: "done"; stopReason: string }
| { type: "error"; message: string; code?: string; retryable?: boolean };
事件流示例
用户: "今天北京天气怎么样?"
事件序列:
1. { type: "status", text: "Thinking..." }
2. { type: "tool_call", name: "weather.get", args: {city: "北京"}, id: "tc_1" }
3. { type: "tool_result", id: "tc_1", result: '{"temp":"15-25°C","condition":"晴"}' }
4. { type: "text_delta", text: "北京今天" }
5. { type: "text_delta", text: "天气晴朗" }
6. { type: "text_delta", text: ",气温" }
7. { type: "text_delta", text: "15-25°C。" }
8. { type: "usage_update", input: 150, output: 25 }
9. { type: "done", stopReason: "end_turn" }
工具调用:Agent 的手脚
问题:LLM 无法直接操作世界
LLM 只能生成文本,不能:
- 查询数据库
- 调用 API
- 读写文件
- 执行代码
解决方案:工具调用协议
flowchart TB
subgraph LLM["LLM"]
DECIDE["决定调用工具"]
end
subgraph Agent["Agent Runtime"]
PARSE["解析工具调用"]
EXEC["执行工具"]
FORMAT["格式化结果"]
end
subgraph Tools["工具系统"]
T1["weather.get"]
T2["web.search"]
T3["fs.read"]
T4["code.execute"]
end
LLM --> |tool_call| Agent
Agent --> PARSE
PARSE --> EXEC
EXEC --> T1
EXEC --> T2
EXEC --> T3
EXEC --> T4
T1 --> |result| FORMAT
T2 --> |result| FORMAT
T3 --> |result| FORMAT
T4 --> |result| FORMAT
FORMAT --> |tool_result| LLM
工具定义
// src/agents/tools/types.ts
interface AgentTool {
// 元信息
name: string; // 工具名称
description: string; // 工具描述(LLM 会看到)
inputSchema: JSONSchema; // 输入参数 Schema
// 执行函数
handler: (params: Record<string, unknown>, ctx: ToolContext) => Promise<ToolResult>;
}
interface ToolContext {
sessionKey: string; // 当前会话
agentId: string; // Agent ID
sandboxed: boolean; // 是否在沙箱中
abortSignal: AbortSignal; // 中断信号
cwd?: string; // 工作目录
}
interface ToolResult {
content: string | ContentBlock[];
isError?: boolean; // 是否错误
}
工具注册机制
// src/agents/tools/registry.ts
export class ToolRegistry {
private tools = new Map<string, AgentTool>();
register(tool: AgentTool): void {
if (this.tools.has(tool.name)) {
throw new Error(`Tool ${tool.name} already registered`);
}
this.tools.set(tool.name, tool);
}
get(name: string): AgentTool | undefined {
return this.tools.get(name);
}
// 生成 LLM 能理解的工具列表
toOpenAITools(): OpenAI.Chat.ChatCompletionTool[] {
return Array.from(this.tools.values()).map(tool => ({
type: "function",
function: {
name: tool.name,
description: tool.description,
parameters: tool.inputSchema,
},
}));
}
}
// 内置工具注册
const registry = new ToolRegistry();
registry.register({
name: "sessions.list",
description: "List all available sessions",
inputSchema: { type: "object", properties: {} },
handler: async (_, ctx) => {
const sessions = await listSessions();
return { content: JSON.stringify(sessions) };
},
});
registry.register({
name: "sessions.send",
description: "Send a message to a session",
inputSchema: {
type: "object",
properties: {
sessionKey: { type: "string", description: "Target session key" },
text: { type: "string", description: "Message text" },
},
required: ["sessionKey", "text"],
},
handler: async (params, ctx) => {
const { sessionKey, text } = params as { sessionKey: string; text: string };
await sendMessage(sessionKey, text);
return { content: "Message sent" };
},
});
工具执行流程
// src/agents/tools/executor.ts
async function executeToolCall(
call: ToolCall,
registry: ToolRegistry,
ctx: ToolContext
): Promise<ToolResult> {
const tool = registry.get(call.name);
if (!tool) {
return {
content: `Unknown tool: ${call.name}`,
isError: true,
};
}
// 1. 验证参数
const validation = validateInput(tool.inputSchema, call.args);
if (!validation.valid) {
return {
content: `Invalid arguments: ${validation.errors.join(", ")}`,
isError: true,
};
}
// 2. 检查权限(沙箱模式)
if (ctx.sandboxed && !isToolAllowedInSandbox(call.name)) {
return {
content: `Tool ${call.name} is not allowed in sandbox mode`,
isError: true,
};
}
// 3. 执行工具
try {
const result = await tool.handler(call.args, ctx);
return result;
} catch (err) {
return {
content: `Tool execution failed: ${err instanceof Error ? err.message : String(err)}`,
isError: true,
};
}
}
沙箱安全
// 沙箱模式下的工具白名单
const SANDBOX_ALLOWED_TOOLS = new Set([
// 只读工具
"sessions.list",
"sessions.get",
"config.get",
// 受限的文件操作
"fs.read",
"fs.readdir",
// 安全的网络请求
"web.fetch", // 只允许 GET
]);
function isToolAllowedInSandbox(toolName: string): boolean {
return SANDBOX_ALLOWED_TOOLS.has(toolName);
}
Subagent:任务分解与协作
问题:复杂任务需要专业化
当用户说"帮我开发一个完整的 Web 应用"时,单个 Agent 难以处理:
- 需要架构设计
- 需要前端开发
- 需要后端开发
- 需要测试
解决方案:Subagent 机制
flowchart TB
subgraph Main["Main Agent"]
PLAN["分析任务"]
DELEGATE["委派给子 Agent"]
COLLECT["收集结果"]
end
subgraph Subagents["子 Agent 池"]
ARCH["architect<br/>架构设计"]
FRONT["frontend<br/>前端开发"]
BACK["backend<br/>后端开发"]
TEST["tester<br/>测试"]
end
TASK["任务: 开发 Web 应用"] --> PLAN
PLAN --> DELEGATE
DELEGATE --> |"设计架构"| ARCH
DELEGATE --> |"实现前端"| FRONT
DELEGATE --> |"实现后端"| BACK
DELEGATE --> |"编写测试"| TEST
ARCH --> COLLECT
FRONT --> COLLECT
BACK --> COLLECT
TEST --> COLLECT
COLLECT --> RESULT["完成的应用"]
Spawn 参数
// src/agents/acp-spawn.ts
interface SpawnAcpParams {
task: string; // 任务描述
agentId?: string; // 目标 Agent ID
mode?: "run" | "session"; // 运行模式
thread?: boolean; // 是否绑定线程
sandbox?: "inherit" | "require"; // 沙箱模式
streamTo?: "parent"; // 流式输出目标
}
interface SpawnAcpResult {
status: "accepted" | "forbidden" | "error";
childSessionKey?: string; // 子会话键
runId?: string; // 运行 ID
streamLogPath?: string; // 流日志路径
error?: string;
}
Spawn 实现
export async function spawnAcpDirect(
params: SpawnAcpParams,
ctx: SpawnAcpContext
): Promise<SpawnAcpResult> {
const cfg = loadConfig();
// 1. 策略检查
if (!isAcpEnabledByPolicy(cfg)) {
return { status: "forbidden", error: "ACP is disabled by policy" };
}
// 2. 解析目标 Agent
const agentResult = resolveTargetAcpAgentId({
requestedAgentId: params.agentId,
cfg,
});
if (!agentResult.ok) {
return { status: "error", error: agentResult.error };
}
// 3. 生成子会话键
const childSessionKey = generateChildSessionKey({
parentSessionKey: ctx.agentSessionKey,
agentId: agentResult.agentId,
});
// 4. 创建子会话
const handle = await getAcpSessionManager().getOrCreateSession({
sessionKey: childSessionKey,
agent: agentResult.agentId,
mode: params.mode === "session" ? "persistent" : "oneshot",
cwd: params.sandbox === "require" ? createSandboxDir() : undefined,
});
// 5. 启动流式中继(如果需要)
if (params.streamTo === "parent") {
await startAcpSpawnParentStreamRelay({
handle,
parentSessionKey: ctx.agentSessionKey,
});
}
// 6. 执行初始 Turn
await runInitialTurn({ handle, task: params.task });
return {
status: "accepted",
childSessionKey,
mode: params.mode ?? "run",
};
}
Agent 配置示例
# ~/.openclaw/openclaw.yaml
agents:
defaults:
model: gpt-4
provider: openai
list:
- id: main
name: General Assistant
default: true
- id: architect
name: System Architect
model: claude-opus-4-6
provider: anthropic
systemPrompt: |
You are a system architect. Your job is to:
1. Analyze requirements
2. Design system architecture
3. Define APIs and data models
Output structured architecture documents.
- id: coder
name: Code Implementer
model: claude-sonnet-4-6
provider: anthropic
systemPrompt: |
You are a code implementer. Your job is to:
1. Take architecture documents
2. Implement the code
3. Write unit tests
Follow clean code principles.
- id: reviewer
name: Code Reviewer
model: claude-sonnet-4-6
provider: anthropic
systemPrompt: |
You are a code reviewer. Your job is to:
1. Review code for bugs and issues
2. Check for security vulnerabilities
3. Suggest improvements
Be thorough but constructive.
Pi Agent:嵌入式运行时
为什么需要 Pi Agent?
ACP 模式虽然灵活,但需要额外的进程通信开销。对于大多数场景,嵌入式运行时更高效。
Pi Agent 架构
flowchart TB
subgraph PiCore["Pi Agent Core"]
PM[Prompt Manager]
TC[Tool Coordinator]
MM[Memory Manager]
ST[Stream Transformer]
end
subgraph PiAI["Pi AI"]
CL[Claude Backend]
OAI[OpenAI Backend]
GM[Gemini Backend]
end
subgraph PiCoding["Pi Coding Agent"]
FS[File System]
CODE[Code Execution]
LINT[Linter/Formatter]
end
Gateway --> PiCore
PiCore --> PiAI
PiCore --> PiCoding
PiAI --> LLM["LLM APIs"]
Pi Agent 依赖
// 基于 @mariozechner/pi-* 包
import { PiAgentCore } from "@mariozechner/pi-agent-core";
import { PiAI } from "@mariozechner/pi-ai";
import { PiCodingAgent } from "@mariozechner/pi-coding-agent";
// 创建 Pi Agent
const agent = new PiAgentCore({
provider: "openai",
model: "gpt-4",
// 工具配置
tools: loadTools(),
// 记忆配置
memory: {
type: "sliding_window",
maxTokens: 4000,
},
// 系统提示词
systemPrompt: buildSystemPrompt(),
});
// 执行 Turn
for await (const event of agent.runTurn({ message: "Hello" })) {
handleEvent(event);
}
实战演练:自定义 Agent
场景:创建一个代码审查 Agent
# ~/.openclaw/openclaw.yaml
agents:
list:
- id: code-reviewer
name: Code Reviewer
model: claude-sonnet-4-6
provider: anthropic
systemPrompt: |
You are a senior code reviewer. When reviewing code:
1. **Correctness**: Does the code do what it's supposed to do?
2. **Security**: Are there any vulnerabilities?
3. **Performance**: Are there any obvious bottlenecks?
4. **Maintainability**: Is the code readable and well-organized?
5. **Testing**: Are edge cases covered?
Format your review as:
## Summary
[Brief summary]
## Issues
- [SEVERITY] Description
## Suggestions
- [Improvement suggestions]
Use severity: CRITICAL, HIGH, MEDIUM, LOW, INFO
测试 Agent
# 通过 CLI 测试
openclaw agent chat --agent code-reviewer
# 通过 WebSocket 测试
wscat -c "ws://127.0.0.1:18789" -H "Authorization: Bearer $TOKEN"
> {"kind":"request","id":"test","method":"message.send","params":{"sessionKey":"main:code-reviewer","text":"Review this code:\n```python\ndef calc(a,b):\n return a+b\n```"}}
< {"kind":"event","event":"agent","payload":{"type":"text_delta","text":"## Summary\nThis is a simple addition function..."}}
调试 Agent 行为
# 启用 Agent 调试日志
LOG_LEVEL=debug LOG_INCLUDE="agent,acp" openclaw gateway start
# 输出示例
[DEBUG] agent: Creating session for agent: code-reviewer
[DEBUG] agent: Loading tools: sessions.list, sessions.get, fs.read, fs.write
[DEBUG] acp: Starting turn, sessionKey=main:code-reviewer
[DEBUG] acp: Prompt tokens: 450
[DEBUG] acp: LLM response: text_delta "## Summary"
[DEBUG] acp: LLM response: text_delta "This is a..."
[DEBUG] acp: Turn complete, total tokens: 520
常见陷阱
陷阱 1:工具调用超时
症状:
[ERROR] Tool execution timed out after 30000ms
[ERROR] Turn aborted: tool_timeout
原因: 工具执行时间超过了默认的超时限制(30秒),导致 Turn 被中断。
错误代码:
// 工具执行没有设置合理的超时
async function handler(params, ctx) {
const result = await fetch('https://slow-api.example.com/data');
// 如果 API 响应慢,会触发超时
return { content: await result.text() };
}
正确代码:
// 正确写法:使用 AbortSignal 控制超时
async function handler(params, ctx) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 25000); // 25秒超时,留缓冲
try {
const result = await fetch('https://slow-api.example.com/data', {
signal: ctx.abortSignal || controller.signal,
});
return { content: await result.text() };
} finally {
clearTimeout(timeoutId);
}
}
调试方法:
# 查看工具执行详情
LOG_LEVEL=debug LOG_INCLUDE="tools,executor" openclaw gateway start
# 输出示例
[DEBUG] tools: Executing tool: weather.get
[DEBUG] tools: Tool params: {"city":"北京"}
[DEBUG] tools: Tool execution started at 2026-03-14T10:30:00.000Z
[DEBUG] tools: Tool execution timed out after 30000ms
源码位置: src/agents/tools/executor.ts
陷阱 2:Subagent 权限拒绝
症状:
{
"type": "tool_result",
"id": "tc_spawn",
"result": "{\"status\":\"forbidden\",\"error\":\"ACP is disabled by policy\"}"
}
原因: Subagent 的 spawn 请求被策略拦截,可能是因为:
- 配置中禁用了 ACP
- 目标 Agent 不在允许列表中
- 沙箱模式不兼容
错误配置:
# ~/.openclaw/openclaw.yaml
# 问题:禁用了 ACP 但尝试使用 Subagent
acp:
enabled: false
正确配置:
# ~/.openclaw/openclaw.yaml
acp:
enabled: true
# 配置允许的 Agent
agents:
allowed:
- main
- architect
- coder
# 沙箱策略
sandbox:
mode: optional # inherit | require | optional
调试方法:
# 检查 ACP 配置
openclaw config get acp
# 输出
acp.enabled: true
acp.agents.allowed: ["main", "architect", "coder"]
# 查看 spawn 请求日志
LOG_LEVEL=debug LOG_INCLUDE="spawn,acp" openclaw gateway start
# 输出示例
[DEBUG] spawn: Spawn request: agent=architect, mode=run
[DEBUG] spawn: Checking policy...
[DEBUG] spawn: Policy check passed
[DEBUG] spawn: Creating child session: main:architect:spawn_abc123
源码位置: src/agents/acp-spawn.ts
陷阱 3:工具参数验证失败
症状:
{
"type": "tool_result",
"id": "tc_123",
"result": "Invalid arguments: sessionKey is required, text is required",
"isError": true
}
原因: LLM 生成的工具调用参数不符合 JSON Schema 定义,导致验证失败。
错误代码:
// Schema 定义不清晰,LLM 容易误解
registry.register({
name: "sessions.send",
description: "Send a message", // 描述太简略
inputSchema: {
type: "object",
properties: {
sessionKey: { type: "string" }, // 缺少描述
text: { type: "string" }, // 缺少描述
},
required: ["sessionKey", "text"],
},
handler: async (params, ctx) => { ... },
});
正确代码:
// 清晰的 Schema 定义
registry.register({
name: "sessions.send",
description: "Send a message to a specific session. Use this to communicate with other sessions.",
inputSchema: {
type: "object",
properties: {
sessionKey: {
type: "string",
description: "The target session key, format: 'channel:identifier' (e.g., 'whatsapp:+1234567890')"
},
text: {
type: "string",
description: "The message text to send"
},
},
required: ["sessionKey", "text"],
},
handler: async (params, ctx) => { ... },
});
调试方法:
# 启用详细日志查看验证错误
LOG_LEVEL=debug LOG_INCLUDE="tools,validation" openclaw gateway start
# 输出示例
[DEBUG] tools: Validating params for tool: sessions.send
[DEBUG] tools: Schema: {"type":"object","properties":{...}}
[DEBUG] tools: Input: {"sessionKey":123} // 类型错误
[DEBUG] tools: Validation failed: sessionKey must be string
源码位置: src/agents/tools/executor.ts
陷阱 4:沙箱模式工具被阻止
症状:
{
"type": "tool_result",
"id": "tc_fs_write",
"result": "Tool fs.write is not allowed in sandbox mode",
"isError": true
}
原因: 当前会话运行在沙箱模式下,某些危险工具被禁止使用。
错误代码:
// 尝试在沙箱中执行受限操作
await ctx.executeTool("fs.write", {
path: "/etc/passwd",
content: "..."
});
正确代码:
// 检查沙箱状态后再执行
if (ctx.sandboxed) {
// 使用沙箱允许的替代方案
const sandboxPath = path.join(ctx.cwd || "/tmp/sandbox", "output.txt");
await ctx.executeTool("fs.write", { path: sandboxPath, content: "..." });
} else {
// 非沙箱模式可以访问完整文件系统
await ctx.executeTool("fs.write", { path: targetPath, content: "..." });
}
调试方法:
# 查看当前会话的沙箱状态
openclaw session get <sessionKey> --json | jq '.sandboxed'
# 查看沙箱允许的工具列表
openclaw config get sandbox.allowedTools
# 输出
["sessions.list", "sessions.get", "fs.read", "fs.readdir", "web.fetch"]
源码位置: src/agents/tools/executor.ts
设计启示:Agent 模式的权衡
当前设计的优势
| 设计 | 优势 |
|---|---|
| ACP 协议 | 统一不同后端,支持自定义 Agent |
| 流式事件 | 实时反馈,支持中断 |
| 工具系统 | 可扩展,支持沙箱隔离 |
| Subagent | 任务分解,专业化处理 |
当前设计的劣势
| 问题 | 原因 | 可能的解决方案 |
|---|---|---|
| 工具调用延迟 | 需要等待 LLM 决定 → 执行 → 继续 | 并行工具调用 |
| 记忆管理 | 上下文窗口有限 | 向量数据库 + RAG |
| Agent 切换 | 需要 NLP 解析意图 | 显式 @mention 或命令 |
与其他 Agent 框架对比
| 特性 | OpenClaw | LangChain | AutoGPT | CrewAI |
|---|---|---|---|---|
| 运行时模式 | Embedded + ACP | 链式调用 | 循环执行 | 多 Agent |
| 工具系统 | 插件 + 沙箱 | Python 函数 | 自定义 | 角色-任务 |
| 流式支持 | ✅ 原生 | ⚠️ 部分 | ❌ | ⚠️ 部分 |
| 多渠道 | ✅ 20+ | ❌ | ❌ | ❌ |
| 状态持久化 | ✅ SQLite | ⚠️ 可选 | ⚠️ JSON | ⚠️ 可选 |
小结
Agent 是 OpenClaw 的核心,它让 LLM 从"文本生成器"变成"智能助手":
| 组件 | 职责 | 关键概念 |
|---|---|---|
| ACP 协议 | 统一后端接口 | AcpRuntime 接口 |
| Turn 执行 | 一次对话的处理 | 事件流 + 工具调用 |
| 工具系统 | 扩展 Agent 能力 | 工具注册 + 沙箱隔离 |
| Subagent | 任务分解 | Spawn 机制 |
| Pi Agent | 嵌入式运行时 | 零通信开销 |
关键源码文件
| 文件 | 职责 |
|---|---|
src/acp/runtime/types.ts |
ACP 协议类型定义 |
src/acp/control-plane/manager.ts |
ACP Session 管理 |
src/agents/tools/registry.ts |
工具注册表 |
src/agents/tools/executor.ts |
工具执行器 |
src/agents/acp-spawn.ts |
Subagent Spawn |
在下一篇文章中,我们将进入 扩展点——如何开发自己的 Channel Plugin、工具和钩子,打造属于你的 OpenClaw。
系列索引: OpenClaw 源码解析:目录索引
上一篇: OpenClaw 源码解析(二):消息的一生 下一篇: OpenClaw 源码解析(四):扩展点