2026年OpenClaw Nanobot 架构拆解:从源码学会 AI Agent 的骨架设计(2026)

OpenClaw Nanobot 架构拆解:从源码学会 AI Agent 的骨架设计(2026)上周五在折腾一个自动化代码审查的 Agent 写到一半发现自己在重复造轮子 任务调度 工具注册 上下文管理 每个都自己糊一遍 代码丑得我自己都不想看 正好那几天 OpenClaw 冲到 GitHub 20 万 Star 热榜上全是它的入门教程 就想着与其瞎搞 不如把 OpenClaw 的 Nanobot 架构拆一遍 看看人家怎么设计的 花了两天啃源码 说实话 OpenClaw 的

大家好,我是讯享网,很高兴认识大家。这里提供最前沿的Ai技术和互联网信息。



上周五在折腾一个自动化代码审查的 Agent,写到一半发现自己在重复造轮子——任务调度、工具注册、上下文管理,每个都自己糊一遍,代码丑得我自己都不想看。正好那几天 OpenClaw 冲到 GitHub 20 万 Star,热榜上全是它的入门教程,就想着与其瞎搞,不如把 OpenClaw 的 Nanobot 架构拆一遍,看看人家怎么设计的。

花了两天啃源码。说实话,OpenClaw 的 Nanobot 架构是我 2026 年见过的最干净的 Agent 设计模式——轻量、可组合、Skills 热插拔。这篇是我的学习笔记,把核心架构、关键代码、踩的坑全记下来,顺便用 Claude 4.6 跑一个完整的 Nanobot 示例。

维度 说明 Nanobot 是什么 OpenClaw 的最小 Agent 执行单元,一个 Nanobot = 一个 System Prompt + 一组 Skills + 一个模型绑定 核心设计思想 单一职责 + 组合模式,多个 Nanobot 可以编排成复杂 Agent Skills 是什么 类似 Function Calling 的工具注册机制,支持热插拔和版本管理 适合谁学 想自己搭 Agent 框架的开发者,或者想深入理解 OpenClaw 而不只是当用户的人 学习成本 有 Python 基础 + 了解 Function Calling 概念,2-3 小时能跑通

先上一张我梳理的架构图,后面所有内容围绕这张图展开:

graph TB User[用户输入] --> Orchestrator[编排器 Orchestrator] Orchestrator --> NB1[Nanobot: 代码分析] Orchestrator --> NB2[Nanobot: 文档生成] Orchestrator --> NB3[Nanobot: 测试编写] NB1 --> SK1[Skill: read_file] NB1 --> SK2[Skill: ast_parse] NB1 --> LLM[LLM API] NB2 --> SK3[Skill: markdown_render] NB2 --> LLM NB3 --> SK4[Skill: run_pytest] NB3 --> SK1 NB3 --> LLM LLM --> Provider[API Provider] Provider --> GPT5[GPT-5] Provider --> Claude[Claude 4.6] Provider --> GLM[GLM-5] 

三层结构:编排器负责调度,Nanobot 负责执行,Skills 负责干活。模型调用是 Nanobot 的内部行为,外部只关心输入输出。

# Python 3.11+ pip install openclaw>=0.9.0 pip install openai # OpenClaw 底层用 OpenAI 兼容协议调模型 

OpenClaw 的模型调用层走 OpenAI 兼容协议,任何兼容 OpenAI API 格式的服务都能接。这一点后面会用到。

一个 Nanobot 的定义文件长这样(YAML 格式):

# nanobot.yaml name: code_reviewer version: "1.0" description: "审查 Python 代码质量并给出改进建议" system_prompt: | 你是一个资深 Python 代码审查员。 审查重点:代码可读性、潜在 bug、性能问题。 输出格式:按严重程度排序,每条包含行号、问题描述、修复建议。  model: provider: openai_compatible model_name: claude-sonnet-4- temperature: 0.3 skills: - read_file - ast_parse - search_codebase 

就这些。没有复杂的继承关系,没有抽象工厂,纯声明式配置。我第一次看到的时候想:就这?

但仔细想想这个设计确实聪明——把 Agent 的行为完全用配置描述,运行时由框架装配。换模型改一行 model_name,加工具在 skills 列表追加一个。

光看 YAML 没意思,从 Python 代码层面理解 Nanobot 的运行机制。

OpenClaw 的核心类是 Nanobot,我把源码里的关键逻辑简化了一版:

from openai import OpenAI import json class Nanobot: """OpenClaw Nanobot 核心逻辑简化版""" def __init__(self, name: str, system_prompt: str, model: str, skills: list = None): self.name = name self.system_prompt = system_prompt self.model = model self.skills = skills or [] self.skill_registry = {} # 初始化 LLM 客户端 self.client = OpenAI( api_key="your-key", base_url="https://api.ofox.ai/v1" # 聚合接口,一个 Key 调所有模型 ) # 注册 skills for skill in self.skills: self._register_skill(skill) def _register_skill(self, skill_func): """把 Python 函数注册为 Skill(本质是 Function Calling 的 tool)""" tool_def = }) } } self.skill_registry[skill_func.__name__] = { "definition": tool_def, "handler": skill_func } def run(self, user_input: str, max_rounds: int = 5) -> str: """执行 Nanobot 的核心循环:LLM 推理 → 调用 Skill → 再推理""" messages = [ {"role": "system", "content": self.system_prompt}, {"role": "user", "content": user_input} ] tools = [s["definition"] for s in self.skill_registry.values()] for round_num in range(max_rounds): response = self.client.chat.completions.create( model=self.model, messages=messages, tools=tools if tools else None, tool_choice="auto" if tools else None ) msg = response.choices[0].message messages.append(msg) # 如果模型没有调用工具,说明推理结束 if not msg.tool_calls: return msg.content # 执行所有 tool calls for tool_call in msg.tool_calls: func_name = tool_call.function.name func_args = json.loads(tool_call.function.arguments) handler = self.skill_registry[func_name]["handler"] result = handler(func_args) messages.append({ "role": "tool", "tool_call_id": tool_call.id, "content": str(result) }) print(f" [Round {round_num+1}] Skill 调用: {func_name}({func_args}) → {str(result)[:100]}...") return messages[-1].content if messages else "达到最大轮次" 

这段代码就是 Nanobot 的核心——一个带 tool 循环的 Chat Completion 调用。看起来简单,但 OpenClaw 在这个基础上加了几个关键设计:

  1. Skill 版本管理:同一个 Skill 可以有多个版本,Nanobot 可以锁定特定版本
  2. 上下文窗口管理:自动 truncate 超长对话,保留 system prompt 和最近 N 轮
  3. 错误重试:Skill 执行失败会把错误信息喂回模型,让它自己修正

Skills 就是普通的 Python 函数,加点元信息装饰就行:

import os import ast def skill(parameters: dict): """装饰器:给函数附加 JSON Schema 参数定义""" def decorator(func): func._parameters = parameters return func return decorator @skill(parameters={ "type": "object", "properties": { "file_path": {"type": "string", "description": "要读取的文件路径"} }, "required": ["file_path"] }) def read_file(file_path: str) -> str: """读取指定路径的文件内容""" if not os.path.exists(file_path): return f"错误:文件 {file_path} 不存在" with open(file_path, 'r', encoding='utf-8') as f: content = f.read() # 限制返回长度,防止撑爆上下文 if len(content) > 10000: return content[:10000] + f" ...[文件过长,已截断,总长度 {len(content)} 字符]" return content @skill(parameters={ "type": "object", "properties": { "code": {"type": "string", "description": "要解析的 Python 代码"} }, "required": ["code"] }) def ast_parse(code: str) -> str: """解析 Python 代码的 AST 结构,返回函数和类的列表""" try: tree = ast.parse(code) result = [] for node in ast.walk(tree): if isinstance(node, ast.FunctionDef): args = [a.arg for a in node.args.args] result.append(f"函数: {node.name}({', '.join(args)}) @ 行{node.lineno}") elif isinstance(node, ast.ClassDef): result.append(f"类: {node.name} @ 行{node.lineno}") return " ".join(result) if result else "未发现函数或类定义" except SyntaxError as e: return f"语法错误:{e}" # 组装 Nanobot 并运行 reviewer = Nanobot( name="code_reviewer", system_prompt="""你是一个资深 Python 代码审查员。 审查流程: 1. 先用 read_file 读取目标文件 2. 用 ast_parse 分析代码结构 3. 基于分析结果给出审查意见 输出格式:按严重程度排序,每条包含行号、问题描述、修复建议。""", model="claude-sonnet-4-", skills=[read_file, ast_parse] ) # 跑一下 result = reviewer.run("请审查 ./src/utils.py 这个文件的代码质量") print(result) 

跑起来的输出大概是这样:

 [Round 1] Skill 调用: read_file({"file_path": "./src/utils.py"}) → import os import sys def ... [Round 1] Skill 调用: ast_parse({"code": "import os import sys..."}) → 函数: load_config(path) @ 行5... [Round 2] 推理完成,返回审查结果 

模型先读文件,再解析 AST,最后综合两个 Skill 的结果给出审查意见。这就是 Nanobot 的 ReAct 循环——推理、行动、观察、再推理。

真正有意思的是把多个 Nanobot 组合起来。OpenClaw 的编排器(Orchestrator)支持串行、并行、条件分支三种模式:

from dataclasses import dataclass from typing import Callable from concurrent.futures import ThreadPoolExecutor @dataclass class NanobotTask: nanobot: Nanobot input_transform: Callable = None # 从上一步结果提取输入 class Orchestrator: """简化版编排器""" def run_sequential(self, tasks: list[NanobotTask], initial_input: str) -> list[str]: """串行执行:上一个的输出是下一个的输入""" results = [] current_input = initial_input for task in tasks: if task.input_transform: current_input = task.input_transform(current_input, results) result = task.nanobot.run(current_input) results.append(result) current_input = result return results def run_parallel(self, tasks: list[NanobotTask], shared_input: str) -> list[str]: """并行执行:所有 Nanobot 拿到同一个输入""" with ThreadPoolExecutor(max_workers=len(tasks)) as executor: futures = [executor.submit(t.nanobot.run, shared_input) for t in tasks] return [f.result() for f in futures] # 实际使用:代码审查 → 生成修复方案 → 编写测试 orchestrator = Orchestrator() review_bot = Nanobot(name="reviewer", system_prompt="审查代码...", model="claude-sonnet-4-", skills=[read_file, ast_parse]) fix_bot = Nanobot(name="fixer", system_prompt="根据审查意见生成修复代码...", model="claude-sonnet-4-", skills=[read_file]) test_bot = Nanobot(name="tester", system_prompt="为修复后的代码编写 pytest 测试...", model="claude-sonnet-4-", skills=[]) results = orchestrator.run_sequential( tasks=[ NanobotTask(nanobot=review_bot), NanobotTask(nanobot=fix_bot), NanobotTask(nanobot=test_bot), ], initial_input="审查并修复 ./src/utils.py" ) 

三个 Nanobot 串起来就是一个完整的代码审查 + 修复 + 测试 pipeline。每个 Nanobot 只管自己那一步,职责清晰。

两天踩了不少坑,记几个印象深的。

坑 1:Skill 返回值太长直接撑爆上下文

一开始没做 read_file 的截断,读了一个 3 万行的文件,直接超了 Claude 4.6 的上下文窗口。报错信息还挺模糊的,排查了半小时才定位到。解决方案就是上面代码里的截断逻辑。另外 OpenClaw 源码里有个 context_window_manager 模块专门处理这个,建议直接用它的。

坑 2:并行执行时的 Rate Limit

三个 Nanobot 并行跑,瞬间打了三个请求,直接触发 429。这个不是 OpenClaw 的问题,是 API 那边的限流。后来换了 ofox.ai 的聚合接口,底层做了多供应商负载均衡,并发能力好很多,三个并行请求没再被限流过。ofox.ai 是一个 AI 模型聚合平台,支持 GPT-5、Claude 4.6、GLM-5 等 50+ 模型,低延迟直连,改个 base_url 就能用。

坑 3:tool_calls 的 arguments 偶尔不是合法 JSON

某些模型(尤其是小模型)返回的 function.arguments 偶尔会带多余的逗号或者缺引号。OpenClaw 源码里用了一个 repair_json 的工具函数做容错,这个思路值得学。自己写的话可以用 json-repair 这个库。

坑 4:system_prompt 里不写清楚调用顺序,模型会乱来

一开始 system_prompt 只写了「你可以用 read_file 和 ast_parse」,结果模型有时候不读文件就直接开始分析,纯靠幻觉编。后来改成明确写「第一步先用 read_file,第二步用 ast_parse,第三步再给出意见」,效果好了很多。Agent 的 prompt 必须写执行流程,光列工具没用。

Nanobot 架构本质不复杂,核心就三个东西:

  • Nanobot = System Prompt + Model + Skills,声明式定义,运行时装配
  • Skills = Function Calling 的封装,加了版本管理和错误重试
  • Orchestrator = 多 Nanobot 编排,支持串行/并行/条件分支

看完源码之后觉得自己之前造的轮子也不是完全白费——思路是对的,只是没有 OpenClaw 这么工程化。如果你也在搞 Agent 开发,建议花半天读一遍 OpenClaw 的 nanobot/core.pyskills/registry.py 这两个文件,比看十篇教程有用。

下一篇打算写 OpenClaw 的 Skills 生态怎么玩,怎么自己发布一个 Skill 包到社区。有兴趣的可以先 star 一下,更新了不迷路。

小讯
上一篇 2026-04-13 10:11
下一篇 2026-04-13 10:09

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/260037.html