惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
WordPress大学
WordPress大学
宝玉的分享
宝玉的分享
人人都是产品经理
人人都是产品经理
博客园 - 聂微东
IT之家
IT之家
V
V2EX
Jina AI
Jina AI
V
Visual Studio Blog
有赞技术团队
有赞技术团队
博客园 - 司徒正美
博客园 - 叶小钗
The Cloudflare Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
小众软件
小众软件
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 三生石上(FineUI控件)
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Google DeepMind News
Google DeepMind News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
腾讯CDC
Google Online Security Blog
Google Online Security Blog
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
N
News and Events Feed by Topic
N
News and Events Feed by Topic
The Last Watchdog
The Last Watchdog
W
WeLiveSecurity
月光博客
月光博客
Security Archives - TechRepublic
Security Archives - TechRepublic
Webroot Blog
Webroot Blog
SecWiki News
SecWiki News
博客园_首页
罗磊的独立博客
量子位
Latest news
Latest news
I
Intezer
V
Vulnerabilities – Threatpost
A
Arctic Wolf
Last Week in AI
Last Week in AI
Recent Commits to openclaw:main
Recent Commits to openclaw:main
S
SegmentFault 最新的问题
S
Security Affairs
阮一峰的网络日志
阮一峰的网络日志
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
酷 壳 – CoolShell
酷 壳 – CoolShell
P
Palo Alto Networks Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
N
News | PayPal Newsroom

博客园_首页

Plist 二进制格式 Milvus 和 PGVector,哪个更好? OpenClaw 已过时?在 VS Code 中运行 Hermes Agent! 第30篇文章:一个大三计科生的自白 Manim如何在数学公式中完美显示中文? Docker 部署 RocketMQ 5 并发编程核心概念辨析 C#事务处理最佳实践:别再让“主表存了、明细丢了”的破事发生 CLI 是什么?为什么大厂突然集体卷命令行? 【从0到1构建一个ClaudeAgent】协作-自主Agent UIImageView 设置图片不生效的原因排查 最小二乘问题详解20:无先验约束下的增量式SFM自由网平差 痞子衡嵌入式:大话双核i.MXRT1180之XIP应用里借助MU实现可靠Flash IAP的方法 AI Chat 封装, SemanticKerne.AiProvider.Unified 已发布 Windows下右键编辑js文件无法打开记事本——在注册表中使用环境变量 在后台服务中使用 Scoped 服务,为什么总是报错? H200 安装驱动并使用sglang启动模型 wireshark 抓包Trap上报告警内容 我用 AI 辅助开发了一系列小工具(2):图片压缩工具 [A Primer On MC and CC] 2.1 Memory Consistency 1 - 指令重排序和 SC 模型 Oracle数据库SCN推进技术详解与实践指南 玩转控件:封装个带图片的Label控件 Claude Code 4.7 真正该升级的不是模型,而是你的工作流 前端小白一句话,AI 帮我做了个颜值拉满的桌面媒体播放器。当代码不再是门槛,一句话编程就是现实。 5. WorkBuddy: 小龙虾的灵魂三件套,让你的小龙虾不只是工具 SQLite 分片方案实战:三种分片策略的深度对比 告别简陋 UI!一款基于 Fluent Design 和基于 WinUI 的开源免费、现代化的 Avalonia UI 控件库 关于二进制排列组合枚举的总结 AI开发-python-LangGraph框架(3-27-LangGraph从零实现大模型智能决策工作流) ElasticSearch主分片和副本分片概念详解 【002】HTTPS 粗解:证书、TLS 握手与对后端配置的影响 Hermes Agent 一周暴涨五万 Star,但我劝你别急着追 明明连接的是Redis的DB0,为什么能查到DB3的数据? 【从0到1构建一个ClaudeAgent】协作-Agent团队 熟悉电子元器件之后,电子小白下一步该怎么走? MAF快速入门(23)通过C#类定义Skills .NET 高级开发 | 手写一个对象映射框架 FastAPI数据库ORM怎么选?我肝了三个Demo后,终于不再纠结了 mysqldump 参数拾遗:在遗忘与铭记之间 C# .NET 周刊|2026年3月5期 Claude code入门 - 陈彦斌 一文学习入门 ThingsBoard 开源物联网平台 GitHub 热门项目 | 2026年04月16日 如何为GIT设置全局勾子,为每次提交追加信息 Number.isFinite和isFinite与isNaN()和Number.isNaN的区别 PortSwigger SQL注入LAB2 推荐一个测试人必备的Skills,从功能到性能全搞定(附详细实操和安装下载方式) 筑基期:掌握Odoo基础核心知识点02(Odoo XML 开发方式详解) GLM模型这么火,咱们用vllm也咧一个呗! 深入理解 AbortController:从底层原理到跨语言设计哲学 字符串学习笔记 多租户系统框架的基础模块设计和分析设计 Apache SeaTunnel Zeta 为什么能做到“又快又稳”? AI开发-python-LangGraph框架(3-26-LangGraph基本概念及第一个简单样例) Vue 3 组件通信,别只会用 Props 和 Emits 了,这几个狠活儿你得看看 ElasticSearch7.X版本配置密码 用Manim实现动态交点计算--从一个动点问题说起 团结引擎+Addressable+Instant Game打包抖音小游戏 function call 实战:让 LLM 自动判断 pod 异常、调用日志工具并完成故障分析 bubseek —— 让 Agent 的足迹,变成团队的洞察 通过 C# 读取并导出 PDF 书签 如何用 GitHub Actions 实现 Steam 自动化发布 【从0到1构建一个ClaudeAgent】并发-后台任务 .NET 高级开发 | 定制 ASP.NET Core 框架 电子小白:什么是运算放大器(运放) zero2Agent:面向大厂面试的 Agent 工程教程,从概念到生产的完整学习路线 堆上的ORW HC32F460 USB CDC通信异常:非对齐访问异常排查 20260413-Hyperbridge 攻击事件:发生在默克尔山上的验证绕过 那些喊着AI 要淘汰你的人,正在靠你的焦虑赚大钱! 深度学习进阶(八)Swin Transformer 最小二乘问题详解19:带先验约束的增量式SFM优化与实现 SnapTranslate 3.0 正式发布:全局划词翻译 + 完整英语学习闭环,一站式搞定查词、记词、复习 工作的意义、工作的困难认知再思考 .NET + AI 进阶实战:基于类的技能开发 - 打造可治理的 Agent 能力模块 【从0到1构建一个ClaudeAgent】规划与协调-技能 上周热点回顾(4.6-4.12) 电子小白的工具三件套:面包板、杜邦线、万能板 单表五亿数据的查询优化 | Mysql、StarRocks 2. WorkBuddy:从“我是谁”到“帮我干活” C# 如何减少代码运行时间:7 个实战技巧 基于HelixToolkit.SharpDX 渲染3D模型 - 笺上知微 从零开始的双臂具身VLA起源及现阶段发展综述 - SkyXZ 记对 xonsh shell 的使用, 脚本编写, 迁移及调优 - pluvium27 受够了Vibe Coding的失控?换个起点,让AI事半功倍 从开始配置漏洞环境到漏洞复现流程 - 難しい 关于10年工作经验的程序员对OpenClaw的实战经验分享以及看法 - 虚无境 Any metadata 的内存布局 C# .NET 周刊|2026年3月2期 - InCerry 我帮你测过了,测试圈排名第二的 Skill 依然很牛逼 Skill Discovery | 无监督技能发现的经典工作总结 - MoonOut 上下文工程是什么?过时了么?一文讲明白! - 一枫说码 开了 TUN 模式还是直连?90% 的人都踩过这个坑 AScript扩展多种脚本语言 - rockey627 AI 学习笔记:Agent 的记忆机制 你能被装进一个文件里吗?——7 万人把同事"蒸馏"成了 AI - 我没有三颗心脏 Claude Code 通关手册(七):给 AI 装上技能包——Skills 完全指南 - 暮色之狐 在浏览器中快速编辑代码:VSCode Web 集成实践 - Newbe36524 蒸馏自己 skill?基于 Deepseek 的蒸馏器,丐版蒸馏方式,简单便捷 - To_Carpe_Diem Spring AI Aliababa和AgentScope,哪个更好? - 苏三说技术
给Code Agent加约束:从AGENTS.md开始
CareySon · 2026-05-19 · via 博客园_首页

image

上一篇文章(链接)里,我们讨论了一个判断:AI Coding 时代,真正变便宜的不是软件本身,而是代码文本的生成成本。Agent 可以很快写出路由、服务、数据访问和测试样例,但代码能不能长期可信、可维护、可演进,依然取决于另一套东西:架构判断、模块边界、接口契约、不变量表达、测试体系,以及团队长期形成的工程约束。

  所以那篇文章最后落到一句话:

  Code is cheap. Show me your constraints.

  这一篇,我想继续往下走一步:当我们说“约束”时,到底在说什么?其中最重要的一个部分就是Agents.md

  换句话说,AGENTS.md 的核心价值不是说明项目,而是约束生成。

  README 解决的是“人如何理解项目”;AGENTS.md 解决的是“Agent 在这个项目里,应该如何做判断”。这两者看起来接近,本质上却完全不同。README 可以介绍项目背景、启动方式、依赖安装、目录结构;AGENTS.md 更应该告诉 Agent:这个项目里,哪些写法是不被接受的,哪些架构选择已经被团队决定过,哪些历史事故不能再次发生,哪些领域规则必须按固定方式处理。

  这也是我现在越来越强烈的一个感受:Agent 时代,工程能力的核心不只是“会不会写代码”,而是“能不能把隐性的工程判断显性化”。因为 Agent 最擅长的是生成,但生成天然有发散性。没有约束,它会从通用平均水平出发;有了约束,它才可能从你的项目经验出发。

  项目不是代码文件的集合,而是一组被约束组织起来的代码。AGENTS.md 要做的,就是把这组约束写下来。

用 AGENTS.md 约束代码风格

第一种约束最容易理解:代码风格约束。

  但这里说的“风格”,不是缩进几个空格、函数名用 snake_case 还是 camelCase 这种表层格式,而是更深一层的设计哲学。一个团队可能偏 DDD,一个团队可能偏 Clean Architecture,一个团队可能喜欢贫血模型加应用服务编排,也可能坚持领域对象要承载行为。这些差异不是简单的审美差异,而是团队对“好代码”的判断标准不同。

  人类工程师加入团队后,会通过 Code Review、老代码、文档和踩坑慢慢理解这些判断标准。Agent 也一样。区别在于,如果你不显式告诉它,它就只能根据当前上下文里最常见、最平均、最容易补全的写法继续往下写。

  比如一个登录系统里,已有一个普通的 User 数据对象和一个 AuthService。

现在需求来了:用户连续 3 次密码错误后,账户临时锁定 30 分钟,锁定期间即使密码正确也不能登录。

Claude Code的输出如图:

image

image

  如果没有 AGENTS.md,Agent 往往会先把功能补完整。比如它会给 User 增加 failed_attempts、locked_until 字段,也会补上 is_locked()、record_failure()、record_success() 方法,并在 AuthService 里注入 clock 方便测试。这个实现不能说差,它已经意识到锁定状态和失败次数应该和 User 有关。

但问题是,它只是做了局部修补,并没有真正进入更深层的领域对象约束。User 仍然是可变对象,状态变化通过 record_failure()、record_success() 直接修改自身;AuthService 仍然负责流程判断和状态保存;登录结果也仍然只是 bool,用户不存在、密码错误、账户锁定这些失败原因都被压平了。

所以,没有显式约束时,Agent 未必会写出明显糟糕的代码。它甚至可能写出一段看起来还不错、也能跑通测试的代码。但它默认追求的是“把功能补上”,而不是“让代码回到项目认可的设计哲学里”。短期看可用,长期看,领域边界和失败语义会一点点变得含糊。

image

把代码风格写进 AGENTS.md

    我用 EO(Elegant Objects,Yegor Bugayenko 的 OOP 设计哲学)的部分哲学作为约束目标。这里用 EO 不是为了证明 EO 一定更好,而是因为它足够有态度,适合做约束效果的演示。换成 DDD、Clean Architecture、洋葱架构,逻辑是一样的:关键不是采用哪一种风格,而是把项目认可的判断标准写清楚。

这段约束的重点是“判断标准清楚”。它没有写一大堆机械规定,比如“不允许 setter”“字段必须 readonly”“方法名必须如何如何”。它只是告诉 Agent:这个项目判断领域对象好坏的标准是什么。

## 领域对象设计哲学

1. 对象有行为,不只是数据。业务逻辑应当存在于持有相关状态的对象上,
   而不是外部服务"把数据拿出来处理完再塞回去"。
2. 创建之后不可变。状态变化通过返回新对象表达。
3. 用类型表达约束,不用注释或运行时检查。

修改已有领域对象时,把它带入合规

  同样的需求,在这个 AGENTS.md 存在时,Agent 更可能生成这样的结构,Cluade Code输出如图:

image

image

  同样是账户锁定需求,有了这组约束后,Agent 更可能把锁定状态机放回 User,把状态变化表达为返回新的 User,把登录失败原因用 LoginResult 之类的类型显式表达,而不是继续返回一个 bool。AuthService 也会从“业务规则容器”退回到“应用层编排器”。

  表面上看,这只是代码结构不同;本质上看,是业务知识归属发生了变化。锁定规则到底属于 User,还是属于 AuthService?失败原因到底应该被类型表达,还是被布尔值压平?状态变化到底是直接修改,还是返回新对象?这些问题都不是 Agent 能凭空知道的,它需要项目给出约束。

  所以,AGENTS.md 的第一层价值,是把团队的代码哲学变成 Agent 每次生成代码时的默认判断标准。

  规则只能覆盖你写到的场景,原则才能延伸到你没写到的场景。好的 AGENTS.md 不只是告诉 Agent“不要这样写”,更重要的是告诉它“为什么这个项目要这样判断”。

用 AGENTS.md 固化项目历史决策

第二种约束更重要,也更容易被忽略:项目历史决策。

  很多时候,Agent 写出来的代码并不是“不专业”,而是“不知道你们项目已经决定过什么”。这件事和模型强不强没有关系。再强的模型,也不可能天然知道:你们过去因为短信重复发送出过事故;你们被合规审计要求过手机号不能进日志;你们线上服务是 async 栈,不能在服务层使用同步 HTTP;你们团队约定所有业务失败都用 Result 表达,而不是异常。

  这些不是通用知识,而是项目知识。更准确地说,它们是项目记忆。

  比如让 Agent 实现一个短信验证码发送函数:失败需要重试,确保用户能收到。

image

没有约束时,它可能写出一段通用工程质量很不错的代码:区分可重试错误和不可重试错误,设置 timeout,使用指数退避,自定义异常类型,甚至还会主动反问你几个实现细节。

  站在通用 Code Review 角度,这段代码可能是合格的,甚至是优秀的。但放到你的项目里,它仍然可能踩中一堆历史上的坑:

  没有 idempotency_key,网络抖动后可能给用户发多条验证码;指数退避没有 jitter,高并发时可能形成重试洪峰;使用 random 生成验证码,不适合安全敏感场景;手机号明文进入日志,存在 PII 合规问题;使用同步 requests.post,如果项目是 async 栈,会阻塞事件循环;用异常表达业务失败,如果项目约定使用 Result 模式,也不符合项目风格。

  这些问题,Agent 不是完全不懂,而是不知道在这个项目里,哪些事情已经是硬约束。

  所以,这类内容非常适合写进 AGENTS.md:

## 外部服务调用

1. 副作用必须幂等。任何“做了就会改变外部状态”的调用
   (发短信、扣款、下单、发邮件、写第三方系统)必须接受 idempotency_key
   参数并透传到下游网关。重试通过同一个 key 安全重放。

2. 失败语义必须保留。返回 Result[T, ErrorCode],
   错误用具名常量区分。异常只用于“本不该发生”的状态。

3. 重试有抖动。退避用 exponential backoff + full jitter。
   thundering herd 是默认假设,不是边界情况。

4. 不可重试的错误立即返回。4xx(429 除外)、Unauthorized、BadRequest
   不消耗重试次数。

## 异步

- 服务层默认 async/await,HTTP 调用统一用 httpx.AsyncClient。
- 任何外部 IO 必须显式传 timeout,禁止使用默认值。

## 日志与 PII

- 日志只记录元数据:调用对象、用时、状态码、错误码。
- PII 字段(手机号、邮箱、身份证、token、金额、姓名)必须脱敏。
- 使用 logger.info(msg, extra={...}) 走结构化字段。

## 安全敏感随机数

任何“被预测就会产生安全问题”的值,例如验证码、token、session id、
密码重置链接,必须使用 secrets 模块。random 仅用于非安全场景。

对此生成的代码如下:

image

  这类约束不是在教 Agent 写代码,而是在告诉 Agent:这个项目里,哪些选择已经不需要重新讨论。

  有了这些约束后,同样的短信发送需求,Agent 的起点就不一样了。它不再只是写一个“通用上还不错”的发送函数,而是会自然带上幂等键、Result 类型、full jitter、async HTTP、PII 脱敏和安全随机数。这些东西不是锦上添花,而是项目曾经用事故、审计、线上问题和团队共识换来的经验。

  这里有一个很重要的分工:

  模型负责变量,AGENTS.md 负责常量。

  模型可以根据需求生成不同实现,这是变量;但项目里哪些选择已经被确认,哪些坑不能再踩,哪些边界不能突破,这是常量。没有常量,Agent 每次都像一个新来的聪明实习生,从通用最佳实践重新猜一遍。写得不一定差,但一定不够像这个项目。

  AGENTS.md 的第二层价值,就是把项目记忆变成可执行的上下文,让 Agent 不再从通用平均值起步,而是从团队已经沉淀过的经验起步。

image

约束领域知识:AGENTS.md 是入口,Skills 是分层手册

第三种约束是专项领域知识

  AGENTS.md 适合放项目里的高频共识,但不适合放所有细节。如果把所有规则、所有领域知识、所有特殊业务流程都塞进去,它很快会变成一份巨大的文档。Agent 每次任务都要读,token 被浪费,重点也会被稀释。约束不是越多越好,约束也需要结构。

  更合理的方式是分层:

  AGENTS.md 放常驻约束,Skills 放专项知识。

  AGENTS.md 像项目宪法,负责告诉 Agent:这个项目的基本边界是什么,哪些原则长期有效,遇到某类问题应该去哪里找更细的规则。Skills 像专项手册,只在特定任务出现时进入上下文。

  比如金额计算。

  一个看起来很简单的需求:商品单价 × 数量得到小计,加上 10% 税,最后取整到分。

image

代码很短,也很直观,但在真实项目里,金额计算往往不是数学问题,而是规则问题:精度如何保留,舍入模式是什么,币种如何表达,跨币种能不能直接相加,数据库如何存储,展示和落库是否使用同一规则。

  这些内容如果都放进 AGENTS.md,会过重;但如果完全不写,Agent 又很容易按通用直觉处理。

  更好的方式,是在 AGENTS.md 里放入口:

## Skills(按需加载,仅在相关任务出现时读取)

- 处理金额计算:先读 skills/money.md

  然后把细节放进 skills/money.md:

# 金额处理

## 类型
- 必须用 Decimal(Python)/ BigDecimal(Java),严禁 float。
- 金额必须和币种一起传递。统一类型是 Money(amount, currency)。
- 跨币种运算必须显式经过 ConversionRate,没有汇率上下文不允许相加。

## 精度与舍入
- 内部计算保 4 位小数。
- 展示和落库时按币种规则取整:
  USD/CNY/EUR 2 位、JPY 整数、BHD/KWD 3 位。
- 舍入模式统一 ROUND_HALF_EVEN,不要依赖语言默认行为。

## 数据库存储
- DECIMAL(18, 4)。
- 币种独立列 VARCHAR(3),遵循 ISO 4217。

## 禁止事项
- 不要用 sum(prices) 直接累计金额,必须使用 Money.sum_safely(prices)。
- 不要临时写 round(x * tax_rate, 2) 算税,必须走 TaxCalculator。
- 不要写 if amount > 100 这种隐式比较,必须写成 amount > Money(100, "USD")。

image

  这样设计的好处是:AGENTS.md 保持简洁,但它能把 Agent 引导到正确的专项知识上。常驻上下文里不需要塞满所有细节,只需要告诉 Agent:遇到金额问题,不要凭直觉写,先读 money.md。

  这背后其实也是一种约束哲学:不是把所有规则一次性压给 Agent,而是让约束按任务逐步展开。高频原则常驻,低频细节按需加载。这样既不会牺牲上下文效率,也不会让重要规则在关键场景缺席。

  AGENTS.md 是入口,Skills 是分层;AGENTS.md 负责让 Agent 知道“这里有约束”,Skills 负责告诉 Agent“这类问题的约束具体是什么”。

约束的本质:降低生成方差,而不是限制生成能力

  到这里再回头看 AGENTS.md,它其实不是一个文档技巧,而是一种工程治理方式。

  Agent 的强项是生成。它可以很快给出一个版本,也可以根据反馈快速修改。但生成能力越强,另一个问题越明显:如果没有稳定的判断标准,它每次生成都会有方差。有时候很好,有时候一般;有时候符合项目习惯,有时候偏到通用写法;有时候注意到了安全和合规,有时候只完成了表面需求。

  AGENTS.md 要解决的,不是“Agent 会不会写”,而是“Agent 每次写的时候,能不能稳定地朝同一个方向收敛”。

  这就是约束的本质:降低方差。

  约束不是把 Agent 变笨,而是让它少走不该走的路。没有约束,Agent 面对的是无限可能;有了约束,它面对的是项目允许的可能性空间。好的约束不会压制创造力,反而会让创造力变得可用。因为工程里的自由从来不是“想怎么写就怎么写”,而是在清楚边界内做出高质量选择。

  一个项目真正成熟的标志,不是文档很多,而是关键判断不再依赖某个人临场解释。新人加入项目,不需要每次问“这个地方为什么不能这样写”;Agent 修改代码,也不需要每次重新猜“这个团队到底偏什么风格”。这些判断被写下来、被复用、被执行,项目才会从“靠人记住”变成“靠系统继承”。

  所以,AGENTS.md 更深层的意义在于:它把团队脑子里的工程秩序,转换成 Agent 可读取、可执行、可延续的项目约束。

image

小结

  所以,AGENTS.md 不是 README 的替代品,也不是提示词技巧。它更像一个项目的约束入口:把团队已经形成的设计哲学、历史决策和领域规则,变成 Agent 每次生成代码前都能读取的上下文。

AI Coding 让代码文本变便宜,但也让项目边界、工程原则和不变量表达变得更重要。

Agent真正需要的,不是更多说明,而是更清楚的约束。