跳转到内容

速率限制与重试

Hashee 所有 API 都有速率限制。本页给完整限速表 + Retry-After 协议 + SDK 内建的重试策略 + 你侧补充逻辑的最佳实践。

速率限制全表

认证类

端点限制维度
POST /auth/login(失败次数)5 失败 → 锁 15 分钟per email
POST /auth/register10/10minper IP
POST /auth/register5/10minper email
POST /auth/send-code1/60sper email
POST /auth/refresh60/minper refresh_token
POST /auth/passkey/begin30/minper IP

E2EE 密钥类

端点限制维度
GET /keys/users/:id/devices60/minper requesting user
POST /keys/groups/:id/rotate6/hper conversation
POST /keys/rotation/request6/hper H2H conversation

Agent 类(per agent_id)

端点限制
POST /agents/:id/messages(发消息)5 req/s
POST /agents/:id/conversations/:cid/messages5 req/s
POST /agents/:id/typing10 req/s
POST /agents/:id/files + PUT /upload5 req/s
PATCH /agents/:id(更新 manifest)1 req/min
POST /agents/:id/token/regenerate5 req/24h
GET /agents/:id/conversations30 req/min
GET /agents/:id/messages/poll60 req/min
POST /agents/:id/grants/request10 req/min
GET /r2/<object_key> (R2 引用)5 req/s

消息读取类(per user)

端点限制
GET /conversations/:id/messages60 req/min
GET /conversations30 req/min
GET /search10 req/min

群组类

端点限制
POST /groups/:id/members(加成员)5 req/min per group
POST /groups/:id/agent-instances1 req/min per group

触发限速时的响应

HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 1
{
"error": {
"code": "RATE_LIMITED",
"message": "Too many requests",
"i18n_key": "error.rate_limited",
"params": {
"retry_after_ms": 1000,
"limit": "5/s",
"scope": "agent_message_send"
}
}
}

Retry-After 是 HTTP 标准秒数;error.params.retry_after_ms 是更精确的毫秒数。

SDK 自动 backoff

@hasheeai/agent-sdk-ts 内建:

操作SDK 行为
收到 429 with Retry-After自动 sleep + 重试一次
收到 429 三次throw 给业务层
WS 断开指数退避 1s, 2s, 4s, 8s, 16s, 30s(cap 30s)
解密失败单条不影响其他消息,调 decryptFailureHandler

业务侧通常不需要写重试逻辑——SDK 已经够用。

业务层重试模板

如果你需要更严格的”必送达”语义,自己加一层重试:

async function sendWithRetry(
conversationId: string,
payload: SendPayload,
maxAttempts = 5,
): Promise<void> {
let attempt = 0;
let backoffMs = 500;
while (true) {
try {
await agent.send(conversationId, payload);
return;
} catch (err: any) {
attempt += 1;
if (attempt >= maxAttempts) throw err;
// 不可重试错误立即抛
const noRetry = ["VALIDATION_ERROR", "AGENT_TOKEN_INVALID", "RELATION_REVOKED"];
if (noRetry.includes(err.code)) throw err;
// 429 用 server 给的等待时间
const wait = err.code === "RATE_LIMITED"
? (err.retry_after_ms ?? 1000)
: backoffMs;
await sleep(wait);
backoffMs = Math.min(backoffMs * 2, 30_000);
}
}
}

幂等保证

所有发消息端点支持 client_message_id(你侧 ULID):

import { ulid } from "ulid";
await agent.send(conversationId, {
type: "text",
text: "...",
client_message_id: ulid(),
});

24 小时内同 (agent_id, client_message_id) 重复 POST 返回原结果,不会插重复行。 SDK 自动注入 client_message_id(如果你没传),所以普通用法已经幂等。

如果你的 retry 逻辑跨进程(e.g. queue 重投),你必须显式持久化 client_message_id 并在 retry 时复用——SDK 自动生成的 ID 在重启后会丢。

// ❌ 错:每次 retry 生成新 ID,可能造成重复消息
await agent.send(convId, { type: "text", text, client_message_id: ulid() });
// ✓ 对:用任务的固定 ID 做幂等 key
const taskId = job.id; // 业务的稳定 ID
await agent.send(convId, { type: "text", text, client_message_id: taskId });

Webhook 模式重试

Webhook agent 由后端发起重试:失败 7 次后进入 unreachable。详见 Webhook 协议 #unreachable-状态机。

你侧(webhook handler)的重试策略只针对 outbound 主动推送

async function pushWithRetry(convId: string, payload: SendPayload, attempt = 0): Promise<void> {
try {
await restRequest({
method: "POST",
baseUrl: "https://api.hashee.ai",
path: `/agents/${AGENT_ID}/messages`,
token: AGENT_TOKEN,
body: { conversation_id: convId, payload },
});
} catch (err: any) {
if (attempt >= 3) throw err;
if (err.code === "RATE_LIMITED") {
await sleep(err.retry_after_ms ?? 1000);
return pushWithRetry(convId, payload, attempt + 1);
}
throw err;
}
}

配额超限 vs 速率限制

不要混淆:

概念错误码处理
配额AGENT_LIMIT_EXCEEDED (50 Agent), MANIFEST_TOO_LARGE (128KB), FILE_TOO_LARGE (100MB)不可重试,业务侧调整
速率限制RATE_LIMITED 系列可重试,按 Retry-After

自我节流的最佳实践

不要”用满限速”——服务器侧 burst 可能立刻触发,导致一连串 429。 推荐保持在限制的 70-80%:

// 用 token bucket 节流
class TokenBucket {
private tokens: number;
private lastRefill: number;
constructor(private capacity: number, private refillPerSec: number) {
this.tokens = capacity;
this.lastRefill = Date.now();
}
async acquire(): Promise<void> {
while (true) {
this.refill();
if (this.tokens >= 1) { this.tokens -= 1; return; }
await sleep(100);
}
}
private refill() {
const now = Date.now();
const delta = (now - this.lastRefill) / 1000;
this.tokens = Math.min(this.capacity, this.tokens + delta * this.refillPerSec);
this.lastRefill = now;
}
}
// 5 req/s 限速 → bucket capacity=4 / refill=4/s(70-80% 利用率)
const sendBucket = new TokenBucket(4, 4);
async function safeSend(convId: string, payload: SendPayload) {
await sendBucket.acquire();
return agent.send(convId, payload);
}

监控

至少要监控:

指标类型报警阈值
429 ratecounter> 5 / min 持续 5 min → warn;> 30 / min → page
Retry attemptshistogramp95 > 3 → warn
Final failure (after retry exhausted)counter> 0 → page
Webhook unreachable transitionscounter> 0 → page

申请扩限

V1 内测期限速是固定的;V2 marketplace 会引入开发者计划等级(带高限速)。

如果 V1 阶段你的合法用法被限速卡住:在 Hashee 后台开 ticket 描述用例 + 预期 RPS。极少数情况下我们会个案放宽(如 enterprise 集成)。

下一步