最小故障定位流程

对应源码

排障层首先检查的源码
安装和命令pyproject.toml、nanobot/cli/commands.py
配置路径和解析nanobot/config/paths.py、nanobot/config/loader.py、nanobot/config/schema.py
Provider 和模型nanobot/providers/registry.py、nanobot/providers/factory.py、nanobot/providers/base.py
Agent 主链nanobot/agent/loop.py、nanobot/agent/runner.py
日志目录nanobot/config/paths.py::get_logs_dir、nanobot/utils/logging_bridge.py
外围运行表面nanobot/channels/、nanobot/api/server.py、nanobot/gateway/、nanobot/webui/

学习目标

遇到“nanobot 不工作”时,不从所有模块同时排查,而是用最短路径确定失败层级。

前置知识

  • 已完成一次 DeepSeek 配置;
  • 能运行带 --logs 的 CLI;
  • 能使用 rg。

总体定位顺序

flowchart TD
    A["命令能否启动?"] -->|否| I["安装 / Python / entry point"]
    A -->|是| B["配置能否加载?"]
    B -->|否| C["JSON / 环境变量 / Pydantic 校验"]
    B -->|是| D["Provider 能否创建?"]
    D -->|否| E["preset / provider / model / apiBase"]
    D -->|是| F["最小 CLI 请求能否回复?"]
    F -->|否| G["认证 / 上游错误 / timeout / AgentRunner"]
    F -->|是| H["只排查出错的入口或子系统"]

第 1 层:安装和命令

python --version
python -m pip show nanobot-ai
nanobot --version
python -m nanobot --version

如果模块形式有效而 nanobot 无效,问题通常在虚拟环境或命令 entry point,不在 AgentLoop。

第 2 层:配置解析

检查:

  • JSON 是否有效;
  • 使用的是哪个 --config;
  • 使用的是哪个 --workspace;
  • ${DEEPSEEK_API_KEY} 是否存在;
  • preset 名称是否与 agents.defaults.modelPreset 一致;
  • camelCase 或 snake_case 字段是否被当前 schema 接受。

PowerShell 中只检查是否存在,不输出 key:

if ([string]::IsNullOrWhiteSpace($env:DEEPSEEK_API_KEY)) {
    "DEEPSEEK_API_KEY 未设置"
} else {
    "DEEPSEEK_API_KEY 已设置"
}

第 3 层:Provider 解析

相关源码:

Config.resolve_preset
  → providers/factory.py::_make_provider_core
  → providers/registry.py::ProviderSpec
  → OpenAICompatProvider

检查:

  • preset 是否显式选择 deepseek;
  • 模型名是否为当前可用名称;
  • DeepSeek 配置块是否存在;
  • apiKey 是否解析;
  • 是否意外配置了错误 apiBase。

第 4 层:最小 CLI Turn

使用最少外围组件:

nanobot agent `
  --config $nanobotConfig `
  --workspace $nanobotWorkspace `
  --logs `
  --message "回复 OK"

如果这里失败,暂时不要启动:

  • Gateway;
  • Channel;
  • WebUI;
  • Cron;
  • MCP。

第 5 层:模型请求和 Runner

按错误类型判断:

错误可能层级
401/403key、权限、Provider endpoint
402账户余额
422模型名或请求参数
429限流
500/503Provider 服务
LLM timeout网络、上游响应、NANOBOT_LLM_TIMEOUT_S
stream idle timeout流长时间无事件、NANOBOT_STREAM_IDLE_TIMEOUT_S
empty final response模型空响应、finalization 分支
tool_errorTool 查找、校验、执行或安全边界
max iterations模型—工具循环没有正常终止

第 6 层:只排查新增的外围

最小 CLI 成功后:

API 失败

检查:

  • HTTP body;
  • multipart;
  • session_id;
  • API session lock;
  • SSE;
  • api/server.py。

Channel 失败

检查:

  • Channel 是否启用;
  • allowFrom;
  • Pairing;
  • ChannelManager 是否成功启动;
  • 入站消息是否发布;
  • outbound 是否被 dispatcher 发送。

WebUI 失败

检查:

  • WebSocket Channel;
  • Gateway 是否运行;
  • RuntimeEventBus;
  • WebuiTurnCoordinator;
  • 浏览器连接和 token;
  • UI 展示,而不是先改 AgentRunner。

Cron 或 Heartbeat 失败

检查:

  • Gateway 是否持续运行;
  • workspace 是否正确;
  • <workspace>/cron/jobs.json;
  • Heartbeat 配置和模板;
  • 任务是否因活跃 session 被延后。

日志路径

nanobot/config/paths.py::get_logs_dir() 将日志目录解析到当前 config 所在实例目录下的 logs/。但并非所有启动方式都必然写同一种日志文件;CLI 的 --logs 主要控制运行日志是否显示。

因此应区分:

  • 控制台日志;
  • 实例 logs/ 目录;
  • Channel/WebUI 自身日志;
  • 第三方 Provider 返回的错误。

用测试缩小范围

Set-Location "example\nanobot\code-EN"
 
pytest tests/agent/test_loop_runner_integration.py -q
pytest tests/agent/test_runner_errors.py -q
pytest tests/providers -q

不要把“测试通过”直接等同于真实 key 和网络一定正常。它只能证明被测试的本地契约没有失败。

一页式检查表

  • Python 3.11+
  • 当前虚拟环境中安装的是本地 editable 源码
  • 明确使用 --config
  • 明确使用 --workspace
  • 环境变量存在,但未打印值
  • preset、Provider 和 model 一致
  • 最小 CLI 请求已测试
  • --logs 已开启
  • 已记录完整错误类型和发生层级
  • 只在核心成功后排查 API、Channel、WebUI 或 Cron

下一步

进入 一次 Turn 学习导航。