跳转到内容

Artifact 入门

Artifact 是 Agent 推给客户端的结构化数据块。客户端用对应的 renderer 把它 渲染成可交互的卡片:表单、进度条、审批、卡片、媒体。本页讲 Artifact 入门: subtype 列表、payload 结构、最简示例。双向交互(artifact_update + 用户回流)见 Artifact 高级

subtype 列表

subtype客户端 renderer典型用途
infoInfoCard信息提示卡
replyReplyCard结构化回复
appAppRenderer(按 payload.ui 路由)小程序 / 小游戏 / 自定义 UI
formFormCard收集用户输入
responseResponseCard用户对 form 的反馈
tool_call(内部)触发 tool 调用 UI详见 Tool Call
tool_response(内部)tool 执行结果详见 Tool Call
approvalApprovalCard危险操作确认
progressProgressCard长任务进度
mediaMediaCard图 / 视频 / 音频聚合展示

最简示例:信息卡

await agent.sendArtifact(conversationId, {
artifact: {
subtype: "info",
title: "部署成功",
payload: {
body: "你的 Cloudflare Worker 已部署到 us-east-1",
icon: "",
actions: [
{ id: "open", label: "查看 logs", url: "https://dash.cloudflare.com/..." },
],
},
},
});

进度卡

const artifactId = ulid();
await agent.sendArtifact(conversationId, {
artifact: {
artifact_id: artifactId,
subtype: "progress",
title: "导出 Q1 数据",
payload: { percent: 0, status: "starting", eta_s: 120 },
},
});
// 长任务更新进度
for (let pct = 10; pct <= 100; pct += 10) {
await new Promise((r) => setTimeout(r, 5000));
await agent.updateArtifact(conversationId, {
ref_artifact: artifactId,
based_on_revision: (pct / 10) - 1,
artifact: {
payload: {
percent: pct,
status: pct < 100 ? "running" : "done",
eta_s: Math.round((100 - pct) * 1.2),
},
},
});
}

详见 Artifact 高级 — artifact_update 与 revision

表单卡

await agent.sendArtifact(conversationId, {
artifact: {
artifact_id: ulid(),
subtype: "form",
title: "新建项目",
payload: {
fields: [
{ id: "name", label: "项目名", type: "text", required: true },
{ id: "description", label: "描述", type: "textarea" },
{ id: "private", label: "私有", type: "checkbox", default: false },
{
id: "visibility",
label: "可见性",
type: "radio",
options: [
{ id: "public", label: "公开" },
{ id: "private", label: "私有" },
],
},
],
submit_label: "创建",
cancel_label: "取消",
},
},
});
agent.addEventHandler(async (event) => {
if (event.type !== "artifact_response") return;
if (event.payload.action !== "submit") return;
const { name, description, private: isPrivate, visibility } = event.payload.payload;
await createProject({ name, description, private: isPrivate, visibility });
});

详见 Artifact 高级 — 用户回流处理

审批卡

await agent.sendArtifact(conversationId, {
artifact: {
artifact_id: ulid(),
subtype: "approval",
title: "确认部署到生产环境",
payload: {
request: {
environment: "production",
version: "v2.4.1",
changes: ["3 commits, 12 files"],
},
approve_label: "批准并部署",
reject_label: "取消",
timeout_s: 300,
},
},
});

approvalform 的一种特殊 UI(内置 approve / reject 双按钮 + 倒计时)。 SDK 在 timeout_s 内未收到响应自动 timeout,给你发 artifact_response status=denied reason=timeout。

媒体卡

// 先上传文件得到 attachment_id
const { attachment_id: imageId } = await agent.uploadFile(conversationId, {
filename: "chart.png",
mime: "image/png",
data: chartPng,
send_as: null, // 不直接发;只为 artifact 用
});
await agent.sendArtifact(conversationId, {
artifact: {
subtype: "media",
title: "Q1 数据图表",
payload: {
items: [
{ type: "image", attachment_id: imageId, caption: "趋势" },
],
},
},
});

应用卡 (subtype: “app”)

最灵活——任意 React 组件渲染。客户端按 payload.ui 路由 renderer:

await agent.sendArtifact(conversationId, {
artifact: {
artifact_id: ulid(),
subtype: "app",
title: "今日午餐投票",
payload: {
ui: "vote_card", // 客户端按 ui 选 renderer
question: "今天午餐吃什么?",
options: [
{ id: "a", label: "拉面", votes: 0 },
{ id: "b", label: "披萨", votes: 0 },
{ id: "c", label: "沙拉", votes: 0 },
],
total: 0,
},
capability_flags: { allows_response: true },
},
});

客户端内置 renderer 支持 vote_card / tic_tac_toe / 2048 / form / progress, 社区自定义 UI 走 fallback。

详见 小程序与小游戏

完整 ArtifactSendPayload 字段

interface ArtifactSendPayload {
artifact: {
artifact_id?: string; // 可选;不传 SDK 会生成 ULID(强烈建议自己传以便后续 update)
subtype: // 必填
| "info" | "reply" | "app" | "form" | "response"
| "tool_call" | "tool_response" | "approval" | "progress" | "media";
title?: string;
payload: object; // 任意 JSON,由客户端 renderer 解释
capability_flags?: {
allows_response?: boolean;
ttl_s?: number;
};
expires_at?: string; // ISO 8601;过期后客户端自动 disable
};
}

限制

上限
单 artifact JSON 大小64 KB(含 wrap)
同对话同时存活的 artifact 数100(超过后老的自动 expire)
artifact 默认存活30 天(除非 expires_at 显式覆盖)
单 artifact update 次数100(防止状态机暴走)

大数据建议放 R2 → artifact payload 里只放引用 url;客户端按需 GET。

客户端 renderer 速读

subtype客户端组件payload 关键字段
infoInfoCardbody, icon, actions[]
formFormCardfields[], submit_label, cancel_label
progressProgressCardpercent, status, eta_s
approvalApprovalCardrequest, approve_label, reject_label, timeout_s
appAppRenderer (按 ui)自定义
mediaMediaCarditems[] (type=image/video/audio + attachment_id)

未匹配的 subtype 走 “Unknown artifact” fallback —— 显示原始 JSON + “Open in browser” 按钮。

接收 artifact_response 概要

agent.addEventHandler(async (event) => {
if (event.type !== "artifact_response") return;
const {
ref_artifact, // 你之前发的 artifact_id
action, // "submit" / "approve" / "reject" / "vote" / 自定义
payload, // 用户提交的数据
sender_id,
} = event.payload;
console.log(`user ${sender_id} did ${action} on artifact ${ref_artifact}`);
});

详细处理见 Artifact 高级

下一步