Vibe Coding Agent 接入架构
一个 Vibe Coding Agent Demo 最危险的时刻,不是第一次调用模型失败,而是第一次调用成功。

因为从这一刻开始,团队很容易把“页面能发出请求、模型能返回内容”误认为“系统已经可以给真实用户使用”。但只要用户在长任务中刷新一次浏览器,很多 Demo 会立刻暴露真正的问题:进度消失、任务状态未知、前端再次提交、后台同时跑出两个任务,最后用户拿到两份互相冲突的结果。

问题通常不在 Prompt,而在恢复协议。

SSE 不是任务本身

很多 Agent 应用把 SSE 连接当成任务生命周期:连接在,任务就在;连接断,任务就没了。

这是一个危险的等号。

SSE 更像观察窗口。它负责把“正在搜索”“正在分析”“正在生成报告”等事件推给前端,但真正的任务应该有独立、可持久化的身份和状态。浏览器刷新只应该关闭一个观察窗口,不应该让后台任务失去身份,更不应该触发一次新的任务提交。

下面这张图里的关键不是组件数量,而是边界:前端只访问自己的后端/BFF;BFF 再通过受控适配层调用 InfiniSynapse。用户、权限、业务状态和确定性数据留在应用侧,长时间研究、泛数据分析和文件交付进入 Agent 层。

一条可靠任务链至少要保存四种状态

不要只保存一段聊天记录。一个可恢复的 Agent 任务至少需要四类状态:

状态由谁负责用途
appJobId你的应用把任务绑定到用户、租户、权限和业务对象
connId适配层建立并恢复事件流,关联一次可观察连接
taskIdAgent 服务唯一标识后台长任务,查询状态和结果
workspace / artifactsAgent 服务与适配层保存报告、表格、图片等最终交付物

此外还应记录 statuslastEventAt、失败原因和已发现的产物索引。它们不需要一开始就做成复杂工作流引擎,但必须落在服务端可恢复的存储里,而不是只存在浏览器内存中。

正确顺序:先建立事件通道,再发任务

一个最小而可靠的启动顺序可以是:

  1. 用户通过你自己的应用完成登录,后端创建一条 appJob
  2. 后端生成或分配 connId,前端通过自己的 BFF 建立 SSE;
  3. SSE 确认可用后,BFF 才向 Agent 服务发送 newTask
  4. 一拿到 taskId,立刻写入 appJob,不要等任务完成;
  5. 后续事件只更新同一条任务记录,不用事件文本充当事实源;
  6. 任务结束后,索引 workspace 中的最终产物,并把可下载入口返回给前端。

伪代码只需要表达这个约束:

const job = await jobs.create({ userId, status: "connecting" });
const connId = crypto.randomUUID();

await events.connect({ appJobId: job.id, connId });

const task = await infiniSynapse.newTask({
  connId,
  prompt: buildPrompt(input),
  capabilities: allowedCapabilities(input),
});

await jobs.bindTask(job.id, {
  connId,
  taskId: task.taskId,
  status: "running",
});

API Key 只能留在服务端或本地安全配置中。前端看到的是你自己的 appJobId,而不是一个可以绕过业务权限直接调用底层服务的凭据。

刷新后的恢复流程

页面重新加载时,前端应该先向自己的后端询问:“这个用户的这个业务任务现在是什么状态?”而不是重新发送用户原始问题。

后端可以按下面的顺序恢复:

  1. appJobId + userId/tenantId 做权限校验;
  2. 如果已有 taskId,查询任务详情,绝不自动再次 newTask
  3. 如果任务仍在运行,使用已有标识重新建立事件观察,或用轮询补偿;
  4. 如果任务已经完成,直接读取 workspace 产物索引;
  5. 如果任务失败,展示可解释状态,再由用户选择是否重试;
  6. 只有确认从未创建出 taskId 时,才允许创建新任务。

这里最重要的一条是:连接丢失不等于任务失败,任务状态未知也不等于可以安全重提。

三个最容易制造重复任务的灰区

1. newTask 已到达服务端,但响应在网络中丢了

前端看到超时,不代表服务端没有创建任务。直接重试会产生重复执行。适配层应该给提交动作增加幂等键,或者先按自己的 appJobId 查询绑定结果。

2. SSE 断开,但后台仍在生成文件

不要把“最后一条事件时间”当作任务完成时间。事件通道可以断,workspace 仍可能继续写入。恢复时要查询任务详情和产物状态。

3. 用户连续点击提交

按钮禁用只是体验优化,不是并发控制。服务端仍要按用户、业务对象和幂等键限制重复任务。

Supabase 与 Agent 层如何分工

如果应用已经使用 Supabase,没有必要推倒重来。

Supabase 可以继续负责 Auth、PostgreSQL 和 Storage:保存用户、租户、appJob、业务对象和你自己的下载授权。InfiniSynapse 承担研究、泛数据分析、工具执行和任务工作区。两者之间由 BFF/适配层控制输入、能力开关、状态映射与产物回收。

这种分工比“让 Agent 直接连前端和核心数据库”多了一层代码,却少了大量线上不确定性。

上线前,强制做四个恢复测试

不要只测 happy path。至少验证:

  • 任务开始 10 秒后刷新页面,进度可以恢复,后台只有一个任务;
  • SSE 主动断开后,任务继续运行,页面可以通过重连或轮询恢复;
  • newTask 返回前模拟网络超时,不会产生两个后台任务;
  • 任务完成后重开页面,报告、表格和图片仍能从 workspace 被发现和下载。

建议同时记录四个指标:任务创建成功率、刷新恢复成功率、重复任务率、从提交到第一个可用产物的时间。没有这些数据,“Agent 看起来挺稳定”只是一种感觉。

最小上线检查清单

  • API Key 从未进入前端包、浏览器存储或公开仓库;
  • SSE 在 newTask 之前建立;
  • taskId 一旦返回就立即持久化;
  • 页面刷新先恢复任务,不自动重提;
  • 服务端对任务提交做幂等控制;
  • 用户权限绑定到自己的 appJob,不能只信任前端传来的 taskId
  • 最终结果从 workspace 产物读取,而不是只依赖最后一条聊天消息;
  • 失败、超时、断流和重复点击都有明确行为。

Vibe Coding 最适合加速页面、交互和场景编排。恢复协议、权限边界和任务状态不应该靠运气。

如果你正在把一个 Agent Demo 推向真实用户,可以从 InfiniSynapse Vibe Coding Guide 开始,把完整指南保存为 SKILL.md,交给 Cursor、Claude Code 或 Codex,让编码工具按真实接口约束完成接入:

https://www.infinisynapse.cn/zh/docs/InfiniSynapse%20Vibe%20Coding%20Guide

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐