返回

硬地周报26w9 / 如何实现一个 Coding Agent?

引言

本周主要分享之前的一个小研究:如何实现一个 Coding Agent?

Coding Agent 无疑是目前 AI 应用里实际价值最大的一类,比如正当红的 Claude Code、 Codex 等。

不知道你是否使用过,以及想过他们到底是如何实现的?

如果没有,你现在可以思考下。下面我们借着 Codex 这个开源项目一起学习下,再看看和你的设想是否一样。


定义场景

我们以一个最简单的前端需求为例:

把导航栏 /AppHeader.tsx 链接之间的间距加大一点。

来拆解它是如何工作的。

这里只看当前场景下的核心逻辑和流程,不会完全展开全部功能和实现细节。

基本保证准确,能力有限错误难免。


核心逻辑

1. 处理用户输入

阶段目标:把用户输入处理成可被 Agent 消费的内容。

核心代码:codex-rs/tui/src/chatwidget.rs

主要逻辑:

2. 构建 TurnContext

阶段目标:基于 UserTurn 构建更完整的 Context 并启动任务。

核心代码:codex-rs/core/src/codex.rs

主要逻辑:

3. 运行 Turn

阶段目标:通过 Agent Loop,完成具体工作,比如修改代码。

核心代码:codex-rs/core/src/codex.rs

主要逻辑:

4. 前端展示结果

阶段目标:把 Agent Loop 的过程展示给用户。

核心代码:codex-rs/tui/src/chatwidget.rs

主要逻辑:把推理接口响应的内容解析后,流式输出给用户,直到循环结束展示 assistant 消息为止。


拆解真实请求

下面我们打印实际日志,看一个完整 Agent Loop 的过程。

第一个回合

请求

Agent 基于我的输入「把 /AppHeader.tsx 链接之间的间距加大一点。」构建了 initial prompt 并发出请求。

响应

核心就是模型要求调用工具,执行 ls 命令。

response.output_item.added
item.type="function_call"
arguments="{\"command\":\"ls\",\"workdir\":\"/Users/...\"}"

第二个回合

请求

Agent 完成了 ls 的执行,带上执行结果再次请求。

响应

模型要求调用 sed 查看指定文件的前 200 行内容。

response.output_item.added
item.type = "function_call"
name = "shell_command"
arguments = "{\"command\":\"sed -n '1,200p' apps/web-backend/src/components/layout/AppHeader.tsx\", \"workdir\":\"/Users/...\"}"

第三个回合

请求

Agent 完成了 sed 命令,带上执行结果再次请求。

响应

模型要求调用 apply_patch 修改指定代码。apply_patch 不是 OpenAI 标准的 function_call,所以是 custom_tool_call

response.output_item.added
item.type = "custom_tool_call"
name = "apply_patch"
input = "*** Begin Patch
*** Update File: apps/web-backend/src/components/layout/AppHeader.tsx
@@
-        <nav className=\"flex items-center justify-center gap-4 text-sm font-medium leading-none text-muted-foreground sm:h-10 sm:justify-self-center\">\n
+        <nav className=\"flex items-center justify-center gap-3 text-sm font-medium leading-none text-muted-foreground sm:h-10 sm:justify-self-center\">\n
*** End Patch"

第四个回合

请求

Agent 完成了工具调用修改了代码,带上执行结果再次请求。

Exit code: 0
Wall time: 0 seconds
Output:
Success. Updated the following files:
M apps/web-backend/src/components/layout/AppHeader.tsx

响应

这次终于没有 tool_call 了,返回了 assistant 消息,最终展示给用户。

"output": [
  {
    "id": "msg_...",
    "type": "message",
    "status": "completed",
    "role": "assistant",
    "content": [
      {
        "type": "output_text",
        "text": "已把导航链接间距从 ..."
      }
    ]
  }
]

我的感受

看完了以上的过程,不知道和你的想象是否一样呢?

说实话,在知道 Codex 是如何实现之后,我其实是很震惊的。

从产品层面来说,真的是大道至简。我试图去理解下 Codex 的产品在做什么:

你应该能感受到模型到底有多重要。而作为一个古典产品出身的人,感受到了一丝「绝望」。

可能 Coding Agent 是一个比较极端的场景,恰好是模型最擅长的领域。但是我感受到了 AI 原生产品的设计思路和非 AI 产品的巨大不同。

一个感受是:传统产品依然是在定义和创造,然后交付给用户; 但是 AI 产品只是在帮助连接用户和模型,从一个创造者变成了传声筒。

还有一个想法是:没有垂直 Agent,只有通用 Agent。

Codex 其实只是给了 Agent 一个运行环境,然后提供各种 tools 和需要的上下文。从某种层面来看,和编程没有什么关系,最近火爆的 OpenClaw 算是某种证明?

同时我对于 Skills 有了新的理解。它其实是 Agent 的拓展,拓展了 instructions 和 tools。夸张地说,凡是通过计算设备交付的工作,Agent 理论上都可以完成。

虽然类比很不准确,还是禁不住想:如果 LLM 是大脑,那它需要的就是一个身体(运行环境)和一台电脑(工具)。