☰
如何读懂zclaw代码:agent.c工具循环驱动ESP32 AI助手多轮LLM调用的完整剖析
2026/10/8 7:07:30 网站建设 项目流程

如何读懂zclaw代码:agent.c工具循环驱动ESP32 AI助手多轮LLM调用的完整剖析

【免费下载链接】zclawYour personal AI assistant at all-in 888KiB (~35KB in app code). Running on an ESP32. GPIO, cron, custom tools, memory, and more.项目地址: https://gitcode.com/gh_mirrors/zc/zclaw

zclaw 是一个运行在 ESP32 上的个人 AI 助手,全部固件仅约 888 KiB。它的核心是 main/agent.c 里一段紧凑的工具循环:反复向大模型发起多轮 LLM 调用,模型要么直接回答,要么要求执行工具;设备执行完工具后把结果"回灌"给模型,继续下一轮,直到拿到最终回答。本文带你完整读懂这套循环的设计与实现。

吉祥物画面:一只龙虾用钳子"操作"着 Seeed XIAO ESP32-C3 开发板——zclaw 就住在这块小小的板子里。

整体架构:一个 FreeRTOS 任务,一条消息一个循环

🧠 zclaw 由多个 FreeRTOS 任务协作,但真正"思考"的只有一个:agent 任务。入口是 agent.c 中的agent_task:

  • 启动时接收三个队列:用户输入队列、本地输出队列、Telegram 输出队列;
  • 之后死循环地从输入队列取消息,逐条交给process_message()处理。

这保证了同一时刻只有一条消息在走工具循环,天然避免了并发写历史。

进入 process_message:循环开始前的准备工作

每条消息进入 process_message() 后,先做四件事:

  1. 拦截斜杠命令(/start、/help、/stop 等)和 USB 本地管理命令,直接应答,不走 LLM,省流量;
  2. 取工具清单:tools_get_all()拿到内置工具表和数量;
  3. 暂停 Telegram 轮询,避免 LLM 长请求期间 TLS 握手互相挤占内存;
  4. 把用户消息写入会话历史,并记录起点history_turn_start——这是出错时"回滚"用的存档点。

核心 while 循环:5 轮上限的 agent.c 工具循环

真正的核心是这段循环,位于 agent.c:

while (!done && rounds < MAX_TOOL_ROUNDS) { rounds++; // 1. 构建请求 JSON(系统提示 + 全部历史 + 工具定义) // 2. 限流检查 // 3. 调用 LLM(带重试) // 4. 解析响应:是工具调用?→ 执行并把结果写回历史,继续下一轮 // 是普通文本?→ 回复用户,done = true }

MAX_TOOL_ROUNDS在 config.h 中定义为5:一条消息最多触发 5 轮 LLM 调用。这个"刹车"是防失控的关键(后面细说)。

构建请求:系统提示 + 滚动历史 + 工具定义

每轮都会重新组装一次请求 JSON:

  • 系统提示词:由agent_build_system_prompt()按当前人格(neutral / friendly / technical / witty)生成,告诉模型"你是一台 400 KB RAM 的 ESP32 上的 agent,回答要简短、只用纯文本";
  • 会话历史:把s_history里已有的全部消息原样带上——包括上一轮的工具调用和工具结果,这是"多轮"的记忆来源;
  • 工具清单:内置工具由 builtin_tools.def 宏展开进 tools.c 的注册表(名称、描述、参数 JSON Schema、执行函数),用户自定义工具一并附上。

限流检查与带预算的重试机制

发送前先过ratelimit_check()(默认100 次/小时、1000 次/天),超限直接回滚并告知用户。

每轮 LLM 调用自带重试机制,参数见 config.h:

参数值含义
LLM_MAX_RETRIES3每轮最多尝试次数(含首次)
LLM_RETRY_BASE_MS2000首次失败后等 2 秒
LLM_RETRY_MAX_MS10000退避间隔封顶 10 秒
LLM_RETRY_BUDGET_MS45000单轮重试总时间预算 45 秒

失败后按指数退避(2s → 4s → 8s…),但总耗时不超过 45 秒预算,防止网络故障时卡死设备。

两种响应分支:工具调用 或 最终回答

json_parse_response()解析出响应后,循环走向两个分支之一:

分支一:模型要调工具(工具名非空且有参数)

  1. 把这条 tool_use 消息(工具名 + 参数 JSON)以 assistant 身份写入历史;
  2. 执行工具,结果写入 512 字节的s_tool_result_buf;
  3. 把工具结果以 user 身份的 tool_result 消息写回历史;
  4. 不回复用户,直接continue进入下一轮 LLM 调用——让模型"看到"自己工具的结果。

工具执行分三类(见 agent.c):

  • 🛠️内置工具(gpio_write、cron_set、memory_set 等):直接在芯片上执行;
  • 🔧用户自定义工具:不直接执行,而是把它的 action 描述变成"Execute this action now: …"交还给模型,由模型再拆解成内置工具完成——这就是"自定义工具组合"的实现方式;
  • 🚫特殊规则:定时任务触发的消息里禁止再调cron_set,防止定时任务不断繁殖新的定时任务。

分支二:模型返回普通文本

写入历史 → 经队列发回 Telegram / 本地串口 →done = true,循环结束。

滚动历史:24 条消息槽位就是全部记忆

ESP32 内存紧张,zclaw 的历史就是一个固定数组s_history[24](MAX_HISTORY_TURNS = 12,见 config.h),每条消息最长 1024 字符。满了怎么办?history_add() 的做法是:丢弃最旧的一条,其余整体前移。

注意它刻意"不按一问一答成对删除"——因为一次工具交互会跨多条消息(user → assistant 工具调用 → user 工具结果),按对删除会把配对拆散,导致 API 报错。这个细节是嵌入式上做 LLM agent 很容易踩的坑。

防失控设计:回滚、上限与指标

🛡️ 工具循环的可靠性不靠运气,靠三道保险:

  • 轮次上限:达到 5 轮仍没拿到文本回复,循环强制终止,回复用户"(Reached max tool iterations)",避免模型陷入无限调工具;
  • 历史回滚:构建请求失败、被限流、LLM 重试耗尽、响应解析失败,任何一个环节出错都会调用history_rollback_to()把历史恢复到本轮起点(agent.c),保证不会把半截的 tool_use 留在记忆里污染后续对话;
  • 指标统计:每次请求都有request_metrics计时——LLM 总耗时、工具总耗时、轮数、调用次数,请求结束时打一行 METRIC 日志,方便你快速定位"为什么这次回答特别慢"。

关键常量与源码地图

常量值作用位置
MAX_TOOL_ROUNDS5每请求最多工具轮数config.h
MAX_HISTORY_TURNS12保留 12 轮(24 条)历史config.h
LLM_MAX_RETRIES3每轮 LLM 最多尝试次数config.h
LLM_RETRY_BUDGET_MS45000单轮重试时间预算(毫秒)config.h
TOOL_RESULT_BUF_SIZE512工具结果缓冲区(字节)config.h

核心文件一览:

  • main/agent.c:agent 任务、消息预处理与工具循环主体;
  • main/config.h:循环轮数、重试、历史长度等全部预算参数;
  • main/tools.c:内置工具注册表与执行分发;
  • main/json_util.c:请求构建与响应解析;
  • main/llm.c:多后端(Anthropic / OpenAI / OpenRouter / Ollama)HTTP 调用。

总结:小设备上的 Agent 循环设计范式

zclaw 把多轮 LLM 调用压缩成了一个固定缓冲 + 固定上限的循环:FreeRTOS 单任务串行处理消息,每轮"构建请求 → 调 LLM → 解析响应",工具结果回灌历史后进入下一轮,普通文本则直接收尾;滚动历史、限流、带时间预算的重试和历史回滚,保证了整个循环在 400 KB RAM 的芯片里稳定可靠。读懂这 200 行核心代码,你就掌握了在资源受限设备上构建 LLM agent 的完整范式。🦞

【免费下载链接】zclawYour personal AI assistant at all-in 888KiB (~35KB in app code). Running on an ESP32. GPIO, cron, custom tools, memory, and more.项目地址: https://gitcode.com/gh_mirrors/zc/zclaw

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询