Script

最后更新:2026年7月23日

设想您经营一家服装网店。每次上架商品时,都要一条条写出吸引人的详细说明,实在麻烦。于是您希望只要填入商品名和关键词,就让 AI 代您写好详细说明。可是,要调用那个 AI 写作服务,需要一把密钥(access token,外部服务凭它确认"是不是付过费的用户")。如果把这把密钥放进客人看到的网站(浏览器)里,任何人都能把它取出来,于是就泄露了。别人拿着泄露的密钥,就可能随意使用这项服务,费用却要您来承担。

因此,您需要这样一个东西:它把密钥藏在客人看不到的地方,代替网站去调用 AI,再把结果填进商品里。Script 就是它。Script 就是把要做的事按顺序写下来,比如"用这把密钥调用 AI,把得到的文字填进这件商品的详细说明里"。它不是用代码,而是用一种固定格式(JSON,一种用花括号来书写条目和值的数据记法)来书写。网站只需通过互联网调用这个 Script 即可,而密钥藏在 Script 内部,客人是看不到的。

可以把它比作把事先写好的菜谱挂在厨房里。客人点了那道菜时(网站调用 Script 时),厨房(WEEGLOO)就照着菜谱上的顺序做好,把完成的菜端出来。店主只是把菜谱写好挂在那里,并不需要每来一单就亲自下厨。本页先来看 Script 是什么、长什么样、调用后会返回什么,然后以服装店的"填充商品说明" Script 为例,看看它的样子。最后,还会看看如何把这个 Script 接起来,让商品一上架它就自动执行。

Script 代劳的工作

哪怕只是填充一条商品说明,背后要做的事也有好几样。它要确认调用方是否有权限,检查发来的值是否正确,用藏起来的密钥去调用外部 AI 服务,把得到的结果放进想要的位置(商品的详细说明),再把响应返回。以前,做这些事的居中程序得您亲手打造、部署到服务器上并加以维护。Script 的目标,就是把这些事不用代码、集中写在一处,交由它来代办。

  • 一个 Script 就是一个调用入口。 网站可以通过互联网调用的一个入口,就对应一个 Script。调用时所用的方式(method)决定要执行哪个 Script
  • 要做的事从上到下依次排列。 Script 里按顺序写下要执行的动作。它们自上而下逐条执行,后一个动作会承接前一个动作的结果。
  • 从预设的动作中挑选并组合。 它并不是让您塞进任意代码,而是从预先备好的动作(创建、读取、修改、删除资源,调用外部服务,暂存值,条件判断,循环等)中挑选出来,逐条排列。

用来写明该做什么的定义

一个 Script 由一份确定了四样东西的"定义"构成。

  • 调用方式method):调用这个 Script 时所用的方式。取 GetPostPutPatchDelete 之一,调用时凭这个值来判定是哪个 Script
  • 执行位置executionMode):是在被调用处立即执行(Sync),还是放到后台执行(Async)。详见下文 即时执行与后台执行
  • 要做的事statements):从上到下依次执行的动作列表。至少要有一个。
  • 输入校验payloadSchema,可选):用来在执行前核对调用时随附发送的输入的格式。一旦设定,不符合格式的输入就不会执行,而是被退回。

下面以服装店的"填充商品说明" Script 为例。这个 Script 处理的,是一件包含商品名和关键词的商品。从网站传来的输入(在后面会看到的自动执行中,被上架的商品会原样传入)是这样的形状。

{
  "sys": { "id": "3trmXRMKq7bd0Prbef1... (商品编号)" },
  "fields": {
    "productName": { "zh-CN": "不锈钢保温杯 500ml" },
    "keywords":    { "zh-CN": "保温、轻便、露营" }
  }
}

下面是接收这件商品、用外部 AI 生成详细说明,并填充该商品的详细说明(body)的 Script 定义。

{
  "method": "Post",
  "executionMode": "Async",
  "statements": [
    { "type": "Http", "method": "POST",
      "url": "https://api.ai-writer.example.com/v1/generate",
      "headers": [
        { "key": "Authorization", "value": "Bearer <秘密 access token>", "secret": true }
      ],
      "body": {
        "product":  "{ /payload/fields/productName/zh-CN }",
        "keywords": "{ /payload/fields/keywords/zh-CN }"
      },
      "name": "gen" },
 
    { "type": "ResourcePatch", "resource": "Content",
      "target": { "sys": { "id": "{ /payload/sys/id }" } },
      "fields": { "body": { "zh-CN": "{ /gen/body/text }" } },
      "publish": true },
 
    { "type": "Return", "value": { "id": "{ /payload/sys/id }" }, "statusCode": 200 }
  ]
}
  • 第一个动作(Http)用藏起来的密钥去调用外部 AI 服务。在装有密钥的请求头上加上 secret: true,那个值就不会显示给客人,只在调用前的一刻才被解开。得到的结果被暂存到名为 gen 的地方。
  • 第二个动作(ResourcePatch)用前面得到的文字({ /gen/body/text })只填充该商品的详细说明(body),商品的其余值不会被触动。
  • 使用把值传递到下一步的占位符 { /… }{ /payload/fields/productName/zh-CN } 指向传入商品的名称,{ /payload/sys/id } 指向该商品的编号,{ /gen/body/text } 指向 AI 返回的文字。
  • 最后一个动作(Return)返回已填充说明的商品编号。
  • 为什么 Content 的值要像 { "zh-CN": … } 这样按语言分别书写、statements 中可以放入的动作的全部种类、以及占位符和条件、计算的语法,都在 值表达式Statement 目录 中介绍。

调用后会返回什么

Script 在最后会把 Return 动作的值返回给调用方。返回的响应中包含以下内容。

  • requestId:指向本次执行的识别编号。
  • durationMs:执行所花费的时间(毫秒)。
  • statusCode:所到达的 Return 的状态码(不另行指定时为 200)。
  • returnerrorReturn 返回的值。通常放在 return 中;若把该值标记为错误,则放在 error 中。两者不会同时出现。

不过,"填充商品说明"要调用外部 AI,因此会以后台方式执行(参见下文 即时执行与后台执行)。所以调用后会先以"已受理"的含义,立即只返回 202requestId,上面那样的响应则稍后凭那个 requestId 再次查询(轮询)来获取。全部完成后的响应是这样的形状。

{
  "requestId": "3trmXRMZ8kqLb2Prdf1eYc0axWnKv",
  "durationMs": 1840,
  "statusCode": 200,
  "return": { "id": "3trmXRMKq7bd0Prbef1... (商品编号)" }
}

网站可以凭这个 return 中的 id 定位刚刚填好说明的商品,把新的详细说明展示给客人。

如果 Script 没有到达 Return 就结束了,那么 returnerror 都不会有,只会返回 statusCode 为 200。关于用 Return 决定响应正文和状态码的详细规则,在 Statement 目录中的 Return 中介绍。

即时执行与后台执行

Script 有两种执行方式,由定义中的 executionMode 决定。

  • 即时执行Sync):在被调用的当场立即执行,并马上返回完成的响应。适合无需外部调用、很快就能结束的工作。
  • 后台执行Async):在后台执行。调用后会先以"已受理"的含义,立即只返回 202requestId,实际结果稍后凭那个 requestId 再次查询(轮询)来获取。

有一条规则。只要其中含有调用外部服务的动作,或是接收文件并将其存入 Media 的动作,哪怕只有一个,那个 Script 就必须采用后台执行。"填充商品说明"也要调用外部 AI,所以是后台执行。若想以即时执行来保存,保存时就会被退回。这是为了即使外部响应迟迟不来,也不会一直拖住调用方。

可用于执行的时间也有预算。即时执行默认为 10 秒,后台执行默认为 60 秒。轮询的方法、哪些动作会要求采用后台执行等详细规则,在 执行语义、约束与安全 中介绍。

Script 由谁来创建

与其让人一条条手写复杂的动作,Script 从设计上就是交给 AI 智能体或程序来创建的。只要用一句话拜托 AI 智能体"帮我做一个填充商品说明的入口",智能体就会替您做出前面看到的那种定义。相当于一句话,就在网站背后多出一个干活的入口。

用 AI 智能体创建 Script 的详细流程,在 用一句话打造后端 中介绍。

创建好的 Script,由人在管理画面(内容工作室)中查看和管理。查看它的名称和定义,必要时进行修改或删除。实际调用 Script 的,是客人看到的网站或应用(前端)。以在产品中注册的会员(ServiceUser)身份,只能执行 Script,不能创建或修改。

与 Webhook 有何不同

ScriptWebhook 都是与外部相连的装置,但调用的方向相反。

  • Webhook 在预定的变化发生时(比如商品被上架)会自动作出反应。即使无人调用,只要事件发生就会自动行动。不过,它不会把结果返回给调用方。
  • Script 是网站在需要时直接调用的入口。要调用才会执行,并把执行结果即时返回,若为后台执行则通过轮询取回。

"店主一按下'填充说明',就调用 AI 取回详细说明并填入",这是调用方在等待结果的事,所以适合用 Script;"商品一上架,就自动发生某件事",这是对事件作出反应的事,所以适合用 Webhook。而且这两者可以搭配使用。下一节马上就会看到。

只要上架,说明就自动填好

到目前为止,都是店主按下"填充说明"按钮,亲自调用 Script。再往前一步,即使不按按钮,也可以让 Script 在上架商品的那一刻自动执行。因为 Webhook 会捕捉那个事件,代为调用我们的 Script

流程是这样的。

  1. 店主上架商品。这时只填写商品名和关键词,详细说明留空。
  2. Webhook 察觉到有新商品被上架这一事件。
  3. Webhook 把刚上架的商品原样传给我们的"填充商品说明" Script 并执行。
  4. Script 用外部 AI 生成详细说明,填充该商品的详细说明(body)。
  5. 稍过片刻,商品的详细说明就自动填好了。

这里用的 Script 与前面完全相同。改变的只是调用的契机。不再是按钮,而是"商品被上架"这一事件来调用。由于被上架的商品会原样成为 Script 的输入,Script 便用 { /payload/sys/id } 取到那件商品,填充其详细说明。

Webhook 一侧要设定的有三样:对什么事件作出反应(有新商品被上架时)、只对哪些商品作出反应(限定为某类商品),以及要做什么(不是向外部地址发送通知,而是调用我们的 Script)。

您也许会担心:Script 填好的详细说明,会不会又引发"商品被改动"这一事件,从而无休止地循环下去。不会的。除非另行开启,Script 的写入不会引发新的事件,平台也会阻止无休止的循环。

这样连接的详细设置,在 Webhook 中介绍。

Script 特别有用的场景

如果只是要向外部通知一声"发生了这样的事",那么一个 Webhook 就足够了。但如果在调用外部服务之后,还要根据它返回的结果继续判断和处理,就需要一个把整个流程汇集到一处的 Script

下面以一项付费生成 AI 图像的功能为例。当客人请求生成图像时,接下来这些事情需要按顺序发生。

  1. 确认客人的额度是否充足。如果不足,就在这里停下,并告知"额度不足"。
  2. 如果充足,就先按费用扣除相应的额度。
  3. 调用外部 AI 服务来生成图像。
  4. 把生成好的图像保存为 Content
  5. 如果第 3 步或第 4 步出了问题,就把刚刚扣除的额度退还回去。

Webhook 虽然能向外部通知"有请求进来了",却无法像这样根据结果来扣除额度,也无法在失败时回退。把多个步骤按条件衔接起来、并在失败时回退前面的步骤,这类工作则由 Script 来承担。Script 特别能发挥作用的场景如下。

  • 需要根据结果继续处理时:根据外部服务返回的响应,当场判断是要保存、扣除,还是回退。
  • 即使同时进来也不能出错时:同一位客人在很短的时间内请求两次,也不能把额度扣除两次。Script 会在读取值之后、就要保存之前,用版本号确认"这期间是否有别的请求改动过这个值",一旦对不上就停下。
  • 需要调用方本身没有的权限时:客人并没有权限自己直接修改额度余额。即便如此,扣除仍能安全地进行,是因为 Script 受托于创建者的权限来执行。对调用方,只需授予执行 Script 的权限即可。这一委托,下文 执行和管理的权限 会详细介绍。

至于如何把这个例子写成实际的 Script 定义,Cookbook 中会通过确认、扣除、退还额度的示例来介绍。

执行和管理的权限

要执行或管理 Script,角色(SpaceRole)中必须具备相应的权限。

  • 执行:要调用 Script,角色中必须有 Script 的执行权限(Execute)。没有就无法执行。
  • 管理:要创建、修改、删除 Script,分别需要创建、修改、删除权限。

执行 Script 时要确认的,只有一件:调用方是否具备执行权限(Execute)。Script 内部排列的各个动作,在执行的那一刻并不会另行确认权限。这就像调用一个已获准执行的程序时,只看是否有权执行这个程序,而不会对它内部所做的每一件事都逐一征得许可。

作为替代,各个动作的权限并不是在执行时确认,而是在 Script 保存时就预先确认。创建者必须实际拥有该 Script 内部动作所涉及的 ContentMedia 操作权限,才能保存。例如"填充商品说明" Script 会修改商品 Content 的详细说明,因此如果创建者没有修改商品的权限,保存就会被退回。含有无权限动作的 Script,从一开始就无法保存。

这样看来,执行 Script 就相当于受托于创建者的权限、代为执行。即便是调用方自己并不具备的操作,只要是创建者能做的操作,就会通过 Script 照样发生。因此在创建 Script 时,必须慎重决定其中放入哪些动作。创建者的权限,就界定了那个 Script 能做的事的范围。

如何把权限装入角色,在 角色与权限 中介绍。

需要了解的事项

  • 没有发布这一步。 Script 并不是那种通过发布来传递给访问者的资源,而是在管理画面中创建好、供网站调用的入口。因此与 ContentMedia 不同,它没有发布、取消发布的状态,一创建就能立即使用。每修改一次,版本号就加一;删除时也无需取消发布这类前置步骤,可以直接删除。
  • 数量有上限。 Script 属于计费对象,因此一个 Organization 能拥有的数量按套餐分别设定(Free 3 个、Basic 10 个、Pro 50 个、Enterprise 无限制)。达到上限后就无法创建新的 Script,删除不用的 Script 就会空出一个名额。

在内容工作室中管理

创建好的 Script,在内容工作室的 Script 画面中查看和管理。在左侧菜单点击 Script,就会以列表形式列出至今创建的 Script。每一行会显示名称、调用方式(HTTP 方法)、指向 ScriptScript ID、执行位置(执行模式),以及最后修改的日期。

Script 列表画面。"填充商品说明" Script 以 HTTP 方法 POST、执行模式 Async 显示为一行的状态

定义通常由 AI 智能体代为创建,不过您也可以在这个画面中亲手创建。新的 Script 通过列表右上角的 创建 按钮来创建。

  1. 点击列表右上角的 创建 按钮。
  2. 名称 栏中输入 填充商品说明
  3. HTTP 方法 选为调用这个 Script 的方式(这里是 POST)。
  4. 执行模式 选为 Async(后台执行)。这个 Script 要调用外部 AI,因此必须采用后台执行。
  5. Statement 栏中填入写明该做什么的定义。把上面"填充商品说明"示例的定义原样填入即可。

新建 Script 画面。名称"填充商品说明"、HTTP 方法 POST、执行模式 Async、Statement 栏中已填入定义的状态

如果想在执行前核对调用时随附发送的输入,就打开 Payload Schema 中的 Payload 校验,并写下要核对的格式。全部填好后,点击右上角的 保存 按钮。

在列表中点击某一个 Script,就会打开详情画面。您可以在这里查看名称和定义,还能看到调用这个 Script 的地址(Execute URL)。修改定义后 保存,版本号就会加一;不再使用的 Script,用 删除 删掉。

填充商品说明 Script 详情画面。可见名称、HTTP 方法、执行模式、ID、Execute URL 以及 Statement 定义的状态

接下来要做的事

  • Script 概览:介绍构成 Script 的定义的顶层结构、执行规则以及语法文档集。
  • Statement 目录:介绍 statements 中可以放入的动作(创建、读取、修改、删除资源,调用外部服务,条件、循环等)的种类和字段。
  • Webhook:介绍如何像"商品一上架 Script 就自动执行"那样,在预定的变化发生时自动作出反应。