本文回答什么问题:nanobot 的 System Prompt 怎么拼接?为什么有 8 段?bootstrap 文件 (AGENTS.md / SOUL.md / USER.md) 起什么作用?Skills / Memory / Tools 怎么注入?

目标读者:LLM Agent 开发者 / 想自定义 System Prompt 的工程师
预计阅读时间:14 分钟
源码版本:GitHub HKUDS/nanobot main 分支主线代码(仓库相对路径)

ContextBuilder.build_system_prompt()(nanobot/agent/context.py)是 nanobot 最长的方法——把 8 段内容拼成最终 system prompt,每段都有特定语义。本章逐段拆解。

1. 整体定位:为什么 System Prompt 要拆 8 段

LLM 的 system prompt 长度有限 + 不能塞太多东西。nanobot 拆 8 段是按优先级 + 模块化:

  • 优先级:identity > bootstrap > tool_contract > memory > skills > history
  • 模块化:每段可独立测试 / 替换 / 自定义

核心要点速查(建议收藏)

  • 核心文件:nanobot/agent/context.py(约 400 行)
  • 8 段拼接:identity / bootstrap / tool_contract / memory / always_skills / skills_summary / recent_history / session_summary
  • 3 个 bootstrap 文件:AGENTS.md / SOUL.md / USER.md(workspace 内,可编辑)
  • SkillsLoadernanobot/skills/ + ~/.nanobot/skills/ 自发现
  • Memory 来自 MemoryStore.get_recent()(详见第 15 章)

2. 8 段拼接

# nanobot/agent/context.py L80-L121
def build_system_prompt(self, ctx: TurnContext) -> str:
    sections = []

    # 1. identity(角色身份,~50 tokens)
    sections.append(self._build_identity(ctx))

    # 2. bootstrap 文件(workspace 内的 AGENTS.md / SOUL.md / USER.md,通常 500-2000 tokens)
    sections.append(self._build_bootstrap(ctx))

    # 3. tool_contract(工具清单 + OpenAI schema,~2000 tokens)
    sections.append(self._build_tool_contract(ctx))

    # 4. memory(最近的 MEMORY.md 摘要,~500 tokens)
    sections.append(self._build_memory(ctx))

    # 5. always_skills(默认开启的 skill,~200 tokens)
    sections.append(self._build_always_skills(ctx))

    # 6. skills_summary(所有 skill 的描述摘要,~300 tokens)
    sections.append(self._build_skills_summary(ctx))

    # 7. recent_history(最近 N 条消息,N=50)
    sections.append(self._build_recent_history(ctx))

    # 8. session_summary(AutoCompact 生成的旧会话摘要)
    sections.append(self._build_session_summary(ctx))

    return "\n\n".join(sections)

每段约几百到 2000 tokens,总长 ~4000-5000 tokens——Claude / GPT-4 都能装下。

3. 逐段详解

3.1 identity(L123-L138)

def _build_identity(self, ctx):
    return f"""你是 nanobot,一个轻量自托管 AI Agent 框架的代理。
    当前通道:{ctx.msg.channel}    当前会话:{ctx.msg.chat_id}
    工作区:{ctx.workspace}    session_key:{ctx.session_key}"""

作用:告诉 LLM"你是谁,当前在哪个上下文"。简短,不可替换。

3.2 bootstrap 文件(L158-L185)

def _build_bootstrap(self, ctx):
    files = ["AGENTS.md", "SOUL.md", "USER.md"]
    sections = []
    for f in files:
        path = ctx.workspace / f
        if path.exists():
            sections.append(f"## {f}\n\n{path.read_text(encoding='utf-8')}")
    return "\n\n".join(sections) if sections else "(no bootstrap files)"

3 个 bootstrap 文件作用:

  • AGENTS.md:Agent 角色定义(“你是一个 Python 工程师助手”)
  • SOUL.md:人格 / 语气(“回答简洁,不要用 emoji”)
  • USER.md:用户信息(“用户是 5 年经验的 Python 开发者”)

完全可编辑——放 ~/.nanobot/workspaces/<key>/ 即可。

3.3 tool_contract(L190-L230)

def _build_tool_contract(self, ctx):
    tools = ctx.tools.list()  # ToolRegistry.list()
    lines = ["## 可用工具\n"]
    for tool in tools:
        lines.append(f"### {tool.name}\n{tool.description}\n")
        lines.append("Parameters:\n" + json.dumps(tool.parameters_schema, indent=2, ensure_ascii=False))
    return "\n".join(lines)

作用:让 LLM 知道有哪些工具可用,每个工具的参数 schema。

3.4 memory(L240-L260)

def _build_memory(self, ctx):
    memory = self._memory_store.get_recent(ctx.session_key, max_chars=2000)
    return f"## 长期记忆\n\n{memory}" if memory else ""

memory 来源:nanobot/agent/memory.pyMemoryStore(详见第 15 章),通常来自 ~/.nanobot/memory/MEMORY.md

3.5 always_skills(L265-L285)

def _build_always_skills(self, ctx):
    skills = self._skills_loader.load_always(ctx.workspace)
    return "\n\n".join(s.sk_prompt() for s in skills) if skills else ""

always skills~/.nanobot/skills/<name>/SKILL.md 里设 always: true,默认注入。

3.6 skills_summary(L290-L310)

def _build_skills_summary(self, ctx):
    skills = self._skills_loader.load_all(ctx.workspace)
    if not skills:
        return ""
    lines = ["## 可用 Skills(用 skill 工具按需加载)\n"]
    for s in skills:
        lines.append(f"- **{s.name}**: {s.description[:100]}")
    return "\n".join(lines)

作用:不直接注入 SKILL.md 内容,只注入清单——按需用 skill 工具加载。

3.7 recent_history(L315-L340)

def _build_recent_history(self, ctx):
    history = self._session_manager.get_recent(ctx.session_key, n=50)
    lines = ["## 最近对话\n"]
    for msg in history:
        lines.append(f"- [{msg.role}] {msg.content[:200]}")
    return "\n".join(lines)

最近 50 条消息——超过用 AutoCompact 摘要(详见第 16 章)。

3.8 session_summary(L345-L365)

def _build_session_summary(self, ctx):
    summary = self._session_manager.get_summary(ctx.session_key)
    return f"## 早期会话摘要\n\n\n{summary}" if summary else ""

AutoCompact 生成的旧消息摘要——避免 history 50 条不够用时丢上下文。

4. 实战:自定义 bootstrap

# ~/.nanobot/workspaces/telegram:123/AGENTS.md
cat > AGENTS.md <<EOF
你是一个 Python 后端工程师助手。
擅长 FastAPI / SQLAlchemy / PostgreSQL。
回答时给出代码示例 + 简短解释。
EOF

# SOUL.md
cat > SOUL.md <<EOF
语气:简洁专业,不用 emoji。
回答长度:每个问题 200 字以内。
EOF

# USER.md
cat > USER.md <<EOF
用户:张三,Python 5 年经验。
当前项目:用 FastAPI 重构老的 Flask 接口。
EOF

下次进入该 workspace,AgentLoop 自动读取这 3 个文件。

5. 常见问题 / 避坑

Q:bootstrap 文件不生效?

A:文件必须放在 ~/.nanobot/workspaces/<session_key>/ 下,文件名严格 AGENTS.md / SOUL.md / USER.md(大写敏感)。

Q:system prompt 太长导致 LLM 报错?

A:检查 8 段总和。建议:

  • bootstrap 文件每个 ≤ 1000 tokens
  • recent_history n=50 → 改为 30
  • skills 关闭不用的(在 ~/.nanobot/skills/<name>/SKILL.mdalways: false)

Q:怎么调试当前 system prompt?

A:nanobot chat --show-promptnanobot chat --verbose(部分版本支持)。

6. 小结

  • 8 段拼接:identity / bootstrap / tool_contract / memory / always_skills / skills_summary / recent_history / session_summary
  • 3 个 bootstrap 文件:AGENTS.md / SOUL.md / USER.md
  • 总长 ~4000-5000 tokens
  • 可定制:bootstrap + skills + memory 三处可编辑

本文要点速查

  1. 8 段拼接 见 §2 + §3
  2. 3 个 bootstrap 文件 决定 Agent 角色 + 人格 + 用户信息
  3. 可定制 点:bootstrap / skills / memory
  4. 下一步:第 13 章《Hook 系统》—— 在 build_messages 之前/之后做什么

按角色推荐

  • LLM Agent 开发者:必读(自定义 workspace / Agent 角色必读)
  • 系统架构师:选读(知道 ContextBuilder 流程即可)
  • LLM Provider 适配者:选读(知道 provider 拿到的 messages 是什么样)
  • 聊天通道开发者:选读
  • Tool / MCP 工具开发者:选读

下一步

  • 第 13 章《Hook 系统》 —— 在回合的 5 个时机插入钩子(主题群"Agent 核心",第 3 周)
  • 第 15 章《记忆与 Dream 整合》 —— 8 段中的 memory 怎么生成(主题群"Agent 核心",第 3 周)
  • 第 16 章《自动压缩 AutoCompact》 —— 8 段中的 session_summary 怎么生成(主题群"Agent 核心",第 3 周)

tags:#nanobot #AI Agent #LLM #Python #源码解析 #ContextBuilder #SystemPrompt

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐