Codex 一次对话到底会给模型发送什么?以 Spring Boot 项目为例讲清 Context、代码读取与 Token 消耗

最近在研究 Codex、AI Agent、Harness、Context、Token 这些概念时,我一直有一个疑问:

我在 Codex 里只输入一句话,比如“开发一个意见反馈模块”,那 Codex 真正给模型发送的到底是什么?会不会把整个 Spring Boot 项目的前后端代码全部发给模型?平时 Token 又是怎么消耗的?

如果把这个问题搞明白,基本就能把 Codex 的 Prompt、AGENTS.md、Context、Tool、Agent Loop、Token 这些概念串起来。

下面就用一个真实的 Spring Boot + 前端项目来讲。


一、先假设有这样一个项目

例如现在有一个项目:

mall-system/
│
├── AGENTS.md
│
├── backend/
│   ├── pom.xml
│   └── src/main/
│       ├── java/com/demo/
│       │   ├── controller/
│       │   │   ├── UserController.java
│       │   │   └── NoticeController.java
│       │   ├── service/
│       │   │   ├── UserService.java
│       │   │   └── NoticeService.java
│       │   ├── mapper/
│       │   ├── entity/
│       │   └── dto/
│       └── resources/
│           ├── application.yml
│           └── mapper/
│
└── frontend/
    ├── package.json
    └── src/
        ├── views/
        ├── api/
        └── components/

现在打开 Codex,在输入框里说:

增加一个“意见反馈”功能。

用户可以提交反馈;
管理员可以查看反馈列表;
管理员可以把反馈标记为已处理;
同时完成前端页面和后端接口。

表面上看,我只输入了这么几句话。

但 Codex 第一次真正调用模型时,给模型准备的内容会多得多。


二、第一次调用模型,到底会发什么?

可以把它理解成一个“大包裹”:

┌───────────────────────────────────────┐
│          第一次给模型的内容           │
│                                       │
│ ① Codex 自己的基础 Instructions       │
│                                       │
│ ② 当前 Sandbox / 权限说明             │
│                                       │
│ ③ Developer Instructions              │
│    (如果配置了)                      │
│                                       │
│ ④ AGENTS.md                           │
│                                       │
│ ⑤ Skills 的说明                       │
│    (如果配置了)                      │
│                                       │
│ ⑥ 当前环境信息                        │
│    cwd、shell 等                       │
│                                       │
│ ⑦ Tools 的定义                        │
│                                       │
│ ⑧ 这个会话之前的聊天历史              │
│    (新会话基本没有)                  │
│                                       │
│ ⑨ 你当前输入的 Prompt                 │
│                                       │
│ “增加一个意见反馈模块……”             │
└───────────────────────────────────────┘
                  ↓
                 模型

也就是说:

Codex 每次给模型的不只是你输入框里的那一句话。

下面把每一部分分别讲清楚。


三、Codex 自己的基础 Instructions 是什么?

这个不是我们自己写的,而是 Codex 自带的。

可以把它理解成:

Codex 上岗前的“员工培训手册”。

概念上类似:

【Codex 内置 Instructions】

你是一个软件开发 Agent。

你的任务是帮助用户完成软件开发工作。

你可以使用提供给你的工具读取文件、
修改文件、执行命令……

在完成任务过程中应检查结果,
必要时使用工具验证修改……

……

注意:

上面的内容只是为了方便理解,不代表 Codex 内部真实提示词逐字就是这样。

我们只需要知道:

Codex 在真正把用户问题交给模型之前,会先告诉模型“你是谁、你应该怎么工作”。

这部分属于 Codex 自身 Harness 提供给模型的基础 Instructions。


四、当前 Sandbox / 权限说明是什么?

这个概念刚开始最容易看不懂。

其实它就是告诉模型:

“你现在有哪些权限,能操作到哪里。”

例如可以简单理解成:

【权限说明】

当前使用 Workspace Sandbox。

允许读取当前项目文件。

允许修改:
/Users/zmc/code/mall-system

不能随意修改项目目录之外的文件。

当前网络访问:
允许 / 受限制

某些 Shell 命令可以直接执行。

某些命令需要用户确认以后才能执行。

它不是在告诉 AI:

“意见反馈模块应该怎么开发。”

而是在告诉 AI:

“你干活时,这双手能伸到哪里。”

可以把它类比成公司的门禁卡权限。

例如:

普通办公区
→ 可以进入

服务器机房
→ 需要审批

某些敏感区域
→ 禁止进入

所以 Sandbox 和 Permission 主要解决的是:

Agent 实际拥有多大的操作权限。


五、AGENTS.md 会发什么?

假设项目根目录有:

mall-system/AGENTS.md

里面写:

# 项目开发要求

这是一个 Spring Boot + Vue 项目。

后端新增接口保持现有:
Controller → Service → Mapper 分层。

优先参考已有模块的代码风格。

不要随意修改现有接口。

数据库字段使用下划线命名。

前端优先复用现有组件。

后端修改完成运行:

mvn test

前端修改完成运行:

npm run build

这些内容会作为项目 Instructions 加入模型上下文。

所以第一次模型已经知道:

用户让我开发:
“意见反馈模块”

同时这个项目告诉我:

“这是 Spring Boot + Vue”
“后端遵循 Controller → Service → Mapper”
“不要乱改现有接口”
“修改完成以后要测试”

所以可以这样理解:

Prompt
=
这一次具体要干什么


AGENTS.md
=
这个项目平时应该怎么干

六、当前环境信息是什么?

这个其实非常简单。

例如:

【当前环境】

当前工作目录:
/Users/zmc/code/mall-system

Shell:
zsh

这里的:

cwd

就是:

Current Working Directory

中文就是:

当前工作目录。

相当于告诉 AI:

“你现在站在 mall-system 这个项目目录里。”

而:

zsh

表示当前 Mac 使用的 Shell。

这部分通常不会很长,但它对 Agent 很重要。

因为 Agent 至少要知道:

自己现在在哪个目录下面干活。


七、Tools 是什么?

Codex 还必须告诉模型:

“你现在有哪些工具可以用。”

否则模型并不知道自己能读取文件、修改代码或者执行终端命令。

例如可以简单理解成:

【可用工具】

Tool:Shell
作用:
执行终端命令。

Tool:文件读取
作用:
读取项目文件。

Tool:文件修改
作用:
修改项目文件。

Tool:搜索
作用:
搜索项目文件和代码。

Tool:MCP
作用:
调用外部系统能力。

……

这里有一个很重要的区别:

给模型的是 Tool 的“说明书”,不是把 Tool 程序本身发给模型。

例如模型知道:

我有 Shell 工具。

以后它才会判断:

我要执行:

mvn test

所以:

模型
负责判断“我要不要用工具”

Harness
负责真正提供和执行工具

八、最关键的问题:项目代码第一次会全部发给模型吗?

答案是:

不会。

假设这个项目有:

1000 个文件
30 万行代码

Codex 一般不会在第一轮直接变成:

Codex 系统提示词

+

AGENTS.md

+

30 万行项目代码

+

你的 Prompt

如果真的这样做,会非常浪费 Context 和 Token。

第一次更接近:

Codex 基础 Instructions
+
权限说明
+
AGENTS.md
+
环境
+
Tools
+
历史聊天
+
你的 Prompt

然后模型自己判断:

“为了完成这个任务,我接下来应该看哪些代码?”

这也是 Agent 和普通聊天模型一个非常大的区别。


九、第一次模型可能先决定:看看项目结构

例如模型判断:

我要开发一个意见反馈模块,先看看这个项目现在有哪些模块。

于是调用工具去:

查看目录

搜索 Controller

搜索 Service

搜索 Mapper

查看 pom.xml

查看 package.json

Codex Harness 真正去本地硬盘执行这些操作。

假设返回:

backend/pom.xml

backend/src/main/java/com/demo/controller/UserController.java

backend/src/main/java/com/demo/controller/NoticeController.java

backend/src/main/java/com/demo/service/UserService.java

backend/src/main/java/com/demo/service/NoticeService.java

frontend/package.json

frontend/src/views/notice/NoticeList.vue

frontend/src/api/notice.js

这个时候:

模型才知道这些文件存在。

也就是说:

一个文件躺在你的电脑硬盘里,不代表模型自动看到了它。

Codex 一般需要通过 Tool 去:

搜索
查看
读取

以后,相应内容才会进入后续 Context。


十、第二次调用模型会多出什么?

第一次模型说:

我要先看看项目结构。

Tool 返回项目目录。

接下来 Codex 再次调用模型。

第二次可以简单理解成:

原来的上下文

+

刚才模型调用工具的记录

+

工具返回的项目目录和搜索结果

例如模型看到:

【用户需求】

开发意见反馈模块。


【搜索结果】

NoticeController.java
NoticeService.java
NoticeMapper.java
NoticeList.vue
notice.js
……

模型发现:

Notice 模块和我要开发的 Feedback 模块很像。

于是继续调用 Tool:

读取 NoticeController.java

读取 NoticeService.java

读取 NoticeMapper.java

读取 NoticeList.vue

读取 notice.js

十一、第三次模型才真正看到 Java / Vue 代码

假设工具读取:

@RestController
@RequestMapping("/notice")
public class NoticeController {

    @Autowired
    private NoticeService noticeService;

    @GetMapping("/list")
    public Result list(...) {
        ...
    }
}

以及:

@Service
public class NoticeService {
    ...
}

再加上:

@Mapper
public interface NoticeMapper {
    ...
}

这些真实代码现在才进入模型 Context。

模型第三次看到的内容就会变成:

Codex 基础 Instructions
+
权限说明
+
AGENTS.md
+
环境
+
Tools
+
用户需求
+
之前的搜索结果
+
NoticeController.java 内容
+
NoticeService.java 内容
+
NoticeMapper.java 内容

这个时候模型才真正知道:

“原来这个项目后端代码是这样写的。”

所以:

项目代码不是一开始全部塞进去,而是在 Agent 工作过程中按需读取。


十二、前端代码会不会全部发?

还是:

不会。

因为当前需求明确要求:

同时完成前端和后端。

所以模型可能继续搜索:

frontend/src/views

frontend/src/api

frontend/src/router

frontend/src/components

然后挑一些真正相关的文件读取,例如:

NoticeList.vue

notice.js

router/index.js

Table.vue

这些被读取的文件内容,会进入后面的 Context。

但:

frontend 下面另外 500 个完全无关的 Vue 文件

不会因为它们存在,就自动全部发给模型。

所以要记住:

项目总代码量
        ≠
模型真正看到的代码量

真正影响 Context 的是:

这次任务过程中,Codex 到底搜索并读取了多少内容。


十三、如果我只让 Codex 改后端呢?

例如 Prompt 写:

只开发“意见反馈”后端接口,
不要修改前端。

那么 Codex 大概率主要围绕:

backend/

去查看:

pom.xml

Controller

Service

Mapper

Entity

DTO

SQL

配置

它没有理由大量读取:

frontend/

所以 Prompt 写得越明确,例如:

只改后端

只改 feedback 模块

参考 notice 模块

不要扫描无关业务模块

越有利于 Codex 收敛搜索范围。

这不只是让 Agent 更听话。

实际上也有利于减少:

无关代码读取

无关 Context

无意义 Token 消耗

十四、一个真实的 Codex 开发任务可能这样运行

整个过程可以简化成:

你:

开发意见反馈模块,
完成前后端。

        ↓

════════════════════
模型调用 ①
════════════════════

模型看到:

Codex Instructions
权限说明
AGENTS.md
环境
Tools
你的 Prompt

        ↓

模型判断:

“先看看项目结构”

        ↓

Codex 执行搜索


════════════════════
模型调用 ②
════════════════════

模型又看到:

前面的内容
+
目录和搜索结果

        ↓

模型判断:

“Notice 模块比较像,
读取它作为参考”

        ↓

Codex 读取:

NoticeController.java
NoticeService.java
NoticeMapper.java
NoticeList.vue
notice.js


════════════════════
模型调用 ③
════════════════════

模型看到:

前面内容
+
这些真实代码

        ↓

模型理解项目写法

        ↓

继续读取:

Entity
DTO
Router
数据库脚本


════════════════════
模型调用 ④
════════════════════

模型看到:

前面内容
+
更多相关代码

        ↓

开始创建:

FeedbackController
FeedbackService
FeedbackMapper
FeedbackEntity
FeedbackList.vue
feedback.js


════════════════════
模型调用 ⑤
════════════════════

模型判断:

“修改完成,需要测试”

        ↓

执行:

mvn test

npm run build


════════════════════
模型调用 ⑥
════════════════════

模型看到:

mvn test 输出
npm run build 输出

如果 ERROR:

分析错误
修改代码
重新测试


════════════════════
模型调用 ⑦
════════════════════

测试通过

        ↓

告诉你:

“意见反馈模块开发完成……”

所以:

你只发了一次消息,并不代表模型只被调用一次。

一次 Agent 任务内部,可能发生很多次:

模型推理
↓
Tool 调用
↓
Tool 返回
↓
再次模型推理

这就是:

Agent Loop。


十五、第二次继续聊天时,会发什么?

假设第一轮已经开发完成。

你没有新开会话,而是在同一个 Codex 对话里继续说:

列表再增加一个“反馈类型”筛选条件。

那么模型通常不会重新失忆开始。

可以简单理解成,新一轮会继续带上:

Codex 基础 Instructions
+
AGENTS.md
+
环境
+
Tools
+
上一轮 Conversation
+
之前相关 Tool Calls / Tool Results
+
你刚刚输入的新 Prompt

这也是为什么:

同一个 Codex 会话越聊越久,Context 往往会越来越大。

因为前面做过的事情:

用户说了什么

模型做了什么

读取过哪些代码

Tool 返回了什么

执行命令有什么结果

都会对后续任务产生影响。


十六、Context 会一直无限增长吗?

不会无限增长。

假设一个会话已经聊了很多轮:

大量 Prompt
+
大量 Java 代码
+
大量 Vue 代码
+
大量 Shell 输出
+
大量错误日志

当上下文越来越大时,Codex 需要进行:

Compaction(上下文压缩)。

可以把它理解成:

以前几十页甚至上百页的工作记录

        ↓

压缩成更短的总结

        ↓

例如:

“目前已完成意见反馈模块;
后端包含 Controller、Service、Mapper;
前端包含列表和新增页面;
当前剩余问题是筛选条件。”

然后继续后面的工作。

所以 Context 不会永远只增不减。


十七、Token 到底消耗在哪里?

现在再说 Token 就非常容易理解了。

假设第一次模型调用,使用一组完全为了方便理解的假数字:

内容 假设 Token
Codex 基础 Instructions 8,000
权限 / 环境说明 1,000
Tool 定义 5,000
AGENTS.md 1,000
你的 Prompt 200
第一次输入 约 15,200

这里有一个非常重要的地方:

这时候还没有把整个 Spring Boot 项目算进去。

然后 Codex 搜索并读取了一些代码。

第二轮又增加:

新增加内容 假设 Token
目录和搜索结果 1,000
NoticeController 1,500
NoticeService 2,000
NoticeMapper 1,000
增加 约 5,500

再读取前端:

新增加内容 假设 Token
NoticeList.vue 3,000
notice.js 800
router 1,000
增加 约 4,800

然后执行:

mvn test

如果返回几百行错误日志,又会继续增加 Context。

所以:

你输入的 Prompt 可能只有几十个字,但整个 Agent 任务累计处理的 Token 可能达到几万、几十万,甚至更多。


十八、真正消耗 Token 的大头通常是什么?

对于项目开发场景,Token 消耗的大头通常不是那句中文 Prompt。

更常见的是:

内容 对 Token 的影响
Codex 内置 Instructions / Tool 定义 每轮都有基础开销
很长的 AGENTS.md 持续占 Context
一次读取大量 Java / Vue 文件 很明显
大段 SQL / XML 很明显
mvn test 超长错误日志 很明显
同一个会话聊几十轮 很明显
MCP 工具很多 Tool 描述增加
普通几十字中文 Prompt 通常相对较少

所以:

Prompt 很短,不代表任务 Token 很少。

真正影响最大的,是 Agent 为了完成任务:

看了多少代码

读取了多少文件

产生了多少 Tool 结果

经历了多少轮模型推理

保留了多少历史上下文

十九、Cached Input Tokens 是什么?

以后可能会看到:

Input Tokens

Cached Input Tokens

Output Tokens

因为:

Codex 基础 Instructions
AGENTS.md
Tools 定义
前面的部分 Context

可能连续很多轮都基本一样。

这些重复内容可能命中缓存。

例如:

Input tokens:         50,000

Cached input tokens:  35,000

Output tokens:         3,000

可以简单理解成:

Input Tokens
=
这一轮模型总共需要处理的输入


Cached Input Tokens
=
其中有多少属于之前处理过、
这次可以利用缓存的内容

所以 Input 很大,并不意味着里面所有内容每次都完全按“全新内容”处理。


二十、怎么查看平时 Token 消耗?

如果使用 Codex CLI,可以在会话中尝试:

/status

它通常可以帮助查看当前会话的一些状态信息。

不同 Codex 版本实际展示字段可能有所不同,例如可能会看到:

Model

Directory

Permissions

Agents.md

Token usage

Context window

其中最值得关注两个概念:

Token Usage

Context Window

它们不是一回事。


二十一、Token Usage 和 Context Window 有什么区别?

假设看到:

Token usage:
800K total

Context window:
80K / 272K

不要觉得矛盾。

Token Usage

表示:

这个会话从开始到现在,模型累计处理过多少 Token。

因为一次用户问题可能触发:

模型调用 1

模型调用 2

模型调用 3

……

模型调用 20

所以累计 Token 完全可能超过模型 Context Window。


Context Window

表示:

当前这一刻,模型脑子里最多能同时放多少内容。

可以这样类比:

Context Window
=
你的办公桌一次最多能放多少资料


Token Usage
=
你从早到晚累计翻过多少页资料

例如:

办公桌一次只能放 500 页

但一天完全可以累计翻:

5000 页

两者并不冲突。


二十二、套餐 Usage 又是什么?

如果是 ChatGPT Plus / Pro 等方式使用 Codex,还可能看到:

5-hour usage

Weekly usage

Credits

这个和:

Token Usage

以及:

Context Window

又不是同一个概念。

可以简单分成:

指标 大白话
Token Usage 当前会话累计让模型处理了多少内容
Context Window 模型当前脑子里同时装了多少内容
5h / Weekly Usage Codex 套餐额度还剩多少

套餐额度不能简单理解成:

1 万 Token = 扣 1%

因为实际使用还会受到:

模型

任务复杂度

Context

推理强度

Tool 调用

任务持续时间

等因素影响。


二十三、自己怎么做一个最直观的 Token 实验?

可以拿一个真实 Spring Boot 项目测试。

第一步:新开一个全新会话

输入:

只告诉我这个项目使用什么技术栈。
不要修改任何文件。
尽量不要读取无关文件。

然后查看:

/status

记录 Token。


第二步:让 Codex 分析一个模块

输入:

详细分析用户管理模块的:

Controller

Service

Mapper

Entity

这时候 Codex 会读取更多代码。

再查看:

/status

Token 通常会明显增加。


第三步:让它分析整个项目

输入:

分析整个项目所有业务模块。

再查看:

/status

通常会看到:

分析整个项目
>>
分析单个模块
>>
只看技术栈

通过这个实验,很容易真正理解:

读取的内容越多,模型处理的上下文越多,Token 也通常越多。


二十四、整个 Spring Boot 功能开发过程可以这样理解

最后把整个过程压缩成一张图:

                     你
                     │
          “开发意见反馈模块”
                     │
                     ▼
┌──────────────────────────────────┐
│          Codex Harness           │
│                                  │
│ 基础 Instructions                │
│ 权限 / Sandbox                   │
│ AGENTS.md                        │
│ Skills                           │
│ cwd / shell                      │
│ Tool 定义                        │
│ 历史 Conversation                │
│ 当前 Prompt                      │
└────────────────┬─────────────────┘
                 │
                 ▼
              模型①
                 │
       “我要先看看项目”
                 │
                 ▼
           搜索项目文件
                 │
                 ▼
         返回相关文件列表
                 │
                 ▼
              模型②
                 │
    “读取类似模块作为参考”
                 │
                 ▼
      ┌──────────┴──────────┐
      ↓                     ↓
NoticeController       NoticeList.vue
NoticeService          notice.js
NoticeMapper           router
      │                     │
      └──────────┬──────────┘
                 ↓
        相关代码进入 Context
                 ↓
              模型③
                 │
            开始写代码
                 ↓
         创建 Feedback 模块
                 ↓
              模型④
                 │
       mvn test / npm build
                 ↓
           返回构建日志
                 ↓
              模型⑤
                 │
        有错 → 修改 → 再测试
                 │
                 ▼
               完成

二十五、最后总结

如果只记住几个结论,可以记下面这些。

1. Codex 不会默认把整个项目全部发给模型

第一次主要是:

Codex 基础 Instructions
+
权限 / Sandbox
+
AGENTS.md
+
环境信息
+
Tools
+
历史对话
+
你的 Prompt

2. 项目代码是“按需读取”的

模型先判断:

我需要看哪些文件?

然后通过 Tool:

搜索
读取
查看

只有真正读取到的代码,才会逐步进入后面的 Context。


3. 前后端不会天然全部发送

如果任务只涉及后端:

主要读取后端相关文件

如果任务同时涉及前后端:

才会分别查找相关前端、后端文件

但也不是把所有前后端代码一次性全部发进去。


4. 一次用户问题可能调用模型很多次

模型
↓
Tool
↓
模型
↓
Tool
↓
模型
……

这就是:

Agent Loop。


5. Token 最大的消耗通常不是你的 Prompt

更大的来源通常是:

代码

日志

Tool 结果

历史会话

多轮模型推理

长期 Context

6. Token Usage 和 Context Window 不是一回事

Token Usage
=
累计处理过多少内容


Context Window
=
当前模型脑子里能同时放多少内容

一句话总结

Codex 不是把整个 Spring Boot 项目一次性塞给模型,而是先把“基础指令、权限、AGENTS.md、环境、工具、历史和当前需求”等内容提供给模型,再由模型通过 Tool 按需搜索和读取相关代码;真正被读取的代码、日志、Tool 结果以及多轮 Agent Loop,才是日常 Token 消耗的重要来源。

理解这一点以后,再回头看:

Prompt

AGENTS.md

Context

Tool

Agent Loop

Token

Harness

这些概念其实就已经串到一起了。

本质上:

Harness 的一个重要工作,就是决定模型这一轮应该看到什么、能使用什么工具、能执行什么操作,以及如何在多轮 Agent Loop 中管理 Context。

posted @ 2026-09-02 13:57  人艰不拆_zmc  阅读(43)  评论(0)    收藏  举报