五个入口与运行边界

对应源码

入口源码
CLI 与 Gateway 命令nanobot/cli/commands.py::agent、_run_gateway
Gateway runtimenanobot/gateway/runtime.py、nanobot/gateway/service.py
HTTP APInanobot/api/server.py
Python facade 与 SDKnanobot/nanobot.py::Nanobot、nanobot/sdk/
Channelnanobot/channels/base.py、nanobot/channels/manager.py、nanobot/channels/
WebUI Turn 协调nanobot/session/webui_turns.py

学习目标

读完后,你应当能够:

  • 区分 CLI、Gateway、HTTP API、Python SDK 和 WebUI;
  • 知道哪些路径使用 MessageBus,哪些直接调用 process_direct();
  • 根据问题选择正确的调试入口;
  • 理解“入口不同”不等于“存在五套 Agent 实现”。

前置知识

先建立一个直觉

nanobot 的多个入口共享核心 runtime,但组装方式和输出协议不同:

flowchart TD
    CLI1["CLI 单次消息"] --> PD["AgentLoop.process_direct"]
    SDK["Python SDK"] --> PD
    API["HTTP API"] --> PD

    CLI2["交互式 CLI"] --> BUS["MessageBus"]
    CH["Chat Channel"] --> BUS
    WS["WebSocket Channel / WebUI"] --> BUS

    BUS --> LOOP["AgentLoop.run / _dispatch"]
    PD --> TURN["AgentLoop._process_message"]
    LOOP --> TURN
    TURN --> RUNNER["AgentRunner"]

共同核心是:

  • AgentLoop;
  • AgentRunner;
  • Provider;
  • ToolRegistry;
  • ContextBuilder;
  • SessionManager。

区别主要在:

  • 谁创建这些对象;
  • 消息是否经过 MessageBus;
  • session key 如何生成;
  • stream 如何展示;
  • 谁负责长期保持进程运行。

1. CLI 单次消息

命令:

nanobot agent -m "Hello"

主要路径:

nanobot/cli/commands.py::agent
  → AgentLoop.from_config
  → AgentLoop.process_direct
  → AgentLoop._process_message

特点:

  • 路径短;
  • 不要求 Gateway 常驻;
  • 适合验证配置、Provider 和核心 Turn;
  • 通过回调显示 stream/progress;
  • 默认 session ID 为 cli:direct。

如果“单次 CLI 也失败”,先不要调试 Channel 或 WebUI。

2. 交互式 CLI

命令:

nanobot agent

交互式模式创建 MessageBus,并运行:

  • AgentLoop 消息消费任务;
  • CLI 输入循环;
  • outbound 消费任务;
  • stream/progress 展示。

它更接近 Channel 模式,但仍然没有外部聊天平台的鉴权、网络和消息格式转换。

3. Gateway

命令:

nanobot gateway

Gateway 是长期运行的组装入口。nanobot/cli/commands.py::_run_gateway 创建并连接:

  • MessageBus;
  • RuntimeEventBus;
  • Provider snapshot;
  • SessionManager;
  • workspace-scoped CronService;
  • AgentLoop;
  • WebuiTurnCoordinator;
  • ChannelManager;
  • 可选 health server。
flowchart TD
    GW["_run_gateway"] --> MB["MessageBus"]
    GW --> RE["RuntimeEventBus"]
    GW --> SM["SessionManager"]
    GW --> CR["CronService"]
    GW --> AL["AgentLoop"]
    GW --> WC["WebuiTurnCoordinator"]
    GW --> CM["ChannelManager"]
    CM --> MB
    MB --> AL
    AL --> RE
    RE --> WC

Gateway 主要用于:

  • Chat Channel;
  • WebUI;
  • WebSocket;
  • Cron;
  • Heartbeat;
  • Dream;
  • 长期后台任务。

nanobot/gateway/runtime.py 不等于核心组装流程

当前核心 Gateway 组装主要位于 cli/commands.py::_run_gateway。nanobot/gateway/runtime.py 还承担进程或服务运行控制。不要仅凭目录名猜调用入口。

4. OpenAI-compatible HTTP API

命令:

nanobot serve

主要接口:

  • POST /v1/chat/completions
  • GET /v1/models
  • GET /health

实现位于 nanobot/api/server.py,使用 aiohttp.web,不是 FastAPI。

请求处理特点:

  • JSON 或 multipart 输入;
  • session key 为 api:<session_id>,未提供时使用 api:default;
  • 每个 API session 使用独立 asyncio.Lock;
  • 调用 AgentLoop.process_direct();
  • stream 模式使用 SSE;
  • SSE 关闭需要等待 process_direct() 完成。

因此 API 问题可以分为两层:

HTTP 解析 / SSE / session lock
  → process_direct
  → 通用 Agent 问题

5. Python SDK

入口类:

from nanobot import Nanobot

主要源码:

  • nanobot/nanobot.py::Nanobot
  • nanobot/sdk/streaming.py
  • nanobot/sdk/types.py

Nanobot.from_config() 内部创建 AgentLoop。run()、run_streamed() 和 stream() 最终复用 process_direct(),同时提供:

  • Python 类型;
  • hooks;
  • stream event;
  • session、memory 和 runtime 客户端;
  • 单次运行覆盖项。

SDK 适合嵌入 Python 程序,不负责长期 Channel 连接。

6. WebSocket 与 WebUI

WebUI 不是独立的 Agent runtime。主要关系是:

React/TypeScript WebUI
  ↔ WebSocket Channel
  ↔ MessageBus
  ↔ AgentLoop

Gateway 中的 WebuiTurnCoordinator 订阅通用 RuntimeEventBus,将 Turn、Goal 和运行状态转换为 WebUI 所需的协调行为。按照项目设计约束:

  • AgentLoop 可以发布通用 runtime event;
  • _turn_end、_goal_status 等具体 wire/UI 行为不应塞入核心 AgentLoop;
  • WebUI/WebSocket 细节留在 coordinator 或 Channel adapter。

五种入口对照

入口是否常驻进入核心方式主要输出最适合
CLI -m否process_direct终端文本/stream最小验证
交互式 CLI会话期间MessageBus终端交互多轮调试
Gateway/Channel是MessageBus各 Channel 消息聊天平台、自动化
HTTP API服务期间process_directJSON/SSE外部程序调用
Python SDK由宿主管理process_directPython 对象/event应用内嵌
WebUIGateway 常驻WebSocket Channel + MessageBusWebSocket/UI浏览器交互

调试起点

现象首先查看
所有入口都失败Config、Provider factory、AgentLoop/Runner
CLI 成功但 API 失败api/server.py 的解析、session 和 SSE
CLI 成功但 Channel 不回复Channel、allowFrom/Pairing、ChannelManager
CLI 成功但 WebUI 不更新WebSocket、RuntimeEventBus、WebuiTurnCoordinator
普通消息成功但 Cron 不运行Gateway、CronService、workspace cron store
SDK 返回事件不完整SDK streaming adapter 和 process_direct callbacks

源码与测试

主题源码测试
CLInanobot/cli/commands.pytests/cli/
Gatewaynanobot/cli/commands.py::_run_gatewaytests/cli/test_gateway_commands.py
APInanobot/api/server.pytests/test_openai_api.py 或当前 API 测试文件
SDKnanobot/nanobot.py、nanobot/sdk/搜索 tests 中的 Nanobot 和 streaming
Channelnanobot/channels/tests/channels/
Runtime UI 协调nanobot/session/webui_turns.pytests/webui/ 和相关 session 测试

测试文件名以当前仓库为准

API 和 SDK 测试可能按功能而不是源码目录命名。运行前使用 rg --files tests | rg "api|sdk|stream" 核对。

自检

  1. 为什么 nanobot serve 不需要先把消息发到 MessageBus?
  2. 为什么 Gateway 需要同时创建 MessageBus 和 RuntimeEventBus?
  3. CLI 成功而 WebUI 失败时,为什么不应该首先修改 AgentRunner?
  4. WebUI 为什么不能被描述为另一套 Agent?

下一步

阅读 源码目录与阅读顺序。