主题
对话编程基础
一句话:对话编程的本质是把需求、上下文、约束和验收显式写出来,让模型在有限范围内产出可验证的结果;换来的是不用记 API 和样板,代价是你必须把脑子里的隐含前提说清楚。
适用:2026 年主流对话式编程工具。不同工具对系统提示词和项目规则文件的加载方式不同,以官方文档为准。
为什么需要
同一个模型,两个人用出完全不同的结果,差别通常不在模型,而在输入:一个人只说“帮我写个导出功能”,另一个人给了技术栈、相关文件、验收标准和禁止项。模型只能根据可见信息做最可能的补全,没说的部分它只能猜,猜错就表现为“看着合理但不能用”。对话还带来两个工程问题:规则只存在于某个人的会话里,换个人就要重新交代;上下文没有预算概念,贴得越多越贵,关键约束反而被淹没。所以对话编程不是“会聊天”,而是把需求、上下文、约束、验收显式化,并让团队共享的部分沉淀到仓库里。
核心机制
Prompt 五要素
| 要素 | 作用 | 缺了会怎样 |
|---|---|---|
| 角色 | 限定语言、领域、经验视角 | 用通用写法,术语和默认方案不对路 |
| 上下文 | 技术栈、目录、相关代码、已有约定 | 代码无法直接落地,接口和风格对不上 |
| 任务 | 做什么 + 验收标准 | 输出发散,不知道何时算完成 |
| 约束 | 必须用、禁止用、不能改 | 顺手重构、引入禁用依赖、破坏接口 |
| 输出格式 | 代码、diff、解释、文件范围 | 解释淹没代码,或改动散落多处 |
角色和上下文决定“像不像这个项目”,任务和约束决定“是不是这件事”,输出格式决定“能不能直接用”。最容易被省略的是验收和约束,而它们恰恰决定产出能不能进仓库。
六种对话模式
text
[生成] 你是 {语言} 工程师,熟悉 {技术栈};实现 {功能},验收 {AC};必须用 {库},禁止 {写法};只给完整代码和改动点。
[解释] 解释 {代码}:整体职责 → 调用链 → 关键分支 → 隐含假设 → 风险;不认识的 API 先说明版本,不要猜。
[补全] 在 {文件} 的 {函数/TODO} 处补全;沿用现有命名、错误处理、日志风格;只返回补全部分,不改其他代码。
[修改] 只改 {函数/行为} 为 {目标};保持 {签名/返回结构/调用方} 不变;先列将改文件,再给 diff,不确定先问。
[审查] 审查 {文件/diff}:正确性、边界、并发与资源、安全、可测试性;按严重度排序,每条给位置、触发条件、修复建议。
[调试] 现象是 {期望 vs 实际},堆栈 {粘贴},最小复现 {粘贴};给 3 个按概率排序的根因假设和验证命令,不要直接大改。生成和修改最容易越界,所以模板里都有“只改哪里、保持什么不变”;审查和调试最容易被泛泛而谈,所以要求排序、触发条件和验证命令。
系统提示词与 AGENTS.md
系统提示词管一次会话的角色和通用规则;AGENTS.md 是跨工具约定,管一个仓库的长期事实,通常放在项目根目录,但各工具加载优先级不同:Claude Code 默认读 CLAUDE.md,是否支持或优先 AGENTS.md 以工具与版本官方文档为准;跨工具可以用软链或导入。它只写“不看就会做错”的内容:技术栈与版本、目录职责、安装/测试/lint/类型检查命令、编码禁区、验证方式。先不写,按重复失败追加:没有实际踩坑时写的规则多半是猜测;常见 20–50 行(经验值),超过 200 行应拆分,因为上下文预算有限,规则越长越容易被忽略;关键条款放前面,细节拆到被引用的子文档。它只是提示,不是权限边界:规则可能被忽略,也可能被仓库内容注入覆盖,硬约束必须放在工具权限和 CI 门禁里。
上下文注入
| 方式 | 适用场景 | 注意 |
|---|---|---|
| @文件 | 参考已有实现、对齐接口 | 只 @ 相关文件,一次 3–5 个(经验值) |
| 贴片段 | 改具体函数、调试 | 贴最小可复现片段和完整错误,不贴整文件 |
| 目录树 | 新功能、找入口 | 只到 2–3 层,标出关键目录 |
| AGENTS.md | 团队共享规范 | 支持该约定的工具自动加载,不在每个 prompt 里重复 |
上下文不是越多越好:无关代码会稀释重点、推高成本,也让模型更难判断哪条约束优先。最小够用原则是先给入口文件、接口和验收,模型说缺什么再补;补的时候按“报错 → 相关函数 → 调用方”逐层展开。
模型只看到被组装进去的内容,没注入的等于不存在;五类输入在同一个入口汇合,缺哪一项都会在输出端表现出来。反馈箭头不是重复提问,而是补上下文或收紧验收;检查节点放在人工审查之前,因为编译和测试比人眼更快暴露低级错误。
约束表达
无效约束的共同点是不可判定:“注意安全”“质量高一点”“尽量别用全局变量”,模型只能把它当语气,改不了行为。有效约束要能被代码、测试或 review 判断:
| 无效 | 有效 |
|---|---|
| 注意安全 | 所有 SQL 参数化;禁止拼接用户输入;密码用 bcrypt/argon2 |
| 代码规范一点 | 禁止 any;公共函数必须有类型签名;错误必须包装后返回 |
| 别改太多 | 只改 src/order/;不改公开接口、数据库 schema 和其他模块 |
公式是“必须 A/B/C + 禁止 X/Y/Z + 不确定就说不确定”。约束也不是越多越好:互相冲突的规则会让模型挑一条执行,风格类要求交给 formatter/linter,prompt 只留影响正确性和边界的硬约束。
多轮协作与纠错
| 好做法 | 坏做法 |
|---|---|
| 先给上下文,再提任务 | 只说“帮我写个 X” |
| 一次一个可验收目标 | 一次要十个功能 |
| 纠错说位置、实际、预期、其他不变 | 只说“不对” |
| 新话题开新会话,长会话重述约束 | 一个会话聊十个不相关话题 |
| 让 AI 列影响面和验证命令 | 不看输出直接复制 |
text
{文件}:{行/函数} 的行为不对:现在是 {实际},预期是 {期望}。
只改这里,其他文件、接口和测试保持不变。
改完给出验证命令和预期输出。不指出位置,模型倾向重写整段,带来无关 diff;不说预期,它只能再猜一次;不说其他不变,回归面会扩大。纠错不是重复原话,而是补上缺失的上下文或验收。
实战场景
案例:同一个 bug 的三次失败对话与一次修复
现象:订单导出接口在大数据量下超时。同一个模型、同一个仓库,两次对话走向完全不同。
第一轮(三次失败):
text
我:/orders/export 接口超时了,帮我修一下。
AI:[给出改后的导出函数,加了分页]
我:还是超时。
AI:[改成批量处理]
我:测试挂了。
AI:[开始改测试]三轮下来 diff 覆盖 4 个文件,超时根因没修掉,两个原有断言被顺手改掉。
第二轮(一次通过):
text
我:修复 /orders/export 超时。背景:该接口由 src/export/orders.py 实现,
内部调用 OrderRepo.query_all() 一次性拉取百万行;日志确认耗时在 DB 查询,
不在序列化。边界:只改 src/export/orders.py 的查询层,不动响应结构和任何调用方。
完成判据:50 万行数据夹具下 test_export_large 通过,pytest tests/export 全绿。
禁止:不改 ORM 分页工具类、不引入新依赖、不重构任务范围外代码。
AI:[先给计划:query_all 改 keyset 分页,列出受影响函数与风险]
我:执行。
AI:[改完,附测试命令与输出]差别不在运气,也不在话术,而在首轮四要素:上下文锚定(哪个文件、耗时定位在哪)、边界(只改哪一层)、完成判据(哪条测试过算做完)、禁止事项(别动什么)。第一轮三次失败不是模型弱,而是“修超时”没有可判定的终止条件:每次失败模型都在同一信息空间里重新猜测,diff 逐轮扩大。这正对应 Prompt 五要素与多轮纠错一节:验收和约束最容易被省略,而纠错要说位置、实际、预期、其他不变——首轮没给,后面就要加倍补回来。
事故复盘:AI 顺手重构了不该动的模块
一次改地址表单校验规则的需求,对话中 AI “为了风格一致”把相邻用户模块的命名也重构了——diff 300 多行(经验值,告警阈值需按团队校准),用户模块两个既有断言被连带修改后静默失败,直到上线前回归测试才暴露。代价:1.5 天回归排查,评审人逐行读完 300 行才定位到那两处。
止损与后续处置按这条路径执行:
机制上根因是“修改”模式没有内建边界:模型的默认目标是“让我看到的代码更合理”,相邻代码天然在它的视野里。修法必须两层都有:事前任务边界声明,“只改 X、不动 Y”,且按约束表达一节写成可判定条款;事后 diff 审查门禁,用 git diff --stat 对照任务声明的文件清单,不一致的部分整体回滚、不部分采纳。前者是提示层软约束,可能被突破;后者是流程层硬约束。两层都在,损失才只发生一次。
场景:上下文喂料的反模式
调试一个权限 bug:把整个仓库 src/ 目录 200 多个文件连同 3000 行完整日志一起贴进对话框。模型给出自信但错误的结论——它引用了同名不同义的旧模块里的权限校验写法,当作本项目现行约定;关键日志段埋在中间,模型优先抓住了首尾一个无关的命名细节来解释。三轮对话,方向错了三轮,成本还随上下文体积同步上涨。
改成指针式引用后一轮解决:
text
现象:admin 角色用户访问 /reports 返回 403,普通角色正常。
关注:src/auth/guards.ts 中 PermissionGuard.can() 一段(约第 80 行),
以及它的调用方 src/reports/router.ts。
错误核心:[完整异常类型 + 堆栈前 10 行]。
先按概率列 3 个根因假设并各给验证命令,不要先改代码。这轮输入总量不小,但信息密度完全不同:文件路径加关注段落让模型按需定位,而不是在 200 个文件里“猜哪个重要”;日志保留类型与堆栈顶、丢掉噪音。对应上下文注入一节的“最小够用”:上下文越长,模型抓住的越是首尾内容和高频模式,中间的关键约束反而被稀释。调试模式模板里“给 3 个按概率排序的根因假设和验证命令,不要直接大改”也同时生效——它强制模型在改代码之前把推理路径暴露出来,让人能先验证假设再付修改成本。
最小上手
在仓库根目录放一份最小项目约定文件(如 AGENTS.md;Claude Code 默认用 CLAUDE.md),再用一个真实小任务跑通“注入—生成—验证”的闭环。
md
# 项目约定
技术栈:{语言/版本}、{框架/版本}、{包管理器}
目录:src/ 业务;tests/ 测试;scripts/ 运维脚本
命令:安装 {cmd};测试 {cmd};lint {cmd};类型检查 {cmd}
规范:分层调用;错误包装后返回;公共函数有类型签名
禁止:全局可变状态、隐式依赖、关闭类型检查
改动:只改任务范围内文件,提交前跑测试和 lint
不确定:先提问,不要猜 API、版本或配置text
读 AGENTS.md 和 src/order/service.ts。实现退款申请接口,验收:返回 202、重复申请幂等、测试通过。
只改 src/order/,不动鉴权中间件和数据库 schema。先给计划和将改文件,确认后再改,改完附测试命令与输出。跑通判据是测试与 lint 通过、diff 不超出范围;安装命令按项目替换。
生产动作
- 项目约定文件(
AGENTS.md/CLAUDE.md)进仓库:走 review、随架构更新,新成员第一周确认工具真的加载了它;系统提示词管会话角色,两者冲突时要明确优先级,否则模型会随机选一条。 - 敏感数据不进对话:密钥、生产数据、客户信息用脱敏样本;企业环境让请求走网关审计。
- 控制上下文体积:大文件先给接口和符号,再按需展开;日志只贴关键段和完整错误类型,不贴整份输出。
- 产出必须过门禁:lint、类型检查、测试全过才算完成。排障顺序是“验收是否可判定 → 上下文是否缺失 → 规则是否被加载”。
边界
- 需求没想清时,对话只会更快产出错误答案:先写一段可判定的验收,再开口。
- 模型会幻觉 API 和版本:签名、配置项以官方文档或编译结果为准。
- 上下文有上限:没给的文件等于不存在,塞太多又会稀释重点;最小够用是唯一平衡点。
- 对话灵活、门槛低,但结果不可复现,且依赖个人表达能力;需要可追溯时应改用书面规格(SDD)。AGENTS.md 是提示不是权限,硬约束必须靠工具与 CI。
讲清楚
对话编程的本质是把隐含前提显式化:角色和上下文让它像这个项目,任务和验收让它收敛,约束和输出格式让它能直接落地。五要素里最容易漏的是验收和约束,而它们决定代码能不能进仓库。六种模式只是骨架,真正拉开差距的是上下文注入和纠错:只给最小够用的相关文件,错了说清位置、实际、预期和其他不变。AGENTS.md 把团队共识沉淀下来,减少重复交代,但它只是提示,硬约束仍要放在权限和 CI 里。对话适合需求清晰、范围可控的任务;需求没想清或需要严格追溯时,先写规格更省。
适用:2026 年主流 AI Coding 工具 | 初稿 2026-10