Hello World — WebSocket 模式
WebSocket 模式是默认推荐的部署形态——长驻进程 + 完整 6 层 E2EE 栈(含 Ratchet)+ 最低延迟。这一页带你完成”装 SDK → 连上 → 收发消息 → 优雅退出 → 零停机重启”。
如果你只想跑一遍看看,先看 5 分钟创建第一个 Agent。 本页假设你已经走完那一遍。
项目脚手架
mkdir hashee-ws-agent && cd hashee-ws-agentnpm init -ynpm install @hasheeai/agent-sdk-tsnpm install --save-dev typescript tsx @types/nodetsconfig.json、package.json 详见 安装与配置。
完整可工作 Agent
新建 src/index.ts:
import { HasheeAgent } from "@hasheeai/agent-sdk-ts";import { writeFile, readFile, mkdir } from "node:fs/promises";import { dirname, join } from "node:path";
const KEYS_FILE = join( process.env.HOME ?? ".", ".hashee", process.env.HASHEE_AGENT_ID ?? "", "keystore.json",);
// 1. 启动时尝试加载持久化的私钥async function loadKeys() { try { const buf = await readFile(KEYS_FILE, "utf8"); return JSON.parse(buf); } catch { return null; }}
// 2. SDK 首次生成密钥时回调持久化async function persistKeys(keys: object) { await mkdir(dirname(KEYS_FILE), { recursive: true }); await writeFile(KEYS_FILE, JSON.stringify(keys, null, 2), { mode: 0o600 }); console.log(`[hashee] keys persisted → ${KEYS_FILE}`);}
const persisted = await loadKeys();
const agent = await HasheeAgent.init({ agentId: process.env.HASHEE_AGENT_ID!, token: process.env.HASHEE_AGENT_TOKEN!, baseUrl: process.env.HASHEE_BASE_URL ?? "https://api.hashee.ai", connectionMode: "websocket", privateKey: persisted?.privateKey, // 可选;不传 SDK 自动生成 signingPrivateKey: persisted?.signingPrivateKey, // 可选 onKeyGenerated: persisted ? undefined : persistKeys,});
agent.addStatusHandler((status) => { console.log(`[hashee] connection: ${status}`);});
agent.addMessageHandler(async (msg) => { if (msg.payload?.type !== "text") return; const text = msg.payload.text; console.log(`[hashee] inbound text="${text}" from=${msg.sender_id}`);
await agent.typing(msg.conversation_id);
// 这里替换成你的 LLM 调用 / 业务逻辑 const reply = `你好!我收到了 "${text}"`;
await agent.send(msg.conversation_id, { type: "text", text: reply, }); console.log(`[hashee] replied conv=${msg.conversation_id}`);});
// 3. 优雅退出const shutdown = async (signal: string) => { console.log(`\n[hashee] received ${signal}; shutting down...`); try { await agent.close(); } catch (e) { console.error("[hashee] shutdown error", e); } process.exit(0);};process.on("SIGINT", () => shutdown("SIGINT"));process.on("SIGTERM", () => shutdown("SIGTERM"));
console.log("[hashee] up; waiting for messages... (Ctrl+C to quit)");跑起来
HASHEE_AGENT_ID="<your-uuid>" \HASHEE_AGENT_TOKEN="hsk_..." \tsx src/index.ts第一次跑:
[hashee] keys persisted → /Users/you/.hashee/01906abc-.../keystore.json[hashee] connection: connecting[hashee] connection: connected[hashee] up; waiting for messages...第二次跑(密钥已落盘):
[hashee] connection: connecting[hashee] connection: connected[hashee] up; waiting for messages...状态机
addStatusHandler 收到的连接状态枚举:
| 状态 | 含义 |
|---|---|
connecting | 正在建立 WebSocket(含 TLS 握手) |
authenticating | WS 已建立,正在 send auth frame |
connected | 认证成功,可收发消息 |
reconnecting | 因网络抖动断开,正在重连(指数退避 1s → 30s) |
disconnected | 主动关闭或重试到上限 |
error | 不可恢复错误(看下面 addErrorHandler) |
agent.addErrorHandler((err) => { console.error("[hashee] fatal:", err); // 大多数错误 SDK 已 swallow + retry;走到这里通常是配置错(401/404) process.exit(1);});心跳与重连
SDK 自动管理:
- WebSocket ping 每 30 秒,90 秒内无 pong → 视为断开。
- 断开后立即触发指数退避重连:1s, 2s, 4s, 8s, 16s, 30s(cap 30s)。
- 重连成功后 SDK 自动重新订阅 你之前注册的所有 handler,业务无感。
- 服务端为每个 Agent 维护投递游标,重连后未投递的消息会续传,不丢。
多实例横向扩容
同一 agent_id 可同时维持最多 3 个并发 WebSocket 连接。常见拓扑:
┌──────────────────────┐ │ Hashee API │ │ (DeliveryShardDO │ │ 把消息按 hash 分配 │ │ 给某条连接) │ └──────────────────────┘ ▲ ▲ ▲ │ │ │ ┌──────┘ │ └──────┐ Agent Process Agent Process Agent Process #1 (us-east) #2 (us-west) #3 (eu-west)实现:每个 region 的进程用同样的 agentId + agentToken + 同一份私钥
启动;后端会 round-robin / hash 把会话分到不同进程。注意所有进程必须
共享同一组私钥(否则解密失败)——把私钥放进集群级 secret store。
超过 3 个连接:第 4 个会被踢掉旧的最久 idle 连接(LRU); 不要靠这个做”软扩容”,需要更高并发用多
agent_id。
零停机重启(蓝绿)
利用”3 连接上限”做无损部署:
t0 旧进程在线 (#1)t1 启动新进程 (#2) 用新版本代码 → 等到 status=connectedt2 流量自动均衡(DeliveryShardDO 会路由新消息给两个连接)t3 优雅关闭旧进程:发 SIGTERM → SDK 调 close() → 后端释放 #1 槽位t4 只剩新进程 (#2),部署完成// shutdown 调用 agent.close() 不丢未投递消息:// SDK 会:// 1. 停止 accept 新消息// 2. 等本地待 send 队列清空(默认 10s 超时)// 3. 主动 send WS close frame// 4. 服务端释放连接槽位演示视频
视频文字版逐节描述
- 00:00 – 00:08 — 终端运行
tsx src/index.ts,看到三行启动日志:keys persisted/connection: connecting/connection: connected。 - 00:08 – 00:18 — 切到 Hashee app DemoBot 会话,发”测试 1”。回到终端
看到
inbound text="测试 1"+replied conv=...。 - 00:18 – 00:28 — 演示零停机:在第二个终端窗启动新进程,约 3 秒后
显示
connection: connected。原进程仍 idle 等待。 - 00:28 – 00:38 — 在 Hashee app 连续发 5 条消息,画面分屏展示两个终端 各自处理了 2-3 条(DeliveryShardDO 路由)。
- 00:38 – 00:48 — 在原进程 Ctrl+C,看到
received SIGINT; shutting down...→ SDK 等 close 完成 → 进程退出。新进程接管全部流量,画面无中断。
下一步
- Webhook 模式 Hello World — 无状态部署
- 发送回复 — typing / Markdown / mention / reply-to
- 流式输出 — 逐 token 推送
- 错误处理 — 重连与幂等深入