用 HelloAgents 组件搭建类 Claude Code 的本地 Code Agent CLI:多轮对话、按需代码探索与安全补丁落盘实战
【免费下载链接】hello-agents📚 《从零开始构建智能体》——从零开始的智能体原理与实践教程项目地址: https://gitcode.com/GitHub_Trending/he/hello-agents
本文以开源仓库Co-creation-projects/YYHDBL-HelloCodeAgentCli中的code_agent/README.md为核心,深入拆解一个基于 HelloAgents 组件(HelloAgentsLLM/ContextBuilder/ReActAgent/TerminalTool/NoteTool/MemoryTool)实现的简易 Code Agent CLI。它面向本地代码仓库提供类似 Claude Code / Codex 的交互体验:支持多轮对话、按需探索代码库、生成补丁并在用户确认后安全落盘。读完本文,你将掌握该 CLI 的安装启动方式、ReActAgent多轮对话与规划机制、GSSC 上下文工程与按需探索(lazy_fetch)模式、终端工具的沙箱与危险命令确认策略,以及 Codex 风格补丁从模型输出到原子落盘的完整链路。
项目定位与整体设计
HelloAgents Code Agent CLI(代码目录Co-creation-projects/YYHDBL-HelloCodeAgentCli/)是一个面向本地代码仓库的命令行智能体。与通用对话机器人不同,它被设计为"在仓库内工作的 CLI 编程助手":工作区固定为仓库根目录,所有路径都必须经过 repo_root 前缀校验,写盘唯一通道是补丁 + apply_patch,禁止cat >/tee/ Here-Doc / 重定向等终端写法。
从源码结构看,系统采用分层设计:
- CLI 层:
code_agent/hello_code_cli.py负责参数解析、环境初始化、交互循环、补丁提取与确认; - 智能体层:
agents/react_agent.py提供 ReAct(推理 + 工具调用)主循环,配合agents/simple_agent.py、agents/plan_solve_agent.py、agents/reflection_agent.py等范式; - 核心层:
core/llm.py(HelloAgentsLLM统一 LLM 接口)、core/message.py、core/config.py、core/exceptions.py; - 上下文层:
context/builder.py实现 GSSC 流水线; - 工具层:
tools/builtin/下的terminal_tool.py、context_fetch_tool.py、note_tool.py、todo_tool.py、plan_tool.py、memory_tool.py等; - 执行器层:
code_agent/executors/apply_patch_executor.py负责安全补丁应用与文件操作。
其中 Code Agent 的主逻辑封装在code_agent/agentic/code_agent.py的CodeAgent类中,CLI 入口main()只负责拼装组件与交互循环(hello_code_cli.py)。
快速开始:从依赖到启动 CLI
1. 准备依赖与环境变量
依赖定义在项目根目录的requirement.txt:
openai>=1.0.0 pydantic>=2.0.0 python-dotenv>=1.0.0 tiktoken>=0.5.0 hello-agents[all]=0.2.7建议先安装根目录的requirements-mvp.txt(见code_agent/README.md),再在仓库根目录创建.env(参考.env.example,不要提交到版本库),至少包含:
DEEPSEEK_API_KEY=sk-xxxxxxxxxxxx可选配置(OpenAI 兼容 provider 均可):
LLM_MODEL_ID=deepseek-chat LLM_BASE_URL=https://api.deepseek.comCLI 启动时会执行load_dotenv(dotenv_path=repo_root / ".env", override=False)加载环境变量,并通过HelloAgentsLLM()自动从环境探测 provider(hello_code_cli.py)。启动时还会做一次 LLM 预检(ping请求,max_tokens=1),若认证失败会给出明确提示并返回退出码 2。
2. 启动 CLI
# 工作区默认为当前目录 python3 -m code_agent.hello_code_cli --repo . # 指定其他代码库 python3 -m code_agent.hello_code_cli --repo /path/to/your/project支持的启动参数:
| 参数 | 说明 | 默认值 |
|---|---|---|
--repo | 代码库根目录(工作区) | . |
--project | 项目名称(默认取 repo 目录名),用于笔记标签等 | 目录名 |
启动后进入交互循环,命令:
:quit(或:q/quit/exit):退出;:plan <目标>:强制生成计划(平时由模型按需调用plan[...]工具);- 直接输入自然语言即触发一轮 ReAct 对话(hello_code_cli.py)。
多轮对话与智能体范式:ReAct 主循环 + 可选规划
Code Agent 的核心循环使用ReActAgent:每次回复必须包含Thought与Action两部分,Action二选一——调用工具(tool_name[tool_input])或以Finish[最终回答]结束;Finish中可携带*** Begin Patch ... *** End Patch补丁(react.md)。
在CodeAgent.__init__中,工具注册表包含六个工具:terminal、note、plan、todo、context_fetch,以及通过MemoryTool启用的情景记忆;ReAct 最大步数设置为 20,并注入observation_summarizer:当工具输出超过 8000 字符时先截断,再交给 LLM 以summarize_observation.md模板压缩为不超过 400 token 的摘要,避免把巨大原始输出直接塞进 Prompt(code_agent.py)。
run_turn每轮流程为:
- 空输入提示、闲聊(
hi/hello/你好/在吗等)直接自然回复,避免无谓工具调用; - 元请求("刚才说了什么 / recap")直接总结最近对话历史,不调用 memory/note;
- 检测到"分步/步骤/计划/改造/完成后"等多步骤词汇时,向系统提示追加轻量 hint,引导模型先用 todo 记录;
- 用
ContextBuilder.build_base构建保底上下文(系统指令 + 对话历史 + 最近工具摘要); - 运行 ReAct 循环,收集
last_trace中的工具证据摘要存入recent_tool_packets(缓冲区上限 8 个); - 追加用户/助手消息到历史(保留最近 50 条)并持久化会话到
sessions/下的 JSON 文件; - 若模型使用了 todo 但未在结尾
todo list汇总,自动补一张 Todo board 快照(code_agent.py)。
规划能力作为可选工具plan[...]暴露给模型,模型按需调用;计划模板要求输出## Plan(5~12 条可运行步骤)、## Risks、## Validation三节(plan.md)。多步骤任务的进度追踪由todo[...]完成,状态为pending / in_progress(仅 1 个)/ completed。
上下文工程:GSSC 流水线与按需探索(lazy_fetch)
上下文构建由context/builder.py的ContextBuilder实现 GSSC 流水线:Gather(从历史、记忆、RAG、工具结果多源收集)→Select(基于优先级、相关性、多样性筛选,支持 MMR)→Structure(组织成结构化模板)→Compress(在 token 预算内压缩)。
Code Agent 的关键设计是ContextConfig(lazy_fetch=True):默认不做全仓扫描、不主动查询 memory/rag,只构建"保底上下文"(系统提示 + 最近 10 轮对话历史 + 上次工具摘要),扩展上下文改由模型通过context_fetch工具按需获取(code_agent.py)。
ContextConfig的核心参数(builder.py):
| 参数 | 默认值 | 说明 |
|---|---|---|
max_tokens | 8000 | 上下文总预算 |
reserve_ratio | 0.15 | 生成余量(可用预算 = max_tokens × (1 − reserve_ratio)) |
min_relevance | 0.3 | 扩展上下文最小相关性阈值 |
max_history_turns | 10 | 最大保留对话轮数 |
enable_mmr/mmr_lambda | True / 0.7 | 最大边际相关性(0=纯多样性,1=纯相关性) |
enable_compression | True | 启用压缩 |
lazy_fetch | True | 按需探索模式:不主动查 memory/rag |
context_fetch是聚合搜索工具,一次调用可搜索多个源(files/notes/memory/tests),自动控制 token 预算(默认每源约 800 token,单次 5 行上下文),比反复单独调用 note/memory search 更省步数;使用策略是"先用保底上下文推理,证据不足再调用"(tools.md)。
安全终端工具:白名单、shell 语义与危险命令确认
TerminalTool是 Code Agent 查看/检索代码库的主要通道,实现于tools/builtin/terminal_tool.py,具有多层安全机制:
- 命令白名单:
ALLOWED_COMMANDS仅包含只读与文本处理命令——ls/dir/tree、cat/head/tail/less/more、find/grep/egrep/fgrep/rg、wc/sort/uniq/cut/awk/sed、echo/printf、mkdir、pwd/cd、file/stat/du/df、which/whereis、git(terminal_tool.py); - shell 语义:默认启用
default_shell_mode=True(体验更像 Claude Code),支持管道等写法(如rg ... | head);但重定向(>/>>,/dev/null除外)、子命令替换($()/反引号)、rm/chmod、git reset --hard均被判定为高风险,必须allow_dangerous=true并通过交互确认(confirm_dangerous=True)后才执行(terminal_tool.py); - 路径沙箱:
cd被限制在工作空间内,rm/chmod/mkdir的路径参数(跳过-选项)逐一resolve()后校验是否位于 workspace 内; - 超时与输出限制:默认超时 30 秒(CodeAgent 实例化时传入 60 秒)、输出上限 10MB,超限截断(terminal_tool.py);
- argv-only 执行:非 shell 模式使用
shlex.split+subprocess.run(shell=False),避免 shell 注入;git 子命令仅放行只读的status/diff。
git的默认策略是"仅允许status/diff",git reset --hard需要显式放行——这与 CLI 层补丁确认策略一致,共同构成"默认只读、危险操作必须人工确认"的安全基调(terminal_tool.py)。
补丁落盘(B 路线):从模型输出到原子写入
补丁格式规范
模型在Finish[...]中输出 Codex 风格补丁,格式必须严格遵守(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/Update后跟完整文件内容、Delete后不需要内容;不要在补丁外包裹 markdown 代码块;路径相对于仓库根目录。
CLI 侧的提取与确认
CLI 使用两个正则从响应中提取补丁:PATCH_FENCE_RE优先匹配 ```patch/diff/text 围栏内的补丁块,PATCH_RE作为宽松兜底(跨行匹配*** Begin Patch ... *** End Patch)(hello_code_cli.py)。_normalize_patch会宽容修复模型常见的格式错误——如缺少前导***的Add File: / Update File: / Delete File:行会被自动补齐(hello_code_cli.py)。
_patch_requires_confirmation定义高风险补丁触发二次确认的条件(hello_code_cli.py):
- 包含
*** Delete File:删除操作; - 文件操作数 ≥ 6 个;
- 变更行数 ≥ 400 行。
命中任一条件即进入y/n确认流程;拒绝则取消落盘。应用成功后,CLI 会自动通过 NoteTool 以note_type=action、tags=[project, patch_applied]记录一条"Patch applied"笔记,失败则记录blocker类型的"Patch failed"笔记,便于后续复盘(hello_code_cli.py)。
ApplyPatchExecutor 的安全执行
落盘由code_agent/executors/apply_patch_executor.py的ApplyPatchExecutor完成,支持三种操作:Add File、Update File、Delete File。其安全特性(MVP)包括:
- repo_root 路径限制:
_safe_path拒绝绝对路径(/、~开头)、拒绝逃逸 repo_root 的路径(resolve 后前缀校验)、拒绝修改符号链接,防止路径穿越(apply_patch_executor.py); - 后缀白名单:
allowed_write_suffixes默认仅允许.py/.md/.toml/.json/.yml/.yaml/.txt/.html/.htm/.css/.js等文本文件,防止误改二进制或敏感文件(apply_patch_executor.py); - 规模限制:单个补丁最多 10 个文件、总变更行数上限 800 行(
_estimate_changed_lines对 add 按行数、delete 按 1 行、update 只计+/-行); - 原子写入:
_atomic_write先写临时文件并os.fsync刷盘,再用os.replace原子替换,避免中断导致文件损坏(apply_patch_executor.py); - 自动备份:每次应用前在
<repo>/.helloagents/backups/<时间戳>/下为被修改文件生成.bak备份(保留仓库相对路径结构); - 冲突检测:
Update File按 hunk(@@或空行分隔)精确匹配上下文子序列,找不到匹配时抛出PatchApplyError并附recheck_targets提示(如rel_path:search:'<上下文行>');匹配失败还会尝试忽略行尾空白的宽松匹配,以及"将 payload 视作新的完整文件"的兜底回退(apply_patch_executor.py)。
记忆与笔记:episodic 情景记忆与结构化笔记
- NoteTool:在
<repo>/.helloagents/notes/下写入结构化 Markdown 笔记,note_type支持action / decision / blocker / task_state等,用于记录决策、阻塞与行动;CLI 还会自动把补丁成功/失败写入笔记。 - MemoryTool:仅启用
episodic类型(SQLite 持久化),默认存储在<repo>/.helloagents/memory/;情景记忆需要显式add,不会自动写入,避免上下文污染;跨会话可通过search回忆"发生过什么"(tools.md)。 - 会话持久化:每轮对话结束后,最近 50 条历史以 JSON 形式写入
<repo>/.helloagents/sessions/<session_id>.json(code_agent.py)。
存储布局默认使用<repo>/.helloagents/(notes/memory/sessions/logs/backups/todos),可通过环境变量覆盖。
配置项与存储布局
core/config.py的Config类集中管理全部配置,支持环境变量加载(CODE_AGENT_<配置项大写>或传统命名)与手动覆盖(config.py)。code_agent/README.md明确给出的覆盖变量:
HELLOAGENTS_DIR=.helloagents:状态存储根目录(也可用CODE_AGENT_STATE_DIR);CODE_AGENT_MAX_STEPS=8:ReAct 最大推理步数(源码默认 20,源码另支持CODE_AGENT_MAX_REACT_STEPS)。
其余可通过环境变量调节的常用项(源码确认):CODE_AGENT_PATCH_MAX_FILES(默认 10)、CODE_AGENT_PATCH_MAX_LINES(默认 800)、CODE_AGENT_TERMINAL_TIMEOUT(默认 60 秒)、LLM_TIMEOUT(默认 60 秒)、TEMPERATURE(默认 0.7)、LOG_LEVEL(默认 INFO)。上下文构建的独立配置ContextConfig见上文表格;补丁确认阈值(6 个文件 / 400 行)对应Config.large_change_threshold_files/large_change_threshold_lines。
约束与已知限制
- 目前"敏感操作确认"优先覆盖:
Delete File、git reset --hard、rm/chmod、大规模变更;更细粒度的策略(如按命令/路径/目录的白名单)后续可扩展; TerminalTool仍是"字符串命令"入口,但非 shell 模式执行为 argv-only,并在工具内拦截 shell 语义(重定向/命令替换/危险命令需确认);更严格的参数级白名单可以继续收紧;- 补丁应用依赖上下文精确匹配,若文件在生成补丁后被改动,
Update File可能失败并给出recheck_targets提示,需要人工复核; - 记忆默认只启用 episodic 类型,semantic/perceptual/working 等其他记忆类型(
memory/types/下均有实现)未在 Code Agent 中启用。
相关文件索引
- CLI 入口:code_agent/hello_code_cli.py
- 主逻辑/上下文工程:code_agent/agentic/code_agent.py
- 补丁执行器:code_agent/executors/apply_patch_executor.py
- 提示词模板:code_agent/prompts/(
system.md/react.md/plan.md/tools.md/summarize_observation.md) - 终端安全工具:tools/builtin/terminal_tool.py
- 上下文构建 GSSC:context/builder.py
- 统一配置:core/config.py
- 依赖清单:requirement.txt
- 上下文工程原理解读:可对照仓库文档 docs/chapter9/第九章 上下文工程.md
如需深入理解 Code Agent 所依赖的组件原理,可继续阅读仓库agents/、core/、memory/、tools/目录下的对应实现。
【免费下载链接】hello-agents📚 《从零开始构建智能体》——从零开始的智能体原理与实践教程项目地址: https://gitcode.com/GitHub_Trending/he/hello-agents
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考