在上一篇中,我们完成了 nanobot 的“启动仪式”。现在,你的 Agent 已经可以跑起来了。但你大概会好奇:当你输入 nanobot agent 并发送一条消息时,代码底层到底发生了什么?为什么它既能支持终端对话,又能轻松扩展到 Telegram 或飞书?本日,我们就通过 nanobot agent 下令来拆解 nanobot 的心脏——MessageBus(消息总线),以及驱动对话的焦点引擎 AgentLoop。
1. agent 下令:通往智能体的入口
agent 下令的实验逻辑位于 nanobot/cli/commands.py 中的 agent 方法。它是用户与 Agent 交互的最直接方式。
参数详解:通过 Typer 框架,nanobot 为我们提供了丰富的参数:
参数缩写范例默认值分析--message-mstrNone发送给 Agent 的消息。提供此参数将进入 单次消息模式。--session-sstrcli:direct会话 ID。用于区分差别的对话上下文。--workspace-wstrNone工作区目次。指定 Agent 运行时的根目次。--config-cstrNone设置文件路径。默以为 ~/.nanobot/config.json。--markdownboolTrue是否以 Markdown 格式渲染 Agent 的输出。--logsboolFalse是否在谈天过程中表现运行时日志(调试神器)。运行模式:单次使命 vs 一连交互
agent 下令根据是否提供 m / -message 参数,会主动切换两种运行模式:
- 单次消息模式 (Single-Message Mode):当你运行 nanobot agent -m "你好" 时,nanobot 会直接处理处罚这条消息,打印复兴后立即退出。这种模式非常适当在脚本中使用,大概举行简朴的单次查询。
- 交互模式 (Interactive Mode):如果你只运行 nanobot agent 而不带 -m 参数,nanobot 会进入一个一连的交互式会话。你可以像在谈天软件中一样,一连发送多条消息,Agent 会生存之前的对话上下文。在交互模式下,你可以输入 exit、quit 或按 Ctrl+C 来退出。
2. 焦点架构:极简消息总线(MessageBus)
nanobot 之以是能支持多渠道,焦点在于它实现了一个极简的 生产者-消耗者模子。这个模子将“消息泉源”(Telegram、终端等)与“消息处理处罚”(Agent 焦点)完全解耦。
源码分析:nanobot/bus/queue.py
你会惊讶于它的实现竟然云云简朴(不到 50 行代码):- class MessageBus:
- def __init__(self):
- self.inbound: asyncio.Queue[InboundMessage] = asyncio.Queue()
- self.outbound: asyncio.Queue[OutboundMessage] = asyncio.Queue()
- async def publish_inbound(self, msg: InboundMessage):
- await self.inbound.put(msg)
- async def consume_inbound(self) -> InboundMessage:
- return await self.inbound.get()
- # ... outbound 同理
复制代码 inbound 队列:全部渠道(CLI、Telegram 等)将用户输入封装成 InboundMessage 丢进这里。
outbound 队列:Agent 处理处罚完后,将复兴封装成 OutboundMessage 丢进这里,由对应的渠道负责取走并发送给用户。
这种计划的精妙之处在于:
Agent 根本不必要知道消息是从哪来的。它只管从 inbound 取消息,处理处罚完丢进 outbound。这为后续接入新渠道提供了极大的机动性。
3. 内置工具集:Agent 的“瑞士军刀”
干系代码位于 nanobot/agent/tools 目次下。nanobot 默认提供了一套精简而强大的内置工具,让 Agent 可以大概与实际天下举行交互。这些工具被分别为三大类:
- 文件体系 (Filesystem):赋予 Agent 读写代码和文档的本领。
- read_file:读取指定文件的内容。
- write_file:创建新文件或覆盖现有文件。
- edit_file:通过正确的行匹配和更换逻辑,安全地修改文件内容。
- list_dir:列出目次下的文件和子目次,资助 Agent 探索项目结构。
- 网页本领 (Web):让 Agent 可以大概获取及时信息。
- web_search:基于 Brave Search 引擎举行联网搜刮。
- web_fetch:抓取指定 URL 的网页内容并转换为 Markdown 格式,方便 LLM 阅读。
- 体系与编排 (System & Orchestration):这是 nanobot 实现复杂使命的焦点。
- exec:在 shell 中实验恣意下令(如运行测试、安装依赖)。
- spawn:创建一个子 Agent(Subagent)来异步处理处罚耗时使命,实现“多智能体协作”。
- message:发送主动消息,用于向用户陈诉进度或在多渠道间通报信息。
- cron:管理定时使命,让 Agent 具备“时间观念”,可以大概按操持实验利用。
4. 智能体循环:AgentLoop 的“五步走”
如果说 MessageBus 是血管,那么 AgentLoop 就是心脏。它负责驱动整个对话的生命周期。在 nanobot/agent/loop.py 中,你可以看到它的焦点逻辑被拆解为五个关键步调:
1)第一步:吸取 (Receive)
Agent 一连监听 MessageBus.inbound 队列。一旦有新消息进入(无论是来自终端、Telegram 还是体系使命),Agent 就会将其取出并启动处理处罚流程。
2)第二步:构建上下文 (Context)
这是 AI 思索的根本。ContextBuilder 会将以下信息“缝合”在一起:
- 对话汗青:迩来的谈天记载。
- 长期影象:从 MEMORY.md 中提取的究竟。
- 当前使命:用户刚发送的消息。
- 技能索引:可用工具的扼要分析。
3)第三步:调用模子 (LLM Call)
将构建好的上下文发送给大模子(如 Gemini 或 GPT-4)。此时,Agent 会告诉模子:“这是现在的状态,请决定下一步该做什么:是直接答复用户,还是调用某个工具?”
4)第四步:实验工具 (Tool Execution)
如果模子决定调用工具(如 read_file 或 web_search),AgentLoop 会代为实验。
循环往复:工具实验的效果会再次作为“新信息”添加回上下文中,然后回到第三步让模子继承思索。这个过程会不绝一连,直到模子以为信息充足,给出终极复兴。
5)第五步:发送复兴 (Respond)
当模子给出终极答案后,AgentLoop 将其封装成 OutboundMessage 发回 MessageBus.outbound。随后,对应的渠道(如 Telegram 插件)会将其推送给用户。
实战演练:Agent 是怎样思索的?
为了让你更直观地明白这个循环,我们来看一个真实的 Debug 案例。当用户问:“为什么这个项目可以直接使用 nanobot 下令?”时,Agent 履历了三次循环:
1)第一次循环:探索环境
输入:
- messages:两条 messages,此中体系提示词会读取工作空间下的 USER.md、SOUL.md 等文件内容,拼接成一个大的提示词。篇幅有限,这里就不把全部的内容都贴出来了。
- tools:符合 OpenAI Function Call 规范的工具界说(JSON Schema)
- [
- {
- "function": {
- "description": "Read the contents of a file at the given path.",
- "name": "read_file",
- "parameters": {
- "properties": {
- "path": {
- "description": "The file path to read",
- "type": "string"
- }
- },
- "required": ["path"],
- "type": "object"
- }
- },
- "type": "function"
- }
- ]
复制代码 调用大模子,提供 messages、tools、temperature、max_tokens 等参数:- response = await self.provider.chat(
- messages=messages,
- tools=self.tools.get_definitions(),
- model=self.model,
- temperature=self.temperature,
- max_tokens=self.max_tokens,
- reasoning_effort=self.reasoning_effort,
- )
复制代码 模子思索:模子意识到必要先相识项目结构,于是决定调用工具。
模子复兴:发出 list_dir 指令。- LLMResponse(
- content=None,
- tool_calls=[
- ToolCallRequest(
- id="PyPXnKIhI",
- name="list_dir",
- arguments={"path": "/Users/chaoxu.ren/PycharmProjects/nanobot"},
- )
- ],
- finish_reason="tool_calls",
- usage={"prompt_tokens": 3388, "completion_tokens": 357, "total_tokens": 3745},
- reasoning_content=None,
- thinking_blocks=None,
- )
复制代码 实验:Agent 实验 list_dir,并将效果(文件列表)追加至上下文。现在上下文中有 4 条消息。
2)第二次循环:定位关键文件
输入:之前的 4 条 messages、tools JSON schema、temperature 等参数。
模子思索:模子在列表中看到了 pyproject.toml,判定这是关键设置文件。
模子复兴:发出 read_file 指令。- LLMResponse(
- content=None,
- tool_calls=[
- ToolCallRequest(
- id="undktOZkf",
- name="read_file",
- arguments={"path": "/Users/chaoxu.ren/PycharmProjects/nanobot/pyproject.toml"},
- )
- ],
- finish_reason="tool_calls",
- usage={"prompt_tokens": 3565, "completion_tokens": 103, "total_tokens": 3668},
- reasoning_content=None,
- thinking_blocks=None,
- )
复制代码 实验:Agent 读取文件内容,并将 pyproject.toml 内容追加至 messages 中。现在上下文中有 6 条消息。
3)第三次循环:给出终极答案
输入:之前的 6 条 messages、tools JSON schema、temperature 等参数。
模子思索:模子在文件中找到了 [project.scripts] 设置,逻辑闭环,可以答复了。
模子复兴:直接给出终极的笔墨表明,不再调用工具。- LLMResponse(
- content="在这个项目中可以直接使用 `nanobot` 命令,是因为在项目的 `pyproject.toml` 配置文件中定义了命令行脚本入口(Entry Points)。\n\n具体来说,在 `pyproject.toml` 文件中有一段这样的配置:\n\n```toml\n[project.scripts]\nnanobot = "nanobot.cli.commands:app"\n```\n\n它的工作原理是:\n1. **`[project.scripts]`** 是 Python 打包标准(PEP 621)中用来定义全局命令行工具的部分。\n2. **`nanobot = ...`** 表示要在系统或虚拟环境中注册一个名为 `nanobot` 的可执行命令。\n3. **`nanobot.cli.commands:app`** 指定了当你在终端输入 `nanobot` 时,Python 应该去执行 `nanobot/cli/commands.py` 文件中的 `app` 对象(通常是一个 Typer 或 Click 的应用实例)。\n\n当你使用 `pip install -e .` 或者 `uv pip install -e .` 在当前目录安装这个项目时,包管理器会自动在你的 Python 环境的 bin 目录(或 Windows 的 Scripts 目录)下生成一个名为 `nanobot` 的可执行文件,从而让你能够在终端里直接调用它。",
- tool_calls=[],
- finish_reason="stop",
- usage={"prompt_tokens": 4788, "completion_tokens": 397, "total_tokens": 5185},
- reasoning_content=None,
- thinking_blocks=None,
- )
复制代码 竣事:Agent 将终极复兴发送给用户,循环竣事。同时将大模子复兴添加到上下文中,以便后续轮次的问答。现在上下文中有 7 条消息。
💡完备的对话记载 nanobot 会生存在工作空间的 sessions 文件夹下。
Debug 日志录录
我的 debug PyCharm 设置如下:
如果你开启了 -logs,你会看到这一连串动作的清晰轨迹:- /Users/chaoxu.ren/PycharmProjects/nanobot/.venv/bin/python -X pycache_prefix=/Users/chaoxu.ren/Library/Caches/JetBrains/PyCharm2025.1/cpython-cache /Applications/PyCharm.app/Contents/plugins/python-ce/helpers/pydev/pydevd.py --module --multiprocess --qt-support=auto --client 127.0.0.1 --port 62024 --file nanobot.cli.commands agent -m 为什么这个项目可以直接使用nanobot命令 --logs -s 2026-03-09 -w ./.nanobot
- Connected to pydev debugger (build 251.26094.141)
- Created HEARTBEAT.md
- Created USER.md
- Created SOUL.md
- Created AGENTS.md
- Created TOOLS.md
- Created memory/MEMORY.md
- Created memory/HISTORY.md
- 2026-03-09 19:51:34.472 | INFO | nanobot.agent.loop:_process_message:357 - Processing message from cli:user: 为什么这个项目可以直接使用nanobot命令
- 2026-03-09 20:03:07.247 | INFO | nanobot.agent.loop:_run_agent_loop:230 - Tool call: list_dir({"path": "/Users/chaoxu.ren/PycharmProjects/nanobot"})
- 2026-03-09 20:09:14.111 | INFO | nanobot.agent.loop:_run_agent_loop:230 - Tool call: read_file({"path": "/Users/chaoxu.ren/PycharmProjects/nanobot/pyproject.toml"})
- 2026-03-09 20:15:29.075 | INFO | nanobot.agent.loop:_process_message:449 - Response to cli:user: 在这个项目中可以直接使用 `nanobot` 命令,是因为在项目的 `pyproject.toml` 配置文件中定义了命令行脚本入口(Entry Points)。
- 具体来说,在 `pyproject.toml` 文件中有一段这样的配置:
- ...
- 🐈 nanobot
- 在这个项目中可以直接使用 nanobot 命令,是因为在项目的 pyproject.toml
- 配置文件中定义了命令行脚本入口(Entry Points)。
- 具体来说,在 pyproject.toml 文件中有一段这样的配置:
-
- [project.scripts]
- nanobot = "nanobot.cli.commands:app"
-
- 它的工作原理是:
- 1 [project.scripts] 是 Python 打包标准(PEP
- 621)中用来定义全局命令行工具的部分。
- 2 nanobot = ... 表示要在系统或虚拟环境中注册一个名为 nanobot 的可执行命令。
- 3 "nanobot.cli.commands:app" 指定了当你在终端输入 nanobot 时,Python 应该去执行
- nanobot/cli/commands.py 文件中的 app 对象(通常是一个 Typer 或 Click
- 的应用实例)。
- 当你使用 pip install -e . 或者 uv pip install -e .
- 在当前目录安装这个项目时,包管理器会自动在你的 Python 环境的 bin 目录(或
- Windows 的 Scripts 目录)下生成一个名为 nanobot
- 的可执行文件,从而让你能够在终端里直接调用它。
复制代码 总结
nanobot 的计划哲学在 agent 下令和 MessageBus 中体现得极尽形貌:用最简朴的 Python 原生工具(如 asyncio.Queue),办理最复杂的解耦题目。
明白了这一层,你就已经把握了 nanobot 跨渠道通讯的精华。下一篇,我们将深入 nanobot 最具特色的部门:Markdown 驱动的体系提示词,明白体系提示词通常成为我们明白整个Agent体系的焦点!
💡nanobot算法上没有什么大的创新,但是其工程头脑是必要我们每个agent从业工程师必要学习的!
免责声明:如果侵犯了您的权益,请联系站长及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金. |