文章

nanobot核心架构解析:4000行代码如何实现完整AI代理功能

nanobot核心架构解析:4000行代码如何实现完整AI代理功能

nanobot核心架构解析:4000行代码如何实现完整AI代理功能

引言

在上一篇文章中,我们介绍了 nanobot 的基本概念和快速入门。本文将深入探讨 nanobot 的核心架构设计,解析这个仅用约4000行核心代码就实现了完整AI代理功能的超轻量级系统是如何做到的。

架构概览

nanobot 采用了一个简洁而高效的分层架构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
nanobot/
├── agent/          # 🧠 核心代理逻辑
│   ├── loop.py     #    代理循环 (LLM ↔ 工具执行)
│   ├── context.py  #    提示构建器
│   ├── memory.py   #    持久化记忆
│   ├── skills.py   #    技能加载器
│   ├── subagent.py #    后台任务执行
│   └── tools/      #    内置工具 (包括 spawn)
├── skills/         # 🎯 捆绑技能 (github, weather, tmux...)
├── channels/       # 📱 聊天渠道集成
├── bus/            # 🚌 消息路由
├── cron/           # ⏰ 定时任务
├── heartbeat/      # 💓 主动唤醒
├── providers/      # 🤖 LLM提供商 (OpenRouter, etc.)
├── session/        # 💬 对话会话
├── config/         # ⚙️ 配置管理
└── cli/            # 🖥️ 命令行接口

核心组件详解

1. Agent Loop (agent/loop.py)

这是 nanobot 的心脏,负责协调 LLM 与工具执行的整个流程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 简化的代理循环逻辑
async def agent_loop(session_id: str, message: str):
    # 1. 构建上下文
    context = build_context(session_id, message)
    
    # 2. 调用LLM
    response = await call_llm(context)
    
    # 3. 解析工具调用
    tool_calls = parse_tool_calls(response)
    
    # 4. 执行工具
    for tool_call in tool_calls:
        result = await execute_tool(tool_call)
        # 5. 将结果反馈给LLM
        context.add_tool_result(result)
        response = await call_llm(context)
    
    # 6. 返回最终响应
    return response

关键设计点:

  • 流式处理:支持工具调用的流式执行
  • 上下文管理:智能的上下文构建和维护
  • 错误处理:完善的异常处理和重试机制

2. Provider Registry (providers/registry.py)

nanobot 的提供商注册表是其灵活性的关键:

1
2
3
4
5
6
7
8
9
# ProviderSpec 定义
ProviderSpec(
    name="openrouter",           # 配置字段名
    keywords=("openrouter",),    # 模型名关键词用于自动匹配
    env_key="OPENROUTER_API_KEY", # LiteLLM的环境变量
    display_name="OpenRouter",   # 在状态显示中的名称
    litellm_prefix="openrouter", # 自动前缀:模型 → openrouter/model
    skip_prefixes=("openrouter/",), # 不要重复前缀
)

这种设计使得添加新提供商变得极其简单,只需要两步:

  1. PROVIDERS 列表中添加 ProviderSpec
  2. ProvidersConfig 中添加配置字段

3. Channel Integration (channels/)

nanobot 支持多种聊天平台,每个平台都有专门的集成模块:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 以Telegram为例
class TelegramChannel:
    def __init__(self, config: TelegramConfig):
        self.bot = Bot(token=config.token)
        self.allow_from = config.allow_from
    
    async def start(self):
        # 启动Telegram机器人
        await self.bot.start()
        
    async def handle_message(self, message: Message):
        # 处理接收到的消息
        if self._is_allowed(message.from_user.id):
            await self.agent.process(message.text)

4. Memory System (agent/memory.py)

nanobot 的记忆系统设计简洁但功能完整:

1
2
3
4
5
6
7
8
9
10
11
12
13
class MemoryManager:
    def __init__(self, workspace: str):
        self.memory_file = Path(workspace) / "MEMORY.md"
        self.daily_dir = Path(workspace) / "memory"
    
    def get_long_term_memory(self) -> str:
        # 读取长期记忆
        return self.memory_file.read_text() if self.memory_file.exists() else ""
    
    def save_daily_log(self, date: str, content: str):
        # 保存每日日志
        daily_file = self.daily_dir / f"{date}.md"
        daily_file.write_text(content)

性能优化策略

1. 代码精简

  • 避免过度抽象和复杂的继承层次
  • 使用类型提示提高可读性而不增加运行时开销
  • 最小化依赖项

2. 异步设计

  • 全面使用 asyncio 进行异步处理
  • 非阻塞的 I/O 操作
  • 并发处理多个请求

3. 缓存机制

  • LLM 响应缓存
  • 配置缓存
  • 会话状态缓存

与 OpenClaw 的架构对比

特性nanobotOpenClaw
代码复杂度~4000行核心代码数万行代码
架构风格简单分层复杂微服务
通信协议基础WebSocket类型化WebSocket协议
安全模型基础访问控制企业级安全体系
部署复杂度pip install 即可需要完整安装流程

总结

nanobot 通过精心的设计和严格的代码约束,在保持极简的同时实现了完整的AI代理功能。其核心思想是”少即是多”——通过减少不必要的复杂性,提高系统的可维护性和可理解性。

在下一篇文章中,我们将深入探讨 nanobot 的模块设计和关键代码实现细节。

本文由作者按照 CC BY 4.0 进行授权