第 6 章:从 Mini Agent 到真实项目¶
目标:理解教学版 Agent 距离可维护、可扩展、可上线项目还差什么,以及应该按什么顺序补齐这些能力。
先说结论:前五章已经解决了什么¶
前五章已经把一个 AI Agent 的核心骨架搭出来了:
Provider:负责和模型通信Tool+Registry:负责声明与执行工具ReAct Loop:负责“思考 -> 行动 -> 观察 -> 再思考”Session/Memory/Context:负责状态与上下文MessageBus/Channel:用简化教学模型说明如何把 Agent 从终端扩展到多平台Skills:负责按需注入领域知识
这意味着你已经不是在看概念图,而是真的有了一个能对话、能做事、能扩展、能接平台的教学版 Agent。
但从“能跑”到“能长期维护”,还差一层工程化能力。
6.1 先承认边界¶
教学版的目标是帮助你理解系统为什么这么设计,不是直接充当生产脚手架。
它最常见的边界有 6 类:
- 配置写死在代码里,不适合多人协作
- 工具边界过松,安全性不足
- 对失败场景缺少重试和恢复
- 多用户并发时没有完整的隔离与锁
- 日志和观测薄弱,出问题难排查
- 测试策略基本靠手动验证
如果你先看清这些边界,就不容易把“教学代码能跑”误解成“项目已经能上线”。
6.2 第一步:把单文件脚本拆成项目结构¶
前几章的 mini_agent.py 很适合教学,但不适合继续增长。一个更稳的最小结构通常像这样:
拆分原则只有一条:按职责拆,不按“看起来专业”拆。
例如:
providers/只管模型接口tools/只管工具定义和实现agent/只管推理循环和上下文组装channels/只管平台接入
这样以后你改 Telegram 适配层时,不会顺手把 ReAct 循环也改坏。
6.3 配置管理¶
最早期教学草稿常把 API Key 和模型写进代码,但这会诱导复制凭据。当前配套示例已经改为从环境变量读取凭据和模型,并默认使用临时教学工作区;真实项目还要做到三件事:
- 密钥不写死在代码里
- 模型、工作区、开关项可配置
- 支持多实例隔离
一个实用的分工方式是:
- 环境变量:放敏感信息,如 API Key
- 配置文件:放模型名、workspace 路径、启用的 channels
- 代码默认值:只放安全且通用的兜底值
这样你就能很自然地从“一个脚本”过渡到“一个可复制的 bot 实例”。
6.4 安全边界¶
Agent 项目最容易被低估的不是 Prompt,而是工具风险。
比如教学版里的 exec 很方便,但真实项目至少要继续补三层限制:
- 命令黑名单或白名单
- 路径限制,只允许访问工作区
- 用户访问控制,例如
allowFrom
你可以把它理解成三道闸:
- 谁能用这个 Bot
- 这个 Bot 能碰哪些文件
- 这个 Bot 能执行哪些动作
缺少任意一道,Bot 都可能从“聪明工具”变成“高权限脚本入口”。
6.5 错误恢复与重试¶
教学版默认的是“调用失败就报错返回”。真实项目至少会遇到这些情况:
- Provider 超时
- 模型返回格式异常
- 外部 API 返回 429
- Tool 调用偶发失败
- Channel 断连后需要恢复
这时候你要补的不是“更多 if”,而是明确的错误策略:
- 哪些错误直接返回用户
- 哪些错误自动重试
- 重试几次
- 失败后是否降级
工程化的本质不是永不失败,而是失败时行为可预期。
6.6 并发与会话隔离¶
单人 CLI 脚本几乎不会暴露并发问题,但一旦接入 Telegram、Discord 这类平台,很快就会遇到:
- 两个用户同时发消息
- 同一个用户短时间内连续触发多轮工具调用
- 一个 session 正在处理时又来了新消息
你至少要把下面两件事想清楚:
session_key如何唯一标识会话- 同一个 session 是否需要串行处理
很多“AI 回答串台”问题,根本不是 Prompt 问题,而是会话隔离没设计好。
6.7 观测与调试¶
教学版适合靠 print() 看过程,但真实项目至少要能回答下面几个问题:
- 这条回复来自哪个 session
- 这轮用了哪个模型
- 调了哪些工具
- 哪一步失败了
- 失败发生在 provider、agent、tool 还是 channel
最低限度建议记录:
- 请求时间
- session_key
- 输入长度
- 调用的 tool 名称
- 错误类型
一旦这些基础日志在,排查效率会差很多个量级。
6.8 测试策略¶
教学版主要靠“最小验证步骤”保证你理解机制。项目化以后,建议至少补 3 层测试:
Tool 单测¶
验证:
- 参数是否合法
- 错误是否可预期
- 输出格式是否稳定
Agent / Session 测试¶
验证:
- Session 是否正确保存与读取
- 历史截断是否符合预期
- Context Builder 是否包含关键部分
集成测试¶
验证:
- 一条消息能否从 channel 进来,再正确走完整个处理链路
- Tool 失败时,最终行为是否符合你的设计
不要一开始就追求大而全的测试矩阵。先把最容易坏的边界测起来。
6.9 如何开始你自己的项目¶
如果你准备从现在开始做自己的 bot,推荐按这个顺序推进:
- 选一个足够窄的场景
- 只接一个 channel
- 先做 1 到 2 个高价值工具
- 再补 1 个真正有用的 Skill
- 跑通后再补安全、日志、重试
一个好的起点通常不是“做个平台”,而是:
- 一个财务顾问 Bot
- 一个代码助手 Bot
- 一个团队 FAQ Bot
- 一个个人助理 Bot
场景越具体,你越容易判断 Tool、Skill 和 Prompt 到底该放在哪一层。
6.10 什么时候该回头读 nanobot 源码¶
你不需要一开始就通读整个仓库。更高效的方式是“带着问题回去看”:
- 想看多 Provider 配置怎么做,读 v0.2.2 固定版本的
providers/ - 想看工具安全边界,读
agent/tools/ - 想看上下文和记忆,读
ContextBuilder与MemoryStore/Consolidator - 想看消息解耦,先对照
MessageBus,再读ChannelManager;第 4 章代码只是把主干摊开的简化模型 - 想看计划任务与 Heartbeat,读
CronService和 Gateway 的cli/commands.py,不要寻找已经不存在的独立 Heartbeat 模块
main 差异:插件化 Channel 的阅读入口
v0.2.2 用户仍按稳定版命令和配置操作。仅当你要审阅固定对照 main@b189a376 的新结构时,才从各插件包的 manifest.py 进入实现,例如 telegram/runtime.py 与 websocket/runtime.py。浏览器服务的其余边界继续沿 webui/ 追踪。
这样源码会从“很大一片目录”变成“带答案的参考实现”。
6.11 这章真正想告诉你的事¶
前五章已经告诉你Agent 是怎么长出来的。这一章想补的是另一半:项目是怎么长稳的。
从这里开始,你应该把教学版 Agent 当成骨架,而不是终点:
- 结构先清楚
- 场景先收窄
- 路径先跑通
- 然后再补安全、并发、重试和测试
这样你做出来的第一个 bot,才更可能继续长成第二个、第三个,而不是在第一次扩展时就塌掉。
从教程走向项目,推荐按这个顺序补¶
如果你现在准备把教学版继续长成自己的项目,最稳的路线通常不是“哪里都补一点”,而是按下面顺序推进:
- 先把配置外置:不要再把 key、model、workspace 写死在代码里
- 再补安全边界:先收紧工具能力和访问范围
- 再补日志与观测:没有日志,后面很多问题根本没法定位
- 再补重试和错误策略:让失败时行为可预期
- 最后再补并发优化和更多平台:这是放大器,不是起步器
很多第一次做 Agent 项目的人,最容易犯的错不是“补少了”,而是补的顺序反了。
如果你现在就想开始自己的 Bot¶
先不要急着做这些:
- 不要一开始就接很多个平台
- 不要一开始就做很宽的通用能力
- 不要一开始就为并发和扩展性设计一个很重的框架
先做一个场景窄、路径短、能稳定完成任务的 Bot,比“看起来架构很完整”的空骨架有价值得多。
相关材料¶
- 想回看教学快照代码:examples/hero/README.md
- 想排查“为什么就是跑不对”:先看附录:常见坑与排障
- 想继续从目录回读前面的架构主线:进阶营导读