发布时间:2026/8/31 16:19:22
文档驱动Agent:把行为规范写进代码,让AI编程更可控 1. 为什么这条帖子值得关注问题的本质不是模型的强弱而是没有把“预期”写下来这两年用 AI 辅助编程的人越来越多但一个现象也变得越来越常见同一个模型同一段代码在不同人手里结果差异极大。有人觉得智能体很聪明改几个文件、跑一轮测试就能交付有人却觉得它只是“高级补全工具”要么改错地方要么反复绕圈子。这个差异往往不是模型能力的问题而是上下文工程的问题。最近有一个思路很值得关注Show HN 上出现了一个方向叫 “Get agents to do what I want with code documentation”核心观点非常直接想让 agent 真正按你的意图执行与其一直去调系统提示词不如把期望写进代码文档里。文档不只是给人看的注释更应该是 agent 的“行为规范”。这篇文章不是推荐某一个具体工具而是想把这条思路背后的问题意识、原理、落地方式和容易踩的坑讲清楚。文章会围绕几件事展开agent 为什么经常“不听话”根本原因在哪。代码文档为什么是约束 agent 行为的好载体。如何设计一份“能驱动 agent”的文档而不是普通备注。如何用文档驱动的思路跑通一个最小示例。以及失败时怎么排查生产环境怎么落地。如果你正在做 agent 应用、或者在用 AI 编程助手重构项目这篇文章应该能帮你省下不少调试时间。2. 核心概念文档驱动 Agent 行为到底在强调什么2.1 “文档驱动”不等于写注释很多团队过去写文档是为了给下一任维护者看或者为了过代码评审。但这条路线的核心在于文档是给 agent 当“可执行规格说明”用的。在传统软件开发里代码和文档经常发生“漂移”代码改了文档没改最后文档失去信任。但在 agent 驱动的开发流程里文档的最大作用是稳定系统提示词之外的非确定性因素。Prompt 是瞬时的写在会话开始时很容易被对话历史稀释。而文档是持久的它放在代码库中每次 agent 读取代码时几乎都会遇到。也就是说你可以通过一份设计良好的 README、文档字符串或 spec 文件让 agent 在每次调用函数、修改模块、运行测试时都“看见”你期望的行为边界。2.2 Agent 的“意图不确定性”从哪里来从实践角度看agent 行为不稳定通常是三层原因叠加造成的第一层是模型本身的概率性。同样的 prompt 多次调用结果不完全一样。 第二层是上下文窗口的稀缺性。当代码库很大时很多细节可能根本没被 agent 读取到。 第三层是表达层的模糊性。你脑子里很清楚“要兼容旧接口”但如果没有写下来agent 只能靠猜。文档驱动要解决的主要是第三层并且间接缓解第二层。它的做法不是让文档变得更长而是让文档变得更“结构清晰、意图明确”。例如一个函数如果只写“处理用户输入”那 agent 可能在五个方向里选一个如果文档写明输入必须是什么格式哪些情况应该拒绝返回错误使用什么类型禁止调用哪些底层 API。agent 的选择空间就大大缩小了。2.3 这是“行为规范”不是普通说明稍等这里有一个很重要的概念需要区分行为规范specification与普通说明description。普通说明描述当前代码“是什么”。比如get_user 函数用于获取用户信息。行为规范描述代码“应该做什么、不应该做什么、在什么条件下做什么”。比如get_user(id) 行为规范 - 仅接受整数型 id字符串数字需先转换。 - 当 id 0 时返回 UserNotFoundError。 - 禁止直接拼接 SQL必须走 user_repository。 - 如果用户不存在记录一条 WARN 日志返回 None。 - 本函数不允许调用外部 HTTP 服务。两者的差别就像“这里有一台冰箱”和“冰箱使用手册中规定了开门时间、温度范围、存放要求”之间的差别。agent 拿到普通说明只能知道函数大意拿到行为规范才能按边界执行。3. 为什么代码文档是 agent 行为约束的好载体3.1 代码文档离“执行现场”最近要让 agent 根据指导行动指导信息必须出现在它做决策的地方。对于代码生成型 agent 来说决策现场就是正在编辑的代码文件。如果行为说明放在外部 Wiki、在线文档或者口头沟通里agent 很可能根本看不到。但如果你把规范放在同目录下的 README、模块级文档字符串、或者类型注释里agent 在读取代码时就一定会读到。这也是文档驱动的优势降低上下文注入的成本。你没有必要把整本产品手册都塞给大模型只需要把与当前文件、当前函数、当前模块相关的规范写好让 agent 在上下文窗口里“就近命中”。3.2 文档是稳定资产可以复用、评审、回滚在实际软件工程里提示词散落在聊天记录里是灾难。今天你给 agent 说“不要用 requests 库”明天新增一个文件时它可能又用了。但如果把这类约定写进项目文档相当于在代码库里建立了“标准操作程序”。每次 agent 读项目文件时约定自然被纳入上下文。另一个好处是可评审性。团队代码评审时你能拿着文档逐条检查 agent 的产出是否符合规范而不需要依赖“我看它表现还行”这种模糊判断。3.3 对交互式 agent 尤其有效这里要提一个很多人容易忽略的场景交互式 agent比如 Playwright test agents。如果你用 Playwright 写 UI 测试agent 需要知道页面结构、需要点击的元素、等待策略、是否需要处理弹窗等。这些信息如果只存在于 agent 的对话上下文里一旦测试场景变长agent 很容易在前面步骤中迷失。把测试行为规范写进测试文件头部的 docstring例如本文件是用户登录流程的 UI 自动化测试。 执行规则 - 所有定位优先使用># AGENTS.md 本项目是订单管理系统后端。 ## 技术栈 - Python 3.11 - FastAPI - PostgreSQL - SQLAlchemy 2.x ## 全局约定 1. 所有新增接口必须提供 Pydantic 请求模型禁止直接返回 dict。 2. 数据库操作必须走 repository 层禁止在路由函数中直接写 SQL。 3. 时间字段统一使用 UTC禁止使用本地时间。 4. 所有外部 API 调用必须添加超时与重试机制。 5. 禁止在日志中输出用户手机号、身份证号等敏感字段。 ## 常用命令 - 启动开发服务: uvicorn app.main:app --reload - 运行测试: pytest tests/ -v - 代码格式: ruff check src/ ruff format src/这样一个文件能让 agent 在生成代码时从一开始就带上项目的工程约定。4.2 函数级规范怎么写才有效函数级 docstring 是 agent 最常读取的信息源。写得好的标准是“机器可以直接执行”。以 Python 风格为例# 文件路径src/services/user_service.py from typing import Optional class UserNotFoundError(Exception): 用户不存在时抛出。 def get_user_by_id(user_id: int) - Optional[dict]: 根据用户 ID 获取用户信息。 Behavior Specification: - 唯一入口禁止绕过此函数直接访问 UserRepository。 - user_id 必须是 int大于 0否则抛出 ValueError。 - 用户不存在时抛出 UserNotFoundError不返回 None。 - 查询时必须排除 deletedTrue 的软删除用户。 - 此函数不允许调用外部 HTTP 服务。 Returns: 包含用户核心信息的字典字段包括: id, name, email, created_at。 Raises: ValueError: user_id 非正整数。 UserNotFoundError: 用户不存在或已被软删除。 ...这里的关键不只是写出参数类型而是把“行为边界”写明。agent 在实现这个函数时遇到边界情况会优先参照这些约束而不是凭空发挥。4.3 用 Spec 文件管理复杂业务规则当规则较多时函数 docstring 会变得臃肿。这时候可以单独建立一个 specs/ 目录用 Markdown 文件描述复杂业务规则。例如处理退款流程# specs/refund_rule.md # 退款行为规范 ## 适用场景 - 用户发起退款 - 客服后台发起退款 ## 规则 1. 订单状态必须为 paid否则拒绝退款。 2. 退款金额不得大于订单实付金额。 3. 已发货订单必须经过人工审核。 4. 退款成功后必须发送站内信和邮件通知。 5. 禁止在事务未提交前发送通知。 ## 禁止事项 - 禁止直接删除订单记录。 - 禁止修改订单历史快照。 ## 异常处理 - 退款接口调用失败时必须将任务写入 retry_queue。 - 重试次数上限为 3 次超过后标记 failed。文件可以很短但边界必须明确。agent 在实现退款相关代码时如果 prompt 引用了这个 spec行为会显著收敛。5. 最小示例用文档让 Agent 实现一个带约束的功能这一节我们来跑一个完整的示例。目标不是依赖某个具体 AI 工具而是展示文档驱动流程的通用模式。5.1 需求背景假设我们有一个简单项目需要让 agent 实现一个parse_duration函数把字符串时长解析成秒数。用户希望在 prompt 里少说废话所有约束都写在源代码文档中。项目目录duration_project/ ├── AGENTS.md └── src/ └── parser.py5.2 AGENTS.md 内容# AGENTS.md ## 项目目标 提供时长解析工具。 ## 已安装依赖 - Python 3.11 标准库不额外安装第三方包。 ## 全局约定 - 所有函数必须带有 Behavior Specification 文档。 - 禁止处理负数时间。 - 禁止使用 datetime 模块解析时长。 - 单元测试放在 tests/ 目录。5.3 源码文件中的函数规范在 src/parser.py 中先写空实现和完整规范# 文件路径src/parser.py def parse_duration(value: str) - int: 解析时长字符串并返回总秒数。 Behavior Specification: - 仅接受字符串输入。非字符串直接抛 TypeError。 - 支持格式: 30s, 5m, 2h, 1d, 1h30m, 90s。 - 数字必须是正数不支持负数、小数、科学计数法。 - 不允许混合大小写统一使用小写单位。 - 没有单位时默认为秒。 - 单位不合法时抛出 ValueError。 - 本函数不允许使用 datetime.timedelta 直接解析。 # 待实现 ...5.4 Agent 的 Prompt 只需要很短请实现 src/parser.py 中的 parse_duration 函数。 先阅读 AGENTS.md 和 src/parser.py 的 Behavior Specification。 按规范实现并补充一个最小测试。注意我们没有在 prompt 里重复任何规则。规则已经在文档里。5.5 一个合理的实现结果下面是一个满足约束的实现示例展示 agent 应该产出的近似结果# 文件路径src/parser.py import re _UNITS { s: 1, m: 60, h: 3600, d: 86400, } def parse_duration(value: str) - int: 解析时长字符串并返回总秒数。 Behavior Specification: - 仅接受字符串输入。非字符串直接抛 TypeError。 - 支持格式: 30s, 5m, 2h, 1d, 1h30m, 90s。 - 数字必须是正数不支持负数、小数、科学计数法。 - 不允许混合大小写统一使用小写单位。 - 没有单位时默认为秒。 - 单位不合法时抛出 ValueError。 - 本函数不允许使用 datetime.timedelta 直接解析。 - 遇到重复单位时累加。 if not isinstance(value, str): raise TypeError(fvalue must be str, got {type(value).__name__}) pattern r(\d)([smhd])? matches re.findall(pattern, value) consumed_length sum(len(num) len(unit) for num, unit in matches) if consumed_length ! len(value): raise ValueError(fInvalid duration format: {value!r}) total 0 for num, unit in matches: total int(num) * _UNITS.get(unit, 1) return total5.6 测试用例建议# 文件路径tests/test_parser.py import pytest from src.parser import parse_duration def test_parse_seconds(): assert parse_duration(30s) 30 def test_parse_minutes(): assert parse_duration(5m) 300 def test_parse_hours(): assert parse_duration(2h) 7200 def test_parse_days(): assert parse_duration(1d) 86400 def test_parse_combined(): assert parse_duration(1h30m) 5400 def test_parse_without_unit(): assert parse_duration(90) 90 def test_parse_invalid_unit(): with pytest.raises(ValueError): parse_duration(10x) def test_parse_negative_should_fail(): with pytest.raises(ValueError): parse_duration(-30s) def test_parse_non_string(): with pytest.raises(TypeError): parse_duration(30) def test_parse_repeated_units(): assert parse_duration(1m30s) 90这里要强调的是agent 的实现如果没有文档约束可能会用datetime.timedelta可能会允许负数也可能会把90直接当作非法输入。但有了行为规范它的自由度被大大限制。6. 如何验证文档驱动的效果6.1 不只验证“能不能跑”还要验证“行为是否收敛”很多人在评估 agent 时只看测试是否通过。但在文档驱动方法里你还要关注另一个维度在多次生成中agent 是否选择了相同的实现路径。比如同样让 agent 实现parse_duration如果第一次生成用正则第二次用timedelta第三次用硬编码判断说明文档并没有真正约束住行为。一个简单的验证方法是固定同一文档和同一 prompt运行多次生成检查实现方案是否一致是否遵守了禁止项是否生成了冗余代码是否误解了边界条件。6.2 用回归测试保证规范性行为规范最好配套对应测试。如果某个规则可以被自动化验证就这样写def test_parse_duration_does_not_use_datetime_timedelta(): import inspect import src.parser as parser source inspect.getsource(parser.parse_duration) assert timedelta not in source这种测试不算优雅但在约束 agent 产出时往往很有效。它把文档里的“禁止事项”变成了可执行的检查。6.3 区分任务成功与任务可复现如果你使用具备长任务执行能力的 agent还会遇到另一个问题任务在中断后能否继续按原目标运行。这正好呼应了一个重要的点deep agents interrupt。在 agent 长时间运行过程中用户可能正在对话中插入新指令或者要求 agent 修正中间结果。如果 agent 只依赖对话上下文一旦中断它可能丢失原始目标。文档驱动的优势在这里就很明显当 agent 需要重新聚焦时它回到代码文件就能重新读到“目标”和“边界”不需要依赖很早之前的对话记录。因此验证时除了关注最终结果还要关注中途打断后的恢复能力在 agent 运行到一半时插入一条新指令然后要求它继续原来的任务观察它是否仍然遵守文档中的行为规范。如果它能回到文档、重新读取约束说明这套方案是有效的。7. 常见问题与排查思路在实际落地中文档驱动方法也会出现问题。下表列出常见现象与排查方向。问题现象可能原因排查方式解决方案agent 忽略了文档中的禁止项文档位置离目标代码太远上下文未被读取检查 agent 是否读取了完整项目文件观察日志中的上下文摘要将关键禁止项复制到模块级 docstring 或目标文件头部文档太长agent 抓不住重点行为规范写成了大段散文缺乏边界列表检查文档结构是否包含“规则”“禁止事项”“异常处理”改用列表、短句、明确的关键词多次生成结果差异大文档只写了功能没写实现边界对比多次产出的实现方案补充实现约束、禁止调用 API、禁止使用某类语法函数级 docstring 没问题但模块行为跑偏缺少项目级或模块级规范先看 AGENTS.md 是否存在建立分层文档体系修改文档后agent 行为没有变化工具缓存了旧文档或 prompt 没有引用该文档清缓存、重新构建索引检查 prompt 中是否指定读取路径在 prompt 中显式要求 agent 阅读相关文档测试场景过长agent 中途改变规则依赖交互式上下文缺少持久化约束在长任务中打断 agent 并观察行为把关键规则下沉到测试文件或 spec 文件agent 过度遵守规范导致代码僵化规范中的边界条件写得过于细碎检查是否把非关键实现细节写死只约束对外行为和项目约定保留内部实现自由排查有一个通用顺序先确认文档是否被读取然后确认文档是否有明确边界最后确认 prompt 是否引入冲突指令。大部分问题出在前两步。8. 最佳实践与工程建议8.1 从“给人类看”到“给 Agent 看”的文档改造清单如果你准备在现有项目中应用文档驱动方法不必大规模重写文档。只需要按以下优先级处理先建立根目录的 AGENTS.md写清楚技术栈、常用命令、全局禁止项。为核心业务模块增加模块级 docstring写清楚模块边界。为高频修改的函数增加 Behavior Specification。把某些业务规则独立成 spec 文件并让代码注释指向该文件。在 prompt 固定模板中统一要求 agent 先阅读文档再动手。8.2 文档中的关键词与行为约束为了让文档更容易被 agent 解析建议使用稳定关键词Behavior Specification规则禁止事项边界条件异常处理Raises这些词本身并不神奇作用是让文档结构保持稳定。很多 agent 在判断“这条是约束还是背景描述”时依赖标题和关键词。8.3 不要把所有东西都写进文档文档驱动虽然有价值但过度使用同样有问题。不要把每个函数内部的算法细节、每行代码的选择理由都写进去。文档应该描述“外部行为和约束”不要描述“内部实现步骤”。例如不要写循环遍历列表将每个元素转为整数如果转换失败则跳过。这是实现细节限制了 agent 的自由度。应当写该函数接收字符串列表返回整数列表。 无法转换的元素跳过不抛异常不写日志。这才是行为规范。8.4 与提示词系统的分工文档驱动不是要替代提示词而是要分工。提示词负责描述“当前任务”比如“实现这个模块”“修复这个问题”。文档负责描述“长期不变的约定”比如 API 风格、事务边界、异常策略、禁止事项。提示词是瞬时的文档是持久的。如果把长期约定也写在 prompt 里每次调用都会重复消耗 token而且容易前后不一致。8.5 生产环境落地顺序在产线环境引入文档驱动模式时不建议一次性改全量。推荐按照以下顺序选择 1 到 2 个维护频繁的模块作为试点。为试点模块补充项目级和模块级规范。设置行为对比指标生成一致性、测试通过率、代码评审修改次数。运行至少一周对比文档驱动前后的输出质量。验证有效后再扩展到其他模块。这样既能控制风险也能沉淀出适合团队的规范模板。8.6 结合测试 Agent 的落地场景如果你正在建设自动化测试 agent比如用 Playwright 实现 UI 测试生成建议在测试文件头部加入约束文档。一个典型的做法登录流程自动化测试。 Behavior Specification: - 定位元素优先使用>

相关新闻

2026/8/31 16:19:22

基于多尺度集成极限学习机回归附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

2026/8/31 16:19:22

三点式振荡电路详解:从反馈原理到面试考点

三点式振荡电路是硬件工程师笔面试中的高频考点,也是很多候选人最容易“背书一时爽、追问就翻车”的知识点。不管是嵌入式硬件、射频电路还是通信岗位,面试官只要把图纸往白板上一放,问一句“这个电路能不能振荡,为什么能振荡”&a…

2026/8/31 16:19:22

京东春招PHP试卷复盘:高频考点与实战解析

每年金三银四的跳槽季和春招季,都会有不少学弟学妹翻出往年的校招真题来练手。其中京东2019春招的这套PHP开发类试卷,虽然过去几年了,但含金量依旧很高,很能反映一线互联网公司对校招PHP工程师的考察偏好。和那些背一背就能过的八…

2026/8/31 16:29:24

阻抗技术线上知识分享与短视频科普内容创作方法

线上阻抗技术分享和线下会议室内训的表达方式有很大区别。线上观众注意力碎片化,缺少讲师实时答疑,对内容结构、可视化素材、知识深度平衡有着更高的要求。本文从选题规划、内容结构、可视化素材、避坑要点几个维度,讲解阻抗线上技术分享内容…

2026/8/31 16:29:24

面向PCB工厂工艺人员阻抗技术分享的内容与沟通方法

阻抗控制问题,很多时候矛盾出现在设计端和 PCB 制造端的信息断层。硬件工程师输出阻抗规格,PCB 工厂工艺人员负责实现阻抗指标,但是双方对于阻抗的理解、关注点、风险认知不一样。工程师以为只要给出 50Ω 阻抗指标,工厂就一定能够…

2026/8/31 16:29:24

2026深度学习框架怎么选?PyTorch两小时速通指南

2026 年了,还在纠结 TensorFlow 和 PyTorch 怎么选?这可能是每一个深度学习入门者都迈不过去的一道坎。网上关于这两个框架的争吵从来没有停止过,各大招聘 JD 里也经常写着“熟悉 TensorFlow 或 PyTorch 优先”,这种模棱两可的说法…

2026/8/31 16:29:24

从零开始搭建Python项目结构的心得

一个空文件夹摆在面前,就像一张白纸摆在作家面前。你盯着它,心里涌起无数种可能,也涌起无数种恐惧。第一行代码该写什么?包名怎么起?是搞个src目录还是直接平铺?这种窒息感不是新手专属,老手只不…

2026/8/31 16:29:24

以案例驱动,阻抗技术分享实战教学方法详解

在高速硬件研发行业当中,很多阻抗技术分享会陷入纯理论灌输的困境。讲师从头到尾讲解传输线理论、阻抗计算公式,台下工程师听得晦涩难懂,培训结束回到实际画图工作中,依旧会出现阻抗设计错误。理论脱离工程实践,是阻抗…

2026/8/31 16:24:23

VLC与WiFi融合:打造高精度可落地的室内定位系统

简介:本资源是一份面向通信工程、物联网及智能定位方向高年级本科生与研究生的课程报告,聚焦室内高精度定位这一实际难题,系统探讨可见光通信(VLC)与WiFi融合的技术路径与实现方案。针对智慧商场、地下车库、工业产线等…

2026/8/31 1:05:20

vSound小提琴数字处理器实操指南:从接线到演出的完整配置

电小提琴或者原声小提琴插电演出,第一个绕不开的坎就是声音难听。原声琴的共鸣和空气感一旦进了拾音器,出来的往往是一坨干瘪、发尖、带着奇怪塑料味的信号。我当初第一次把琴接上乐队调音台,直接被主唱吐槽"你这声音像在锯钢丝"。…

2026/8/31 2:14:20

传感器接口IC如何攻克生物化学传感的微弱信号难题?

1. 从电极到比特流:为什么生物化学传感必须依赖专用接口IC 做生物化学传感的人都有过类似的经历:明明传感器本身性能很好,信号输出却一塌糊涂——噪声大、漂移明显、重复性差,怎么调都达不到预期。很多时候问题并不在传感器&#…

2026/8/31 1:41:28

STM32F411CEU6多通道ADC采集:扫描模式+DMA实现详解

1. 多通道 ADC 的用武之地把“Multichannel ADC”和“STM32F411CEU6”这两个关键字放在一起,其实就是嵌入式开发里最常遇到的一类需求:用一块不算贵的 MCU,同时采集多路模拟信号。STM32F411CEU6 是 48 引脚的 Cortex-M4F 主控,主频…

2026/8/31 0:07:32

STM32C5设备支持包(IAR DFP)安装指南与常见坑

上一阵子在IAR里折腾一块基于STM32C5系列的新板子,工程从STM32CubeMX导出来之后怎么都编译不过。报错信息很干脆:找不到设备描述文件。跟着错误路径去查,发现指向的是一个让我愣了一下的名字:STMicroelectronics.stm32c5xx.2.1.0.…

2026/8/31 0:07:32

STM32N657 SWO引脚矛盾:CubeMX显示PB3,数据手册为PB5

拿到STM32N657这颗料的第一天,我就撞上了一个让人原地懵圈的引脚矛盾:CubeMX里清清楚楚显示SWO在PB3,翻开数据手册的引脚说明表,却赫然写着PB5。对于一个靠SWO输出调试日志吃饭的人而言,这种"工具和手册打架"…

2026/8/31 12:44:45

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/31 9:19:59

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/31 6:53:02

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…