跳转到内容

发送回复

收到消息容易,发好消息难。这一页讲 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
\`\`\`typescript
console.log("Hello");
\`\`\`
[链接](https://hashee.ai) | ![图片 alt 文字](https://example.com/x.png)`,
});

客户端按 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 收到”你的部署 完成了”消息。

下一步