API 调用指导
VeyraOS 为每个智能体实例提供两个对外接口:
- OpenAI 兼容接口(本页主体):
/v1/chat/completions等,用标准 OpenAI SDK 即可直接调用, 流式与非流式都兼容。 - 完整能力接口(VES):
/v1/runs系列,返回平台统一事件流 VES,除正文外还带工具调用、 思考过程与任务取消。门户界面走这个接口,同样对外开放——需要完整过程或中途取消时用它 (见下文「完整能力接口」)。
两个接口用同一把 API Key。你可以在智能体工作台「渠道」页签的 HTTP API 卡片(或实例详情页 「API Key」页签)创建 sk- 风格 API Key。
准备工作
- 已部署一个智能体实例(状态为
RUNNING) - 在智能体工作台「渠道」页签的 HTTP API 卡片单击生成(或实例详情页「API Key」页签)创建一个 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。生产环境通常已配置域名与 HTTPS, 此时把http://<服务器IP>:30080整体替换为https://<平台域名>即可,路径不变。用
sk-API Key 调用时,请求路由到的智能体由 Key 本身决定,无需额外请求头。 若改用平台 JWT(Authorization: Bearer <JWT>)调用/v1/*,需同时带X-Agent-ID(智能体 ID)与X-Engine-Type(智能体引擎标识,见智能体详情); 缺少引擎标识或取值不支持时返回400。
curl 示例
curl -X POST http://<服务器IP>:30080/v1/chat/completions \
-H "Authorization: Bearer sk-xxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "hermes-default",
"messages": [
{"role": "user", "content": "你好,介绍一下自己"}
],
"stream": false
}'响应(非流式):
{
"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 兼容工具直接兼容。
curl -N -X POST http://<服务器IP>: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 示例(非流式)
from openai import OpenAI
client = OpenAI(
base_url="http://<服务器IP>: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 示例(非流式)
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "http://<服务器IP>: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 示例(流式)
from openai import OpenAI
client = OpenAI(
base_url="http://<服务器IP>: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 一定在最后。除正文外,这里还有工具调用、思考过程、用量与任务取消。
curl -N -X POST http://<服务器IP>: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}],role 取 user / 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 | 处理步骤的进度(如工作流型智能体的节点执行;status 为 waiting 表示该步骤在等待人工处理) |
interaction.requested / interaction.resolved | 需要用户确认的交互(如命令审批) |
usage.updated | 用量统计 |
platform.* | 平台保留命名空间(如长时间无输出时的心跳提示) |
客户端解析时忽略未知
type。type以x.开头的是引擎扩展帧,同样可安全忽略。
任务状态与取消
| 操作 | 请求 | 说明 |
|---|---|---|
| 查状态 | GET /v1/runs/{run_id} | 返回 {"run_id":"...","status":"running"},status 取 running / 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 帧解析)
import json
import requests
resp = requests.post(
"http://<服务器IP>: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 字段 | 备注 |
|---|---|---|
| Hermes | hermes-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:
# 创建会话
curl -X POST http://<服务器IP>:30080/v1/sessions \
-H "Authorization: Bearer sk-xxx" \
-H "Content-Type: application/json" \
-d '{"title": "我的会话"}'
# 列出会话
curl http://<服务器IP>:30080/v1/sessions \
-H "Authorization: Bearer sk-xxx"
# 列出会话消息
curl http://<服务器IP>:30080/v1/sessions/<session_id>/messages \
-H "Authorization: Bearer sk-xxx"文件管理
# 列出文件
curl http://<服务器IP>:30080/v1/files \
-H "Authorization: Bearer sk-xxx"管理 API:定时任务
定时任务让实例按周期自动执行指令(如每天早会前汇总昨日工单)。接口走管理 API(JWT 鉴权),路径为 /api/manager/agent-instances/{instance_id}/cron-jobs;外接 Dify 实例不支持定时任务。
# 创建任务(成功返回 201)
curl -X POST http://<服务器IP>:30080/api/manager/agent-instances/<instance_id>/cron-jobs \
-H "Authorization: Bearer <JWT>" -H "Content-Type: application/json" \
-d '{
"name": "每日晨会汇总",
"schedule": "0 9 * * *",
"timezone": "Asia/Shanghai",
"prompt": "汇总昨日工单并给出今日重点",
"timeout_seconds": 1800,
"enabled": true,
"notify_config": {
"on_success": true,
"on_failure": true,
"targets": {"type": "users", "user_ids": ["<终端用户ID>"]},
"alert_channel_ids": []
}
}'
# 任务列表(默认不含已归档;加 ?include_archived=true 一并列出)
curl "http://<服务器IP>:30080/api/manager/agent-instances/<instance_id>/cron-jobs" \
-H "Authorization: Bearer <JWT>"
# 查看单个任务 / 部分更新(PATCH 只传要改的字段)
curl "http://<服务器IP>:30080/api/manager/agent-instances/<instance_id>/cron-jobs/<job_id>" \
-H "Authorization: Bearer <JWT>"
curl -X PATCH "http://<服务器IP>:30080/api/manager/agent-instances/<instance_id>/cron-jobs/<job_id>" \
-H "Authorization: Bearer <JWT>" -H "Content-Type: application/json" \
-d '{"prompt": "新的执行内容"}'
# 启用 / 停用
curl -X POST "http://<服务器IP>:30080/api/manager/agent-instances/<instance_id>/cron-jobs/<job_id>/toggle" \
-H "Authorization: Bearer <JWT>" -H "Content-Type: application/json" \
-d '{"enabled": false}'
# 立即触发一次执行(受理返回 202,异步执行;结果在执行记录中查看)
curl -X POST "http://<服务器IP>:30080/api/manager/agent-instances/<instance_id>/cron-jobs/<job_id>/run" \
-H "Authorization: Bearer <JWT>"
# 执行记录(分页)与单条详情
curl "http://<服务器IP>:30080/api/manager/agent-instances/<instance_id>/cron-jobs/<job_id>/runs?limit=20&offset=0" \
-H "Authorization: Bearer <JWT>"
curl "http://<服务器IP>:30080/api/manager/agent-instances/<instance_id>/cron-jobs/<job_id>/runs/<run_id>" \
-H "Authorization: Bearer <JWT>"
# 归档任务(归档后不再触发,历史执行记录保留可查)
curl -X POST "http://<服务器IP>:30080/api/manager/agent-instances/<instance_id>/cron-jobs/<job_id>/archive" \
-H "Authorization: Bearer <JWT>"字段与行为说明:
schedule为 5 段 cron 表达式;timezone缺省Asia/Shanghai;timeout_seconds取值 60–14400(默认 1800,即 30 分钟)。notify_config.targets.type取users(推送指定终端用户)或group(全组广播,需组管理员权限);alert_channel_ids可同时推送到告警渠道的群机器人。- 任务有正在执行中的运行时,修改
schedule会被拒绝(400);响应中的has_running_run标记当前是否有执行中的运行。 - 执行记录的
status取RUNNING/SUCCESS/FAILED/SKIPPED(SKIPPED时skip_reason给出原因,如上一次执行尚未结束、实例未运行);trigger_type取SCHEDULED/MANUAL。 - 每次触发创建独立的执行会话,不混入日常对话上下文;实例处于暂停状态时会自动唤醒后执行。
外部应用接入
本节与上文「Dify 外接应用绑定」是两套不同机制:本节讲的是把平台能力开放给第三方应用(
external_app_id+ 外部用户 ID 绑定);Dify 外接是平台对接你自管的 Dify 实例,二者互不影响。
第三方应用可使用绑定外部应用的 API Key 接入,让每位终端用户拥有独立的会话与上下文:
- 管理员创建外部应用:
POST /api/manager/external-apps(管理 API,JWT 鉴权)。 - 为智能体实例创建 API Key 时指定该外部应用(请求体带
external_app_id)。 - 为平台终端用户建立与外部用户 ID 的绑定:
POST /api/manager/end-users/{终端用户ID}/external-user-bindings(同一外部应用下,一个外部用户 ID 对应一位终端用户)。 - 应用服务端每次请求携带
X-External-User-Id头:
curl -X POST http://<服务器IP>: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 等客户端——否则任一终端用户篡改该头即可冒充其他用户,访问其会话与数据。客户端请一律经由你自己的服务端中转调用。
管理 API:创建终端用户
管理员可通过管理 API 创建终端用户。接口使用管理台 JWT 鉴权,成功返回 201:
curl -X POST http://<manager-host>/api/manager/end-users \
-H "Authorization: Bearer <admin-jwt>" \
-H "Content-Type: application/json" \
-d '{
"username": "enduser-demo",
"password": "<strong-password>",
"real_name": "演示终端用户",
"email": "enduser-demo@example.com",
"group_ids": ["<user-group-id>"]
}'username 必须唯一,password 至少 8 位且需达到强度要求;real_name、email、phone 可选。平台员工与租户管理员可以不传 group_ids,部门管理员必须至少选择一个本人管理的部门。邮箱和手机号创建时为未认证状态,需用户本人完成认证后才能用于对应方式登录。
常见错误
| HTTP | 原因 | 处理 |
|---|---|---|
| 401 | API Key 无效 / 已删除 / 外部用户 ID 未绑定 | 重新创建 Key;注意删除后最长 60s 内可能仍生效;外部接入先完成用户绑定 |
| 400 | 请求体格式错误 | 检查 messages 字段是否合法 |
| 503 | 引擎 Pod 未就绪 | 在实例详情页确认状态为 RUNNING |
| 502 | 网关无法连接引擎 | 检查实例是否已部署、Pod 是否健康 |
安全建议
- 不要把 API Key 提交到代码仓库,使用环境变量或密钥管理服务
- 每个场景独立 Key:生产/测试/开发各用不同 Key,方便撤销与追踪
- 定期轮换:删除旧 Key 创建新 Key,60s 内切换
- 设置用量告警:在监控中心配置异常告警,发现异常调用及时处理
管理 API:级联删除智能体
删除智能体定义走 Manager 管理 API(JWT 鉴权,非 sk- Key):
# 预览删除影响:列出定义下全部实例
curl http://<服务器IP>:30080/api/manager/agent-definitions/<definition_id>/instances \
-H "Authorization: Bearer <JWT>"
# 级联删除:定义与其全部实例一并删除,实例数据(含归档)不可恢复
curl -X DELETE "http://<服务器IP>:30080/api/manager/agent-definitions/<definition_id>?cascade=true" \
-H "Authorization: Bearer <JWT>"
# 强制级联删除:实例无法归档时跳过归档直接清理(数据不可恢复,仅级联删除支持)
curl -X DELETE "http://<服务器IP>:30080/api/manager/agent-definitions/<definition_id>?cascade=true&force=true" \
-H "Authorization: Bearer <JWT>"- 不传
cascade(默认false)时,若仍有实例引用该定义则返回409,删除被拒绝。 cascade=true时逐实例删除;部分实例失败返回409,detail中含失败清单,已删成功的实例不回滚,重试即可续删。- 实例无法归档(例如从未暂停过、没有可用备份)时,销毁会被拒绝并返回
409;确认可丢数据后带force=true重试即可跳过归档强删。 force=true必须与cascade=true同时使用,单独传force返回400。- 全部成功返回
204。
管理 API:技能版本与绑定
技能工作室的「发布 / 绑定 / 上架」链路走 Manager 管理 API(JWT 鉴权)。发布接口同时供 skill-engine 内部调用(X-Internal-Token),普通用户不需要直接调用。
# 按 skill-engine 工作区查询技能与已发布版本(含绑定数、上架状态)
curl http://<服务器IP>:30080/api/manager/skills/by-workspace/<workspace_id> \
-H "Authorization: Bearer <JWT>"
# 把技能版本直接绑定到智能体定义(写入定义的 skill_config)
curl -X POST http://<服务器IP>:30080/api/manager/agent-definitions/<definition_id>/skills/install-from-skill \
-H "Authorization: Bearer <JWT>" -H "Content-Type: application/json" \
-d '{"skill_version_id": "<skill_version_id>"}'
# 把技能版本提交到资产中心审核(已有 Hub 版本时只重新提交,不重复导入)
curl -X POST http://<服务器IP>:30080/api/manager/skills/<skill_id>/versions/<version_id>/submit-to-hub \
-H "Authorization: Bearer <JWT>" -H "Content-Type: application/json" \
-d '{"industry": "制造", "scenario": "报表", "reason": "共享给其他团队"}'install-from-skill响应里的sync字段给出下发结果:total(目标实例数)、failed(失败数)、failed_instances(失败实例 id);failed > 0时提示「部分实例未更新」,失败项会由后台对账自动补齐。submit-to-hub只提交到「待审核」,批准与发布仍由平台员工在资产中心完成;同一版本已上架或审核中时返回409。- 技能版本包存放在对象存储的
skill-packages/<skill_id>/<version_id>.zip;发布失败或记录回滚时自动清理,遗留对象由后台补偿任务回收。 - 资产中心侧删除未上架版本(运维/清理用,需
version:delete权限):
curl -X DELETE http://<服务器IP>:30080/api/hub/versions/<version_id> \
-H "Authorization: Bearer <JWT>"管理 API:查看实例部署产物
每次部署都会记录一份该实例的最终引擎消费配置(环境变量全集 + 模型/技能/MCP 清单 + 知识库绑定),可用于审计「这次部署到底给引擎喂了什么」:
curl http://<服务器IP>:30080/api/manager/agent-instances/<instance_id>/prepared-config \
-H "Authorization: Bearer <JWT>"- 实例尚未部署过时返回
404。 - 响应中的敏感环境变量值已掩码(仅末 4 位可见,如
***1234)。 - 重新部署时若配置无变化会自动跳过引擎重启。
管理 API:引擎版本升级
发版后存量引擎实例不会自动升级,用滚动发布 API 分批升级(平台员工 JWT):
# 预览影响范围(不落库、不执行)
curl -X POST http://<服务器IP>:30080/api/manager/engine-rollout \
-H "Authorization: Bearer <JWT>" -H "Content-Type: application/json" \
-d '{"engine_type": "HERMES", "dry_run": true}'
# 正式发起:可按资源池(resource_pool_id)或单实例(agent_id)灰度,
# batch_size 控制每批并发数
curl -X POST http://<服务器IP>:30080/api/manager/engine-rollout \
-H "Authorization: Bearer <JWT>" -H "Content-Type: application/json" \
-d '{"engine_type": "HERMES", "batch_size": 5}'
# 查询进度(含逐实例明细)与历史
curl http://<服务器IP>:30080/api/manager/engine-rollout/<rollout_id> \
-H "Authorization: Bearer <JWT>"
curl http://<服务器IP>:30080/api/manager/engine-rollout \
-H "Authorization: Bearer <JWT>"
# 回滚:把该任务涉及的实例滚回升级前版本(原任务须已结束)
curl -X POST http://<服务器IP>:30080/api/manager/engine-rollout/<rollout_id>/rollback \
-H "Authorization: Bearer <JWT>"target_image缺省取当前引擎版本配置;休眠中的实例只登记新版本,下次恢复运行时生效。- 回滚要求该任务所有实例升级前版本一致;不一致时返回
400,请用agent_id逐实例回滚。
管理 API 认证
管理 API(/api/manager/*)使用 JWT 鉴权,与智能体调用的 sk- API Key 相互独立。JWT 分两类,token 的 aud claim 标记所属账号体系,两类 token 不可跨体系使用:
- 管理台账号:
POST /api/manager/auth/login(另支持邮箱/手机号密码、短信验证码登录)→ tokenaud="admin" - 终端用户账号:
POST /api/manager/auth/enduser/login(另支持/api/manager/auth/enduser/login-by-contact、/api/manager/auth/enduser/login-by-sms-code)→ tokenaud="enduser"
管理 API 的完整端点清单见 API 参考(Swagger UI 自动生成),此处不重复罗列。
当前用户与权限
# 当前账号信息(含 roles / permissions / platform_scopes / is_platform_admin)
curl http://<服务器IP>:30080/api/manager/auth/me \
-H "Authorization: Bearer <JWT>"
# 当前工作空间下生效的权限码(需带空间头)
curl http://<服务器IP>:30080/api/manager/auth/permissions \
-H "Authorization: Bearer <JWT>" \
-H "X-Org-ID: <account_org_id>" \
-H "X-Workspace-Group-ID: <部门组 ID>"/me返回roles、permissions(登录时所在空间的权限码快照)、platform_scopes(平台员工 scope 列表)与is_platform_admin。/auth/permissions返回{permissions, platform_scopes, workspace_id};X-Org-ID指定企业空间,X-Workspace-Group-ID指定部门(缺省为整个企业空间)。- 权限码是后端鉴权的唯一依据;带
X-Org-ID/X-Workspace-Group-ID的接口一律按该空间解析权限。 GET /api/manager/workspaces返回default_id(登录后的默认空间):优先最深所属部门空间,其次企业组织空间,最后个人空间。部门空间 id 形如<account_org_id>:<group_id>,访问时同时带X-Org-ID: <account_org_id>与X-Workspace-Group-ID: <group_id>。- 操作被拒绝时返回 403,
detail为可读原因码(workspace_read_only当前空间只读、not_in_workspace资源不在当前空间、workspace_forbidden无权访问该空间、无权限缺少动作权限码),管理台按原因码提示用户。 /api/skill-engine/*由 manager 代理转发并注入身份头(X-Actor-ID、X-Groups、X-Space-Admin等);客户端自带的同名头会被丢弃,调用方无需自行构造。
角色绑定
租户 / 部门作用域的角色分配走 /api/manager/role-bindings(需带空间头):
# 列表:某作用域下的绑定明细
curl "http://<服务器IP>:30080/api/manager/role-bindings?scope_type=department&scope_id=<组ID>" \
-H "Authorization: Bearer <JWT>"
# 可分配成员名册(同一作用域内)
curl "http://<服务器IP>:30080/api/manager/role-bindings/candidates?scope_type=department&scope_id=<组ID>&search=<关键词>" \
-H "Authorization: Bearer <JWT>"
# 分配 / 撤销
curl -X POST http://<服务器IP>:30080/api/manager/role-bindings \
-H "Authorization: Bearer <JWT>" -H "Content-Type: application/json" \
-d '{"user_id": "<用户ID>", "role_id": "<角色ID>", "scope_type": "department", "scope_id": "<组ID>"}'
curl -X DELETE http://<服务器IP>:30080/api/manager/role-bindings/<绑定ID> \
-H "Authorization: Bearer <JWT>"scope_type取tenant(作用域为整个企业)或department(作用域为某部门及下级部门)。- 分配边界:租户管理员可分配本租户角色;部门管理员只能分配标记为「可委派」的角色,且范围限本部门及下级部门;由组织/部门归属自动派生的租户管理员、部门管理员无需分配。
GET /api/manager/role-bindings/me返回当前用户的显式绑定。
SaaS 运营操作(ops 门户)
客户 SaaS 运营操作(客户状态管理、对公到账确认、通知/支付通道配置等)已迁至 account 运营接口(/api/account/ops/*,门户 JWT 鉴权 + 平台员工 scope 门禁)。运营人员 使用 ops 门户操作;权限由平台员工绑定(platform_staff scopes)授予。
SaaS 账号登录
门户用户登录走 Account 认证 API(无需 Bearer 头;返回的 access_token / refresh_token 用于门户自助接口):
# 手机号 / 邮箱 + 密码登录
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_type为email(或平台开启手机能力后的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 自动生成)。