资深大牛踩坑总结!构建生产级Agent系统的六项原则:认真打磨你的系统提示词!精心设计你的工具集!

发布于 2025-7-29 19:21
浏览
0收藏

作者 | Arseni Kravchenko

编译 | 云昭

出品 | 51CTO技术栈(微信号:blog51cto)

有时候,总有人会问我:

“我刚接触 agentic development,正在做一个项目,但总觉得好像少了点‘圈内人’才知道的经验。你能不能帮我补补课?”

我常常想推荐一些硬核的课程,比如 HuggingFace 或伯克利的多周训练营,但也理解不是每个人都想那么深入。

于是我决定写下这篇文章,分享六条我在开发 app.build 过程中总结出来的实用经验。这篇更通用,也更适合作为 Agentic 工程入门者的快速参考。

原则一:认真打磨你的 System Prompt

我曾经对 Prompt Engineering 很怀疑,总觉得那像是某种巫术:什么“我会给你 $100 小费”、"我奶奶命悬一线需要这份答案”、"请务必100%准确否则后果严重"……这些技巧偶尔能奏效,本质上是在利用模型的小瑕疵,但从来不是长期解法。

直到我意识到一件事,我才改变了对 Prompt 和 Context Engineering 的看法:

现代大模型其实并不需要什么套路,它们只需要明确、具体、不含矛盾的信息。

没错,就是这么简单。不用操控、也不用博感情。它们擅长执行指令,真正的问题往往是:你的指令本身就不清晰。

现在,各大 LLM 厂商(比如 Anthropic 和 Google)都有一些 prompt 编写的最佳实践文档。你只需要照着做:保持清晰具体,不要玩“聪明人把戏”。比如我们给 Claude 生成 ast-grep 规则的系统提示里,没有用任何花招,只是非常详尽地解释工具的使用方式而已。

我们有个小技巧:可以用像 Deep Research 这种风格的 LLM 来生成系统 prompt 初稿,再由人类润色。这种方式虽然不是最终答案,但是一个非常不错的起点。

同时,把一些上下文内容长期固化在 prompt 里,有利于 prompt 缓存机制的命中率。技术上当然可以缓存用户输入,但我们发现把系统部分设为大而稳定、用户部分保持小而动态,是一种很有效的结构。

原则二:把上下文拆分开来

你已经有了一个不错的 system prompt。但为什么现在“上下文工程”比“提示词工程”更火?因为现实中,管理上下文是一个很有取舍的工程活。

缺少上下文,模型容易胡说八道、偏离主题,甚至直接拒绝回答;上下文太大,又会出现注意力衰减(attention attrition)的问题 —— 模型很难聚焦到真正重要的中间细节,还会带来算力开销和响应延迟。

我们发现一个非常实用的原则是:

一开始只提供最小必要的信息,后续需要的话可以通过工具再拉取更多上下文。

比如在我们的项目中,我们会在提示中列出所有项目文件,并给模型一个“读取文件”的工具,这样它只需要在必要时调用就好。如果我们明确知道某个文件对当前请求至关重要,也可以提前把它的内容放进上下文里。

但也要小心:日志和反馈环节的其他产物很容易让上下文“肿胀”。定期做上下文压缩非常有帮助。

一句话总结就是:封装很重要 —— 把不同的上下文职责分开,只给每个子任务分配它绝对需要的上下文。

原则三:精心设计工具集

AI Agent 的核心能力就是调用工具:一个 LLM + 工具接口 + 控制流操作符,构成了最基本的 agent。

给 Agent 设计工具集其实有点像设计 API,但更复杂。人类开发者可以“意会”,能看懂复杂文档,甚至能绕过 bug;但 Agent 不行。工具太多容易污染上下文,接口不清晰就会用错。

给 Agent 设计工具时,请记住:

工具要接口直接、功能清晰、逻辑干净,就像你要交给一个聪明但容易分神的新手程序员。

好工具的特点:

  • 粒度相似
  • 参数数量少而明确(最好是强类型)
  • 功能单一但可靠
  • 尽量幂等,避免状态混乱

在多数软件工程场景里,agent 工具不超过 10 个,典型的有 ​​read_file​​​, ​​write_file​​​, ​​edit_file​​​, ​​execute​​ 等,每个 1-3 个参数即可。

有时候,让 agent 写一段 DSL(领域专用语言)来表示动作,比一个个工具调用更优雅。这种做法被 smolagents 带火了。但前提是:你要先设计好这套 DSL 的语义和函数,不能只做表面功夫。

原则四:设计反馈闭环(Feedback Loop)

一个真正有生产力的 Agent 系统,往往融合了传统软件工程和 LLM 的优势。

我们借鉴了“Actor-Critic”结构:Actor 负责做动作,Critic 负责评估结果。

在 app.build 中,我们让 Actor 生成文件或修改文件,让 Critic 检查它们是否符合我们的预期。这个预期是根据编译成功、测试通过、类型检查、代码格式等硬性标准来的。

不同领域的 agent,都需要类似的“验证机制”。这其实是引入“归纳偏置”(inductive bias)的一种方式 —— 即不管 agent 怎么操作,结果必须满足某些永远不变的规则。

比如,旅行类 Agent 规划多段航班时,要验证这些航班真的存在;财务类 Agent 要满足复式记账原则,否则结果就不成立。

Feedback loop 和“guardrails(护栏)”关系密切。Agent 有一定的恢复能力,如果结果不好,可以尝试提示“你的答案错在 X”,引导其修复。但如果连续几轮都修不好,那就该放弃这个路径,重新开始。

这就像蒙特卡洛树搜索:有些分支值得继续,有些该尽早砍掉。

原则五:用 LLM 做错误分析

当你已经有了 agent + feedback loop,下一步就是持续优化。

AI/ML 工程中,错误分析一直是最核心的环节,agent 也一样。

问题是:agent 太能干了。你一旦开跑几十个 agent 并发任务、产出大量日志,几乎不可能手动读懂它们。

这个时候就该用 “meta-agentic” 的方式:

  1. 选定一个 baseline 版本;
  2. 跑出一些轨迹 / 日志;
  3. 用 LLM 分析这些日志(尤其是像 Gemini 这种大上下文模型);
  4. 根据 insight 调整系统设计。

大多数情况下,这个流程会揭示出上下文管理或工具设计的盲区。

原则六:让你抓狂的行为,往往是系统问题

现在的大模型已经很强了,所以当 agent 做出明显愚蠢的事时,你会本能地感到沮丧。但现实是:

agent 出错不一定是 LLM 不行,往往是系统没设计好 —— 缺工具、提示不清晰、上下文没给够。

有次我快气疯了:agent 为什么不调用我准备好的数据接口,非要生成一些随机数据?我明明写了“不准用模拟数据”啊!

结果我一看日志,发现锅在我:我忘了给 agent 提供 API Key。它其实尝试调过接口,失败了几次后才换了备选方案。

类似的还有:agent 写文件失败,是因为没开文件系统权限。

总结:agent 出错时,先别怪模型,先查查系统。

结语

构建高效 agent,不是靠一个神奇提示词或酷炫框架,而是:

扎实的系统设计 + 可靠的软件工程方法。

关注清晰的指令、简洁的上下文管理、稳健的工具接口和自动化验证闭环。遇到奇怪的行为,先从系统层排查:是不是少了工具?prompt 有歧义?上下文不够?

最重要的:把错误分析当作一等公民。在迭代中用 LLM 找出失败原因,一步步修正。

目标不是完美的 Agent,而是一个能可靠运行、出错后能优雅恢复、可以不断优化的系统。

参考链接:​​https://www.app.build/blog/six-principles-production-ai-agents​

本文转载自51CTO技术栈,编译:云昭

收藏
回复
举报
回复
相关推荐