|
文档
预约演示平台
平台MCPCLIAPI
工作流
指南更新日志

欢迎

  • 概览
  • 身份验证
  • 错误与状态码
  • Webhook 签名

本地化

  • 概览
  • 创建任务
  • 锁定不可翻译的键
  • 查看任务组状态
  • 获取单个作业
  • 列出作业
  • Webhook 结果投递
  • 实时进度(WebSocket)

流水线

  • 概览
  • 本地化前 AI 预编辑
  • 人工审核
  • AI 审校(后编辑)
  • 改写成更自然的文案
  • 回译检查
  • 配置 Pipeline
  • 查看流水线运行记录

预配

  • 概览
  • 创建预配作业
  • 来源类型
  • AI 会提取哪些内容
  • Webhook 投递
  • 实时进度(WebSocket)

同步

  • 本地化
  • Recognize

引擎管理

  • Engine Suggestions

Webhook 投递

你创建了一个预配任务,并拿到了一个202:一个引擎 ID,以及 status: "in_progress"。现在,AI 代理正在后台抓取你的源内容,并将品牌语调、术语表条目和指令应用到这个引擎上。这个过程可能很快,也可能需要一些时间,取决于它要抓取多少链接。你当然可以保持一个实时 WebSocket连接,实时看它运行——但你大概并不想只是为了知道代理何时完成、以及它到底构建了什么,就一直维持着连接不断开。

Webhook 就是为此而生。创建任务时,如果你传入 callbackUrl,Lingo 会在任务结束的第一时间将最终结果 POST 到该 URL——引擎一准备好,你就会收到通知,并拿到已构建内容的完整清单。 成功完成的任务会以 provisioning.completed 的形式送达,其中包含 AI 创建的每一条记录的摘要。失败的任务则会以 provisioning.failed 的形式送达,并附带失败原因。无论结果如何,你的配置流程都会收到通知,无需主动查询。

本页会介绍这两种负载,以及该如何处理它们。投递带有签名,也会自动重试——这套机制与本地化共用,统一说明见Webhook 签名验证页面;在你会用到的地方,这里都会附上对应链接。

本页内容

  • 投递如何运作
  • completed 负载
  • failed 负载
  • 如何处理 Webhook
  • 什么时候不该用投递

投递如何运作#

一个预配任务只会结束一次。它一旦进入终态——要么所有源都已抓取并分析完成,要么运行被放弃——结果就会以单个 POST 的形式投递到你的 callbackUrl。本地化分组会拆成每个目标语言区域一个任务,因此每个任务都会各自回调;而预配任务就是一个任务,所以也只会有一次投递。

在创建任务时,通过 callbackUrl 设置投递目标。线上会传输两种负载格式,通过它们的 type 字段区分:provisioning.completed 和 provisioning.failed。两者都会标明所属的 jobId 和 engineId,因此同一个处理器就可以根据 type 做路由,并更新正确的记录。

仅支持 HTTPS

callbackUrl 必须使用 HTTPS。创建任务时,如果提供的是 HTTP URL,就会被拒绝——Webhook 是带签名的,而通过明文传输已签名负载,就失去了签名本身的意义。

优雅处理未知事件类型

目前线上传输的是 provisioning.completed 和 provisioning.failed。请把事件类型集合视为开放的——处理你已知的类型,忽略其余类型,这样未来新增事件类型时,也不会破坏已部署的处理器。

completed 负载#

任务完成后,负载会携带 summary——也就是你通过读取任务本应拿到的同一份清单,只不过现在是主动推送给你,而不是靠你轮询。它会列出 AI 在你的引擎上创建的每个品牌语调、术语表条目和指令,并列出过程中遇到的所有逐项失败。

json
{
  "type": "provisioning.completed",
  "jobId": "pjb_A1b2C3d4E5f6G7h8",
  "engineId": "eng_X1y2Z3a4B5c6D7e8",
  "summary": {
    "brandVoices": { "count": 3, "ids": ["bv_A1b2C3d4", "bv_B2c3D4e5", "bv_C3d4E5f6"] },
    "glossaryItems": { "count": 12, "ids": ["gi_A1b2C3d4", "..."] },
    "instructions": { "count": 5, "ids": ["ins_A1b2C3d4", "..."] },
    "errors": []
  }
}
字段说明
typeprovisioning.completed
jobId已完成的预配任务(前缀为 pjb_)
engineId它所配置的引擎(前缀为 eng_)
summaryAI 在引擎上创建的内容——各组件的数量和 ID,以及 errors 中的逐项失败

summary 与任务中携带的是同一个对象,而它逐字段的含义——每个组件是什么、条目如何映射到语言区域、哪些内容会落入 errors——统一记录在 AI 会提取什么 页面。这里你只需要知道:completed 负载会把代理构建出的所有内容 ID 直接交给你,这样你的处理器就可以直接记录它们,或在仪表盘中展示它们,而无需重新获取任务。

即使 errors 数组非空,也仍会以 completed 送达。

逐项失败不会让整个任务失败。如果某个源无法抓取,或者某条记录无法创建,它会被写入 summary.errors,其余内容仍会应用到引擎上——而负载依然是 provisioning.completed,不是 provisioning.failed。completed 事件表示任务已完整跑完;请查看 errors 了解需要修复的内容。只有当整个运行完全没有产出任何可用引擎时,才会发送 provisioning.failed 负载。

failed 负载#

当一次运行没有产出任何可用结果时,预配任务就会失败——例如,所有源都抓取失败,导致代理没有任何内容可供分析。即便如此,你仍然会收到通知。该负载类型为 provisioning.failed,并且会用一个 error 字符串来替代摘要:

json
{
  "type": "provisioning.failed",
  "jobId": "pjb_A1b2C3d4E5f6G7h8",
  "engineId": "eng_X1y2Z3a4B5c6D7e8",
  "error": "All sources failed to crawl. No content available for analysis."
}
字段说明
typeprovisioning.failed
jobId失败的预配任务
engineId已创建但未完成配置的引擎
error说明任务为何无法完成的可读原因

细心的读者此时很可能会问:如果任务失败了,我是不是连引擎也一起丢了? 不会。此负载中的 engineId 与你在 202 中收到的是同一个引擎——它依然存在,并且在你发起调用的那一刻就已经创建好了,只是没有加上那次失败运行原本会补上的配置。失败只会让你失去提取结果,不会让你失去引擎。你可以调整提交的内容后重试,或者直接在仪表盘里手动配置该引擎。当任务因抓取失败时,问题通常出在源本身——源类型 页面介绍了什么样的源才值得接入。

如何处理 Webhook#

细心的读者看到这里,第一个反应其实是对的:我的处理器要做真正的工作——写数据库、发通知、刷新仪表盘——那不会让连接一直开着,最后把 Webhook 拖到超时吗?

会,所以别让 Lingo 等。先返回 200,再处理。 先确认已收到,再在响应发出后做真正的工作。完整的投递约定——为什么要先确认,以及如果不这么做,后续会按怎样的计划重试——都在 签名与投递 页面;下面的处理器示例展示了它在预配负载里的基本形态。

javascript
app.post("/webhooks/provisioning", verifyWebhook, async (req, res) => {
  // Acknowledge first - the job ends once, so this fires once.
  res.status(200).send("ok");

  const { type, jobId, engineId } = req.body;

  if (type === "provisioning.completed") {
    const { summary } = req.body;
    await db.engines.update({
      where: { engineId },
      data: {
        status: "ready",
        brandVoiceCount: summary.brandVoices.count,
        glossaryCount: summary.glossaryItems.count,
        instructionCount: summary.instructions.count,
      },
    });
  }

  if (type === "provisioning.failed") {
    console.error(`Provisioning failed: ${jobId} (${engineId})`, req.body.error);
    await db.engines.update({
      where: { engineId },
      data: { status: "needs_configuration" },
    });
  }
});

本页唯一没有展开定义的是 verifyWebhook 中间件。每次投递都遵循 Standard Webhooks 规范进行签名——三个请求头、基于原始请求体计算的 HMAC,以及一个 whsec_ 密钥,该密钥会在你第一次提交带回调的任务时生成。预配和本地化回调都原样使用这套方案,因此相关说明统一放在 Webhook 签名验证 页面。请务必在信任负载之前先接入这层中间件——未经验证的请求体,就是未经认证的请求体。

先验证,再信任请求体

你的端点是一个公开 URL;任何人都可以向它 POST。在对任何负载采取行动之前——例如把某个引擎标记为就绪,或存储它声称已创建的 ID——都要先根据原始请求体验证签名。具体做法——请求头、HMAC,以及 whsec_ 密钥——请参见 签名验证 页面。

什么时候不该用投递#

Webhook 是一种推送层面的便利机制,不是系统记录的唯一来源。有两种情况更适合用别的方式,而且都只差一个链接。

如果结果投递时你的端点不可用,平台会按照 Lingo 所有 Webhook 共用的同一重试计划继续重试——而结果并不会被困在回调里。AI 创建的记录就是引擎的真实配置;completed 摘要只是对已经发生在真实引擎上的工作的报告,并不是唯一副本。所以,一段时间的宕机只会让你错过通知,不会让你失去引擎。重试计划本身请参见 签名与投递 页面。

如果你真正想要的是在引擎配置期间获得实时进度——比如在 UI 中展示“先抓取、再配置”的状态,而不是在结束时只向你的服务器发一次回调——那你需要的是预配任务 WebSocket,而不是 Webhook。它会在连接建立时推送快照,并在运行推进过程中持续发送进度事件;你可以在任何时候连接,即使任务已经结束也没问题。

实时进度(WebSocket)
在引擎配置期间流式接收快照和进度事件,而不是只在结束时收到一次回调。可随时连接,即使任务已经结束。
Webhook 签名验证
验证签名、读取请求头并处理重试计划——这是所有 Webhook 投递共用的机制。
AI 会提取什么
摘要中各字段的含义:品牌语调、术语表条目、指令,以及哪些内容会进入 errors。

这个页面对你有帮助吗?

Max PrilutskiyMax Prilutskiy·已更新 12 天前·2 分钟阅读