---
title: "语音序列节点参考"
description: "查阅内联语音序列定义中所有正式可用的步骤，包括每种类型、字段、允许的值和结果。"
---

# 语音序列节点参考

> **Warning:** Voice sequences are in preview. Steps, entry data, and the sequence definition format can change in ways that break existing sequences and API requests.

使用本参考编写通过[创建通话](/docs/guides/voice/create-calls#run-an-inline-sequence)发送的 `sequence.definition`。Bird 会运行一次内联定义且不会保存它。如需保留序列，请在[控制台编辑器](/docs/guides/voice/sequences/editor)中构建。

## 定义

| 字段                     | 值                                                                                                          |
| ------------------------ | ----------------------------------------------------------------------------------------------------------- |
| `schema_version`         | `1`。                                                                                                       |
| `expression_environment` | `"bird.cel.v1"`。                                                                                           |
| `nodes`                  | 节点对象数组。数组顺序不影响执行。                                                                          |
| `settings`               | 省略该字段或发送 `{}`。非空对象会返回 `unsupported_contract` 错误；非对象值会返回 `invalid_envelope` 错误。 |
| `presentation`           | 可选的编辑器布局和标签。不影响执行，但计入大小限制。                                                        |

每个节点包含以下字段：

| 字段           | 值                                                                       |
| -------------- | ------------------------------------------------------------------------ |
| `id`           | 在定义中唯一。以小写字母开头，后接小写字母、数字或 `_`，最多 64 个字符。 |
| `type`         | 本页中的一种节点类型，例如 `voice.say`。                                 |
| `type_version` | 本页每种节点类型的 `1`。                                                 |
| `config`       | 固定节点形态的配置，例如声明的结果。节点没有配置时使用 `{}`。            |
| `input`        | 节点运行时使用的值。节点没有参数时使用 `{}`。                            |
| `connections`  | 从结果名称到 `{ "node_id": "<target>", "port": "input" }` 的映射。       |

连接不能形成循环，且每个节点必须从某个入口可达。未出现在 `connections` 中的结果为未连接状态。未连接的结果会正常结束运行，除非节点另有说明。

## 值和表达式

大多数字段接受字面量 JSON。标记为 **binds** 的字段还接受 `$expr` 或 `$template`；标记为 **expr** 的字段仅额外接受 `$expr`：

- `{"$expr": "trigger.data.customer_name"}` 返回一个带类型的值。
- `{"$template": ["Hello ", {"$expr": "trigger.data.customer_name"}, "."]}` 返回文本。模板是数组；`{{name}}` 保持为纯文本。

表达式使用 CEL，可以读取以下值：

| 值                                     | 内容                                                                              |
| -------------------------------------- | --------------------------------------------------------------------------------- |
| `trigger.data`                         | 入口数据，与入口的 `data_schema` 匹配。                                           |
| `trigger.node_id`                      | 启动本次访问的入口 ID。                                                           |
| `trigger.type`                         | 启动本次访问的入口类型，例如 `trigger.start_call`。                               |
| `steps.<id>.output`                    | 本次访问中先前已完成节点的输出。                                                  |
| `variables.<key>`                      | 本次访问中由 `data.set` 节点保存的值。                                            |
| `execution.id`、`execution.started_at` | 运行 ID 及其开始时间。在语音中使用 `string(execution.started_at)`。               |
| `execution.call`                       | 通话的 `id`、`session_id`，以及原始参与方 `orig` 和 `dest`，每个都可以是 `null`。 |

读取可选值之前先做防护检查，例如 `has(trigger.data.name) ? trigger.data.name : 'caller'`。`has` 宏可用；`map`、`filter`、`all`、`exists` 和 `exists_one` 不可用。

## 入口

### `trigger.start_call`

通话的起始位置。Create Call 请求中的 `entry_node_id` 指定此节点。

| 字段                 | 值                                                                                                               |
| -------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `config.data_schema` | 可选的 JSON Schema（draft 2020-12）对象模式，用于 `trigger_data`。仅支持本地 `$ref`。若未提供，入口仅接受 `{}`。 |
| 结果                 | `event`。                                                                                                        |

入口数据限制为 16 KiB。

## 语音与音频

### `voice.say`

| 字段             | 值                                              |
| ---------------- | ----------------------------------------------- |
| `input.text`     | 必填，**可绑定**。要朗读的文本，最多 160 字节。 |
| `input.language` | 必填。语音语言代码，例如 `en`。                 |
| 结果             | `next`。                                        |

### `voice.play`

| 字段             | 值                                                                            |
| ---------------- | ----------------------------------------------------------------------------- |
| `input.asset_id` | 必填。此工作区中可用的音频资源 ID。不可用的资源会在该步骤运行时导致通话失败。 |
| 结果             | `next`。                                                                      |

### `voice.tone`

| 字段                 | 值                      |
| -------------------- | ----------------------- |
| `input.frequency_hz` | 必填。`100` 到 `3000`。 |
| `input.duration_ms`  | 必填。`1` 到 `10000`。  |
| 结果                 | `next`。                |

### `logic.pause`

在通话保持连接的状态下等待。

| 字段                | 值                     |
| ------------------- | ---------------------- |
| `input.duration_ms` | 必填。`1` 到 `60000`。 |
| 结果                | `next`。               |

## 键盘输入

### `voice.gather`

播放提示音，按键可中断提示，并收集键盘输入的数字。

| 字段                                | 值                                                                                                                                                                                                                                                                                  |
| ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `input.prompts`                     | 必填。最多 4 个提示。每个提示为 `{"type": "say", "text", "language"}`、`{"type": "play", "asset_id"}`、`{"type": "tone", "frequency_hz", "duration_ms"}` 或 `{"type": "pause", "duration_ms"}`，限制与对应节点相同。音调和暂停时长合计最多 60000 毫秒。提示的 `text` 支持**绑定**。 |
| `input.max_digits`                  | 必填。`1` 到 `32`。                                                                                                                                                                                                                                                                 |
| `input.timeout_seconds`             | 必填。等待第一个按键的秒数，`1` 到 `10`。                                                                                                                                                                                                                                           |
| `input.inter_digit_timeout_seconds` | 必填。按键之间等待的秒数，`1` 到 `5`。                                                                                                                                                                                                                                              |
| `input.finish_on_key`               | 必填。结束输入的按键，为 `0`–`9`、`*`、`#`、`A`–`D` 之一，或 `null`。                                                                                                                                                                                                               |
| `input.matches`                     | 必填。从结果名称到选中该结果的精确按键数字的映射，例如 `{"hours": "1"}`。名称和数字必须唯一。名称不能是 `input`、`timeout` 或 `fallback`。数字最长为 `max_digits`，且不能包含 `finish_on_key`。                                                                                     |
| `input.private`                     | 可选，默认 `false`。当值为 `true` 时，后续步骤无法读取按键数字，且数字不会出现在追踪记录中。                                                                                                                                                                                        |
| 结果                                | `matches` 中的每个名称、无按键时的 `timeout`，以及其他任何输入对应的 `fallback`。                                                                                                                                                                                                   |
| 输出                                | `digits` 和 `reason`：`initial_timeout`、`max_digits`、`finish_key` 或 `inter_digit_timeout`。                                                                                                                                                                                      |

## 逻辑与数据

### `logic.branch`

按顺序检查条件，沿第一个为真的条件继续执行。

| 字段                  | 值                                                                    |
| --------------------- | --------------------------------------------------------------------- |
| `config.cases`        | 必填。至少一个 `{"port": "<name>", "when": {"$expr": "<boolean>"}}`。 |
| `config.default_port` | 必填。没有条件为真时的结果名称。                                      |
| 结果                  | `cases` 中的每个 `port`，以及 `default_port`。                        |
| 输出                  | `branch`：所选的结果名称。                                            |

### `data.set`

保存值供同一次访问中的后续步骤使用。

| 字段    | 值                                                                                                   |
| ------- | ---------------------------------------------------------------------------------------------------- |
| `input` | 值对象，每个值支持 **binds**。每个键会变为 `variables.<key>`。所有值根据该节点执行前的变量状态计算。 |
| 结果    | `next`。                                                                                             |
| 输出    | 已保存的对象。                                                                                       |

## 通话与转接

### `voice.dial`

呼叫另一个号码并将其接入当前通话。

| 字段                    | 值                                                                                                                                                             |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `input.to`              | 必填，**binds**。E.164 格式号码，例如 `+12025550123`。                                                                                                         |
| `input.timeout_seconds` | 必填，**expr**。振铃秒数，`1` 到 `120`。                                                                                                                       |
| 结果                    | `success`、`busy`、`no_answer` 和 `failure`。`success` 在已接通的通话结束且原始通话音频恢复后触发，而非在被叫方接听时触发。未连接的 `failure` 会导致运行失败。 |

### `logic.voice_goto`

在同一定义中启动另一个入口。新的访问会获得新的 `trigger.data`，并清除之前步骤的输出和变量；通话继续进行。

| 字段                  | 值                                                        |
| --------------------- | --------------------------------------------------------- |
| `input.entry_node_id` | 必填。此定义中某个 `trigger.start_call` 节点的 ID。       |
| `input.data`          | 可选，**expr**，默认 `{}`。该节点 schema 对应的入口数据。 |
| 结果                  | 无。                                                      |

## 结束通话

### `logic.exit`

以一个结果结束通话。

| 字段            | 值                                                                                                                   |
| --------------- | -------------------------------------------------------------------------------------------------------------------- |
| `config.status` | 必填。`succeeded` 或 `failed`。                                                                                      |
| `config.reason` | 可选，**expr**。由小写字母、数字和 `_` 组成的稳定代码，以字母或数字开头，最多 64 个字符。省略该字段而非发送 `null`。 |
| `input.output`  | 必填对象，可以为 `{}`。其顶层值支持 **binds**。                                                                      |
| 结果            | 无。                                                                                                                 |

### `voice.hangup`

结束通话，不产生自定义结果。该节点没有字段，也没有结果。

## 抢先体验步骤

`voice.webhook`、`voice.record_start`、`voice.record_stop` 和带有 `dependency_id` 的 `logic.voice_goto`（用于托管语音信箱或通话录音）处于抢先体验阶段，此处未提供文档。使用这些步骤需要为您的工作区开通访问权限。

## 示例：转接至某人

此定义向接听方播放问候语，拨打客服号码，并记录转接是否成功：

```json
{
  "schema_version": 1,
  "expression_environment": "bird.cel.v1",
  "nodes": [
    {
      "id": "start",
      "type": "trigger.start_call",
      "type_version": 1,
      "config": {},
      "input": {},
      "connections": { "event": { "node_id": "greeting", "port": "input" } }
    },
    {
      "id": "greeting",
      "type": "voice.say",
      "type_version": 1,
      "config": {},
      "input": { "text": "Connecting you to our support team.", "language": "en" },
      "connections": { "next": { "node_id": "support", "port": "input" } }
    },
    {
      "id": "support",
      "type": "voice.dial",
      "type_version": 1,
      "config": {},
      "input": { "to": "+12025550123", "timeout_seconds": 30 },
      "connections": {
        "success": { "node_id": "connected", "port": "input" },
        "busy": { "node_id": "unavailable", "port": "input" },
        "no_answer": { "node_id": "unavailable", "port": "input" },
        "failure": { "node_id": "unavailable", "port": "input" }
      }
    },
    {
      "id": "connected",
      "type": "logic.exit",
      "type_version": 1,
      "config": { "status": "succeeded", "reason": "transferred" },
      "input": { "output": {} }
    },
    {
      "id": "unavailable",
      "type": "logic.exit",
      "type_version": 1,
      "config": { "status": "failed", "reason": "support_unavailable" },
      "input": { "output": {} }
    }
  ]
}
```

将其作为 `sequence.definition` 连同 `"entry_node_id": "start"` 和 `"trigger_data": {}` 一起发送。

## Related resources

- [Voice sequences](/docs/guides/voice/sequence-builder) (docs)
