跳到主要内容
文章
Vibe Coding4 分钟阅读

我花 7 天用 Vibe Coding 做了一个 AI 外贸数字员工

从询盘分类到报价草稿,完整记录 7 天里的架构决策、三次推倒重来,以及一个让我改掉整个设计的原则:确定性优先。

一句话结论

能用代码判断的,绝不交给模型。模型擅长措辞,不擅长把关。

本文目录 · 6

第 1 天早上我给自己定了一个很具体的验收标准:

收到一封英文询盘邮件,系统能自动判断意图、查库存、生成一份不会报错的报价草稿, 并给出下一步跟进时间。

7 天后这个标准达到了。中间推倒重来三次,第三次重来才是真正的转折点。

第一天:先别写 Agent,先写数据流#

我一开始就想直接上 Agent 框架,写了半天发现根本不知道「好的输出」长什么样。

于是掉头,先手写了 20 条真实的询盘记录,人工标注了意图、优先级、需要的字段:

询盘原文片段意图优先级缺失字段
"Please quote 500pcs, need it by Nov"报价产品型号
"Are you a factory or trading company?"资质问询
"Your price is too high, competitor offers..."议价目标价

这 20 条成了后面所有决策的基准。没有标注数据之前,任何架构讨论都是空谈。

第二次重来:把 LLM 从「把关人」的位置上拿下来#

最初的版本是这样:询盘进来 → 丢给模型 → 模型判断意图、决定报价、生成回复。

结果误报率 12%。具体是三类错误:

  1. 低于底价的报价被放行——模型看到了底价,但没算对
  2. 库存不足时仍生成了可发货的措辞
  3. 客户在禁运名单上,模型完全没提

问题不在模型能力,在于我把需要精确计算的判断交给了概率系统

改成三层结构:

text
第 1 层(代码):硬约束校验
  - 报价 >= 底价
  - 库存 >= 需求量
  - 客户不在禁运名单
  → 任何一条不过,直接拦下,不进模型
 
第 2 层(模型):意图分类 + 措辞组织
  - 读询盘,输出结构化意图
  - 基于已校验的报价数字,组织邮件语言
 
第 3 层(代码):输出校验
  - 从模型输出里提取所有数字
  - 与第 1 层的计算结果比对
  - 不一致则丢弃重生成

误报率从 12% 降到 0

这个改动是整个项目里最重要的一次。它让我意识到: Agent 设计的核心问题不是「怎么让模型更聪明」, 而是「怎么让模型只做它擅长的那部分」。

第 3 层的数字回验尤其关键。模型偶尔会在措辞里「顺手」改一个数字, 让它读起来更顺。这一层就是专门抓这个的:

ts
function verifyNumbers(generated: string, facts: QuoteFacts): boolean {
  // 抽出模型输出里所有形如 $1,234.56 / 500pcs 的数字
  const mentioned = extractNumbers(generated);
 
  const allowed = new Set([
    facts.unitPrice.toFixed(2),
    String(facts.quantity),
    facts.totalPrice.toFixed(2),
    String(facts.leadTimeDays),
  ]);
 
  // 输出里出现的每个数字,都必须能在事实集合里找到
  return mentioned.every((n) => allowed.has(n));
}

第三次重来:用 MCP 替换硬编码工具#

工具涨到 9 个之后,注册表开始失控。每个工具都直接写在主流程里:

ts
// 改造前:加一个工具要动主流程代码
const tools = [
  classifyInquiry,
  checkInventory,
  getPriceFloor,
  checkSanctions,
  draftQuote,
  scheduleFollowUp,
  // ... 每加一个都要改这里,还要改类型定义
];

问题有三个:

  1. 加工具必须改主流程,风险高
  2. 工具和主流程共享进程,一个工具卡住全卡住
  3. 没法单独测试某个工具

迁到 MCP 之后,工具变成可独立部署的服务,主流程只认协议:

ts
// 改造后:工具通过 MCP 协议接入,主流程完全不知道有几个工具
const client = new Client({ name: "quote-agent", version: "1.0.0" });
 
await client.connect(new StdioTransport({ command: "inventory-server" }));
 
const tools = await client.listTools();
// 加工具 = 加一个 server,主流程一行不用改

迁移成本大概是两天。收益在第二周就回来了:加了 4 个新工具,主流程代码零改动。

第 7 天:最终形态#

text
询盘邮件

   ├─► [代码] 硬约束层 ── 不过 ──► 人工队列
   │        报价底线 / 库存 / 合规

   ├─► [模型] 意图分类 ──► 结构化 JSON

   ├─► [MCP] 工具调用
   │        库存查询 / 价格计算 / 历史成交

   ├─► [模型] 生成报价草稿

   ├─► [代码] 数字回验 ── 不一致 ──► 丢弃重生成

   └─► 草稿进入人工确认队列

注意最后一步:草稿进的是人工确认队列,不是直接发出

这一点我犹豫过。全自动的演示效果好得多,但我不信任它。 现在这个版本的正确用法是:业务员早上花 15 分钟过一遍草稿, 改几处措辞,点发送。相比从零写,省下的时间大概是 70%。

现在还不能做什么#

诚实清单:

  • 议价环节完全无法放手。 涉及价格谈判必须人工。模型不懂「这个客户去年下了三个柜」这种上下文。
  • 多 Agent 之间的上下文传递有信息衰减。 我试过拆成「询盘 Agent + 报价 Agent + 跟进 Agent」,结果是每个 Agent 都要重新理解一遍客户背景,反而更慢。现在退回单 Agent + 多工具。
  • 非英语询盘的分类质量不稳定。 西班牙语和阿拉伯语的意图识别准确率明显低于英语,需要人工兜底。

七天的时间分配#

阶段天数实际产出
标注 20 条真实数据0.5后面所有决策的基准
第一次实现(失败)1.5发现模型不能当把关人
三层结构重构2误报率 12% → 0%
MCP 工具层迁移2工具可独立部署
收尾与人工流程对接1可用的东西

如果用传统方式写,我估计要三周。Vibe Coding 省下的时间主要在两处: 写样板代码(数据库层、API 路由、类型定义)和调试(把报错直接丢给它)。

但省不掉的恰恰是最重要的那部分:决定什么该交给模型、什么不该。 这个判断只能自己下,而且下错了要推倒重来。


项目现在还在迭代。架构图和 MCP 工具层的设计我在 AI Digital Employee 项目页 里持续更新。