附件:图片与文件 (Attachments)
给 Agent 发图片或文件分两步:先把字节上传拿到一个稳定的 URL,再把这个 URL 作为消息的一个「部件 (part)」随消息发出去。 SDK 把这两步合成了一个调用,浏览器端的聊天组件更是连调用都省了——选择、粘贴、拖拽都开箱即用。
Agent 回复里带的图片(图表、处理过的照片)同样能取出来,见下文读取 Agent 发回的图片。
需要
@openhex-ai/agent-sdk0.4.0 及以上。
上传并发送
client.files.uploadPart 上传字节并直接返回一个可发送的部件:图片类型返回 image_url 部件,其余返回 file 部件(按 MIME / 扩展名判断)。
import { readFile } from 'node:fs/promises';
const parts = [
await client.files.uploadPart(
{ data: await readFile('chart.png'), filename: 'chart.png' },
{ agentId }
),
await client.files.uploadPart(
{ data: await readFile('report.pdf'), filename: 'report.pdf' },
{ agentId }
),
];
// 文本和附件一起发出去
const turn = await client.sendMessage('这两份材料里有什么值得注意的?', { parts });
传 agentId 的作用:服务端在存下文件的同时,会把它放进该 Agent 的 NAS 工作区,这样 Agent 里那些需要真实文件路径的工具(脚本、数据处理等)才能读到它。只是想让 Agent「看一眼」图片的话,不传也可以。
在浏览器里直接把 File / Blob 交给 uploadPart 即可,不用另外给文件名:
const part = await client.files.uploadPart(fileFromInput, { agentId });
强制部件类型
类型判断走 MIME 与扩展名。想覆盖它(例如让一张图以文件形式发送,让 Agent 当附件处理而不是「看图」),用 as:
await client.files.uploadPart(blob, { agentId, as: 'file' });
已经有 URL 了
文件如果已经传到别处并且是公开可访问的,跳过上传,自己拼部件就行:
const parts = [
{ type: 'image_url', image_url: { url: 'https://…/chart.png' } },
{ type: 'file', file: { filename: 'report.pdf', file_url: 'https://…/report.pdf' } },
];
只要 URL,不要部件
client.files.upload 是更低一层的调用,返回上传结果本身(url、filename、size、mimeType 等),适合你想自己保存 URL 或复用到多条消息的场景:
const uploaded = await client.files.upload(
{ data: bytes, filename: 'chart.png' },
{ agentId }
);
uploaded.url; // 稳定 URL,可反复引用
读取 Agent 发回的图片
Agent 生成的图片以图片内容块的形式回到流里。extractImages 从记录中把 URL 取出来:
import { extractImages } from '@openhex-ai/agent-sdk';
for await (const record of client.runTurn('把这份数据画成柱状图', { parts })) {
for (const url of extractImages(record)) {
console.log('agent image:', url);
}
}
它和 extractText / extractToolCalls 是一组辅助函数,用法一致:传入一条记录,拿到你关心的那部分。
在 React 组件里
内置聊天组件默认就支持附件——选择按钮、粘贴(⌘/Ctrl+V 贴图)、拖拽三种方式都能用,上传由组件代劳,发送前还会显示预览条。消息携带的附件(用户自己发的,以及 Agent 回复的图片)会直接渲染在气泡里:图片显示为缩略图,文件显示为可下载的卡片。
// 默认全开,什么都不用写
<ChatBox agentId="…" token={token} />
// 只允许图片
<ChatBox agentId="…" token={token} acceptFileTypes="image/*" />
// 完全关掉附件
<ChatBox agentId="…" token={token} allowAttachments={false} />
acceptFileTypes 的取值就是 HTML 文件选择框的 accept,例如 "image/*"、".pdf,.docx"。
用无头 Hook 时,send 的第二个参数接收原始 files(组件替你上传)或已经拼好的 parts:
const { send } = useOpenhexChat({ agentId: '…', token });
await send('帮我看看这个', { files: [myFile] }); // 交给 SDK 上传
await send('帮我看看这个', { parts }); // 自己上传好的部件
组件的完整用法见示例:3 分钟做一个客服组件。