最近和朋友讨论了一个观点:随着 prompting 演变为生产级 agent 系统,核心问题正在回归经典软件工程——规约、安全、正确性。我们实际上在定义一种 DSL for agent behavior。
这来自实践。过去几个月,我一直在运行一个多 agent 协作系统:多个 AI agent 分别承担 PM、前端、后端、QA 角色,通过消息频道协作,有明确的任务流转和权限边界。踩了不少坑之后,我发现 agent 系统的核心工程问题,和传统软件工程几乎完全重合。
五个从实践中长出来的观点
1. 显式状态机 > 隐式协调
任务在多个 agent 之间流转时,如果没有明确的状态定义,任务会漂移。
我最终用了一个显式的状态机:
提案 → DISPATCHED → DONE → QA_PASS / QA_FAIL
每个状态转换都有明确的触发条件和责任人。PM 审批后标记 DISPATCHED,开发完成后标记 DONE 并触发 QA,QA 通过后标记 QA_PASS。
这和传统工作流引擎没有本质区别。区别在于,执行者是 LLM agent,它们会「创造性地」理解模糊指令——所以状态定义必须更严格,而不是更宽松。
2. 权限约束是刚需,不是可选项
不约束 agent 的能力边界,它们会找到创造性的方式绕过流程。
实践中我发现必须显式定义:
- 工具白名单:每个 agent 能用哪些工具
- 目录映射:不同工作频道对应不同代码目录,agent 不能越界
- 分支规则:禁止直接推送到主分支,必须走 PR 流程
- 通信协议:agent 之间的消息必须走指定频道,不能私下注入
这本质上是 capability-based security。在传统系统里是操作系统和容器做的事,在 agent 系统里需要在配置层显式声明。
3. 不变量从事故中生长
系统中最重要的安全规则,往往来自最痛的事故。
我经历过一次数据丢失:重启服务触发了自动同步,同步清理了「孤儿记录」,导致数千条对话历史永久丢失。数据本来还在数据库里,但因为没有在发现问题时立即备份,而是急于修复功能,最终不可逆地丢失了。
这件事之后,系统多了几条铁律:
- 先备份,再操作 —— 任何涉及数据库的操作前必须备份
- 数据 > 功能 —— 数据丢了不可逆,功能坏了能修
- 不确定就问 —— 宁可多确认一步,不要假设
这些不变量(invariants)写在 agent 的配置文件里,每次启动都会加载。它们是硬约束,写死在配置里。
4. Prompt 只是组件
很多人把 prompt engineering 当成 agent 开发的全部。但实际跑起来会发现,prompt 只是系统中的一个组件。
真正的「程序」是这些东西的组合:
- 角色定义(人格、行为准则)
- 工作流规则(状态机、审批流程)
- 权限模型(工具、目录、分支)
- 状态管理(任务追踪、记忆系统)
- 通信协议(频道路由、消息格式)
- 定时任务(巡检、日志、自动化)
把这些加在一起,你会发现你实际上在写一种 DSL(领域特定语言)。运行这个 DSL 的 runtime,就是 agent 框架本身。
5. Agent 越接近生产,对工程能力要求越高
Demo 阶段,agent 能聊天、能调工具、能写代码,看起来很酷。但要真正可靠地运行,你需要:
- 精确规约:模糊的指令在生产环境里就是 bug
- 失败模式设计:agent 会犯错,系统需要能回滚、能审计
- 可观测性:每次操作都要有日志,关键决策需要人类审批
- 幂等性:同一个任务重复执行不应该产生副作用
这些都是传统软件工程里老生常谈的东西。但在 agent 系统里,它们变得更重要——因为执行者是非确定性的 LLM,比确定性代码更需要工程约束。
结论
Agent 系统的未来取决于更好的工程,远胜于更聪明的模型。
当你的 agent 从 demo 走向生产,你会发现自己花在 prompt 上的时间越来越少,花在状态管理、权限控制、失败恢复、审计日志上的时间越来越多。
这恰恰说明 agent 系统正在成熟——它正在变成真正的软件工程。
而最好的 agent 工程师,很可能就是最好的软件工程师。