1. 为什么我要在本地折腾 nanobot 多智能体协作如果你正在找一个能跑在自己机器上、代码量不大、还能让多个智能体分工干活的多智能体框架nanobot 值得花一个下午试一遍。它的核心代码大约 5000 行定位不是通用开发框架而是一个可以 24/7 常驻的个人 AI 智能体运行时。它最吸引我的两个点一是 SubAgent 机制主智能体可以把耗时任务丢给后台子智能体自己继续响应用户二是 Message Bus 消息总线把渠道层和智能体层彻底解耦消息怎么进来、怎么出去都不影响中间的处理逻辑。这篇不聊空泛的架构图聚焦落地配置视角怎么用 SubAgent 拆分任务、怎么配消息总线把协作链路串起来、启动后怎么验证智能体之间的消息真的在流转。面向的是本地多智能体编排场景所以我会给出可复制的配置文件骨架和消息总线参数示例你照着改就能跑通一个最小协作闭环。过程中涉及模型调用我会用 TaoToken 作为统一接入层来演示因为它兼容 Anthropic 和 OpenAI 两种协议风格配置起来省事。先说清楚适合谁如果你已经会用命令行、能看懂 JSON 配置、想在自己电脑上跑一个多智能体小系统做实验或做个人助手那这篇的步骤你能直接跟。如果你只是想调个 API 问问题那用不上 nanobot直接开个对话就行。2. 前置准备TaoToken 接入与 nanobot 运行环境nanobot 本身不绑定某一家模型服务它通过统一的 LLMProvider 层去调用不同提供商。为了少踩密钥管理和协议差异的坑我建议用 TaoToken 作为模型网关它同时提供 Anthropic 风格和 OpenAI 风格的接口nanobot 里切换 provider 时不用改业务代码。2.1 拿到 API Key 并确认接入地址第一步是去控制台创建一个 API Key。地址是 https://taotoken.net/api-keys 登录后新建一个密钥复制保存好后面配置文件里要用。注意这个 Key 只在创建时完整显示一次丢了就得重建。接入地址分两种协议nanobot 配置里按需选协议风格Base URL适用场景Anthropic 兼容https://taotoken.net/apiClaude 系列模型、Anthropic SDK 风格调用OpenAI 兼容https://taotoken.net/apiGPT 系列、多数国产模型、OpenAI SDK 风格调用注意Base URL 统一用 https://taotoken.net/api 不要自己拼 /v1 之类的后缀具体路径由 SDK 或框架内部处理。如果你不确定该用哪种协议先看 nanobot 配置里 provider 字段填的是什么再对应选。2.2 本地环境与依赖nanobot 依赖很轻主要是 Python 标准库加少量异步相关包。我实测下来 Python 3.10 以上都能跑。建议用虚拟环境隔离python3 -m venv nanobot-env source nanobot-env/bin/activate pip install --upgrade pip然后把 nanobot 的代码拉到本地假设你已经拿到仓库git clone nanobot-repo-url nanobot cd nanobot pip install -r requirements.txt如果你的环境里没有 requirements.txt说明这个版本把依赖压到了极简直接跑主程序报缺什么再补什么即可。这一步不用追求一次到位后面启动验证时会暴露缺失项。3. 可复制配置SubAgent 拆分与消息总线参数nanobot 的配置集中在一个 JSON 文件里我把它拆成三块讲模型接入、消息总线、SubAgent。这样你改的时候知道每一段在管什么。3.1 模型接入段这段决定智能体调用哪个模型、走哪个网关。用 TaoToken 的话provider 填兼容协议对应的名字base_url 填 https://taotoken.net/api api_key 填你刚才创建的密钥。{ llm: { provider: anthropic, base_url: https://taotoken.net/api, api_key: sk-你的TaoToken密钥, model: claude-sonnet-4-20250514, max_tokens: 4096, temperature: 0.7 } }如果你用的是 OpenAI 兼容协议把 provider 改成 openaimodel 换成对应模型名即可base_url 不变。nanobot 会根据 model 名称自动路由所以 provider 字段主要是告诉它用哪套请求格式。3.2 消息总线段消息总线是 nanobot 解耦的核心。它本质上是一个异步队列渠道层把消息塞进 InboundMessage智能体循环从队列取处理完再以 OutboundMessage 塞回去由渠道层投递。配置里主要调队列容量和重试策略。{ message_bus: { inbound_queue_size: 100, outbound_queue_size: 100, delivery_retry: 3, retry_backoff_seconds: 2, poll_interval_ms: 50 } }参数含义对照参数作用建议值inbound_queue_size入站消息队列容量本地实验 100 够用outbound_queue_size出站消息队列容量与入站保持一致delivery_retry投递失败重试次数3 次retry_backoff_seconds重试退避基数2 秒避免打爆下游poll_interval_ms队列轮询间隔50ms本地够灵敏提示本地单机跑的时候队列容量不用开太大否则消息积压了你反而不好定位是哪一环卡住。等协作链路验证通了再按需放大。3.3 SubAgent 段这是多智能体协作的关键。主智能体通过 spawn 工具派生子智能体子智能体在独立的 asyncio.Task 里跑有自己受限的工具集和迭代上限。配置里控制它的行为边界。{ subagent: { enabled: true, max_iterations: 15, max_concurrent: 4, inherit_tools: false, allowed_tools: [read_file, write_file, web_search], result_notify: system_message, timeout_seconds: 300 } }几个参数值得展开说。max_iterations 是子智能体的工具调用轮次上限主智能体默认能到 200 次子智能体压到 15 次是为了防失控一个后台任务不该无限循环。inherit_tools 设为 false 表示子智能体不继承主智能体的完整工具集只拿 allowed_tools 里列的这样它没法再派生新的子智能体也没法直接给用户发消息结果只能通过系统消息回报给主智能体。max_concurrent 控制同时能跑几个子任务本地机器别开太高4 个已经能看出并发效果了。3.4 把三段合成一个文件实际配置文件是上面几段的合并我给出完整骨架你直接替换密钥就能用{ llm: { provider: anthropic, base_url: https://taotoken.net/api, api_key: sk-你的TaoToken密钥, model: claude-sonnet-4-20250514, max_tokens: 4096, temperature: 0.7 }, message_bus: { inbound_queue_size: 100, outbound_queue_size: 100, delivery_retry: 3, retry_backoff_seconds: 2, poll_interval_ms: 50 }, subagent: { enabled: true, max_iterations: 15, max_concurrent: 4, inherit_tools: false, allowed_tools: [read_file, write_file, web_search], result_notify: system_message, timeout_seconds: 300 }, agent: { max_iterations: 200, session_persistence: true, history_limit: 50 } }保存为 config.json放在项目根目录。agent 段里的 max_iterations 是主智能体的迭代上限history_limit 是注入上下文的历史消息条数这两个先保持默认跑通后再调。4. 启动与验证确认智能体间消息真的在流转配置写完不算完得验证消息总线确实在传、SubAgent 确实在后台跑。我分三步做检查。4.1 启动主程序python -m nanobot --config config.json启动后你应该看到类似日志消息总线初始化、渠道层注册、智能体循环进入等待。如果卡在模型连接上多半是 api_key 或 base_url 写错了回头核对第 2.1 节的地址。4.2 触发一次 SubAgent 协作在对话入口发一条会触发后台任务的指令比如让它处理一个稍耗时的分析任务。主智能体应该立刻回你一句「已派发任务任务 ID 是 xxx」而不是等任务跑完才回。这就是 SubAgent 的价值主循环不阻塞。此时观察日志你应该能看到子智能体在独立任务里启动、执行工具调用、最后把结果以系统消息注入主队列。关键日志行大概长这样[SubAgent] spawned task_idtask-001 iterations0 [SubAgent] task-001 tool_call read_file path./data.txt [SubAgent] task-001 completed, result injected to main queue [AgentLoop] system message received, will report on next turn4.3 验证消息流转的检查动作光看日志还不够我习惯做两个主动检查。第一再发一条普通消息看主智能体是否在回复里带出了子任务的结果这说明系统消息确实被主循环消费了。第二查会话追踪映射nanobot 内部维护 session_key 到 task_ids 的对应关系你可以通过调试接口或日志确认任务状态从 running 变成 completed。如果你想要更直观的验证可以临时把 subagent.timeout_seconds 调小到 30 秒故意让一个长任务超时观察主智能体是否能感知到子任务失败并给出提示。这个反向测试能帮你确认异常路径也是通的。5. 本篇常见错排查配置和验证过程中我踩过几个坑列出来帮你省时间。第一个是消息总线队列满导致消息丢失。本地实验时如果你一次性灌很多消息inbound_queue_size 设太小会丢。表现是渠道层发了但智能体没反应。解决办法是把队列调大或者降低发送频率看日志里有没有 queue full 相关提示。第二个是 SubAgent 工具集配错。如果你在 allowed_tools 里写了主智能体才有的工具名子智能体启动时会报工具未注册。对照第 3.3 节的工具列表填别把 spawn 和 message 写进去这两个是主智能体专属的。第三个是模型协议不匹配。provider 填 anthropic 但 model 填了 OpenAI 系列的名字请求会失败。nanobot 虽然会自动路由但 provider 字段决定了请求格式两者要对上。用 TaoToken 的话两种协议都支持改 provider 就行base_url 不用动。第四个是子智能体结果没回报。检查 result_notify 是不是设成了 system_message如果设成别的值主智能体可能不会在下一轮感知到结果。另外确认主智能体的 max_iterations 没被耗尽耗尽了它就没机会处理系统消息了。第五个是并发数过高导致本地资源紧张。max_concurrent 设成 4 以上时如果你的机器核数少子任务会互相抢资源表现是都变慢。本地实验保持 2 到 4 之间比较稳。6. 继续深入的方向与接入入口跑通最小协作闭环之后你可以往几个方向扩。一是给子智能体加更多 allowed_tools让它能处理更复杂的后台任务比如定时抓取加分析。二是调消息总线的重试和退避参数模拟网络抖动下的可靠投递。三是接更多渠道nanobot 的渠道层是统一抽象新渠道实现 start、stop、send 三个方法就能接入消息总线那边不用改。如果你在配置模型接入时想先确认某个模型能不能正常返回可以直接用模型对话页面测一下地址是 https://taotoken.net/model-chat 选好模型发一条消息看响应确认通了再写进 nanobot 配置能省掉不少排查时间。长期跑编码类或 Agent 类任务的话可以考虑 Coding Plan地址是 https://taotoken.net/coding-plan 适合需要持续调用、对额度有预期的场景。接入文档在 https://taotoken.net/doc 里面把两种协议的请求格式和参数都列了配置 nanobot 的 LLMProvider 段时对着看就行。控制台入口是 https://taotoken.net/console 密钥管理、用量查看都在这里。最后说个实用技巧nanobot 的配置文件改完不用重启整个进程如果你用的是带热加载的版本改完保存后发一条消息触发重载即可。但消息总线参数改动建议还是重启因为队列是在启动时初始化的热改不一定生效。这个细节文档里没写是我反复试出来的。
