嵌入集成 API
面向第三方网站与 iframe 嵌入的 Agent 对话与工作流执行 API
嵌入集成 API(Embed API)专门用于将 Clouisle 的 Agent 对话组件和工作流执行集成到第三方网页、内部平台或无 Cookie 客户端中。基础路径为 /api/v1/embed。
认证与安全策略
所有嵌入端点均仅支持 API Key 认证(前缀为 clou_),不接受 Cookie 会话。认证凭据可通过以下两种方式传入:
- 请求头:
Authorization: Bearer clou_... - 查询参数:
?token=clou_...
解析顺序是先看 token 查询参数,再看 Authorization 头;两处都必须以 clou_ 开头,否则视同缺少凭据并返回 401(业务码 2000,embed_api_key_required)。
除鉴权外,目标还必须处于可嵌入状态:Agent 与工作流必须是 published,且 embed_config.enabled 为 true,否则分别返回 404(agent_not_found / workflow_not_found)与 403(embed_not_enabled)。
浏览器嵌入页面
除 REST 命名空间外,产品还提供两个可直接用于 <iframe> 的页面(不经过 /api/v1 前缀):
| 页面 | 用途 | 查询参数 |
|---|---|---|
/embed/agent/{agent_id} | 完整的免登录 Agent 聊天界面(复用公开聊天页) | token=clou_...(必填)、mode=fullscreen 或 bubble(默认 fullscreen) |
/embed/workflow/{workflow_id} | 工作流运行界面(复用运行详情页) | token=clou_...(必填) |
<iframe
src="https://your-domain.com/embed/agent/550e8400-e29b-41d4-a716-446655440000?token=clou_xxx&mode=bubble"
style="width: 420px; height: 640px; border: 0"
></iframe>为避免把 API Key 暴露在 URL 中,页面支持通过 postMessage 传递凭据:iframe 加载后会向父窗口发送 { "type": "clouisle:ready" },父窗口回传 { "type": "clouisle:token", "token": "clou_..." } 即可;URL 中的 token 仍可用作兜底。若两者都没有,页面停在加载态(Agent 页面)或提示 invalidToken(工作流页面)。
iframe 还会向父窗口发送两类事件,便于宿主页面联动:{ "type": "clouisle:conversation", "conversationId": "..." }(会话创建/切换时)与 { "type": "clouisle:close" }(用户点击关闭)。
嵌入模式的能力边界:会话历史保存在浏览器 localStorage(键为 clouisle:embed:history:agent:{agent_id}),不依赖登录态;消息编辑、重新生成与版本切换在嵌入模式不可用(前端直接禁用)。
域名白名单校验(allowed_domains)
若 Agent 或工作流在 embed_config 中配置了 allowed_domains:
- 服务端将提取请求头中的
Origin或Referer,并与配置的白名单逐一比对(支持通配符子域名如*.example.com)。 - 若来源域名不匹配,服务端拒绝请求并返回
403 Forbidden(业务码3000,错误提示embed_domain_not_allowed)。 - 无来源头的内部直接调用(如测试阶段)或未配置域名白名单时,允许访问。
- 工作流流式事件订阅(
GET /workflows/runs/{run_id}/stream)豁免域名校验。
Agent 嵌入端点
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/v1/embed/agents/{agent_id}/info | 获取嵌入组件所需的公共配置与变量 |
| POST | /api/v1/embed/agents/{agent_id}/chat/stream | SSE 流式发送聊天消息 |
| POST | /api/v1/embed/agents/{agent_id}/chat/runs | 创建持久化异步 Agent 运行(返回 202) |
| GET | /api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/stream | 订阅持久化运行的重放与实时 SSE 事件流 |
| GET | /api/v1/embed/agents/{agent_id}/chat/runs/{run_id} | 查询持久化运行的状态 |
| GET | /api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/events | 按序号回放已缓冲的运行事件 |
| POST | /api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/inputs | 运行过程中发送干预引导(steer)或追问消息 |
| POST | /api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/answers | 提交模型调用 ask_user 等待的结构化答案 |
| POST | /api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/stop | 协作式终止当前运行 |
| GET | /api/v1/embed/agents/{agent_id}/conversations/{conversation_id}/messages | 获取嵌入会话的历史消息列表 |
| POST | /api/v1/embed/agents/{agent_id}/upload/file | 上传嵌入会话中的附件文件 |
1. 获取嵌入 Agent 信息
GET /api/v1/embed/agents/{agent_id}/info HTTP/1.1
Authorization: Bearer clou_api_key成功响应(200 OK)
{
"code": 0,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "在线客服助手",
"description": "回答用户关于退换货和价格的问题",
"icon": "🤖",
"avatar_url": null,
"opening_message": "您好!请问有什么可以帮助您?",
"suggested_questions": [
"如何办理退换货?",
"发票怎么开具?"
],
"variables": [],
"enable_attachments": true,
"attachment_config": {
"max_file_count": 5,
"max_file_size_mb": 10
},
"hide_tool_calls": false,
"hide_message_actions": false,
"hide_reasoning": false,
"embed_config": {
"enabled": true,
"allowed_domains": ["https://example.com"]
}
},
"msg": "success"
}2. 流式发送聊天消息
POST /api/v1/embed/agents/{agent_id}/chat/stream HTTP/1.1
Authorization: Bearer clou_api_key
Content-Type: application/json
{
"message": "退换货的期限是几天?",
"conversation_id": "conv-uuid-optional",
"variables": {}
}响应以 text/event-stream SSE 形式返回,事件与主聊天流式端点完全相同(message_start、content_delta、rag_start/rag_context、reasoning_start/reasoning_delta/reasoning_end、tool_call/tool_result、media_result、compression_start/compression_end、output_truncated、iteration_cap_reached、message_end、error),详见 SSE 流式事件。
3. 创建持久化运行(Durable Run)
对于支持断线重连、长流程工具调用的场景,推荐使用运行管理流程:
POST /api/v1/embed/agents/{agent_id}/chat/runs HTTP/1.1
Authorization: Bearer clou_api_key
Content-Type: application/json
{
"message": "生成本季度销售报告",
"conversation_id": null,
"variables": {}
}响应(202 Accepted)
{
"code": 0,
"data": {
"run_id": "run-uuid-1234",
"conversation_id": "conv-uuid-5678",
"status": "queued",
"stream_url": "/embed/agents/550e8400-e29b-41d4-a716-446655440000/chat/runs/run-uuid-1234/stream"
},
"msg": "success"
}客户端可随时发起 GET /api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/stream?after_sequence=N 订阅事件流,并通过 after_sequence 实现去重与断点续连。
4. 运行控制与查询参数
| 方法 | 路径 | 查询参数 / 请求体 |
|---|---|---|
| GET | /api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/stream | after_sequence(默认 0,负值按 0)——先回放序号更大的缓冲事件再跟随实时流 |
| GET | /api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/events | after_sequence(默认 0)——非流式读取已缓冲事件 |
| GET | /api/v1/embed/agents/{agent_id}/chat/runs/{run_id} | 无——返回 RunOut(status、error_code、pending_tool_* 等) |
| POST | /api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/inputs | JSON:delivery(steer/follow_up/auto,默认 auto)、content、attachments、request_id(幂等键) |
| POST | /api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/answers | JSON:tool_call_id(必填)、answers(ID → 答案)、skipped |
| POST | /api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/stop | 无请求体——协作式终止,随后事件流收到 run_end(status: "stopped") |
| GET | /api/v1/embed/agents/{agent_id}/conversations/{conversation_id}/messages | 无——返回该会话的可见消息(含 version_count);会话必须属于该 API Key 绑定的用户,否则 404(6210) |
| POST | /api/v1/embed/agents/{agent_id}/upload/file | multipart/form-data,字段名 file,查询参数 category(默认 documents) |
运行状态的取值、run_end 的唯一性与断点续连策略与主聊天一致,见 Agent 聊天 API 的持久运行与控制 与 SSE 流式事件。
工作流嵌入端点
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/v1/embed/workflows/{workflow_id}/info | 获取工作流嵌入信息(输入参数定义等) |
| POST | /api/v1/embed/workflows/{workflow_id}/run | 启动嵌入工作流运行 |
| GET | /api/v1/embed/workflows/runs/{run_id}/stream | SSE 流式订阅工作流节点执行过程与结果 |
1. 运行工作流
POST /api/v1/embed/workflows/{workflow_id}/run HTTP/1.1
Authorization: Bearer clou_api_key
Content-Type: application/json
{
"inputs": {
"query": "分析最近客户反馈",
"format": "markdown"
}
}响应(200 OK)
{
"code": 0,
"data": {
"run_id": "wf-run-uuid-1234",
"stream_url": "/api/v1/workflows/runs/wf-run-uuid-1234/stream"
},
"msg": "success"
}返回的 stream_url 指向主工作流流式路由(/api/v1/workflows/runs/{run_id}/stream),该路由面向登录会话;嵌入客户端应改为订阅 GET /api/v1/embed/workflows/runs/{run_id}/stream?from_sequence=N。
2. 订阅工作流运行进度
GET /api/v1/embed/workflows/runs/{run_id}/stream?from_sequence=0| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
from_sequence | integer | 否 | 0 | 从该序号之后开始回放,再跟随实时事件;用于断线续读 |
注意与 Agent 运行流的命名差异:工作流侧用 from_sequence,Agent 侧用 after_sequence。该路由不做域名白名单校验(其余工作流嵌入端点都会校验),但会检查运行必须由当前 API Key 绑定的用户触发,否则返回 404(workflow_run_not_found)。
3. 工作流嵌入信息
GET /api/v1/embed/workflows/{workflow_id}/info返回 id、name、description、icon、variables(输入参数定义)与 embed_config。工作流必须已发布且开启嵌入,否则返回 404(workflow_not_found)或 403(embed_not_enabled)。
错误代码
| 错误码 | 标识 | 说明 |
|---|---|---|
2000 | UNAUTHORIZED | 缺少 API Key、凭据前缀不是 clou_,或 Key 无效/过期(embed_api_key_required) |
3000 | PERMISSION_DENIED | 未开启嵌入功能(embed_not_enabled),或请求来源域名不在白名单中(embed_domain_not_allowed) |
4000 | NOT_FOUND | 工作流不存在或未发布(workflow_not_found);工作流运行不存在或不是由该 API Key 用户触发(workflow_run_not_found) |
6200 | AGENT_NOT_FOUND | Agent 不存在或未处于已发布状态(agent_not_found) |
6210 | CONVERSATION_NOT_FOUND | 会话不存在或不属于当前 API Key 绑定的用户 |
这篇文章对你有帮助吗?