ClouisleClouisle

SDK 与代码示例

从 OpenAPI 规范生成类型化客户端并调用 API

Clouisle 不发布官方 SDK(Python、JavaScript、Go、Ruby 等均无)。API 是标准的 REST + JSON 接口,所有请求使用 https://your-domain.com/api/v1 基础路径、JSON 请求/响应体,并在 Authorization 请求头中携带 Bearer JWT 或 clou_ 开头的 API Key。响应使用统一信封 {"code": 0, "data": ..., "msg": "success"},使用 data 前先检查 code。

获取 OpenAPI 规范

入口地址
Swagger UIhttps://your-domain.com/docs
OpenAPI JSONhttps://your-domain.com/api/v1/openapi.json

需要类型化客户端时,用 openapi-generator 或 openapi-typescript 从 OpenAPI JSON 自行生成:

# TypeScript 类型
npx openapi-typescript https://your-domain.com/api/v1/openapi.json -o api.d.ts

# Python 客户端
openapi-generator generate -i https://your-domain.com/api/v1/openapi.json -g python -o ./client

认证

登录接口 POST /api/v1/login/access-token 使用表单编码的 username 与 password,返回的 Token 有效期由站点设置 session_timeout_days 决定(默认 30 天),没有刷新端点,临近过期重新登录即可。服务端之间的调用建议使用 API Key(通过界面或 POST /api/v1/api-keys 创建),同样以 Bearer 方式发送:

export CLOUISLE_API_KEY="clou_your_full_key_here"
curl -X GET "https://your-domain.com/api/v1/agents" \
  -H "Authorization: Bearer $CLOUISLE_API_KEY"

TypeScript 最小示例

sdk-example.ts
const API_BASE = 'https://your-domain.com/api/v1';
const headers = {
  Authorization: `Bearer ${process.env.CLOUISLE_API_KEY}`,
  'Content-Type': 'application/json',
};

// 列出 Agent(分页信封见 ./conventions)
const listRes = await fetch(`${API_BASE}/agents?page=1&page_size=20`, { headers });
const listBody = await listRes.json();
if (listBody.code !== 0) throw new Error(listBody.msg);
for (const agent of listBody.data.items) console.log(agent.id, agent.name);

// 运行工作流(异步返回 run_id + stream_url)
const runRes = await fetch(`${API_BASE}/workflows/${workflowId}/run`, {
  method: 'POST',
  headers,
  body: JSON.stringify({ inputs: { customer_email: 'customer@example.com' } }),
});
const runBody = await runRes.json();
console.log(runBody.data.run_id, runBody.data.stream_url);

Python 最小示例

sdk_example.py
import os
import requests

API_BASE = "https://your-domain.com/api/v1"
headers = {"Authorization": f"Bearer {os.getenv('CLOUISLE_API_KEY')}"}

# 登录换取 JWT(表单编码)
login = requests.post(
    f"{API_BASE}/login/access-token",
    data={"username": "your_username", "password": "your_password"},
).json()
token = login["data"]["access_token"]

# 用 JWT 聊天(会话隐式创建,传 conversation_id 继续同一会话)
chat = requests.post(
    f"{API_BASE}/agents/{agent_id}/chat",
    headers={"Authorization": f"Bearer {token}"},
    json={"message": "Hello! I need help with my order.", "conversation_id": None, "variables": {}},
).json()
print(chat["data"]["conversation_id"], chat["data"]["message"]["content"])

# 检索知识库
search = requests.post(
    f"{API_BASE}/knowledge-bases/{kb_id}/search",
    headers=headers,
    json={"query": "How to reset password?", "search_mode": "hybrid", "top_k": 5},
).json()
for item in search["data"]["results"]:
    print(item["document_name"], item["score"])

流式聊天(SSE)

POST /api/v1/agents/{agent_id}/chat/stream 返回 text/event-stream,事件含 content_delta 与 message_end。完整事件表见 流式事件:

const response = await fetch(
  `https://your-domain.com/api/v1/agents/${agentId}/chat/stream`,
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${apiKey}`,
      'Content-Type': 'application/json',
      Accept: 'text/event-stream',
    },
    body: JSON.stringify({ message: 'Tell me a story', conversation_id: null, variables: {} }),
  }
);

const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });
  const lines = buffer.split('\n');
  buffer = lines.pop() || '';
  let eventType = '';
  for (const line of lines) {
    if (line.startsWith('event: ')) eventType = line.slice(7);
    else if (line.startsWith('data: ') && eventType) {
      const data = JSON.parse(line.slice(6));
      if (eventType === 'content_delta') process.stdout.write(data.delta);
      if (eventType === 'message_end') console.log('\n[Done]');
      eventType = '';
    }
  }
}

错误处理

校验失败返回 HTTP 422,data.errors 为字段到消息列表的字典。先判断 code 再使用 data:

result = requests.post(
    f"{API_BASE}/agents",
    headers={"Authorization": f"Bearer {token}"},
    json={"name": "x"},  # 缺少必填的 team_id
).json()

if result["code"] != 0:
    if result["code"] == 1001:
        for field, messages in result["data"]["errors"].items():
            print(f"{field}: {', '.join(messages)}")
    else:
        print(f"Error {result['code']}: {result['msg']}")

相关文档

这篇文章对你有帮助吗?

本页目录