Skip to Content
帮助文档代码扩展Runtime API 参考

Runtime API 参考

Zion 会为每个项目生成 Runtime GraphQL API。你可以通过它在自定义前端、服务端程序或其他系统中访问项目数据库,并调用行为流、AI 智能体和第三方 API。

项目的数据模型和功能配置会共同决定最终的 GraphQL Schema。本文说明稳定的调用方式和字段命名规则;具体项目中可用的字段、参数和返回类型,请以 开发者接入 中的 GraphiQL 为准。

开始使用

在编辑器中打开 开发者接入,可以复制以下项目专属信息:

  • GraphQL 接口地址:发送 Query 和 Mutation。
  • GraphQL 订阅地址:建立 Subscription 连接。
  • Admin Bearer Token:以项目管理员权限访问后端。
  • GraphiQL:查看当前项目的 Schema,并直接调试请求。

接口地址的格式如下:

https://zion-app.functorz.com/zero/{projectExId}/api/graphql-v2 wss://zion-app.functorz.com/zero/{projectExId}/api/graphql-subscription

数据模型、行为流入参或出参、AI 智能体和第三方 API 发生变化后,需要先同步变更或发布,再刷新 GraphiQL Schema。

HTTP 请求

Query 和 Mutation 使用标准 GraphQL JSON 请求体:

{ "query": "query GetPosts($limit: Int!) { post(limit: $limit) { id title } }", "operationName": "GetPosts", "variables": { "limit": 10 } }

认证

Runtime API 根据请求携带的身份执行权限校验。

身份认证方式适用场景
游客不发送 Authorization访问允许游客使用的数据和功能。
当前用户Authorization: Bearer <jwt>按登录用户的角色和权限执行请求。
项目管理员Authorization: Bearer <admin_token>可信服务端、脚本或本地开发环境中的后台管理操作。
⚠️

Admin Bearer Token 拥有项目级高权限。不要把它写入网页、客户端应用、公开仓库或任何会发送给终端用户的代码。

获取用户 JWT

不同登录方式会生成不同的认证字段。以下示例使用用户名和密码获取 JWT:

mutation AuthenticateWithUsername( $username: String! $password: String! $register: Boolean! ) { authenticateWithUsername( username: $username password: $password register: $register ) { account { id permissionRoles } jwt { token } } }

register: true 表示注册并登录,register: false 表示登录已有账号。将返回的 jwt.token 放入后续 HTTP 请求头:

Authorization: Bearer <jwt>

认证 Subscription

Subscription 使用 graphql-ws 协议。建立连接时,在 connection_init 消息的 payload 中传入 Token:

{ "type": "connection_init", "payload": { "authToken": "<jwt_or_admin_token>" } }

请求、响应与错误

Runtime API 支持三类 GraphQL Operation:

类型用途常见场景
query读取数据查询数据表、查询异步任务结果、获取上传地址。
mutation修改数据或触发执行添加、修改、删除数据,调用行为流或 AI 智能体。
subscription持续监听结果监听异步行为流、AI 智能体或数据变化。

GraphQL 只返回 Operation 中显式选择的字段。成功响应通常包含 data:

{ "data": { "post": [{ "id": 1, "title": "Hello" }] } }

执行失败时,响应包含 errors。GraphQL 也可能同时返回部分 data 和 errors,调用方应分别处理:

{ "data": null, "errors": [ { "message": "permission denied", "path": ["post"] } ] }

排查错误时,优先检查 message、path 和响应中的请求标识,再到运行日志中定位对应请求。

接口参考

数据库

Zion 根据数据模型生成表查询、关联查询、聚合和写入字段。以下示例使用 post 表;请在 GraphiQL 中替换为项目的实际表名和字段。

数据类型

Zion 数据类型GraphQL 类型说明
文本String文本值。
长整数bigint 或生成的长整数类型常用于数据 id;以 Schema 中的实际类型为准。
无限精度小数Decimal高精度小数。
布尔值Booleantrue 或 false。
JSONBjsonbJSON 数据。
日期时间(带时区)timestamptz包含日期、时间和时区的时间点。
时间(带时区)timetz包含时区的时间。
日期date不包含时间的日期。
经纬度geography地理位置。
图片FZ_Image图片资源。
视频FZ_Video视频资源。
文件FZ_File文件资源。

写入媒体字段时,单个资源通常使用 {field_name}_id,资源数组使用 {field_name}_ids。例如,图片字段 cover 对应入参 cover_id。

查询数据

常见查询字段如下。部分字段只会在对应功能或字段类型存在时生成。

字段格式说明
{table_name}查询列表,支持筛选、排序和分页。
{table_name}_by_pk按主键查询单条数据。
{table_name}_aggregate查询数量、合计等聚合结果。
{table_name}_group_by分组查询。
fz_{table_name}_by_{column_name}按地理位置字段执行距离查询。

列表查询常用参数包括:

参数说明
where筛选条件,类型通常为 {table_name}_bool_exp。
order_by排序条件。
distinct_on按指定字段去重。
limit返回条数上限。
offset跳过指定条数。

常用比较操作符包括 _eq、_neq、_gt、_gte、_lt、_lte、_in、_nin、_like、_ilike 和 _is_null;使用 _and、_or、_not 组合条件。

query GetPublishedPosts($where: post_bool_exp!, $limit: Int!) { post( where: $where order_by: { created_at: desc } limit: $limit ) { id title author { id name } } }
{ "where": { "status": { "_eq": "published" }, "author": { "name": { "_ilike": "%明%" } } }, "limit": 20 }

操作符优先筛选

需要先对字段执行数据库函数再比较结果时,可以使用操作符优先筛选。例如,判断 created_at 的月份是否为 12:

{ "where": { "_eq": { "left_operand": { "extract": { "field": "created_at", "part": "MONTH" } }, "right_operand": 12 } } }

可用函数和入参由字段类型及当前 Schema 决定,请在 GraphiQL 中查看对应的输入类型。

添加数据

mutation CreatePost($object: post_insert_input!) { insert_post_one(object: $object) { id title created_at } }
{ "object": { "title": "My first post", "status": "draft", "cover_id": 1020000000000097 } }

批量添加使用 insert_{table_name},入参通常为 objects,并返回 affected_rows 和所选择的 returning 字段。

修改数据

mutation PublishPost($id: bigint!, $set: post_set_input!) { update_post_by_pk(pk_columns: { id: $id }, _set: $set) { id status } }
{ "id": 100000000000001, "set": { "status": "published" } }

批量修改使用 update_{table_name},通过 where 选择记录,并通过 _set、_inc 等参数指定变更。

删除数据

mutation DeletePost($id: bigint!) { delete_post_by_pk(id: $id) { id } }

批量删除使用 delete_{table_name}(where: ...)。删除前应确认表关联和删除规则,避免级联影响其他数据。

事务

在同一个 Mutation 中依次声明多个数据库写入字段,可以整批原子执行:全部成功时提交,任一数据库操作失败时整体回滚。

mutation CreateOrder($order: order_insert_input!, $items: [order_item_insert_input!]!) { insert_order_one(object: $order) { id } insert_order_item(objects: $items) { affected_rows } }

事务保证只覆盖这次 Mutation 中的数据库写入。外部 HTTP 请求、AI 智能体或行为流产生的外部副作用不属于该数据库事务。

行为流

行为流入参和出参由项目配置决定。同步变更或发布后,在 GraphiQL 中确认当前字段和类型。当前接口会调用已部署的行为流,不需要指定版本。

字段类型说明
fz_invoke_action_flow_default_by_latest_versionmutation同步调用行为流并返回输出。
fz_create_action_flow_taskmutation创建异步任务并返回任务 id。
fz_listen_action_flow_resultsubscription监听异步任务结果。
fz_action_flow_resultquery主动查询异步任务结果。

Schema 中的 versionId 参数和 fz_invoke_action_flow 字段仅用于兼容早期已经接入的调用。新调用不要传入行为流版本。

同步调用

mutation InvokeActionFlow($actionFlowId: String!, $args: Json!) { fz_invoke_action_flow_default_by_latest_version( actionFlowId: $actionFlowId args: $args ) }
{ "actionFlowId": "d3ea4f95-5d34-46e1-b940-91c4028caff5", "args": { "order_id": 10001 } }

返回值来自行为流声明的出参。

异步调用

先创建任务:

mutation CreateActionFlowTask($actionFlowId: String!, $args: Json!) { fz_create_action_flow_task( actionFlowId: $actionFlowId args: $args ) }

返回的长整数是 taskId。随后可以订阅结果:

subscription ListenActionFlowResult($taskId: Long!) { fz_listen_action_flow_result(taskId: $taskId) { status output } }

不使用 Subscription 时,可以轮询:

query GetActionFlowResult($taskId: Long!) { fz_action_flow_result(taskId: $taskId) { status output } }

output 是行为流声明的出参;可用状态以 GraphiQL 中的 TaskStatus 枚举为准。

AI 智能体

Runtime Schema 为兼容既有接口,仍使用 fz_zai_* 字段前缀;产品中的功能名称为 AI 智能体。

字段类型说明
fz_zai_create_conversationmutation创建会话。
fz_zai_listen_conversation_resultsubscription监听流式或最终结果。
fz_zai_conversation_resultquery轮询会话状态与最终结果,供无法建立 WebSocket 连接的客户端使用(不返回流式增量)。
fz_zai_send_ai_messagemutation向已有会话发送消息。
fz_zai_provide_more_informationmutation为等待补充信息的工具调用提供信息。
fz_zai_stop_respondingmutation停止当前响应。
fz_zai_delete_conversationmutation删除会话。

创建会话时,inputArgs 的键是 AI 智能体为每个输入参数生成的 argKey,形如 dpmfu92py 的短随机串,不是你在编辑器里给参数起的显示名。argKey 只能从设计态读取(在 AI 智能体配置的输入参数中查看),无法由参数名推导。

⚠️

用参数显示名作为键不会报错,但该参数会被当作未传入,智能体收到的是空值。若智能体的回答像是忽略了你的输入,先检查这里。

媒体类型参数(图片、视频、文件,含其数组形式)的值传资源 id:键可以直接用 argKey,也可以用 {argKey}_id 后缀形式,两者都会被识别。数组同样使用 _id 后缀,没有 _ids 这种写法。

mutation CreateAgentConversation( $inputArgs: Map_String_ObjectScalar! $agentId: String! ) { fz_zai_create_conversation( inputArgs: $inputArgs zaiConfigId: $agentId ) }
{ "agentId": "zai_01HZXEXAMPLE", "inputArgs": { "dpmfu92py": "请总结这篇文章", "k3n8vq1ax_id": 1020000000000097, "b7wme40sd_id": [1020000000000098, 1020000000000099] } }

使用返回的 conversationId 监听结果:

subscription ListenAgentResult($conversationId: Long!) { fz_zai_listen_conversation_result(conversationId: $conversationId) { conversationId status data reasoningContent images { id url } } }

会话状态包括 CREATED、IN_PROGRESS、THINKING_CHAIN_STREAMING、STREAMING、COMPLETED、FAILED 和 CANCELED。流式文本可能多次返回;应以最终状态判断本次响应是否结束。

如果客户端无法建立 WebSocket 连接(例如服务端脚本、命令行工具或定时任务),改用 fz_zai_conversation_result 轮询同一个 conversationId:

query AgentConversationResult($conversationId: Long!) { fz_zai_conversation_result(conversationId: $conversationId) { conversationId status data reasoningContent images { id url } } }

该查询返回的字段与 subscription 相同,但只返回当前快照,不返回流式增量:轮询期间的中间 token 不会补发。请轮询到状态变为 COMPLETED、FAILED 或 CANCELED 为止,并控制轮询频率。访问权限与 subscription 一致,调用方需要有权访问该会话。

继续多轮会话时,使用固定的消息参数,而不是创建会话时的自定义参数名:

mutation SendAgentMessage( $conversationId: Long! $text: String $imageIds: [Long] $fileId: Long $videoId: Long ) { fz_zai_send_ai_message( conversationId: $conversationId text: $text imageIds: $imageIds fileId: $fileId videoId: $videoId ) }

发送消息、停止响应和删除会话都要求当前身份有权访问该会话。操作后继续监听同一个 conversationId。

第三方 API

在 API 中配置并发布的接口会生成 fz_api_{api_unique_id} 字段。实际字段名、Operation 类型、入参类型和响应字段取决于当前 API 配置,请直接从 GraphiQL 复制。

mutation CallCreateOrderApi($input: fz_api_create_order_input!) { fz_api_create_order(input: $input) { responseCode responseStatus responseContentType fz_api_create_order_response { order_id status } } }
{ "input": { "order_id": 10001, "amount": 99 } }

先检查 responseCode 和 responseStatus,再读取配置生成的结构化响应字段。

旧版第三方 API 可能仍以 operation_{operationId} 暴露,并将请求体生成为 fz_body 参数。旧项目应以 GraphiQL 中仍存在的字段为准;新集成使用当前 API 功能。

媒体资源

上传资源

通过 Runtime API 上传图片、视频和文件分为三步:

  1. 计算文件内容的 MD5(原始 16 字节摘要),并转换为标准 Base64 字符串。不要使用 URL-safe 变体,否则服务端无法解码。
  2. 调用 V2 预签名字段,获取 uploadUrl、uploadHeaders、contentType 和资源 id。
  3. 使用返回的 URL 和全部请求头上传原始文件,再把资源 id 写入数据或传给行为流、AI 智能体。
资源单个资源字段批量字段返回的资源 id
图片imagePresignedUrlV2presignedImageListV2imageId
视频videoPresignedUrlV2presignedVideoListV2videoId
文件filePresignedUrlV2—fileId

以上均为 Query 字段。不带 V2 的旧版字段(imagePresignedUrl、presignedImageList 等)是 Mutation 且已废弃,新接入请使用 V2 字段。

以下为图片示例;imageSuffix、acl 等枚举值以 GraphiQL 为准:

query PrepareImageUpload($md5: String!, $format: MediaFormat!) { imagePresignedUrlV2(imgMd5Base64: $md5, imageSuffix: $format) { imageId uploadUrl uploadHeaders downloadUrl contentType } }

上传文件时,向 uploadUrl 发起上传请求,使用 uploadHeaders 中返回的全部请求头,并将原始文件作为请求体。不要自行省略或改写签名请求头。

富文本中的图片

富文本(HTML)内容不会保存图片地址,而是保存图片占位符。数据库中实际存储的形式如下:

<p><img src="fz_image_1020000000002458"></p>

fz_image_ 后面有两种形式,都指向同一张图片资源:

形式示例说明
资源 idfz_image_1020000000002458图片 id,与上传接口返回的 imageId 一致。
exIdfz_image_0rvO5qMzVND图片 id 的编码形式,固定 11 位字符。

之所以存标识而不是地址,是因为图片地址是带有效期的签名地址:写进正文的地址过一段时间就会全部失效。

Zion 应用中的富文本、富文本编辑器和 Markdown 组件会在渲染前自动把占位符换成当时有效的地址,无需额外处理。数据表格和 Runtime API 读到的是原始占位符,这是正常的。

在自定义前端或服务端直接读取富文本字段时,需要自行替换:

  1. 用正则 fz_image_([0-9]+|[A-Za-z0-9]{11}) 取出正文中的全部图片标识并去重。
  2. 调用 getImageListByIds(图片id)或 getImageListByExIds(图片exId)批量换取地址。
  3. 把 <img> 的 src 替换为返回的 url,再渲染正文。
query ResolveRichTextImages($imageIds: _int8) { getImageListByIds(imageIds: $imageIds) { id exId url urlInfo { urlExpireAt } } }
{ "imageIds": [1020000000002458, 1020000000002459] }
⚠️

返回的 url 有有效期,urlInfo.urlExpireAt 是过期时间。请按过期时间缓存,不要把替换后的地址写回数据库字段,否则正文中的图片会在地址过期后集体失效。

写入富文本时同理:先按上一节的流程上传图片,再把 src 写成 fz_image_{imageId}。直接写入外部图片地址不会被转换,正文会一直依赖该外部地址的可用性。

需要缩略图时,可以改用 getResizedImageListByIds 传入缩放参数换取处理后的地址。

常见问题

问题检查方法
permission denied检查是否传入正确身份,以及该身份是否拥有数据、行为流、AI 智能体或 API 权限。
Cannot query field刷新 GraphiQL Schema,确认变更已经同步或发布,并使用实际生成的字段名。
Variable 类型不匹配在 GraphiQL 中查看参数的非空标记、列表结构和标量类型。不要根据其他项目猜测类型。
HTTP 状态正常但 data 为空同时检查响应中的 errors;第三方 API 还应检查 responseCode。
Subscription 没有结果确认使用订阅地址、graphql-ws 协议和 connection_init.payload.authToken。
异步行为流没有完成使用 fz_action_flow_result 查询状态,并结合行为流运行日志排查节点错误或超时。
AI 智能体会话无法继续检查会话状态、当前身份是否拥有该会话,以及是否仍有上一条消息正在生成。
上传后无法使用资源确认上传请求包含全部 uploadHeaders,并使用预签名响应返回的资源 id。
富文本正文里的图片不显示确认已把 fz_image_ 占位符替换为 getImageListByIds 返回的 url,并检查地址是否已过期。
找不到第三方 API 字段确认 API 已发布,并在 GraphiQL 中搜索其 API 唯一标识。

更多 GraphQL 语法请参考 GraphQL 官方文档 。

Last updated on