发送回复
收到消息容易,发好消息难。这一页讲 agent.send 系列 API 的全部参数、消息内
富文本支持、@mention、引用回复、typing 指示、撤回、以及”在没有触发消息时主动
给用户推送”的 4 种姿势。
文本消息(最简)
await agent.send(conversationId, { type: "text", text: "你好",});支持的 payload.type:
| type | 说明 |
|---|---|
text | 纯文本(含 Markdown) |
image | 图片(需先上传到 R2) |
video | 视频 |
audio | 语音 |
file | 任意附件 |
artifact | 结构化卡片(form / app / progress / approval / etc) |
system | 系统通知(标灰小字) |
每种 type 的字段约定见后面分章节。
Typing 指示
让用户看到”对方正在输入…”:
await agent.typing(conversationId);// SDK 默认在 5 秒内自动消失;调 send() 后立即清除最佳实践:
agent.addMessageHandler(async (msg) => { await agent.typing(msg.conversation_id); // 立即让用户看到响应感 const reply = await callExpensiveLLM(msg.payload.text); await agent.send(msg.conversation_id, { type: "text", text: reply, });});如果 LLM 调用超过 5 秒,SDK 会自动续签 typing(每 4 秒重发一次),
直到你 send 或显式 agent.stopTyping(conversationId)。
Markdown
text 消息支持 GitHub-flavored Markdown:
await agent.send(conversationId, { type: "text", text: `# 标题**加粗** *斜体* ~~删除~~ \`code\`
- 列表 1- 列表 2
\`\`\`typescriptconsole.log("Hello");\`\`\`
[链接](https://hashee.ai) | `,});客户端按 docs/product/Hashee_Message_Spec_v6.0.md
渲染:H1-H4、列表、代码块、行内代码、链接、图片、表格、blockquote、删除线、
任务列表。
禁用:原始 HTML、JavaScript 链接、custom CSS。客户端会过滤。
@Mention(群聊场景)
群聊中 @ 某个成员:
await agent.send(groupConversationId, { type: "text", text: "请大家关注 @<U:01906abc-...> 提的方案", mentions: ["01906abc-..."],});mentions 数组里放被 @ 的 user_id(不是 display name)。
客户端会把 @<U:user_id> 占位符替换成 user 当前显示名 + 跳转。
Reply-to(引用回复)
await agent.send(conversationId, { type: "text", text: "好的,已收到", reply_to: { message_id: msg.message_id, // 被引用消息的 id sender_id: msg.sender_id, // 被引用消息的发送者 preview_text: msg.payload.text.slice(0, 80), // 给客户端做卡片预览用 },});客户端在你的回复上方显示一张缩略卡片,点击可跳转到原消息位置。
撤回
await agent.recallMessage(conversationId, messageId);限制:
- 只能撤回自己发的消息。
- 撤回窗口:发送后 2 分钟(V1 默认;后端可配)。
- 撤回不删除
messages表行,只标记recalled_at+ 客户端隐藏。
撤回后所有客户端会收到一条 system.message_recalled 事件,原消息位置显示
“该消息已被撤回”。
主动推送(无触发消息时)
4 种姿势:
1. 直接 send
最简单——只要你有 conversation_id 就能 send:
const conversationId = await lookupConversationByUserId(targetUserId);await agent.send(conversationId, { type: "text", text: "提醒:你的部署完成了" });conversation_id 怎么来:第一次用户加你 Agent 后会进 relation.established
事件,你应该把 (user_id, conversation_id) 持久化。
2. REST 主动推送(Webhook 模式专用)
Webhook agent 没有长连接,没法用 agent.send,需要 REST:
import { restRequest } from "@hasheeai/agent-sdk-ts";
await restRequest({ method: "POST", baseUrl: "https://api.hashee.ai", path: `/agents/${AGENT_ID}/messages`, token: AGENT_TOKEN, body: { conversation_id: targetConversationId, payload: { type: "text", text: "提醒:你的部署完成了" }, },});3. 群组广播
往一个 H2G 群里发:
await agent.send(groupConversationId, { type: "text", text: "@<U:user_a> @<U:user_b> 注意这条", mentions: ["user_a_id", "user_b_id"],});详见 群组消息处理。
4. Artifact 卡片
主动推一张 artifact 卡片(如进度条 / 投票):
await agent.sendArtifact(conversationId, { artifact: { subtype: "progress", title: "导出进度", payload: { percent: 75, eta_s: 120 }, },});详见 Artifact 入门。
撤销 & 失败处理
try { await agent.send(conversationId, { type: "text", text: "..." });} catch (err) { if (err.code === "RELATION_REVOKED") { // 用户已撤销关系,清理本地数据 await cleanupUser(...); } else if (err.code === "RATE_LIMITED") { // SDK 已自动 backoff;这里拿到说明是 burst 限速 setTimeout(() => retry(), err.retry_after_ms); } else { // 网络抖动等 → SDK 会自动重试,这里通常不会跑到 throw err; }}详见 错误处理。
流式输出(Streaming)
短回复直接 send,长 LLM 回复推荐流式(每个 delta 一帧推送,UI 边收边渲染):
const stream = agent.createStreamSession(conversationId);for await (const chunk of llmStream) { await stream.delta(chunk.text);}await stream.done();完整文档:流式输出。
性能注意
- 不要在循环里 await
agent.send——会 serialize。如需批量,用Promise.all。 - 每 send 一次产生一次 E2EE 加密管线(一次 CEK 生成 + 一次签名 + per-recipient wrap);相对于 LLM 调用基本可忽略,但批量大时仍要注意。
- WS 模式下 send 走帧推送,typical latency < 100ms;Webhook 模式走 REST, typical latency 200-500ms。
演示视频
视频文字版逐节描述
- 00:00 – 00:10 — 终端 Agent 进程 idle。Hashee app 用户发”测试”。
Agent 终端
inbound text="测试"→[hashee] typing sent→ 几秒后[hashee] reply sent。 - 00:10 – 00:20 — 演示 Markdown:用户发”给我列出 SDK 的关键能力”, Agent 回一段含标题、列表、代码块的 Markdown。Hashee app 正确渲染。
- 00:20 – 00:35 — 演示 Reply-to:用户发”那个文件链接是什么”,
Agent 用
reply_to引用上一条消息回复”https://…”, app 显示一张被引用消息的缩略卡片。 - 00:35 – 00:48 — 演示 typing 自动续签:模拟一次 12 秒的 LLM 调用, Hashee app 持续显示”正在输入…”直到回复完成。
- 00:48 – 01:00 — 演示主动推送:在另一终端跑
node send-reminder.ts脚本(用 restRequest 调 REST 推一条消息),Hashee app 收到”你的部署 完成了”消息。
下一步
- 流式输出 — StreamSession API 详解
- Artifact 入门 — 结构化卡片
- 接收消息 — 全消息类型解析
- 群组消息 — H2G 加密与 @mention