HelloCodeAgentCli 内置工具使用指南:从"何时用"到"源码级原理"的完整解析
【免费下载链接】hello-agents📚 《从零开始构建智能体》——从零开始的智能体原理与实践教程项目地址: https://gitcode.com/GitHub_Trending/he/hello-agents
导读
本文围绕 HelloAgents 共创项目YYHDBL-HelloCodeAgentCli中 Code Agent 的六个内置工具(terminal、context_fetch、todo、note、memory、plan)展开,逐一定义其"何时用 / 何时不用 / 如何用",并结合tools/builtin/下的真实源码(terminal_tool.py、context_fetch_tool.py 等)剖析底层实现与安全机制。读完本文,你将掌握一套类似 Claude Code/Codex 风格的"按需探索 + 最小工具调用 + 补丁落盘"的 Agent 工具使用范式,并能在自己的 Agent 工程中复刻这套工具编排与安全边界设计。
一、背景:一套 Claude Code 风格的工具体系
HelloCodeAgentCli 是一个基于 HelloAgents 组件(HelloAgentsLLM/ContextBuilder/ReActAgent等)搭建的简易 Code Agent CLI,目标体验类似 Claude Code/Codex:支持多轮对话、按需探索代码库、生成补丁并在确认后落盘。其整体架构与启动方式见 code_agent/README.md。
该项目的提示词工程集中管理在code_agent/prompts/目录(见 prompts/README.md):
| 文件 | 职责 |
|---|---|
system.md | 全局行为与安全边界(按需探索 / 敏感操作确认 / 补丁格式) |
react.md | ReAct 回合格式与工具输入约定 |
plan.md | 规划工具(plan[...])专用提示词 |
summarize_observation.md | 工具输出摘要提示词 |
tools.md | 六种内置工具的完整使用指南(本文主体) |
其中 tools.md 的核心设计理念是"明确何时用 / 何时不用 / 如何用",避免模型盲目调用工具。这与system.md中的"按需探索"原则一脉相承:先有足够上下文就推理,证据不足再调用工具,绝不无端全库扫描。
六种工具均实现在tools/builtin/目录下(tools/builtin),并通过统一的 Tool 基类 与 registry 注册、编排。
二、工具调用总则:三种思维
在逐一展开六个工具前,先记住三个总原则(原文与源码共同强调):
- 先推理,后取证:优先使用"保底上下文"(系统提示 + 对话历史 + 上次工具摘要)推理,不足时再调用工具,避免无端多次搜索。
- 聚合优先于零散:需要搜索时优先
context_fetch(一次查多源),而不是反复单独调用 note/memory 的 search。 - 写盘唯一通道是补丁:写/改文件必须用
*** Begin Patch ... *** End Patch格式,严禁cat > file/ Here-Doc /tee/ 重定向写盘。
三、terminal:只读检索与快速查看
3.1 使用边界(原文要点)
- 用途:只读检索与快速查看(
ls/rg/cat/sed/head/tail/grep/git status/diff)。 - 何时用:定位文件/符号/报错;小范围查看片段;确认目录结构。
- 何时不用:写文件(用补丁);大范围全库扫描(除非用户要求);危险命令(
rm/chmod/git reset --hard)。 - 调用示例:
terminal[{"command":"rg -n \"foo\" context/**/*.py","allow_dangerous":false}]
3.2 源码级安全机制
terminal_tool.py 将上述边界落地为多层安全检查(run()主流程,见 L138-L216):
- 命令白名单:
ALLOWED_COMMANDS(L65-L86)只放行ls/cat/head/tail/find/grep/rg/wc/sort/uniq/sed/awk/pwd/cd/file/git等只读或轻量命令,白名单外直接拒绝并列出允许项。 - 路径沙箱:
cd与mkdir的目标路径必须解析后位于workspace内(_handle_cd见 L535-L591),rm/chmod放行时同样逐参数校验路径,防止符号链接/相对路径逃逸。 - 危险操作确认:
DANGEROUS_BASE_COMMANDS = {"rm", "chmod"},DANGEROUS_GIT_SUBCOMMANDS覆盖git reset --hard(L93-L97)。这些命令默认拒绝,allow_dangerous=true且开启confirm_dangerous时才会交互式询问y/n。 - shell 语义分级:支持管道(如
rg ... | head)而无需确认;但重定向(>/>>,排除>/dev/null)、命令替换($()/ 反引号)会被_shell_requires_allow_dangerous标记为需危险权限(L344-L395);git默认只允许status/diff子命令(L397-L459)。 - 资源护栏:默认超时 30 秒、输出上限 10MB(构造函数参数
timeout/max_output_size,见 L99-L136),防止长时间命令与超大输出耗尽上下文预算。
可见terminal的"何时不用写文件"并非仅靠提示词约束,而是底层直接禁掉了写盘通道——写文件被强制走补丁流程。
四、context_fetch:聚合搜索,控制预算
4.1 使用边界(原文要点)
- 用途:聚合搜索(files / notes / memory / tests),自动摘要,控制预算。
- 何时用:需要"更多证据"时;搜类名/函数名/错误栈;需要相关笔记/记忆;比单独 note/memory 搜索更省步数。
- 何时不用:已经有足够证据;用户仅问对话历史(此时直接读对话历史即可,不需要调用工具)。
- 调用示例:
context_fetch[{"sources":["files","notes"],"query":"ContextBuilder","paths":"context/**/*.py"}]
4.2 源码级实现:一次调用,多源取证
context_fetch_tool.py 的设计理念在文件头注释中写得很清楚:"保底上下文由 ContextBuilder 自动注入(系统提示、对话历史、上次工具摘要);扩展上下文通过此工具按需获取(notes、memory、files、tests);模型自行决定何时需要更多证据,避免盲目全局扫描。"
核心实现要点:
- 参数模型(L57-L84):
sources(必填):notes/memory/files/tests可多选;query(必填):搜索关键词/符号名/错误栈片段;paths(可选):限定文件搜索范围的 glob,如'src/**/*.py',避免全仓库扫描;budget_tokens(可选):单个数据源的 token 上限,默认 800。
- 预算控制:每个数据源返回最多约 800 tokens,
_truncate按"1 token ≈ 4 字符(英文)/ 2 字符(中文)"粗估截断;_format_file_results还按文件数平分预算并截断更多结果(L269-L296)。 - files 源:底层调用
rg -n -C <context_lines>(默认前后各 5 行)做带上下文的搜索,命中行按文件分组返回结构化证据;rg不可用时降级为grep(L166-L222)。 - tests 源:检索
.pytest_cache/v/cache/lastfailed、test-results.xml、.coverage等测试产物(L224-L247)。 - 结果缓存:以
sources|query|paths为键做 LRU 缓存(上限 20 条),命中时返回[缓存命中],避免同一查询重复消耗(L96-L125)。
这正是"比单独 note/memory 搜索更省步数"的底层原因:一次工具调用完成多源检索 + 结构化汇总 + 预算截断,把上下文爆炸的风险消化在工具内部。
五、todo:多步骤任务跟踪
5.1 使用边界(原文要点)
- 用途:多步骤任务跟踪,状态机为
pending | in_progress(仅 1 个)| completed。 - 何时用:3 步以上或多文件/多特性;用户列出多项需求;跨回合/需确认的任务;开始工作前先标记
in_progress,完成后立即completed。 - 何时不用:单一步、琐碎或纯问答。
- 示例(原文完整继承):
todo[{"action":"add","title":"设计简介页布局","desc":"头部/简介/技能","status":"pending"}]todo[{"action":"update","id":1,"status":"in_progress"}]todo[{"action":"update","id":1,"status":"completed"}]todo[{"action":"list"}]
5.2 源码级约束:强制的"单 in_progress"
todo_tool.py 的核心是状态强约束:
- 状态枚举
STATUSES = ("pending", "in_progress", "completed")(L21); _enforce_single_in_progress(L107-L113)保证同时最多一个in_progress:若已存在进行中任务,新的in_progress会被拒绝,并提示"先完成/更新它后再切换"——这是防止 Agent 多任务并发失控的工程化手段;- 存储:
.helloagents/todos/todos.json,采用"临时文件 +os.replace"原子写入,写前自动备份todos.json.bak(L90-L98); list输出按in_progress / pending / completed分组,用 ANSI 颜色与☒/☐标记,便于 LLM 快速消化(L167-L213)。
在 react.md 的策略中进一步细化了 todo 的触发条件:任务有 ≥2 个子步骤、需用户确认或跨回合继续时,先todo add再行动,结尾todo list汇总;当用户表达"分步/步骤/三步/改造/计划/完成后"等语义时,多数情况下应主动用 todo。
六、note:结构化笔记,Markdown 持久化
6.1 使用边界(原文要点)
- 用途:结构化笔记(
action/decision/blocker/task_state等),Markdown 持久化。 - 何时用:记录关键结论/风险/阻塞;补丁成功/失败总结;阶段小结。
- 何时不用:临时想法可先留在对话,不必频繁写笔记。
- 示例:
note[{"action":"create","title":"Patch applied","content":"...","note_type":"action","tags":["patch"]}]
6.2 源码级实现:YAML frontmatter + 索引
note_tool.py 支持create / read / update / delete / list / search / summary七种动作(run()分发见 L193-L215),并内置完整参数定义(title/content/note_type/tags/note_id/query/limit,见 L217-L276)。实现细节:
- 笔记类型:
task_state(任务状态)、conclusion(关键结论)、blocker(阻塞项)、action(行动计划)、reference(参考资料)、general(通用),默认general; - 存储格式:每条笔记是一个独立
.md文件,头部携带 YAML frontmatter(id/title/type/tags/created_at/updated_at),正文为 Markdown(_note_to_markdown见 L128-L146),天然可被人类阅读与版本管理; - 索引与限额:
notes_index.json维护元数据索引,支持按类型过滤与关键词搜索(标题/内容/标签);max_notes默认上限 1000 条。
七、memory:跨会话情景记忆(SQLite 持久化)
7.1 使用边界(原文要点)
- 用途:情景记忆(SQLite);跨会话回忆"发生过什么"。默认不开自动写,需要显式添加。
- 何时用:需要在未来回忆本次决策/阻塞/结论;会话结束前写一条小结;复用过往经验时可先
search。 - 何时不用:即时对话短期内容已有 history;信息尚不确定。
- 示例(原文完整继承):
memory[{"action":"add","memory_type":"episodic","content":"完成 hello.html 样式改造,见补丁...","importance":0.7}]memory[{"action":"search","query":"hello.html 样式","memory_types":["episodic"],"limit":5}]
7.2 源码级实现:四类记忆 + 重要性评分
memory_tool.py 是连接 MemoryManager 的工具适配层,支持动作多达 9 种:add / search / summary / stats / update / remove / forget / consolidate / clear_all(见 L98-L127)。关键参数与设计:
- 记忆类型:
working(工作记忆)、episodic(情景记忆)、semantic(语义记忆)、perceptual(感知记忆,支持通过file_path+modality记录图片/音频等模态,扩展名自动推断见 L169-L179)。在 Code Agent 场景下仅启用episodic,SQLite 持久化于<repo>/.helloagents/memory/; - 重要性评分:
importance取值 0.0~1.0(默认 0.5),search支持min_importance过滤,summary会按重要性排序输出"重要记忆"Top N; - 记忆生命周期:
forget支持importance_based/time_based/capacity_based三种遗忘策略(默认重要性阈值 0.1、最大保留 30 天);consolidate可将重要短期记忆(默认working,阈值 0.7)整合提升为长期记忆(默认episodic)——对应人类记忆的"睡眠巩固"机制; - 明确性设计:"默认不开自动写,需要显式添加"对应源码中
auto_record_conversation这类自动记录方法并不在默认 ReAct 循环里强制触发,避免每轮对话都污染长期记忆。
八、plan:显式规划工具
8.1 使用边界(原文要点)
- 用途:显式规划工具,生成分步计划。
- 何时用:任务模糊或明显多步骤;用户要求出计划;执行前需要拆解。
- 何时不用:非常简单的一步任务。
- 示例:
:plan 添加 dark mode 开关或plan[{"goal":"优化渲染性能,先梳理瓶颈再改"}]
8.2 源码级实现:LLM 驱动的计划生成
plan_tool.py 是一个可选工具:默认提示词要求输出"可执行计划(5~12 步),并包含 Risks 与 Validation";若配置了prompt_path(即code_agent/prompts/plan.md),则读取该文件作为系统提示词。参数包括:
goal(必填):计划目标;constraints(可选):额外约束;output(可选):markdown | json,默认markdown。
实现上它通过HelloAgentsLLM.invoke调用大模型生成计划(max_tokens=800)。在 CLI 中还有一个配套入口:plan <目标>命令,用于用户强制要求出计划;平时则由模型按需调用plan[...]工具,不强制每步都规划。
九、重要提醒:补丁是唯一写盘通道
原文的"重要提醒"部分必须原样继承并加深:
- 写/改文件必须用补丁(
*** Begin Patch ...),禁止cat > file/ Here-Doc /tee/ 重定向写盘。 - 先用已有上下文推理,不足再调用工具;避免无端多次搜索。
- todo 只保持 1 个
in_progress;完成立刻标记completed;阻塞则新增一条说明阻塞。
补丁格式的规范在 system.md 中有完整定义,核心规则如下(原文完整继承):
*** Begin Patch *** Add File: path/to/new_file.py 文件内容... 可以多行... *** Update File: path/to/existing_file.py 更新后的完整文件内容... *** Delete File: path/to/old_file.py *** End Patch关键规则:第一行必须是*** Begin Patch(前面不能有任何文字);最后一行必须是*** End Patch;操作行为*** Add File:/*** Update File:/*** Delete File:;Add/Update 后跟完整文件内容,Delete 后不需要内容;不要用 markdown 代码块(```)包裹补丁;路径相对于仓库根目录。react.md 还补充了"说明文字与补丁之间要有空行分隔"等易错点。
补丁落盘执行器的源码级保障
补丁由 apply_patch_executor.py 负责解析与应用,其安全特性(MVP)从工程上坐实了"补丁是唯一写盘通道":
- 路径限制:
_safe_path拒绝绝对路径(/、~开头)、拒绝符号链接、解析后必须位于repo_root内(L185-L207); - 后缀白名单:默认仅允许
.py / .md / .toml / .json / .yml / .yaml / .txt / .html / .htm / .css / .js等文本文件,防止误改二进制与敏感文件(L72-L84); - 规模限制:单个补丁默认最多 10 个文件、800 行变更(
max_files/max_total_changed_lines),防止一次补丁造成失控改动(L114-L121); - 原子写入与备份:先写临时文件再
os.replace,改前备份到.helloagents/backups/<timestamp>/(L245-L260); - 冲突检测:Update 的 hunk 需在文件中精确匹配上下文,匹配失败会抛出带
recheck_targets提示的异常,并支持"整文件替换"宽松回退(L369-L494)。
十、综合工作流:六种工具如何协同
将六种工具串起来,一个典型的 Code Agent 任务遵循system.md定义的节奏:计划 → 取证 → 补丁 → 确认 → 落盘 → 验证。示例如下:
- 用户提出多步改造需求 →
todo[{"action":"add","title":"...","status":"pending"}]登记,随后todo[{"action":"update","id":1,"status":"in_progress"}]; - 任务模糊或步骤多 →
plan[{"goal":"..."}]生成分步计划; - 需要定位代码 → 优先
terminal[{"command":"rg -n \"ContextBuilder\" context/**/*.py","allow_dangerous":false}]小范围检索;证据仍不足时 →context_fetch[{"sources":["files","notes","memory"],"query":"ContextBuilder","paths":"context/**/*.py"}]聚合取证; - 得到结论 →
note[{"action":"create","title":"...","content":"...","note_type":"decision","tags":[...]}]记录决策; - 会话结束前 →
memory[{"action":"add","memory_type":"episodic","content":"...","importance":0.7}]写入跨会话小结; - 修改代码 → 在
Finish[...]中输出*** Begin Patch ... *** End Patch,经执行器校验后落盘,并todo[{"action":"update","id":1,"status":"completed"}]收尾。
这套流程的底层支撑全部可在仓库中验证:提示词约定见 react.md 与 system.md,工具实现见 tools/builtin,补丁落盘见 apply_patch_executor.py。若要在本地体验,可参考 code_agent/README.md 配置DEEPSEEK_API_KEY等环境变量后运行python3 -m code_agent.hello_code_cli --repo .启动 CLI。
总结:tools.md表面上是一份工具使用清单,实质上定义了一套"最小工具调用 + 强安全边界 + 显式状态管理"的 Agent 工程哲学——何时该出手取证、何时该忍住不调、何时必须走补丁,均有提示词约定与源码强制双重保障。理解这份指南,等于同时掌握了 Claude Code 风格 Agent 的"用户手册"与"实现原理"。
【免费下载链接】hello-agents📚 《从零开始构建智能体》——从零开始的智能体原理与实践教程项目地址: https://gitcode.com/GitHub_Trending/he/hello-agents
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考