网关 API¶
ZeroClaw 网关提供 HTTP API 用于外部应用与 ZeroClaw 交互。
端点概览¶
| 端点 | 方法 | 认证 | 描述 |
|---|---|---|---|
/health | GET | 无 | 健康检查(公开) |
/pair | POST | 配对码 | 交换配对码获取 Token |
/webhook | POST | Token | 发送消息给助手 |
/whatsapp | GET | 查询参数 | WhatsApp Webhook 验证 |
/whatsapp | POST | 签名 | WhatsApp 消息 Webhook |
健康检查¶
端点: GET /health
认证: 无需认证
用途: 检查网关服务是否运行
响应:
示例:
配对终端¶
端点: POST /pair
认证: 需要配对码头部
用途: 使用一次性配对码交换 Bearer Token
请求:
响应:
错误响应:
配对流程¶
- 启动网关获取配对码:
- 客户端发送配对码:
TOKEN=$(curl -s -X POST http://localhost:8080/pair \
-H "X-Pairing-Code: 123456" \
| jq -r '.token')
- 保存 Token 用于后续请求:
Webhook 消息¶
端点: POST /webhook
认证: Bearer Token
用途: 发送消息给 ZeroClaw 助手
请求:
curl -X POST http://localhost:8080/webhook \
-H "Authorization: Bearer eyJ..." \
-H "Content-Type: application/json" \
-d '{
"message": "你好,ZeroClaw!"
}'
请求参数:
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
message | string | 是 | 用户消息 |
session_id | string | 否 | 会话 ID(用于上下文连续性) |
model | string | 否 | 覆盖默认模型 |
temperature | number | 否 | 覆盖默认温度 |
max_tokens | number | 否 | 最大输出 tokens |
响应:
{
"response": "您好!我是 ZeroClaw,很高兴为您服务。",
"model": "anthropic/claude-3-5-sonnet",
"tokens_used": {
"prompt": 25,
"completion": 42,
"total": 67
},
"session_id": "sess_abc123"
}
流式响应¶
端点: POST /webhook/stream
请求:
curl -X POST http://localhost:8080/webhook/stream \
-H "Authorization: Bearer eyJ..." \
-H "Content-Type: application/json" \
-d '{"message": "介绍一下 Rust"}'
响应: Server-Sent Events (SSE)
data: {"type": "start", "session_id": "sess_abc123"}
data: {"type": "token", "content": "Rust"}
data: {"type": "token", "content": " 是"}
data: {"type": "token", "content": "一门"}
...
data: {"type": "end", "tokens_used": 156}
工具调用¶
端点: POST /webhook/tools
请求:
curl -X POST http://localhost:8080/webhook/tools \
-H "Authorization: Bearer eyJ..." \
-H "Content-Type: application/json" \
-d '{
"message": "读取工作区中的 README 文件",
"auto_execute": true
}'
响应:
{
"response": "README.md 文件的内容如下:\n\n# 项目介绍\n...",
"tools_called": [
{
"name": "file_read",
"args": {
"path": "README.md"
},
"result": "文件内容..."
}
]
}
WhatsApp 集成¶
Webhook 验证¶
端点: GET /whatsapp
参数:
| 参数 | 描述 |
|---|---|
hub.mode | 必须是 subscribe |
hub.verify_token | 配置中的验证令牌 |
hub.challenge | 回显的挑战字符串 |
示例:
curl "http://localhost:8080/whatsapp?hub.mode=subscribe&hub.verify_token=secret&hub.challenge=123456"
响应: 返回 hub.challenge 值
Webhook 消息¶
端点: POST /whatsapp
认证: Meta 签名(X-Hub-Signature)
请求: Meta 推送的 WhatsApp 消息
响应: 200 OK
错误处理¶
错误格式¶
所有错误响应遵循统一格式:
常见错误码¶
| 状态码 | 错误码 | 描述 |
|---|---|---|
| 401 | UNAUTHORIZED | 缺少或无效的 Token |
| 403 | FORBIDDEN | Token 权限不足 |
| 429 | RATE_LIMITED | 请求过多 |
| 500 | INTERNAL_ERROR | 服务器内部错误 |
示例¶
# 无效的 Token
curl -X POST http://localhost:8080/webhook \
-H "Authorization: Bearer invalid" \
-d '{"message": "test"}'
# 响应
{
"error": "Invalid token",
"code": "UNAUTHORIZED"
}
速率限制¶
默认配置:
| 类型 | 限制 |
|---|---|
| 1 分钟请求数 | 100 |
| 1 小时请求数 | 1000 |
配置方式:
速率限制响应¶
示例客户端¶
Python 客户端¶
import requests
class ZeroClawClient:
def __init__(self, base_url, token):
self.base_url = base_url
self.headers = {"Authorization": f"Bearer {token}"}
def send_message(self, message):
response = requests.post(
f"{self.base_url}/webhook",
headers=self.headers,
json={"message": message}
)
return response.json()
# 使用
client = ZeroClawClient("http://localhost:8080", "eyJ...")
result = client.send_message("你好")
print(result["response"])
JavaScript 客户端¶
class ZeroClawClient {
constructor(baseUrl, token) {
this.baseUrl = baseUrl;
this.headers = { 'Authorization': `Bearer ${token}` };
}
async sendMessage(message) {
const response = await fetch(`${this.baseUrl}/webhook`, {
method: 'POST',
headers: {
...this.headers,
'Content-Type': 'application/json'
},
body: JSON.stringify({ message })
});
return response.json();
}
}
// 使用
const client = new ZeroClawClient('http://localhost:8080', 'eyJ...');
client.sendMessage('你好').then(result => {
console.log(result.response);
});
Go 客户端¶
package main
import (
"bytes"
"encoding/json"
"net/http"
)
type ZeroClawClient struct {
BaseURL string
Token string
}
func (c *ZeroClawClient) SendMessage(message string) (map[string]interface{}, error) {
payload := map[string]string{"message": message}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", c.BaseURL+"/webhook", bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer "+c.Token)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
return result, nil
}
func main() {
client := ZeroClawClient{BaseURL: "http://localhost:8080", Token: "eyJ..."}
result, _ := client.SendMessage("你好")
println(result["response"].(string))
}
WebSocket 支持¶
连接 WebSocket¶
端点: ws://localhost:8080/ws?token=eyJ...
JavaScript 示例:
const ws = new WebSocket('ws://localhost:8080/ws?token=' + token);
ws.onopen = () => {
console.log('WebSocket 已连接');
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'response') {
console.log('收到回复:', data.content);
} else if (data.type === 'tool_call') {
console.log('工具调用:', data.tool_name);
}
};
// 发送消息
ws.send(JSON.stringify({
type: 'message',
content: '你好'
}));
调试¶
启用详细日志¶
测试工具¶
# 测试健康检查
curl http://localhost:8080/health
# 测试配对(需要先获取配对码)
PAIRCODE=123456
curl -X POST http://localhost:8080/pair \
-H "X-Pairing-Code: $PAIRCODE"
# 测试 Webhook
TOKEN=eyJ...
curl -X POST http://localhost:8080/webhook \
-H "Authorization: Bearer $TOKEN" \
-d '{"message": "test"}'