事情是这样的。
前两天有个朋友找我聊天,说他转 Agent 开发快半年了,LangChain 学了,CrewAI 跑了,AutoGen 也玩过了,Demo 跑起来那叫一个顺。
但一到公司真实项目,卡住了。
他说了一句话我印象特别深。
「我会调 API、会写 Prompt、能用框架跑通 Demo,但总觉得自己只是在拼积木。」
拼积木。
这个词真的太精准了。
我当时就跟他说,你不是一个人。我自己刚转 Agent 开发的时候也这样,觉得自己好像什么都会了,又好像什么都没真的会。框架是学了不少,但一到那种「需求不明确、边界很模糊、老板只说一句我们也做个 AI 助手吧」的场景,整个人就懵了。
后来我花了很长时间才想明白一个问题。
卡住你的不是框架,是你脑子里的能力模型还没换过来。
你还在用传统开发的能力模型做 Agent。那套模型是编码能力、调试能力、架构能力、性能优化。这套东西在传统开发里好使了几十年,因为传统软件是确定性的,你写 if a > b return a,它到死都返回 a。
但 Agent 开发不是这样的。
你跟 Agent 说「帮我分析一下这份数据」,同样的输入跑三次,模型可能给你三种不同的输出。不是你代码写错了,是模型在推理,推理本身就是概率性的。
所以你会发现一个很诡异的事。
你在传统开发里最引以为傲的调试能力,在 Agent 开发里几乎用不上。
你没法打断点看模型为什么在第三步推理偏了。你只能看 trace、看概率分布、看统计指标。
这不是能力退化了,是能力模型需要重构。
我觉得这件事,可能是所有转 Agent 开发的人最容易被忽略、但最重要的一步。
我自己的感受是,Agent 开发真正需要的能力模型是这样的。
Prompt 设计、评测思维、容错设计、产品判断力、系统编排。
这五项,每一项都跟传统开发不一样。
下面我一个一个聊。
1
先说 Prompt 工程。
很多人以为 Prompt 工程就是把需求用自然语言写清楚。
这是最大的误解。
Prompt 工程的本质不是写指令,是设计模型的行为边界。
我举个例子你就明白了。
写指令的思路是这样。
你是一个客服助手,请友好地回答用户的问题。设计行为的思路是这样。
你是一个客服助手。
你是XX公司的客服助手,代表公司立场。
你能做的事,查询订单状态、解释退款规则、引导用户提交工单。
你不能做的事,退款操作、修改订单、承诺赔偿金额。
你不知道的事,如果用户问的问题超出以上范围,回答「这个问题我需要帮您转接人工客服」。
永远先确认用户身份,订单号或手机号后四位。
涉及金额时只引用规则原文,不做任何推测。
用户情绪激动时先共情再解决问题。
每次回答控制在 200 字以内。看出区别了吗。
写指令是告诉模型做什么。设计行为是定义模型是什么、能做什么、不能做什么、做错了怎么办。
坦率的讲,大部分录友卡在写指令和设计行为之间。能把需求说清楚,但边界设计不到位,所以 Agent 的行为很不稳定。
我自己把 Prompt 工程分成了三层。
第一层,指令清晰。能把需求说清楚,模型能理解你要什么。这是入门水平。
第二层,边界设计。能定义清楚模型的行为边界,什么能做、什么不能做、边界模糊时怎么处理。这是合格水平。
第三层,行为塑造。能通过 few-shot、chain-of-thought、角色设定这些方式,稳定地塑造模型的输出风格和推理路径。这是高手水平。
我贴一段代码你就懂了。
// 第一层,指令清晰(入门)
systemPrompt := "你是一个客服助手,请友好地回答用户的问题。"
// 第二层,边界设计(合格)
systemPrompt := `你是一个客服助手。
你能做的事,查询订单、解释规则。
你不能做的事,退款操作、承诺赔偿。
超出范围的事,引导转人工。
`
// 第三层,行为塑造(高手)
systemPrompt := `你是一个客服助手。
你是XX公司的资深客服,语气专业但不冷漠,可以适度用「呢」「哈」拉近距离,但不要过度。
当用户情绪激动时。
第一步,共情,「我完全理解您的心情」。
第二步,确认事实,「您方便提供订单号吗?我帮您查一下具体情况」。
第三步,给出方案,「根据我们的退款规则……」
第四步,确认满意度,「这样的处理方式您觉得可以吗?」
反面示例。
❌「我们公司规定不能退款」(生硬拒绝)
✅「根据退款规则,您这个订单目前不符合退款条件。不过我可以帮您看看有没有其他解决方案,您方便说一下具体情况吗?」
`这块需要注意一下。
Prompt 工程不是一次写完就完事了。它需要迭代、需要评测、需要看数据。
如果你写完 Prompt 就上线,从来不看模型的实际输出分布,那你其实不会 Prompt 工程,你只是会写 Prompt。
2
顺着上面的再聊聊第二个能力,评测思维。
传统开发的思路很简单。代码写完,跑单元测试,通过就上线。
Agent 开发完全不是这回事。
你没法「通过」一个 Agent,你只能「评估」它。
因为同样的输入,模型可能给出不同的输出。今天通过了,明天可能就不过了。
传统测试是这样的。
func TestCheckOrder(t *testing.T) {
result := CheckOrder("ORD-001")
assert.Equal(t, "可退款", result) // 要么过,要么不过
}Agent 评测是这样的。
func EvalAgent(t *testing.T) {
dataset := LoadEvalDataset("agent_eval_cases.json") // 至少 100 条
var passCount int
for _, c := range dataset {
result := agent.Run(c.Input)
// 不要求完全一致,只要求关键信息一致
if containsKeywords(result, c.ExpectedKeywords) &&
toolCallCorrect(result, c.ExpectedTools) {
passCount++
}
}
accuracy := float64(passCount) / float64(len(dataset)) * 100
fmt.Printf("评测通过率: %.1f%%\n", accuracy)
// 不是通过/不通过,而是通过率是多少
if accuracy < 85 {
t.Errorf("通过率 %.1f%% 低于 85%% 阈值", accuracy)
}
}传统测试是二元的,通过或不通过。Agent 评测是连续的,0% 到 100%。
这个思维转变非常关键。
我自己把评测也分了三层。
第一层,人工抽检。跑几个 case 看看效果,觉得还行就上线。这是 Demo 水平。
第二层,规则评测。定义关键词匹配、工具调用正确率、输出格式合规率这些规则指标,批量跑评测集。这是工程化入门水平。
第三层,模型评测。用 LLM-as-Judge 评估答案质量,准确性、完整性、友好度,结合规则指标和人工抽检,建立多层评测体系。这是生产级水平。
说真的,这也是面试里最能体现你工程化水平的地方。
能说出评测体系怎么搭,比会说「我用了 LangChain」强十倍。
3
第三个能力,容错设计。
这块我觉得是最反直觉的。
传统开发里,我们追求的是别出错。空指针检查、边界条件、异常处理,目的是让程序不崩溃。
Agent 开发里,你没法追求别出错。因为模型本身就是概率性的,它一定会出错。
所以 Agent 开发的容错设计,思路完全反过来了。
不是别出错,而是假设一定会出错,出错后怎么恢复。
传统开发的容错是这样。
func GetOrder(orderID string) (*Order, error) {
order, err := db.Query(orderID)
if err != nil {
return nil, fmt.Errorf("查询订单失败: %w", err)
}
if order == nil {
return nil, errors.New("订单不存在")
}
return order, nil
}目标是「要么返回正确结果,要么返回明确错误」。
Agent 开发的容错是这样。
func AgentGetOrder(ctx context.Context, userInput string) (*Response, error) {
// 尝试 1,让 Agent 正常处理
resp, err := agent.Run(ctx, userInput)
if err == nil && validateOutput(resp) {
return resp, nil
}
log.Warn("Agent 首轮失败,触发重试", "error", err)
// 尝试 2,重试,换模型或调低温度
resp, err = agent.RunWithRetry(ctx, userInput, RetryConfig{
MaxRetries: 2,
Temperature: 0.3,
})
if err == nil && validateOutput(resp) {
return resp, nil
}
log.Warn("Agent 重试失败,触发降级", "error", err)
// 尝试 3,降级,不靠 Agent,直接返回检索结果
docs := searchKnowledgeBase(ctx, userInput)
if len(docs) > 0 {
return &Response{
Content: fmt.Sprintf("我找到了以下相关资料,供您参考:\n\n%s\n\n如需进一步帮助,请点击转人工。", formatDocs(docs)),
Source: "fallback",
}, nil
}
// 尝试 4,最终兜底
return &Response{
Content: "抱歉,我暂时无法处理您的问题,正在为您转接人工客服...",
NeedHuman: true,
}, nil
}看出来了吧。
传统开发是检查、报错、终止。Agent 开发是尝试、重试、降级、兜底。
容错设计有四层。
第一层,重试。同样的输入再跑一次,很多时候模型第二次就对了。简单但有效。
第二层,降级。重试失败后换一个更简单但更可靠的方式。比如 Agent 回答不了,就只返回检索到的原始文档。
第三层,转人工。涉及金钱、权限、敏感信息的时候,不要硬撑,直接转人工。
第四层,静默失败。对于不重要的辅助功能,比如推荐相关文章,失败了就别告诉用户,悄悄跳过。
容错设计的核心不是技术,是心态。
承认模型一定会出错,然后为每一个出错场景设计恢复路径。
4
第四个能力,产品判断力。
这是最容易被技术人员忽视的。
传统开发里,需求是产品经理给的。你拿到 PRD,评估技术可行性,然后做。
Agent 开发里,很多时候没有 PRD。老板说「我们也要做一个 AI 助手」,然后就没了。
这时候你能不能判断,这个场景适合用 Agent 吗,用 Agent 比不用 Agent 到底好在哪里。
很多录友一上来就想,我要做一个能自动写代码、自动修 Bug、自动部署的全能 Agent。
想法很好。
但你先问自己三个问题。
第一,这个任务的容错率是多少。
Agent 的正确率可能是 85%、90%,很难到 99%。如果任务容错率低,比如自动退款,Agent 就不适合做主链路。
第二,用 Agent 比用规则能好多少。
很多所谓的智能客服其实就是把 FAQ 匹配了一下,根本不需要 Agent。能用规则解决的问题,不要上 Agent。Agent 是手段,不是目的。
第三,用户愿意为智能付出什么代价。
Agent 的响应时间比规则慢 3 到 5 倍,成本高 10 到 50 倍。用户真的需要智能,还是只需要快。
不是哥们,有些时候你觉得「用 Agent 多酷啊」,但用户可能就想快点查到物流,三秒钟出不来他就走了。
我写了一个简单的判断逻辑,贴出来给大家参考。
type AgentSuitability struct {
Task string
ErrorTolerance string // 高 / 中 / 低
RuleComplexity string // 简单可用规则 / 规则难以穷举
UserExpectation string // 需要精准 / 可以接受建议
}
func evaluateSuitability(s AgentSuitability) string {
// 容错率低 + 规则可穷举,别用 Agent
if s.ErrorTolerance == "低" && s.RuleComplexity == "简单可用规则" {
return "不适合 Agent,用规则引擎更可靠"
}
// 容错率高 + 规则难穷举 + 用户接受建议,Agent 的甜点区
if s.ErrorTolerance == "高" && s.RuleComplexity == "规则难以穷举" &&
s.UserExpectation == "可以接受建议" {
return "Agent 的最佳场景"
}
// 容错率低 + 规则难穷举,Agent + 人工审核
if s.ErrorTolerance == "低" && s.RuleComplexity == "规则难以穷举" {
return "可以上 Agent,但需要人工审核兜底"
}
return "需要进一步评估"
}能做出来是初级能力,该不该做才是高级能力。
面试的时候,当面试官问你「你觉得这个场景适合用 Agent 吗」,如果你能从这个角度分析,而不是一上来就说「可以,我用 LangChain 实现」,你已经在大多数候选人之上。
5
最后一个能力,系统编排。
很多录友入门 Agent 开发后第一个冲动是什么。
做一个超级 Agent,什么都能干。
这是最大的坑。
Agent 的能力和可靠性成反比。 一个 Agent 能做的事情越多,它的 Prompt 越复杂、工具越多、上下文越大,幻觉和失控的概率就越高。
正确的思路是把复杂任务拆成多个专职 Agent,每个只做好一件事。
不是「一个超级 Agent 搞定一切」,而是「怎么拆、怎么连」。
怎么拆,三个原则。
按职责拆,不按步骤拆。 不是说第一步的 Agent、第二步的 Agent,而是负责售后的 Agent、负责售前的 Agent。职责边界清晰,Agent 的行为才好约束。
一个 Agent 只给它需要的工具。 客服 Agent 不需要退款工具,销售 Agent 不需要查 Bug 工具。你给 Agent 的工具越多,它用错工具的概率越大。
Agent 之间通过结构化数据通信,不通过自然语言。 这一点太重要了。
我举个实际例子。
Agent A 用自然语言告诉 Agent B。
用户张三的订单 ORD-001 在 2024 年 3 月 5 日购买了一个手机壳,金额 39.9 元,目前状态是已发货Agent B 需要从自然语言里再解析一遍,容易出错。
正确的做法是这样。
type OrderInfo struct {
UserName string `json:"user_name"`
OrderID string `json:"order_id"`
Product string `json:"product"`
Amount float64 `json:"amount"`
Status string `json:"status"`
CreatedAt string `json:"created_at"`
}
result := OrderInfo{
UserName: "张三",
OrderID: "ORD-001",
Product: "手机壳",
Amount: 39.90,
Status: "已发货",
CreatedAt: "2024-03-05",
}Agent 之间用 JSON 不要用自然语言。每多一层自然语言解析,就多一层出错概率。
编排模式也有三种。
串行编排,适合有明确先后顺序的任务。检索、分析、生成回复,一个一个来。
路由编排,适合需要先判断意图再分发的场景。先判断用户想干嘛,再分给对应的专职 Agent。
并行编排,适合需要同时收集多方信息的场景。同时查订单、查物流、查退款规则,汇总后生成回复。
一个 Agent 能解决的不用 Chain,一个 Chain 能解决的不用 Multi-Agent。
编排不是为了炫技,是为了让每个 Agent 的职责足够小、行为足够可控。
面试怎么答
说到这里,我想聊一个很实际的问题。
当面试官问你「Agent 开发和传统开发最大的区别是什么」,你怎么答。
很多录友会说,传统开发是确定性的,Agent 开发是概率性的。
这话对不对。
对。
但只答对了一半。
更好的回答是,区别不只是确定性 vs 概率性,而是整个能力模型的重构。
我自己的回答思路是这样的。
Agent 开发和传统开发最大的区别,不是技术栈的变化,而是能力模型的重构。
传统开发的核心能力是编码、调试、架构、性能优化,围绕确定性系统展开。Agent 开发的核心能力是 Prompt 设计、评测思维、容错设计、产品判断力和系统编排,围绕概率性系统展开。
具体来说五件事。
第一,从编码驱动到设计驱动。传统开发里逻辑是我一行一行写出来的,Agent 开发里逻辑是我通过 Prompt 设计出来的。Prompt 不是写指令,是设计模型的行为边界。
第二,从调试到评测。传统开发里出 Bug 了打断点看调用栈,Agent 开发里出问题了只能看 trace、看概率分布。质量保证从通过/不通过变成了成功率 85% 还是 92%。这要求你建立评测体系,规则评测加 LLM-as-Judge 加人工抽检,三位一体。
第三,从别出错到假设一定出错。传统开发追求的是不崩溃,Agent 开发必须假设模型一定会出错,然后设计重试、降级、转人工、兜底的多层容错链路。
第四,从能做出来到该不该做。Agent 开发需要产品判断力,不是所有场景都适合 Agent。容错率低的不适合,规则能解决的不适合,用户等不了的不适合。能判断什么时候不该用 Agent,比会用 Agent 更体现功力。
第五,从一个系统搞定一切到怎么拆怎么连。一个超级 Agent 看起来很酷,但可靠性很差。真正的工程做法是把任务拆成多个专职 Agent,每个只做好一件事,Agent 之间用结构化数据通信。
如果只用一句话总结。
传统开发的核心是「我能写出正确的代码」,Agent 开发的核心是「我能设计出一个在不确定性中仍可控的系统」。
这个回答的重点不是列举区别,而是告诉面试官,我不只是会用框架调 API,我理解 Agent 开发背后的工程思维转变。
这才是面试官想听到的。
回到拼积木
还记得开头那个朋友说的「拼积木」吗。
我觉得这个词其实特别精准。不是因为 Agent 开发低级,而是因为当你的能力模型没换过来的时候,你确实只能用拼积木的方式做 Agent。
学会一个框架,拼一块。学会一个工具,再拼一块。
但积木拼得再多,你还是不会盖房子。
盖房子需要的是设计能力、评测能力、容错能力、判断能力、编排能力。这些才是 Agent 开发真正的承重墙。
我自己也是从拼积木的阶段过来的。
一开始用 LangChain 跑了个 Demo,觉得 Agent 开发不过如此。然后接了个真实项目,用户问的问题稍微偏一点,Agent 就开始胡说八道。我当时就想,这玩意怎么这么不可控。
后来我才慢慢意识到,不是 Agent 不可控,是我没给它设计边界。不是模型不行,是我没搭评测体系。不是框架不够好,是我没有做容错设计。
当我把思维从编码驱动切换到设计驱动之后,Agent 开发的世界完全不一样了。
这让我想起一个事。
工业革命刚开始的时候,那些最优秀的工匠反而最难适应。不是因为他们手艺不行,恰恰是因为他们手艺太好了。他们太习惯用自己的双手去控制每一个细节,反而很难接受「设计一台机器,让它自己运转」的思路。
我们现在可能也处在一个类似的转折点上。
从「亲手控制每一行代码」到「设计一个能在不确定性中自己运转的系统」。
这个转变不容易。
说实话我自己也还在摸索,可能有些想法还不成熟。但我始终坚信一件事。
能力模型的重构,是转 Agent 开发最容易被忽略、但最重要的一步。
我不知道对大家有没有用,但我已经毫无保留地分享了。
以上,既然看到这里了,如果觉得不错,随手点个赞,如果想第一时间收到推送,也可以关注我⭐~
谢谢你看我的文章,我们,下次再见。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。