跳转到主要内容
BeeOS OpenAPI 让你通过同一份契约以三种模式调用任何你拥有的智能体 (或任何公开可见的智能体)。三种模式共用同样的认证(JWT 或 oag_ 用户 API Key —— 获取方式参见 认证与 API Key)、同样的智能体标识(agentId)、 以及同样的任务生命周期语义 —— 只是 wire 格式不同。
模式端点何时用
阻塞调用POST /api/v1/agents/{agentId}/invoke短 prompt、期望几秒内返回;你想要单条 JSON 响应。
流式调用 (SSE)POST /api/v1/agents/{agentId}/invokeAccept: text/event-stream长 prompt,你想要 token 级渲染。
异步任务POST /api/v1/agents/{agentId}/tasks + 轮询 / SSE /events发后即走,智能体可能跑几分钟到几小时;你需要 task_id 用于取消 / 续传 / 审计。
按你的 UX 需求选择。底层三者都汇集到同一个 chatinvoke 核心 (参见 ADR 0017), 所以三种模式的 result 形状、状态语义和 SSE wire 格式是一致的。

1. 阻塞调用

最简单的模式。智能体跑完后(或网关超时,默认 120s)返回单条 JSON。

请求

POST /api/v1/agents/agent_abc123/invoke
Authorization: Bearer oag_...
Content-Type: application/json

{
  "message": "总结最近的 BeeOS 发布说明。",
  "context_id": "ch-optional-conversation-pin"
}

响应(200)

{
  "success": true,
  "data": {
    "text": "BeeOS 1.0.x 发布了统一任务核心 …",
    "context_id": "ch-resolved-channel-id",
    "is_error": false
  }
}

TypeScript SDK

import { Configuration, AgentsApi } from "@beeos-ai/sdk";

const cfg = new Configuration({
  basePath: "https://openapi.beeos.ai",
  accessToken: process.env.BEEOS_API_KEY,
});
const agents = new AgentsApi(cfg);

const reply = await agents.invokeAgent({
  agentId: "agent_abc123",
  invokeAgentRequest: { message: "总结最近的 BeeOS 发布说明。" },
});
console.log(reply.data.text);

Go SDK

import beeos "github.com/beeos-ai/sdk-go"

cfg := beeos.NewConfiguration()
cfg.Servers = beeos.ServerConfigurations{{URL: "https://openapi.beeos.ai"}}
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("BEEOS_API_KEY"))
client := beeos.NewAPIClient(cfg)

req := beeos.InvokeAgentRequest{Message: "总结最近的 BeeOS 发布说明。"}
resp, _, err := client.AgentsAPI.InvokeAgent(ctx, "agent_abc123").InvokeAgentRequest(req).Execute()
fmt.Println(resp.Data.Text)

2. 流式调用 (SSE)

同一个端点,换一下 Accept header。响应体是一个 SSE 流:delta 事件(增量文本)+ 一个终止 done 事件。

请求

POST /api/v1/agents/agent_abc123/invoke
Authorization: Bearer oag_...
Accept: text/event-stream
Content-Type: application/json

{ "message": "写一篇关于智能体的 500 字短文。" }

响应(SSE)

流由三种 frame 形状之一组成,契约里建模为 InvokeEventStreamInvokeAgentSSEDelta / InvokeAgentSSEError / InvokeAgentSSEDoneoneOf)。与 /tasks/{id}/events 不同,invoke 端点的 SSE 帧 不命名 event —— 全部是裸 data: 行,客户端通过 JSON 的 type 字段做区分:
data: {"type":"delta","text":"智能体是"}

data: {"type":"delta","text":"自主的"}

data: {"type":"done","text":"智能体是自主的 …","context_id":"ch-...","is_error":false}
如果网关在智能体产出终止回复之前放弃了(超时、智能体拒绝、内部错误), 会在最终 done 之前发一个 error 帧:
data: {"type":"error","code":"service_timeout","status_code":504,"message":"agent invocation timed out"}

data: {"type":"done","text":"","context_id":"ch-...","is_error":true,"error":"agent invocation timed out","code":"service_timeout"}
timeout_ms服务端钳制在 115s 上限的(见 OpenAPI spec 的 InvokeAgentRequest.timeout_ms.maximum)。超出该值的钳制是静默的 —— 如果智能体没在有效窗口内回复,网关仍会发 service_timeout。 对于可能超过 ~2 分钟的工作,请切到异步任务 API, 它立即返回,让你通过 SSE 观察进度。

SSE frame 字段

Frame字段类型说明
deltatype"delta"frame 标识符
deltatextstring增量 token 块;按序拼接
errortype"error"frame 标识符
errorcodestring稳定机器码(见错误码参考
errorstatus_codeinteger等价的 HTTP 状态码(如果是阻塞调用的话)
errormessagestring人类可读说明
donetype"done"frame 标识符;始终是终止 frame
donetextstring完整拼接后的回复(与阻塞响应一致)
donecontext_idstringMS 通道 id;可复用以延续会话
doneis_errorbooleanrun 以错误结束则为 true;此时 error / code 字段填充
doneerrorstringis_error=true 时的人类可读错误消息
donecodestring稳定错误码(流式错误镜像 error.code;从未发流的同步 apierror 也会映射到这里)

错误码参考

同样的码会出现在 error.code / done.code 以及阻塞 JSON 错误信封里。 用它们作为 switch 键 —— status_code / message 是展示,不是契约。 完整表格在 错误参考,是 HTTP 状态 × wire code × SSE frame 的单一真相源。调用路径上你最常 处理的几个:
  • agent_not_found (404) —— 检查所有权 / 可见性
  • agent_service_unavailable / agent_offline (503) —— 短暂重试
  • conflict (409) —— 智能体忙 / 拒绝 / 重复 idempotency key(看 message 区分)
  • service_timeout (504) —— 切到异步 tasks
  • forbidden (403) —— 用一个拥有该智能体的凭证
  • rate_limited (429) —— 尊重 Retry-After

TypeScript(raw fetch)

生成的 SDK 的阻塞 invokeAgent 不能流式 —— SSE 直接用 fetch
const res = await fetch("https://openapi.beeos.ai/api/v1/agents/agent_abc123/invoke", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.BEEOS_API_KEY}`,
    Accept: "text/event-stream",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ message: "写一篇关于智能体的 500 字短文。" }),
});

const reader = res.body!.getReader();
const decoder = new TextDecoder();
let buffer = "";
while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });
  for (const event of buffer.split("\n\n")) {
    // 解析裸 "data: {...}" 帧(invoke 不带 event: 前缀),通过 JSON `type`
    // 字段分发;把 delta 渲染到 UI
  }
}

3. 异步任务(推荐用于长任务)

标准任务核心。Submit 立即返回 202 + task_id。用 GET /tasks/{taskId} 轮询,或订阅 GET /tasks/{taskId}/events(SSE) 获取实时更新。生命周期支持 cancel 和 continue。

3a. 提交

POST /api/v1/agents/agent_abc123/tasks
Authorization: Bearer oag_...
Content-Type: application/json

{
  "message": "索引盘里每一个 PDF 并产出一张知识图。",
  "deadline_ms": 1800000,
  "idempotency_key": "indexer-2026-05-14"
}
{
  "success": true,
  "data": {
    "task_id": "ch-uuid",
    "agent_id": "agent_abc123",
    "status": "queued",
    "created_at": "2026-05-14T18:00:00Z"
  }
}

3b. 轮询状态

GET /api/v1/agents/agent_abc123/tasks/ch-uuid
{
  "success": true,
  "data": {
    "task_id": "ch-uuid",
    "agent_id": "agent_abc123",
    "status": "running",
    "started_at": "2026-05-14T18:00:02Z"
  }
}
当任务到达终止态时,status 翻为 succeeded / failed / canceled / timeout / rejected 之一,result(成功)或 error(失败)字段被填充。终止态是状态机的叶节点 —— 轮询可短路。

3c. 实时 SSE 事件流

GET /api/v1/agents/agent_abc123/tasks/ch-uuid/events
Accept: text/event-stream
event: message
data: {"type":"agent_message_chunk","offset":3,"payload":{"text":"正在扫描第 12 页 …"}}

event: message
data: {"type":"agent_reply","offset":8,"payload":{"text":"完成。共索引 312 页。","is_error":false}}

event: end
data: {"reason":"task_terminal"}
终止 event: end 总是发生一次。它的 reason 字段是以下之一:
reason含义
task_terminal任务到达了终止 TaskStatussucceeded / failed / canceled / timeout / rejected)。前一个 event: message 是终止回复。
channel_closed底层 Message Service 通道被外部关闭(如被管理员或 reaper 关闭)。按终止态处理。
stream_closed客户端关闭,或网关因 idle 超时丢弃流。重新订阅以续传。
每个 event: message frame 里 type 取值的完整列表见 TaskEventStream schema

3d. 取消

POST /api/v1/agents/agent_abc123/tasks/ch-uuid/cancel
Content-Type: application/json

{ "reason": "user_aborted" }
Cancel 是幂等的 —— 对已经终止的任务调用是空操作,返回当前快照。

3e. 续传(resume input_required / auth_required)

某些智能体在任务中间暂停以请求额外输入或一次 OAuth 风格的授权。 状态会翻为 input_required(或 auth_required)。用以下方式续传:
POST /api/v1/agents/agent_abc123/tasks/ch-uuid/continue
Content-Type: application/json

{ "input": { "approval": "yes" } }
对于 auth_required 暂停,设 "auth_grant": true 以发送 user.auth_grant 信封。

TypeScript SDK

import { TasksApi } from "@beeos-ai/sdk";
const tasks = new TasksApi(cfg);

const created = await tasks.createTask({
  agentId: "agent_abc123",
  createTaskRequest: { message: "长索引任务", deadlineMs: 1800000 },
});

// Poll
let state = await tasks.getTask({ agentId: "agent_abc123", taskId: created.data!.taskId! });
while (!["succeeded", "failed", "canceled", "timeout", "rejected"].includes(state.data!.status!)) {
  await new Promise(r => setTimeout(r, 2000));
  state = await tasks.getTask({ agentId: "agent_abc123", taskId: created.data!.taskId! });
}

3f. 列出你的任务

翻页查看你提交到某个智能体的任务。该列表由 Message Service 通道 元数据支撑,所以和 §3b 拿到的 GetTask 快照是一致的。
GET /api/v1/agents/agent_abc123/tasks?state=active&limit=50
Authorization: Bearer oag_...
{
  "success": true,
  "data": {
    "tasks": [
      {
        "task_id": "ch-uuid-1",
        "agent_id": "agent_abc123",
        "caller_owner_id": "user_xyz",
        "state": "active",
        "metadata": { "protocol": "openapi" },
        "created_at": "2026-05-14T18:00:00Z",
        "deadline_at": "2026-05-14T18:30:00Z"
      }
    ],
    "next_since": "2026-05-14T17:00:00Z"
  }
}
Query 参数:
名称类型默认说明
stateactive | closed | allactive按通道生命周期过滤。active 匹配开放任务;closed 匹配终止任务。
sinceRFC3339 时间戳不设仅返回该时刻及之后创建的任务。和 next_since cursor 配合做前向分页。
limitinteger50(最大 200)每页最大行数。
该端点仅返回通道元数据 protocolopenapi 的任务 —— 会话通道在 GET /api/v1/agents/{agentId}/conversations

跨智能体变体 —— GET /api/v1/tasks

如果你已经向多个智能体提交了任务,想要一份统一的”我的任务”视图 (多智能体 UI 常见),改用跨智能体端点:
GET /api/v1/tasks?state=active&limit=50
Authorization: Bearer oag_...
wire 形状与单智能体变体一致 —— 同样的 tasks[] 行、同样的 next_since cursor —— SDK 可以共享 decode + 分页代码。可选 agent_id query 参数把范围收回到单个智能体,无需切换端点路径。 当你预先不知道调用方提交到哪些智能体时,用这个。

3g. 回放任务消息

取一个任务的完整消息日志。常用于在 SSE 事件流已经关闭后,展示 智能体的中间步骤。
GET /api/v1/agents/agent_abc123/tasks/ch-uuid/messages?since=0&limit=200
Authorization: Bearer oag_...
{
  "success": true,
  "data": {
    "messages": [
      { "offset": 1, "type": "chat_message",        "payload": {"text": "索引每个 PDF …"} },
      { "offset": 2, "type": "agent_reply_delta",   "payload": {"text": "正在扫描第 1 页 …"} },
      { "offset": 3, "type": "agent_reply_delta",   "payload": {"text": " 第 1 页完成。"} },
      { "offset": 4, "type": "agent_reply",         "payload": {"text": "所有页索引完成。", "is_error": false} }
    ],
    "latest_offset": 4
  }
}
Query 参数:
名称类型默认说明
sinceinteger (offset)0仅返回 offset > since 的消息。前向翻页传上一页最后一条的 offset 即可;当响应里的 latest_offset 与该值相等就说明追上了。
limitinteger200(最大 500)每页最大行数。

TypeScript SDK(列表助手)

import { TasksApi } from "@beeos-ai/sdk";
const tasks = new TasksApi(cfg);

// List active tasks for an agent
const active = await tasks.listAgentTasks({
  agentId: "agent_abc123",
  state: "active",
  limit: 50,
});
for (const t of active.data.tasks ?? []) {
  console.log(t.taskId, t.state, t.createdAt);
}

// Replay one task's history
const log = await tasks.listTaskMessages({
  agentId: "agent_abc123",
  taskId: "ch-uuid",
  limit: 200,
});
for (const m of log.data.messages ?? []) {
  console.log(m.offset, m.type, m.payload);
}

对比小结

invoke(阻塞)invoke(SSE)tasks(异步)
HTTP 形状单 JSONSSE 流202 + 轮询 / SSE
Cancel无(调用方断连)无(调用方断连)有(显式)
Continue有(input_required / auth_required)
服务端超时默认 120s默认 120sdeadline_ms(最大 7 天)
状态可见性仅终态流式 + 终态per-poll + per-event
跟踪用 task_id无(用 context_id无(用 context_id
幂等有(idempotency_key
最适合快速查询、RAG聊天 UX长任务、批处理、无头

状态参考(ADR-0017)

status终止态含义
queued已提交,未被拾起
running智能体正在产出
input_required暂停,等 user.continue
auth_required暂停,等 user.auth_grant
succeeded终止成功;result 填充
failed终止错误;error 填充
canceled调用方取消
timeoutdeadline 在到达终态前消耗完
rejected智能体拒绝(如单回合设备上 agent_busy
状态转换文档见 TaskStatus schema 组件。

另请参阅