深入剖析 nanobot:轻量级 AI Agent 框架的架构之道

张开发
2026/4/11 5:52:20 15 分钟阅读

分享文章

深入剖析 nanobot:轻量级 AI Agent 框架的架构之道
1.2 源码结构图解nanobot 的项目结构非常扁平核心模块一目了然nanobot/ ├── agent/ # [核心] 智能体大脑 │ ├── loop.py # ReAct 主循环 (引擎心脏) │ ├── context.py # 上下文组装 (Prompt 构建) │ ├── memory.py # 记忆系统 (三层存储) │ ├── skills.py # 技能管理 │ └── tools/ # 工具箱 (Shell, Web, File 等) ├── bus/ # [通信] 消息总线 │ ├── queue.py # 异步消息队列 (核心解耦机制) │ └── events.py # 事件定义 ├── channels/ # [触角] 多平台接入 │ ├── base.py # 标准接口定义 │ ├── manager.py # 渠道管理器 │ └── feishu/ # 具体实现 (如飞书、微信等) ├── config/ # [配置] Pydantic 配置管理 ├── session/ # [存储] 会话持久化 (JSONL) └── cli/ # [入口] 命令行启动器二、 核心架构设计nanobot 采用了一种经典的分层架构确保了各个模块的高内聚和低耦合。InfrastructureAgent Core (核心引擎)Message Bus (异步解耦)用户Access Layer: Channels (飞书/微信/CLI)Inbound QueueOutbound QueueAgent Loop(ReAct 循环)Context BuilderMemory SystemSkill RegistryLLM ProviderFile System架构分层解析接入层 (Access)负责与外部世界交互无论是飞书消息还是命令行输入都统一封装为标准 Message 对象。总线层 (Bus)全异步的消息高速公路通过双向队列隔离了“通信”与“思考”。核心层 (Agent Core)系统的“大脑”负责调度 LLM、管理记忆、执行工具。基建层 (Infrastructure)提供模型能力 (Provider) 和数据持久化能力。三、 亮点设计虚拟工具 (Virtual Tools)设计哲学如何让不可控的 LLM 稳定输出结构化数据nanobot 给出的答案是——利用Function Calling协议而不是依赖 Prompt 指令。3.1 痛点Prompt 的局限性通常我们要求 LLM 输出 JSON 时会使用如下 Prompt请返回 JSON 格式包含 action 和 reason 字段...但 LLM 经常会“自作聪明”地添加 Markdown 代码块或者在 JSON 前后废话导致解析失败。即使使用 JSON Mode也难以严格约束字段类型Schema。3.2 解决方案幽灵工具nanobot 引入了“虚拟工具”的概念。这是一种不注册到执行列表但发送给 LLM 的工具定义。工作流程定义 Schema构造一个 Function Definition描述你想要的 JSON 结构。欺骗 LLM在 API 调用时传入这个 Tool让 LLM 以为它需要调用这个函数。截获参数当 LLM 返回tool_calls时直接读取其arguments参数——这就是经过严格校验的结构化数据。跳过执行Agent 并不真的执行这个 Tool而是直接使用数据。代码示意# 定义一个并不存在的工具仅用于约束输出格式 VIRTUAL_TOOL_SCHEMA [{ type: function, function: { name: submit_decision, parameters: { type: object, properties: { decision: {type: string, enum: [ignore, reply]}, reason: {type: string} }, required: [decision, reason] } } }] # 调用 LLM response await llm.chat(messages, toolsVIRTUAL_TOOL_SCHEMA) # 直接获取结构化结果无需正则解析 result response.tool_calls[0].arguments # result {decision: reply, reason: User is asking for help}这种模式在 nanobot 的记忆归档和心跳检测模块中被广泛使用极大地提高了系统的稳定性。四、 核心模块深度拆解4.1 Message Bus45 行代码的解耦艺术nanobot 的总线设计极度精简却实现了完美的异步解耦。Inbound Queue所有 Channel 接收到的消息经过标准化封装后扔进这个队列。Outbound QueueAgent 思考产生的回复扔进这个队列由 Channel Manager 派发回对应的渠道。AgentBusFeishuChannelUserAgentBusFeishuChannelUserChannel 此时可以继续处理其他请求无需等待loop[异步监听]loop[异步监听]发送消息 你好put(InboundMessage)get(InboundQueue)收到消息思考 (ReAct Loop)put(OutboundMessage)get(OutboundQueue)获取回复回复消息4.2 Agent LoopReAct 引擎agent/loop.py是整个系统的主循环。它并不复杂本质上是一个状态机Observe (观察)获取当前上下文Context。Reason (推理)将上下文和工具列表发送给 LLM。Act (行动)如果 LLM 决定调用工具执行工具 - 获得结果 - 将结果追加到上下文 -回到步骤 2。如果 LLM 决定回复用户生成最终文本 - 结束循环。4.3 Memory三层记忆体系为了解决 LLM 上下文窗口限制Context Window的问题nanobot 设计了一套精巧的三层记忆模型。第一层Session (原始会话)形式.jsonl文件。内容原汁原味的对话日志包含所有的 Tool Call 和详细参数。作用作为“短期记忆”的物理载体用于保持对话的连贯性。策略永不删除但为了节省 Token超长工具输出会被截断图片会被替换为占位符。第二层History (事件日志)形式HISTORY.md。内容带时间戳的关键事件摘要。[2024-03-20 10:00] 用户询问了 nanobot 的部署方式。作用作为“中长期记忆”供 Agent 在需要时通过grep工具主动搜索查阅。特点只追加 (Append Only)。第三层Memory (认知快照)形式MEMORY.md。内容去时间化的事实性知识。用户偏好使用 Python 语言。项目的部署环境是 Ubuntu 22.04。作用作为“长期记忆”全量注入 System Prompt让 Agent 始终“记得”这些关键信息。特点全量覆写 (Rewrite)。每次记忆整理时LLM 会重新生成一份完整的认知快照覆盖旧文件。五、 总结nanobot 并没有发明新的算法它的高明之处在于工程实现的克制与优雅极简的接口设计让接入一个新的 IM 渠道变得异常简单。巧妙的 Prompt 工程利用虚拟工具解决了结构化输出的难题。务实的记忆管理通过分层存储在 Token 消耗和记忆持久性之间找到了平衡。

更多文章