Skip to content

API 调用指导

VeyraOS 为每个智能体实例提供两个对外接口:

  • OpenAI 兼容接口(本页主体):/v1/chat/completions 等,用标准 OpenAI SDK 即可直接调用, 流式与非流式都兼容。
  • 完整能力接口(VES)/v1/runs 系列,返回平台统一事件流 VES,除正文外还带工具调用、 思考过程与任务取消。门户界面走这个接口,同样对外开放——需要完整过程或中途取消时用它 (见下文「完整能力接口」)。

两个接口用同一把 API Key。你可以在智能体工作台「版本」页签的 HTTP API 卡片(或实例详情页 「API Keys」页签)创建 sk- 风格 API Key。

准备工作

  1. 已部署一个智能体实例(状态为 RUNNING
  2. 在智能体工作台「版本」页签的 HTTP API 卡片单击生成(或实例详情页「API Keys」tab)创建一个 API Key,复制明文 key 妥善保存(创建后不再显示)

基础调用

Endpoint

POST http://<服务器IP>:30080/v1/chat/completions
Authorization: Bearer sk-xxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

<服务器IP>:30080 为 admin 门户地址,nginx 已反代 /v1/* 到 gateway。

sk- API Key 调用时,请求路由到的智能体由 Key 本身决定,无需额外请求头。 若改用平台 JWT(Authorization: Bearer <JWT>)调用 /v1/*,需同时带 X-Agent-ID(智能体 ID)与 X-Engine-Type(智能体引擎标识,见智能体详情); 缺少引擎标识或取值不支持时返回 400

curl 示例

bash
curl -X POST http://190.92.230.115:30080/v1/chat/completions \
  -H "Authorization: Bearer sk-xxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "hermes-default",
    "messages": [
      {"role": "user", "content": "你好,介绍一下自己"}
    ],
    "stream": false
  }'

响应(非流式):

json
{
  "id": "chatcmpl-xxx",
  "object": "chat.completion",
  "model": "hermes-default",
  "choices": [
    {
      "index": 0,
      "message": {"role": "assistant", "content": "你好!我是..."},
      "finish_reason": "stop"
    }
  ],
  "usage": {"prompt_tokens": 12, "completion_tokens": 30, "total_tokens": 42}
}

流式响应(OpenAI chunk)

"stream": true 时返回标准 OpenAI chunk 流(data: {"choices":[{"delta":{...}}]},以 data: [DONE] 收尾),与 OpenAI SDK 及各类 OpenAI 兼容工具直接兼容。

bash
curl -N -X POST http://190.92.230.115:30080/v1/chat/completions \
  -H "Authorization: Bearer sk-xxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "hermes-default",
    "messages": [{"role": "user", "content": "写一首短诗"}],
    "stream": true
  }'
data: {"id":"chatcmpl-xxx","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","content":"春"}}]}

data: {"id":"chatcmpl-xxx","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"眠"}}]}

data: {"id":"chatcmpl-xxx","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: {"id":"chatcmpl-xxx","object":"chat.completion.chunk","choices":[],"usage":{"prompt_tokens":12,"completion_tokens":30,"total_tokens":42}}

data: [DONE]

本接口只保证正文与用量的 OpenAI 兼容:工具调用过程、思考过程、任务取消等不在此接口输出, 需要时请用下方的「完整能力接口」。

Python 示例(非流式)

python
from openai import OpenAI

client = OpenAI(
    base_url="http://190.92.230.115:30080/v1",
    api_key="sk-xxxxxxxxxxxxxxxxxxxx",
)

resp = client.chat.completions.create(
    model="hermes-default",
    messages=[{"role": "user", "content": "你好"}],
    stream=False,
)
print(resp.choices[0].message.content)

Node.js SDK 示例(非流式)

javascript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "http://190.92.230.115:30080/v1",
  apiKey: "sk-xxxxxxxxxxxxxxxxxxxx",
});

const resp = await client.chat.completions.create({
  model: "hermes-default",
  messages: [{ role: "user", content: "你好" }],
});

console.log(resp.choices[0].message.content);

Python 示例(流式)

python
from openai import OpenAI

client = OpenAI(
    base_url="http://190.92.230.115:30080/v1",
    api_key="sk-xxxxxxxxxxxxxxxxxxxx",
)

stream = client.chat.completions.create(
    model="hermes-default",
    messages=[{"role": "user", "content": "写一首短诗"}],
    stream=True,
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

完整能力接口(VES)

POST /v1/runs 返回平台统一事件流 VES(Veyra Event Stream):每条 data: 行是一个 JSON 帧, 以帧内 type 字段区分,同一轮内 seq 递增,run.completed / run.failed / run.cancelled 一定在最后。除正文外,这里还有工具调用、思考过程、用量与任务取消。

bash
curl -N -X POST http://190.92.230.115:30080/v1/runs \
  -H "Authorization: Bearer sk-xxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "input": "写一首短诗",
    "session_id": "my-session-1",
    "model": "hermes-default"
  }'

请求体:

字段必填说明
input本轮用户输入
session_id会话标识;同一会话的多轮传相同值(首次可留空或自定义)
conversation_history历史轮 [{role, content}]roleuser / assistant
attachments附件列表(与 /v1/chat/completions 同格式)
model模型名(不传用实例默认)

响应(节选):

data: {"type":"run.started","run_id":"run_xxx","seq":1}

data: {"type":"message.started","run_id":"run_xxx","message_id":"...","seq":2}

data: {"type":"message.delta","run_id":"run_xxx","message_id":"...","delta":"春","seq":3}

data: {"type":"message.completed","run_id":"run_xxx","message_id":"...","seq":8}

data: {"type":"usage.updated","run_id":"run_xxx","usage":{"prompt_tokens":12,"completion_tokens":30},"seq":9}

data: {"type":"run.completed","run_id":"run_xxx","seq":10}

主要帧类型:

type含义
run.started / run.completed / run.failed / run.cancelled本轮对话的开始与终止(终止帧必为最后一帧)
message.started / message.delta / message.completed回复正文(delta 为增量文本)
reasoning.delta / reasoning.completed模型的思考过程(引擎支持时才有;Dify 型智能体也会输出)
tool.started / tool.progress / tool.completed / tool.failed工具调用生命周期(引擎支持时才有)
step.started / step.completed处理步骤的进度(如工作流型智能体的节点执行;statuswaiting 表示该步骤在等待人工处理)
interaction.requested / interaction.resolved需要用户确认的交互(如命令审批)
usage.updated用量统计
platform.*平台保留命名空间(如长时间无输出时的心跳提示)

客户端解析时忽略未知 typetypex. 开头的是引擎扩展帧,同样可安全忽略。

任务状态与取消

操作请求说明
查状态GET /v1/runs/{run_id}返回 {"run_id":"...","status":"running"}statusrunning / completed / failed / cancelled
取消任务POST /v1/runs/{run_id}/cancel受理返回 202;任务已结束时幂等返回 200 与原状态

取消会同时停止引擎侧执行,流内随即以 run.cancelled 收尾。客户端直接断开连接也视同取消。

事件续接(GET /v1/runs/{run_id}/events)与交互应答(POST /v1/runs/{run_id}/approval) 目前仅部分引擎支持;不支持时返回 404 与稳定的错误码(replay_not_supported / interaction_not_supported),不会静默失败。

Python 示例(按 VES 帧解析)

python
import json

import requests

resp = requests.post(
    "http://190.92.230.115:30080/v1/runs",
    headers={"Authorization": "Bearer sk-xxxxxxxxxxxxxxxxxxxx"},
    json={
        "input": "写一首短诗",
        "session_id": "my-session-1",
        "model": "hermes-default",
    },
    stream=True,
)
for line in resp.iter_lines():
    if not line or not line.startswith(b"data: "):
        continue
    frame = json.loads(line[len(b"data: "):])
    if frame["type"] == "message.delta":
        print(frame["delta"], end="", flush=True)
    elif frame["type"] in ("run.completed", "run.failed", "run.cancelled"):
        break

引擎差异

不同引擎类型的智能体,调用行为略有差异:

引擎model 字段备注
Hermeshermes-default 或自定义走 Profile 默认 Pod
Dify-Chat任意(仅占位)走 Dify chat-messages API
Dify-Workflow任意走 Dify workflows/run API
Dify-Agent任意Dify 平台限制,必须 stream: true
Dify 全部类型不生效实际使用的模型由 Dify 平台上的应用编排决定——可能经本平台网关调用,也可能由 Dify 直连模型服务(工作台绑定面板可查看该应用的模型通道)
DeepSeek模型组(如 deepseek-chat走 DeepSeek Harness 引擎,模型经统一模型网关
  • 两个接口(/v1/chat/completions/v1/runs)对各引擎都可用,引擎差异由平台消化。
  • 运行续接(GET /v1/runs/{id}/events)与交互应答(POST /v1/runs/{id}/approval)目前仅 Hermes 支持;其余引擎在这些端点上返回 404(运行状态查询与取消对全部引擎可用)。
  • API Key 决定路由:sk- Key 绑定单个智能体实例,model 字段不会切换实例。

会话管理

OpenAI 兼容 API 支持会话 CRUD:

bash
# 创建会话
curl -X POST http://190.92.230.115:30080/v1/sessions \
  -H "Authorization: Bearer sk-xxx" \
  -H "Content-Type: application/json" \
  -d '{"title": "我的会话"}'

# 列出会话
curl http://190.92.230.115:30080/v1/sessions \
  -H "Authorization: Bearer sk-xxx"

# 列出会话消息
curl http://190.92.230.115:30080/v1/sessions/<session_id>/messages \
  -H "Authorization: Bearer sk-xxx"

文件管理

bash
# 列出文件
curl http://190.92.230.115:30080/v1/files \
  -H "Authorization: Bearer sk-xxx"

外部应用接入

本节与上文「Dify 外接应用绑定」是两套不同机制:本节讲的是把平台能力开放给第三方应用(external_app_id + 外部用户 ID 绑定);Dify 外接是平台对接你自管的 Dify 实例,二者互不影响。

第三方应用可使用绑定外部应用的 API Key 接入,让每位终端用户拥有独立的会话与上下文:

  1. 管理员创建外部应用:POST /api/manager/external-apps(管理 API,JWT 鉴权)。
  2. 为智能体实例创建 API Key 时指定该外部应用(请求体带 external_app_id)。
  3. 为平台终端用户建立与外部用户 ID 的绑定:POST /api/manager/end-users/{终端用户ID}/external-user-bindings(同一外部应用下,一个外部用户 ID 对应一位终端用户)。
  4. 应用服务端每次请求携带 X-External-User-Id 头:
bash
curl -X POST http://190.92.230.115:30080/v1/chat/completions \
  -H "Authorization: Bearer sk-xxxxxxxxxxxxxxxxxxxx" \
  -H "X-External-User-Id: app-user-123" \
  -H "Content-Type: application/json" \
  -d '{ ... }'

说明:

  • 携带已绑定的外部用户 ID 时,请求自动路由到对应终端用户的独立上下文,不同终端用户互不混淆。
  • 未携带 X-External-User-Id 头时,与普通 API Key 行为一致(使用实例默认上下文)。
  • 携带了未绑定的外部用户 ID 会返回 401,请先完成第 3 步绑定。

API Key 必须只保留在应用服务端

X-External-User-Id 头本身不含签名,网关依据 API Key 信任该头。绑定外部应用的 API Key 只能由你的服务端持有并发起调用,不得下发到浏览器、App 等客户端——否则任一终端用户篡改该头即可冒充其他用户,访问其会话与数据。客户端请一律经由你自己的服务端中转调用。

常见错误

HTTP原因处理
401API Key 无效 / 已删除 / 外部用户 ID 未绑定重新创建 Key;注意删除后最长 60s 内可能仍生效;外部接入先完成用户绑定
400请求体格式错误检查 messages 字段是否合法
503引擎 Pod 未就绪在实例详情页确认状态为 RUNNING
502网关无法连接引擎检查实例是否已部署、Pod 是否健康

安全建议

  • 不要把 API Key 提交到代码仓库,使用环境变量或密钥管理服务
  • 每个场景独立 Key:生产/测试/开发各用不同 Key,方便撤销与追踪
  • 定期轮换:删除旧 Key 创建新 Key,60s 内切换
  • 设置用量告警:在监控中心配置异常告警,发现异常调用及时处理

管理 API:级联删除智能体

删除智能体定义走 Manager 管理 API(JWT 鉴权,非 sk- Key):

bash
# 预览删除影响:列出定义下全部实例
curl http://190.92.230.115:30080/api/manager/agent-definitions/<definition_id>/instances \
  -H "Authorization: Bearer <JWT>"

# 级联删除:定义与其全部实例一并删除,实例数据(含归档)不可恢复
curl -X DELETE "http://190.92.230.115:30080/api/manager/agent-definitions/<definition_id>?cascade=true" \
  -H "Authorization: Bearer <JWT>"
  • 不传 cascade(默认 false)时,若仍有实例引用该定义则返回 409,删除被拒绝。
  • cascade=true 时逐实例删除;部分实例失败返回 409detail 中含失败清单,已删成功的实例不回滚,重试即可续删。
  • 全部成功返回 204

管理 API:查看实例部署产物

每次部署都会记录一份该实例的最终引擎消费配置(环境变量全集 + 模型/技能/MCP 清单 + 知识库绑定),可用于审计「这次部署到底给引擎喂了什么」:

bash
curl http://190.92.230.115:30080/api/manager/agent-instances/<instance_id>/prepared-config \
  -H "Authorization: Bearer <JWT>"
  • 实例尚未部署过时返回 404
  • 响应中的敏感环境变量值已掩码(仅末 4 位可见,如 ***1234)。
  • 重新部署时若配置无变化会自动跳过引擎重启。

管理 API 认证

管理 API(/api/manager/*)使用 JWT 鉴权,与智能体调用的 sk- API Key 相互独立。JWT 分两类,token 的 aud claim 标记所属账号体系,两类 token 不可跨体系使用

  • 管理台账号POST /api/manager/auth/login(另支持邮箱/手机号密码、短信验证码登录与「一键演示」/api/manager/auth/demo-login)→ token aud="admin"
  • 终端用户账号POST /api/manager/auth/enduser/login(另支持 /api/manager/auth/enduser/login-by-contact/api/manager/auth/enduser/login-by-sms-code/api/manager/auth/enduser/demo-login)→ token aud="enduser"

管理 API 的完整端点清单见 API 参考(Swagger UI 自动生成),此处不重复罗列。

SaaS 运营操作(ops 门户)

客户 SaaS 运营操作(客户状态管理、对公到账确认、通知/支付通道配置等)已随 #480 迁至 account 运营接口(/api/account/ops/*,门户 JWT 鉴权 + 平台员工 scope 门禁)。运营人员 使用 ops 门户操作;权限由平台员工绑定(platform_staff scopes)授予。

SaaS 账号登录

门户用户登录走 Account 认证 API(无需 Bearer 头;返回的 access_token / refresh_token 用于门户自助接口):

bash
# 手机号 / 邮箱 + 密码登录
curl -X POST http://<account-host>/api/account/auth/login \
  -H "Content-Type: application/json" \
  -d '{"contact_type": "email", "contact": "user@example.com", "password": "<密码>"}'

# 账号名 + 密码登录(平台开启账号名登录后可用;账号名在「账号中心 → 账号安全」设置)
curl -X POST http://<account-host>/api/account/auth/login \
  -H "Content-Type: application/json" \
  -d '{"contact_type": "account", "contact": "alice", "password": "<密码>"}'
  • contact_type 取值:email / phone / account(账号名)。账号名规则:小写字母开头,可含数字、_-,长度 3–32 位。
  • 验证码登录(POST /api/account/auth/login-or-register):contact_typeemail(或平台开启手机能力后的 phone)+ code,仅登录已注册的联系方式;未注册返回 404 contact_not_registered(请改走注册接口)。注册统一走 POST /api/account/register(个人)/ POST /api/account/register/organization(企业)/ POST /api/account/register/invite(凭邀请码入组),username / password 均为必填。
  • 登录响应的 user 对象携带 username 字段(未设置账号名时为 null)。
  • 失败(密码错误 / 账号不存在 / 账号名登录未开启)统一返回 401 invalid_credentials;连续失败 2 次后要求图形验证码(400 captcha_required),连续失败 5 次锁定 15 分钟(423 account_locked)。
  • 设置账号名:登录后调用 POST /api/account/username/set(仅未设置时可用,请求体 {"username": "alice"};被占用返回 409 username_taken)。

API 参考文档

完整的 Manager 管理 API(智能体定义/实例管理/用户/角色等)请查看 API 参考(Swagger UI 自动生成)。

基于内网部署的企业级 AI 智能体平台