跳到主要内容

消息推送

消息推送流程把外部 HTTP 请求转成 Soln 通知。外部系统向流程 Webhook 发送 JSON 报文,流程把报文渲染成消息,再投递到应用消息或群聊。

消息推送流程归属某个 OpenLink 系统,与入站、出站流程的区别:

  • 不绑定表单,也不会新增、修改或删除本地表单记录
  • 画布只包含一个开始节点、一个或多个消息节点和一个结束节点;不允许出现源、转换、目标、分支、查询节点
  • 触发方式固定为 webhook,不支持轮询、推送和服务调用
  • 消息节点之前可以放智能体执行节点;有智能体执行时,智能体的输出作为消息正文

消息节点配置​

在设计画布中选中消息节点,配置通知的发送方式。

配置项说明
发送方式应用消息 发送站内消息;群聊消息 发送到群聊
消息通道仅应用消息。接收消息的非 Luna 应用通道
消息模板仅应用消息。需要启用中的站内信模板;消息推送流程没有表单绑定,因此不能使用表单记录类模板
接收人仅应用消息。固定成员、表单成员字段,或从请求体解析出的成员
发送智能体仅群聊消息。提供群聊中的发送身份,消息节点不会执行该智能体
目标群聊仅群聊消息。目标群聊中必须已包含该发送智能体
执行时机始终、成功时 或 失败时;当前面没有智能体执行节点时生效

消息正文​

场景消息正文
消息前有智能体执行节点智能体输出的文本,原样发送
没有智能体节点且执行失败失败原因
没有智能体节点、报文顶层有 markdown 字符串该 Markdown,原样发送
没有智能体节点且没有失败由 Webhook 报文或上游结果渲染出的 Markdown

Markdown 渲染会把对象转成 - **字段**: 值 列表,把对象数组内联为 - **code**: A · **qty**: 2,跳过空值,并对过长正文做截断。群聊里的发送智能体只是载体:没有智能体执行节点时,流程不会调用 AI 生成内容。

如何请求​

项目取值
方法POST
地址<your-runtime-origin>/api/open-link/message-push/<flowCode>
内容类型application/json;其他类型会返回 OPEN_LINK_CONTENT_TYPE_INVALID
请求头X-Idempotency-Key 可选;其余按该系统的入站鉴权配置,详见入站鉴权
请求体一个 JSON 对象,参数见下表;不是 JSON 对象(数组或单个值)时返回 OPEN_LINK_EXECUTION_PAYLOAD_INVALID

<your-runtime-origin> 是工作空间 Runtime 的地址,也就是你在浏览器里打开 Soln 的那个地址,例如 https://runtime.example.com。<flowCode> 是流程记录上的流程编码,形如 open_link_flow_889b5ea7abae,不是流程定义的 UUID。设计画布的开始节点会显示该流程的完整地址,直接复制即可:

https://runtime.example.com/api/open-link/message-push/open_link_flow_889b5ea7abae

消息推送使用独立接口:入站 Webhook 地址只服务入站流程,调用消息推送流程会被拒绝。

请求参数​

请求体的参数都是可选的,按消息节点的发送方式选用;同一个请求可以同时带上多种参数。

参数类型必填说明
markdownstring否群聊消息的自定义正文,原样按 Markdown 发送
memberIdsstring[]否请求体传入的接收人,成员 UUID 或外部成员标识,例如 ["1001"],详见下文
messageobject否应用消息的模板变量,键名与模板变量名一致
其他字段任意否供智能体执行节点分析,或供节点输入映射按 input.*、record.data.* 读取

请求示例​

群聊消息,自己写 Markdown 正文(消息节点的发送方式必须是群聊消息):

curl --request POST \
'https://runtime.example.com/api/open-link/message-push/notification-push' \
--header 'Content-Type: application/json' \
--header 'X-OpenLink-Token: ${OPENLINK_TOKEN}' \
--header 'X-Idempotency-Key: notification-001' \
--data '{
"markdown": "> 生活是一大堆无聊的时间,欢乐的玫瑰难得点缀其中;\n> 谁想第一个得到欢乐的玫瑰,谁就最先被它的荆棘扎痛。\n\n— 托·穆尔"
}'

群聊消息,正文由报文生成,接收人由 memberIds 传入:

curl --request POST \
'https://runtime.example.com/api/open-link/message-push/order-alert-push' \
--header 'Content-Type: application/json' \
--header 'X-OpenLink-Token: ${OPENLINK_TOKEN}' \
--data '{
"memberIds": ["1001"],
"stage": "review",
"owner": "A. Lee",
"tags": ["draft", "review"]
}'

应用消息,模板变量放在 message 里(示例模板声明了 quote、signature 两个变量):

curl --request POST \
'https://runtime.example.com/api/open-link/message-push/quote-push' \
--header 'Content-Type: application/json' \
--header 'X-OpenLink-Token: ${OPENLINK_TOKEN}' \
--data '{
"message": {
"quote": "我从来不认为人的自由在于想做什么就做什么,而是在于想不做什么就不做什么",
"signature": "------让·雅克·卢梭 <一个孤独者漫步者的遐想>"
}
}'

X-OpenLink-Token 只在 OpenLink 配置了共享令牌入站鉴权时发送,请求头名称以安全配置为准;配置的是签名校验时,改为发送 App ID、时间戳和 HMAC 签名请求头,签名原文必须包含本次请求的原始 JSON。

请求说明​

群聊消息正文。 取值顺序是:智能体执行节点的输出 → 执行失败原因 → 报文里的 markdown → 由报文渲染的 Markdown。报文没有 markdown 字段时按字段渲染:每个字段一行 - **字段**: 值,嵌套对象渲染成缩进子项,对象数组内联为 - **date**: 2026-09-15 · **hours**: 2,空值跳过,超过 3800 字符截断。例如:

{ "stage": "review", "owner": "A. Lee", "tags": ["draft", "review"] }
- **stage**: review
- **owner**: A. Lee
- **tags**
- draft
- review

正文不能超过群聊消息 4000 字符上限,超出报 WORKFLOW_GROUP_CHAT_BODY_TOO_LONG。消息节点前有智能体执行节点时,智能体的输出始终作为群聊正文,即使请求里带了 markdown;此时请求体里放的是给智能体分析的字段。

应用消息模板。 模板变量在消息节点上用「请求体」映射方式取值,按 input.message.<变量名> 解析,映射键名必须与模板变量名完全一致。上面的示例模板正文写成 {{input.quote}} 和 {{input.signature}},收到的就是普通文案,不是字段清单:

我从来不认为人的自由在于想做什么就做什么,而是在于想不做什么就不做什么
------让·雅克·卢梭 <一个孤独者漫步者的遐想>

请求体缺少被映射的字段时执行失败,执行日志会记录缺失路径,例如 RUNTIME_CONTEXT_PATH_NOT_FOUND:input.message.quote。

请求体传入接收人。 在消息节点上打开配置接收人,切到请求体传入,勾选成员组,请求体传入的接收人就与固定接收人一样直接生效:请求体解析出谁,消息就发给谁。memberIds 里的值先按该 OpenLink 系统的组织映射解析成成员,例如 1001 已映射为 00000000-0000-4000-8000-000000000010,消息就发给该成员;映射不到、也不是成员 UUID 的值会被跳过。接收人不会从其他字段推断,全部解析不到时执行失败,日志报 MESSAGE_APP_CHANNEL_TARGETS_UNRESOLVED。

请求被接受的前提:OpenLink 系统为 active、流程已 published、调用方通过该系统配置的入站鉴权与白名单,并且请求计入入站限流与并发保护。

响应​

执行排入队列后接口返回 202 Accepted,消息是异步投递的。

{
"accepted": true,
"duplicate": false,
"logId": "00000000-0000-4000-8000-000000000001",
"traceId": "00000000-0000-4000-8000-000000000002",
"status": "queued",
"definitionId": "00000000-0000-4000-8000-000000000003",
"flowCode": "order-alert-push",
"workflowId": "open-link:...",
"workflowStartDeferred": false,
"callbackRequested": false,
"statusQueryUrl": null
}
字段说明
accepted请求已被接受执行
duplicate相同幂等键已受理时为 true,此时返回原有的 logId、traceId
logId / traceId执行标识,用于在执行日志中定位本次运行
status初始执行状态,queued
definitionId / flowCode受理该请求的流程
callbackRequested / statusQueryUrl消息推送固定为 false 和 null:该接口不创建异步回执

用返回的 logId 打开流程执行日志,确认消息是否投递成功、失败时查看失败原因。流程运行期间产生的错误(例如解析不到接收人)记录在执行日志里,不会通过 HTTP 响应返回。

常见错误​

错误码含义
OPEN_LINK_FLOW_DEFINITION_NOT_FOUND没有匹配该流程编码的流程
OPEN_LINK_FLOW_DEFINITION_NOT_PUBLISHED流程存在但尚未发布
OPEN_LINK_SYSTEM_NOT_ACTIVEOpenLink 系统未启用
OPEN_LINK_FLOW_EXECUTION_TYPE_INVALID该流程不是消息推送流程;应改用入站 Webhook 或查询接口
OPEN_LINK_CONTENT_TYPE_INVALID请求内容类型不是 application/json
OPEN_LINK_JSON_VALUE_INVALID请求体不是合法 JSON
OPEN_LINK_PAYLOAD_TOO_LARGE请求体超过大小限制
OPEN_LINK_WEBHOOK_AUTH_INVALID / OPEN_LINK_WEBHOOK_TIMESTAMP_EXPIRED入站鉴权校验失败
OPEN_LINK_WEBHOOK_SOURCE_DENIED白名单规则拒绝该调用方
OPEN_LINK_INBOUND_RATE_LIMIT_EXCEEDED / OPEN_LINK_INBOUND_CONCURRENCY_LIMIT_EXCEEDED被入站限流或并发保护拒绝
OPEN_LINK_IDEMPOTENCY_KEY_CONFLICT该幂等键已被其他流程使用
MESSAGE_TEMPLATE_REQUIRED_INPUT_MAPPING_MISSING:<变量名>模板的必填变量在消息节点上没有配置输入映射(发布时报错)
MESSAGE_TEMPLATE_INPUT_MAPPING_UNKNOWN:<键名>映射键名和模板变量名不一致(发布时报错)
MESSAGE_TEMPLATE_INPUT_MAPPING_PATH_INVALID:<变量名>映射路径不是允许的上下文路径(发布时报错)
RUNTIME_CONTEXT_PATH_NOT_FOUND:input.message.<变量名>请求体里没有映射要读取的 message 字段(日志报错)
MESSAGE_APP_CHANNEL_TARGETS_UNRESOLVED消息节点既没有固定接收人,也没有从请求体解析出的成员(日志报错)

消息推送流程与其他流程一样,在流程列表里创建发布,或使用 Openlink 系统命令参考中的 Runtime 命令创建发布。

推荐配置流程​

  1. 创建或选择通知所属的 OpenLink 系统
  2. 为该配置入站鉴权与白名单规则
  3. 通过 Runtime 命令或流程列表创建消息推送流程
  4. 进入设计画布,添加并配置消息节点;需要分析内容时,在消息节点之前添加智能体执行节点
  5. 保存、发布并启用流程
  6. 从外部系统调用 POST /api/open-link/message-push/<flowCode>,并在执行日志中核对结果