目录
- 【OpenClaw】通过 Nanobot 源码学习架构 —(4)SubAgent
- 0x00 概要
- 0x01 基础背景
- 1.1 原理:为什么需要 SubAgent?
- 1.2 架构拓扑的演进
- 1.3 领域隔离
- 1.4 工作场景:Skills vs SubAgent,如何选择?
- 1.5 工作流:主从协作的典型模式
- 0x02 Nanobot SubAgent 功能
- 2.1 SubAgent 与主 Agent 的区别
- 2.1.1 设计目的
- 2.1.2 Subagent 优势
- 2.2 SubagentManager 类
- 2.2.1 初始化参数
- 2.2.2 内部状态管理
- 2.3 创建子代理流程
- 2.3.1 spawn() 方法详解
- 2.3.2 子代理创建步骤
- 2.4 子代理执行逻辑
- 2.4.1. 构建子代理专用工具集
- 2.4.2. 构建子代理专用提示
- 2.4.3. 运行 Agent 循环(限制迭代次数)
- 2.4.4. 处理工具调用
- 2.4.5. 处理完成条件
- 2.4.6. 处理未完成情况
- 2.4.7. 通知结果
- 2.4.8. 错误处理
- 2.5 结果通知机制
- 2.5.1 通知内容构建
- 2.5.2 注入消息总线
- 2.6 会话级取消机制
- 2.7 状态查询方法
- 0x03 Subagent 与 Main Agent 的关系分析
- 3.1 相同的组件
- 3.1.1 LLM Provider 完全共享
- 3.1.2 MessageBus 共享
- 3.1.3 Workspace 路径相同
- 3.1.4 配置参数
- 3.2 不同的组件
- 3.2.1 工具集(ToolRegistry)完全不同且受限
- 3.2.2 System Prompt 完全不同
- 3.2.3 消息历史完全隔离
- 3.2.4 最大迭代次数不同
- 3.2.5 结果处理方式不同
- 3.2.6 会话管理方式不同
- 3.3 创建流程对比
- 3.3.1 Main Agent 创建(在 gateway()):
- 3.3.2 Subagent 创建(在 SubagentManager.spawn()):
- 0xFF 参考
OpenClaw 应该有40万行代码,阅读理解起来难度过大,因此,本系列通过Nanobot来学习 OpenClaw 的特色。
Nanobot是由香港大学数据科学实验室(HKUDS)开源的超轻量级个人 AI 助手框架,定位为”Ultra-Lightweight OpenClaw“。非常适合学习Agent架构。
nanobot 的 Subagent 实现是一个简洁但强大的后台任务执行机制。通过复用主 Agent 的 LLM provider 但限制工具集和迭代次数,实现了任务隔离和资源控制。消息总线机制确保子代理结果能够顺利通知主 Agent,最终传达给用户。这种设计使得主 Agent 可以保持专注的对话交互,同时将复杂任务委派给后台子代理执行。
Parent agent Subagent +——————+ +——————+ | messages=[…] | | messages=[] | <– fresh | | dispatch | | | tool: task | ———-> | while tool_use: | | prompt=”…” | | call tools | | | summary | append results | | result = “…” | <———- | return last text | +——————+ +——————+
Parent context stays clean. Subagent context is discarded.
注:本系列借鉴的文章过多,可能在参考文献中有遗漏的文章,如果有,还请大家指出。
SubAgent(子智能体)是从现有 Agent 运行中生成的后台独立运行实例。它们在独立的会话中执行任务,完成后将结果自动通告回请求者的聊天渠道。
表面上看,SubAgent 解决的是「并行执行」问题——多个任务同时推进,提升效率。然而事实上,拆分 Agent 不只是为了”分工”,更是为了”上下文压缩”或者说”上下文隔离”。
我们思考下:当一个 Agent 试图”全包”所有角色时会发生什么?随着对话轮次增加,系统提示词和历史记录会越来越臃肿。这直接导致三个连锁反应:
- 模型更容易遗忘早期约束
- 推理漂移——偏离原始任务目标
- 成本上升——Token 消耗持续累积
最终,单一上下文窗口已经无法承载当前任务的复杂度需求。
这引出了单 Agent 架构的本质权衡:
因此,关键问题浮现:当单点突破遇到上下文瓶颈时,我们该如何通过架构演进,在保持灵活性的同时解决知识承载的问题?
这正是 SubAgent 被引入的核心动机。
从协作模式看,SubAgent 的引入形成了两种典型架构:
后一种模式的核心逻辑在于”路由分发“与”领域隔离“:
- 主 Agent(Orchestrator):扮演”大脑”角色,仅负责意图识别与任务路由,判断”这个问题该交给谁”,而无需背负所有领域的知识重担。
- 子 Agent(Sub-Agent):拥有独立的 Identity 空间,内化特定领域的专业知识。每个子 Agent 只需专注于解决某一类垂直场景,其 Prompt 指令更精简,领域知识更聚焦。
从上下文工程(Context Engineering)的角度看,SubAgent 实现了 Isolate 机制——上下文隔离。这种隔离通常由三种触发条件驱动:
- 隔离噪声——避免失败路径或中间探索污染后续推理
- 隔离关注点——让专业化的工具集各司其职,减少干扰
- 突破物理限制——通过并行扩展单 Agent 的 Token 上限
如何识别需要拆分的信号? 当以下现象出现时,便是架构调整的时机:
- 上下文窗口接近极限(表现为幻觉率上升、忽略早期指令)
- 工具集过大(频繁选错工具,且工具集内有明显的专业领域区分)
- 需要覆盖大信息空间(搜索覆盖面不足,单 Agent 无法遍历)
把任务拆给专业 Agent,让它在独立上下文中完成子任务再返回结果,相当于把上下文按职责切片。这不仅通常会更稳、更便宜,更是一种主动的上下文噪声隔离。
我们用操作系统类比来理解两者的定位差异:Skills 是应用程序,装在主系统里按需调用;SubAgent 是虚拟机,独立运行完再把结果交回来。
一句话总结选择逻辑:任务简单用应用,任务复杂开虚拟机。
SubAgent 是典型的主从协作管理模式。我们以一个具体场景为例:
用户要求:”帮我分析这个代码仓库,同时整理几份竞品资料,然后给我一份对比报告”
执行流程如下:
- 主 Agent 继续和用户保持对话,确认细节
- 同时
spawn一个 SubAgent 去分析仓库结构 - 再
spawn一个 SubAgent 去整理竞品资料 - 两个 SubAgent 并行执行,各自拥有精简的 System Prompt
- 最后统一收口,主 Agent 基于两份摘要完成对比分析
我们拆解这个流程的 Context Engineering 价值:通过 层层外包 + 只传结果 的机制,将大任务分解后的中间过程”隔离”在子 Agent 内,主 Agent 的 Context 始终保持精简。
主Agent接收任务
↓
[tool_use] Spawn(分析仓库结构), Spawn(整理竞品资料)
↓
两个Sub-agent并行执行(各自有精简System Prompt)
↓
返回仓库结构、竞品资料
↓
主Agent Context中只有库结构、竞品资料的摘要,没有详尽的信息
↓
主Agent完成比较分析
因此,SubAgent 的本质定义是:Agent 可以召唤的”子实例”,以精简 System Prompt 专注单一任务,主 Agent 只接收摘要结果,Context Window 中不保留子任务的完整执行过程。
SubAgent 是 nanobot 的后台任务执行机制,允许主 Agent 派生独立的子代理来执行耗时或独立的任务,而不阻塞主对话流程。
2.1.1 设计目的
- 主 Agent:专注于用户对话,提供即时响应,管理会话状态和记忆
- Subagent:专注于执行耗时任务,不阻塞主对话,独立完成后通知主 Agent,子代理有独立的工具集和执行限制
2.1.2 Subagent 优势
- 响应性:主 Agent 不会被耗时任务阻塞,保持与用户的实时交互
- 并发性:多个子代理可以同时运行,执行不同任务
- 隔离性:子代理有独立的工具集和限制,不会干扰主对话
- 可取消性:通过 session_key 实现会话级的任务取消
- 结果聚合:子代理结果通过主 Agent 统一格式化后发送给用户
2.2.1 初始化参数
class SubagentManager:
"""Manages background subagent execution.""" def __init__( self, provider: LLMProvider, # LLM 提供商(复用主 Agent 的) workspace: Path, # 工作空间路径 bus: MessageBus, # 消息总线(用于通知主 Agent) model: str | None = None, # 模型名称 temperature: float = 0.7, # 温度参数 max_tokens: int = 4096, # 最大 token 数 brave_api_key: str | None = None, # 网络搜索 API 密钥 exec_config: ExecToolConfig | None = None, # Shell 执行配置 restrict_to_workspace: bool = False, # 是否限制到工作空间 ):
2.2.2 内部状态管理
_running_tasks:映射 task_id 到 asyncio.Task,存储所有运行的子代理任务-
_session_tasks:映射 session_key 到 task_id 集合,追踪每个会话关联的子代理
self._running_tasks: dict[str, asyncio.Task | None] = {} self._session_tasks: dict[str, set[str]] = {}
2.3.1 spawn() 方法详解
spawn() 方法是创建子代理的入口点:
async def spawn( self, task: str, # 子代理要执行的任务描述 label: str | None = None, # 显示标签(用于用户识别) origin_channel: str = "cli", # 原始渠道(用于结果通知) origin_chat_id: str = "direct", # 原始聊天 ID session_key: str | None = None, # 会话键(用于会话级取消)
) -> str:
2.3.2 子代理创建步骤
- 生成唯一标识符
task_id = str(uuid.uuid4())[:8] # 生成 8 字符的 UUID4,如 “a1b2c3d4” display_label = label or task[:30] + (“…” if len(task) > 30 else “”)
- 记录原始来源
origin = {“channel”: origin_channel, “chat_id”: origin_chat_id}
用于后续将结果通知回正确的用户/渠道。
- 创建并启动后台任务
bg_task = asyncio.create_task( self._run_subagent(task_id, task, display_label, origin)
) self._running_tasks[task_id] = bg_task
创建异步任务来运行子代理,并将其注册到 _running_tasks 字典中。
- 关联到会话
if session_key: self._session_tasks.setdefault(session_key, set()).add(task_id)
如果提供了 session_key,将 task_id 加入该会话的子代理集合。这使得 /stop 命令可以取消整个会话的所有子代理。
- 设置清理回调
def _cleanup(_: asyncio.Task) -> None: self._running_tasks.pop(task_id, None) if session_key and (ids := self._session_tasks.get(session_key)): ids.discard(task_id) if not ids: del self._session_tasks[session_key]
bg_task.add_done_callback(_cleanup)
当子代理任务完成(无论成功或失败)时,回调函数执行:
- 从
_running_tasks移除 task_id - 从会话的 task_id 集合中移除
- 如果该会话没有剩余的子代理,删除会话集条目
- 返回用户反馈
return f”Subagent [{display_label}] started (id: {task_id}). I’ll notify you when it completes.”
_run_subagent() 是子代理的核心执行方法,负责完整的 Agent 循环,其具体逻辑如下:
2.4.1. 构建子代理专用工具集
tools = ToolRegistry() allowed_dir = self.workspace if self.restrict_to_workspace else None tools.register(ReadFileTool(workspace=self.workspace, allowed_dir=allowed_dir)) tools.register(WriteFileTool(workspace=self.workspace, allowed_dir=allowed_dir)) tools.register(EditFileTool(workspace=self.workspace, allowed_dir=allowed_dir)) tools.register(ListDirTool(workspace=self.workspace, allowed_dir=allowed_dir)) tools.register(ExecTool(
working_dir=str(self.workspace), timeout=self.exec_config.timeout, restrict_to_workspace=self.restrict_to_workspace, path_append=self.exec_config.path_append,
)) tools.register(WebSearchTool(api_key=self.brave_api_key)) tools.register(WebFetchTool())
重要设计:子代理的工具集与主 Agent 不同:
- 包含:文件读写、目录列表、Shell 执行、网络搜索和获取
- 排除:MessageTool(不能直接发送消息给用户)
- 排除:SpawnTool(不能派生更多子代理)
- 排除:CronTool(不能创建定时任务)
这种设计确保子代理专注于执行任务,不会干扰主对话流程或创建递归任务。
2.4.2. 构建子代理专用提示
system_prompt = self._build_subagent_prompt(task) messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": task},
]
系统提示明确子代理的角色和限制:
# Subagent Current Time
{now} ({tz})
You are a subagent spawned by main agent to complete a specific task.
Rules
- Stay focused - complete only the assigned task, nothing else
- Your final response will be reported back to main agent
- Do not initiate conversations or take on side tasks
- Be concise but informative in your findings
What You Can Do
- Read and write files in workspace
- Execute shell commands
- Search web and fetch web pages
- Complete task thoroughly
What You Cannot Do
- Send messages directly to users (no message tool available)
- Spawn other subagents
- Access main agent’s conversation history
Workspace
Your workspace is at: {workspace} Skills are available at: {workspace}/skills/ (read SKILL.md files as needed)
When you have completed the task, provide a clear summary of your findings or actions.
这个提示确保子代理:
- 专注于分配的任务
- 不会发起新对话
- 不会尝试与用户直接交互
- 知道自己的能力边界
2.4.3. 运行 Agent 循环(限制迭代次数)
子代理使用与主 Agent 相同的 LLM provider,但迭代次数限制为 15 次,避免子代理运行过久。
max_iterations = 15 # 子代理的最大迭代次数(主 Agent 是 40) iteration = 0 final_result: str | None = None while iteration < max_iterations:
iteration += 1 response = await self.provider.chat( messages=messages, tools=tools.get_definitions(), model=self.model, temperature=self.temperature, max_tokens=self.max_tokens, )
2.4.4. 处理工具调用
工具调用处理逻辑与主 Agent 类似:
- 将工具调用添加到消息历史
- 逐个执行工具
- 将工具结果添加到消息历史
- 继续循环,等待 LLM 下一轮响应
if response.has_tool_calls: # 构建工具调用消息 tool_call_dicts = [ { "id": tc.id, "type": "function", "function": { "name": tc.name, "arguments": json.dumps(tc.arguments, ensure_ascii=False), }, } for tc in response.tool_calls ] messages.append({ "role": "assistant", "content": response.content or "", "tool_calls": tool_call_dicts, }) # 执行工具 for tool_call in response.tool_calls: result = await tools.execute(tool_call.name, tool_call.arguments) messages.append({ "role": "tool", "tool_call_id": tool_call.id, "name": tool_call.name, "content": result, })
2.4.5. 处理完成条件
当 LLM 返回文本响应而没有工具调用时,视为任务完成,退出循环。
else: final_result = response.content break
2.4.6. 处理未完成情况
如果达到最大迭代次数仍未产生最终响应,使用默认消息。
if final_result is None: final_result = "Task completed but no final response was generated."
2.4.7. 通知结果
成功完成时调用 _announce_result() 方法通知主 Agent。
logger.info("Subagent [{}] completed successfully", task_id)
await self._announce_result(task_id, label, task, final_result, origin, “ok”)
2.4.8. 错误处理
如果执行过程中发生异常,捕获并通知主 Agent 错误信息。
except Exception as e: error_msg = f"Error: {str(e)}" logger.error("Subagent [{}] failed: {}", task_id, e) await self._announce_result(task_id, label, task, error_msg, origin, "error")
子代理完成任务后,需要将结果通知给主 Agent,主 Agent 再转发给用户。_announce_result() 方法完成了此功能。
async def _announce_result( self, task_id: str, label: str, task: str, result: str, origin: dict[str, str], status: str,
) -> None:
2.5.1 通知内容构建
status_text = “completed successfully” if status == “ok” else “failed” announce_content = f”“”[Subagent ‘{label}’ {status_text}] Task: {task} Result: {result}
Summarize this naturally for the user. Keep it brief (1-2 sentences). Do not mention technical details like “subagent” or task IDs.“””
通知内容包含:
- 子代理标签和状态
- 原始任务描述
- 执行结果
- 指示主 Agent 如何处理(简洁地总结给用户)
2.5.2 注入消息总线
InboundMessage 通过 bus.publish_inbound() 将通知发布到入站队列。这会被 AgentLoop 接收并处理,最终将总结转发给用户。
msg = InboundMessage( channel="system", # 使用 system 渠道标识 sender_id="subagent", # 标识来自子代理 chat_id=f"{origin['channel']}:{origin['chat_id']}", # 原始渠道和聊天 ID content=announce_content, # 通知内容
)
await self.bus.publish_inbound(msg)
cancel_by_session() 方法实现了会话级取消机制。这个方法被主 Agent 的 /stop 命令处理调用,实现会话级的任务清理。
async def cancel_by_session(self, session_key: str) -> int: """Cancel all subagents for a given session. Returns count cancelled.""" tasks = [ self._running_tasks[tid] for tid in self._session_tasks.get(session_key, []) if tid in self._running_tasks and not self._running_tasks[tid].done() ] for t in tasks: t.cancel() if tasks: await asyncio.gather(*tasks, return_exceptions=True) return len(tasks)
取消流程如下:
- 从
_session_tasks获取该会话关联的所有 task_id - 筛选出未完成的任务
- 对每个任务调用
cancel()方法 - 等待所有任务取消完成
- 返回取消的任务数量
get_running_count() 返回当前运行的子代理数量,可用于监控和状态报告。
def get_running_count(self) -> int: """Return number of currently running subagents.""" return len(self._running_tasks)
Subagent 不是 Main Agent 的完全克隆,而是一个共享部分组件但功能受限的独立执行单元。Subagent 的设计模式是"共享基础组件 + 独立执行环境":
- 共享资源:LLM Provider、MessageBus、Workspace、配置参数
- 隔离执行:独立的工具集、消息历史、系统提示
- 受限能力:不能发送消息、不能派生子代理、无对话历史
- 结果聚合:通过 MessageBus 通知 Main Agent,由 Main Agent 统一输出
这种设计避免了子代理干扰主对话流程,同时确保资源高效利用。
架构关系图如下:

主Agent和SubAgent的对比如下:
3.1.1 LLM Provider 完全共享
共享原因:避免重复创建 API 连接,节省资源和维护成本。LLM 调用是无状态的,多个 Agent 可以安全地共享同一个 provider。
# SubagentManager 初始化时
self.provider = provider # 和 Main Agent 使用同一个实例
Subagent 执行时
response = await self.provider.chat(
messages=messages, tools=tools.get_definitions(), model=self.model, temperature=self.temperature, max_tokens=self.max_tokens,
)
3.1.2 MessageBus 共享
共享原因:Subagent 需要通过 MessageBus 将结果通知给 Main Agent,不是用来处理用户消息。
self.bus = bus # 和 Main Agent 使用同一个实例 Subagent 完成任务后
await self.bus.publish_inbound(msg) # 通知 Main Agent
3.1.3 Workspace 路径相同
共享原因:Subagent 访问相同的文件系统,能够读写主 Agent 工作空间中的文件。
self.workspace = workspace # 和 Main Agent 使用同一个路径 Subagent 中的工具
tools.register(ReadFileTool(workspace=self.workspace, …))
3.1.4 配置参数
主Agent和Subagent的配置参数相同,虽然具体数值会有不同。
3.2.1 工具集(ToolRegistry)完全不同且受限
设计意图:Subagent 是”工具型”执行单元,专注于完成任务,不进行交互式对话或启动更多子任务。
Subagent 使用的工具:
tools = ToolRegistry() tools.register(ReadFileTool(…)) # 文件读取 tools.register(WriteFileTool(…)) # 文件写入 tools.register(EditFileTool(…)) # 文件编辑 tools.register(ListDirTool(…)) # 目录列表 tools.register(ExecTool(…)) # Shell 执行 tools.register(WebSearchTool(…)) # 网络搜索 tools.register(WebFetchTool(…)) # 网页获取
Subagent 排除的工具:
- ❌ MessageTool:不能直接发送消息给用户
- ❌ SpawnTool:不能派生更多子代理(避免递归爆炸)
- ❌ CronTool:不能创建定时任务
Main Agent 包含的工具:
# 除了上述 7 个工具外,还包含:
- MessageTool (发送消息给渠道)
- SpawnTool (派生子代理)
- CronTool (引用 cron_service)
- MCPServersTool (连接 MCP 服务器)
- SkillsTool (动态加载技能)
3.2.2 System Prompt 完全不同
区别:Subagent 的提示是”聚焦式”的,强调专注任务、不发起对话;Main Agent 的提示是”对话式”的,包含完整指南和记忆。
Subagent 的系统提示:
def _build_subagent_prompt(self, task: str) -> str: return f”“”# Subagent Current Time
{now} ({tz})
You are a subagent spawned by main agent to complete a specific task.
Rules
- Stay focused - complete only assigned task, nothing else
- Your final response will be reported back to main agent
- Do not initiate conversations or take on side tasks
- Be concise but informative in your findings
What You Can Do
- Read and write files in workspace
- Execute shell commands
- Search web and fetch web pages
- Complete task thoroughly
What You Cannot Do
- Send messages directly to users (no message tool available)
- Spawn other subagents
- Access main agent’s conversation history …“””
Main Agent 的系统提示:
# nanobot 🐈 You are nanobot, a helpful AI assistant.
Runtime
{system} {machine}, Python {version}
Workspace
Your workspace is at: {workspace_path}
nanobot Guidelines
- State intent before tool calls…
- Before modifying a file, read it first… …
(还会包含 Bootstrap Files、Long-term Memory、Skills 等)
3.2.3 消息历史完全隔离
区别:Subagent 没有对话历史,每次都是”全新”的开始;Main Agent 有完整的会话记忆,支持多轮对话。
Subagent 的消息:
messages = [ {"role": "system", "content": subagent_system_prompt}, {"role": "user", "content": task}, # 只有当前任务描述
]
Main Agent 的消息:
messages = [ {"role": "system", "content": main_system_prompt}, *history, # 完整的会话历史(可能数百条) {"role": "user", "content": runtime_context}, # 运行时元数据 {"role": "user", "content": current_message},
]
3.2.4 最大迭代次数不同
原因:Subagent 执行的任务应该是相对独立的和快速的,避免子代理运行过久占用资源。
3.2.5 结果处理方式不同
Subagent 的结果:
# Subagent 不直接发送结果给用户 final_result = response.content await self._announce_result(task_id, label, task, final_result, origin, “ok”) 通过 MessageBus 通知 Main Agent,Main Agent 再转发给用户
Main Agent 的结果:
# Main Agent 直接发送结果给用户 await self.bus.publish_outbound(OutboundMessage(
channel=msg.channel, chat_id=msg.chat_id, content=final_content,
))
3.2.6 会话管理方式不同
Subagent:
- 没有 SessionManager 引用
- 消息历史在内存中(
messages列表) - 不持久化会话到磁盘
- 不涉及记忆归档
Main Agent:
- 有 SessionManager 引用
- 会话持久化到 JSONL 文件
- 支持 memory 归档到 MEMORY.md
- 支持多轮对话记忆
3.3.1 Main Agent 创建(在 gateway()):
agent = AgentLoop( bus=bus, # 共享 provider=provider, # 共享 workspace=workspace, # 共享 model=config.agents.defaults.model, temperature=config.agents.defaults.temperature, max_tokens=config.agents.defaults.max_tokens, max_iterations=40, # 完整对话需要更多迭代 memory_window=config.agents.defaults.memory_window, session_manager=SessionManager(...), # 独有:会话持久化 cron_service=cron, # 独有:定时任务服务 mcp_servers=config.tools.mcp_servers, # 独有:MCP 服务器 channels_config=config.channels, # 独有:渠道配置
)
3.3.2 Subagent 创建(在 SubagentManager.spawn()):
# 通过 _run_subagent() 内部直接创建,不通过构造函数 async def _run_subagent(self, task_id, task, label, origin): # 工具集:受限的 7 个工具 tools = ToolRegistry() tools.register(ReadFileTool(...)) # ... (不含 MessageTool, SpawnTool, CronTool) # System Prompt:聚焦式提示 system_prompt = self._build_subagent_prompt(task) # 消息:只有当前任务,无历史 messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": task}, ] # 迭代次数:15 次 max_iterations = 15 # 循环执行 while iteration < max_iterations: response = await self.provider.chat(...) # 使用共享的 provider # ...
多智能体的记忆瓶颈,和CPU缓存一致性是同一个问题?
SubAgent 与 Skills:AI Agent 的两种扩展方式
万字】带你实现一个Agent(上),从Tools、MCP到Skills
3500 行代码打造轻量级AI Agent:Nanobot 架构深度解析
Kimi Agent产品很厉害,然后呢?
OpenClaw真完整解说:架构与智能体内核
https://github.com/shareAI-lab/learn-claude-code
深入理解OpenClaw技术架构与实现原理(上)
深度解析:一张图拆解OpenClaw的Agent核心设计
OpenClaw小龙虾架构全面解析
OpenClaw架构-Agent Runtime 运行时深度拆解
OpenClaw 架构详解 · 第一部分:控制平面、会话管理与事件循环
从回答问题到替你做事,AI Agent 为什么突然火了?
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/260481.html