扩展开发导航
扩展 nanobot 的第一步不是写代码,而是判断能力应该落在哪个边界。放错位置通常比实现细节更难维护。
对应源码
| 扩展类型 | 源码 |
|---|---|
| Tool | nanobot/agent/tools/base.py、loader.py、registry.py |
| Skill | nanobot/agent/skills.py、nanobot/skills/、nanobot/agent/context.py |
| MCP | nanobot/agent/tools/mcp.py、nanobot/config/schema.py、nanobot/agent/loop.py |
| Provider | nanobot/providers/base.py、registry.py、factory.py |
| Channel | nanobot/channels/base.py、registry.py、manager.py |
| Command、API、SDK、WebUI | nanobot/command/、api/、sdk/、webui/、webui/src/ |
学习目标
完成本部分后,你应当能够:
- 根据需求选择 Tool、Skill、MCP、Provider、Channel 或运行表面;
- 找到每种扩展的发现、注册、配置、测试和安全契约;
- 控制最小修改范围,避免把平台或 UI 细节塞进 Agent core;
- 设计一个先可验证、再逐步增加复杂度的实现顺序。
前置知识
1. 先做边界判断
| 需求 | 优先选择 | 原因 |
|---|---|---|
| 教模型怎样组合已有能力 | Skill | 主要变化是指令和流程 |
| 给模型一个新的本地 Python 动作 | Tool | 需要结构化参数和确定性执行 |
| 复用已有外部工具服务 | MCP | 协议已定义,不必把客户端写进 core |
| 接入新的模型 API | Provider | 需要把上游响应归一为 LLMResponse |
| 接入新的聊天平台 | Channel | 需要完成入站/出站和平台生命周期 |
| 增加用户控制命令 | Command | 不需要让模型决定是否调用 |
| 给 Python 应用提供能力 | SDK | 同进程、类型化调用 |
| 给 HTTP 客户端提供兼容接口 | API | 进程外请求/响应协议 |
| 增加浏览器交互 | WebUI | 前端状态与 WebSocket/HTTP 协议 |
2. 三个容易放错的位置
“调用外部 API”不一定要写 Provider
只有当该 API 是 LLM 推理后端,并需要产出 LLMResponse 时才是 Provider。天气、搜索、数据库查询更可能是 Tool 或 MCP。
“一套工作流”不一定要写 Tool
如果已有 Tool 足以完成任务,只是模型不知道正确顺序,先写 Skill。Skill 不引入新的执行权限。
“浏览器要展示一个状态”不一定要改 AgentRunner
核心只应发布通用 Runtime Event。WebSocket envelope、replay sequence、组件状态和样式属于 coordinator/channel/WebUI。
3. 复杂度阶梯
flowchart LR A["Skill<br/>只有说明"] --> B["Tool<br/>本地契约"] B --> C["MCP<br/>外部进程/服务"] C --> D["Provider<br/>模型协议"] D --> E["Channel<br/>长连接与平台语义"] E --> F["跨 API / SDK / WebUI<br/>多消费者契约"]
这不是价值排序,而是常见测试面和故障面逐步增加。初学者应从 Skill 和只读 Tool 开始。
4. 推荐阅读顺序
5. 所有扩展都要回答的九个问题
- 谁发现或注册它?
- 它的稳定名称是什么?
- 输入契约在哪里定义?
- 输出如何回到 Turn?
- 配置从哪里加载和验证?
- 生命周期由谁启动、取消和关闭?
- 会产生什么副作用?
- 最小测试如何隔离网络和真实凭据?
- 哪些文档、UI 或索引需要同步?
后面的每篇文档都用这九个问题收束实现范围。
当前学习阶段
example/nanobot/code-EN在整个学习过程中都作为只读事实基线,不直接修改。需要动手改代码的练习只在learning-CN/examples、独立临时工作区或明确复制出的隔离副本中进行。
下一篇:新增 Tool