Skip to main content
多 Agent 一旦开始交接,产物就成了绕不开的问题:消息传不下、权限收不住、版本回不去。我现在会把文件当成需要治理的基础设施来看。

Q1: Agent 为什么需要”产物(Artifact)“这一层?消息内联不够吗?

对话消息适合传”意图和结论”,不适合传”交付物”。一旦产物变多、变大、需要被多个 Agent 共享,消息内联就会出问题:
消息传”指针”,产物存”内容”。Agent 之间应该传 artifact 引用,而不是把文件内容塞进 prompt。

Q2: 一次会话中,产物经历了怎样的生命周期?

各阶段的存储选型:
工作区是”草稿纸”,对象存储才是”档案室”。工作区随 Pod 销毁而丢失,且多副本之间不一定强一致。需要交付、审计、回滚的产物必须提升为不可变 artifact。

Q3: 产物协作的参考架构长什么样?

核心组件职责:
MCP 的 Resource 用 URI 唯一标识资源,并提供 resources/read 读取;ResourceLink 让 Agent 拿到的是一个句柄而不是内联内容。A2A 协议里的 Artifact 也有唯一 ID 和名称、由多个 Part 组成、可增量流式传输。两者都指向同一个工程结论:跨 Agent 传引用,不传大块内容。

Q4: A Agent 写、B Agent 读,三种模式怎么选?

怎么选

经验规则:默认用 Artifact 引用传递,因为它的权限、审计、版本最完整;只有在同机协作且对延迟极敏感时,才用共享挂载作为性能优化,并且仍然要把最终产物提交成 artifact。
沙箱执行的是模型生成的代码,属于不可信环境。正确做法是沙箱只拿到短期、单对象、只读或只写的 presigned URL,或者只拿到一个指向 Artifact Service 的会话令牌。长期 AK/SK 一旦进入沙箱,就等于把整个桶交出去。

Q5: artifact manifest 与上传 / 下载 API 怎么设计?

manifest schema

API 形态

先申请上传、再 commit,是为了让”对象已写入”和”元数据可见”解耦。只有 commit 成功,产物才对下游可见;上传中断留下的孤儿对象由生命周期规则清理。这样避免了”文件写了一半就被读到”。

Q6: 并发写同一文件、大文件、跨沙箱传输怎么处理?

并发写:用 CAS,不要用”后写覆盖”

关键原则:不可变对象 + 版本指针。永远不原地覆盖,冲突就产生新版本,由 Lead 或规则决定哪个版本是”当前”。

大文件与流式

  • 大文件绝不要 base64 内联进消息,token 会直接爆炸。
  • 上传用分片(multipart),每片校验 MD5 / SHA256。
  • 下载用 Range 请求,支持断点续传。
  • 下游 Agent 先读 manifest 判断是否真的需要内容,再决定是否拉取。
  • 对文本类产物可只传 diff / patch,而不是整份文件。

跨沙箱传输


Q7: 场景走查:流水线交接、专家团汇总、版本回滚

场景一:硅基员工流水线

每一级只通过 artifactRefs 拿上游产物,不继承上游完整对话。产物天然形成一条血缘链,出问题能逐级回溯。

场景二:专家团多份产物汇总

汇总要先按 manifest 对齐、按 hash 去重,再把冲突项交给裁决逻辑;“把三份报告粘起来”做不到这些。

场景三:失败后基于版本回滚

回滚 = 移动指针,不是覆盖历史。 这样任何时刻都能回答”当时交付的是哪一版、由谁产出、基于什么上游产物”。

Q8: 产物协作的安全边界怎么划?

保留策略

存储 key 必须由服务端根据 artifactId 生成,绝不能直接使用客户端传来的路径。文件名只作为展示字段,不参与寻址。

Q9: 八道深度追问(及格 vs 满分)

八题覆盖”为什么需要产物层 / 生命周期 / 三种协作模式 / presigned 安全 / 内容寻址 / 并发冲突 / 大文件 / 版本回滚”。
及格回答: 因为文件太大,塞进去会超上下文。满分回答: 大小只是表象,核心问题是消息无法承载交付物应有的属性:无法多 Agent 共享一份不可变副本、无法表达版本和回滚、无法按产物粒度授权、无法审计、无法检测并发写冲突。所以我用”消息传引用、对象存储存内容”的方式:消息里只放 artifactId 或 ResourceLink,下游按需读取。这样上下文可控,权限和版本也能约束。
及格回答: 先生成文件,再传到对象存储,最后删掉临时文件。满分回答: 我分五段:临时产物放沙箱本地盘,分钟级清理;确认要保留的提升为工作区文件,落在共享卷供同会话读写;需要跨 Agent 或交付时,上传到对象存储并生成 manifest、hash 和版本,成为不可变 artifact;下游通过引用读取;任务结束按 retention 清理或归档。关键是把”工作区”和”档案室”分开,工作区随 Pod 销毁而丢失,不能当产物库用。
及格回答: 文件大就用对象存储,文件小就直接发消息。满分回答: 我按三个维度选:隔离、一致性、审计。共享挂载延迟低,但卷级授权粒度粗、跨节点一致性弱,适合同 Pod 协作;Artifact 引用是默认选择,权限能细到单个产物,服务端记录完整访问审计,版本和冲突处理也最完整;消息内联只适合小块结构化结果,下游看一眼就够。即便用共享挂载做性能优化,最终交付物仍然要提交成不可变 artifact。
及格回答: 设置一个过期时间就安全了。满分回答: 过期时间只是一层。完整的边界包括:只授权单个对象而不是整个桶、只给需要的动作(读或写)、TTL 尽量短、绑定租户和会话、必要时限制来源 IP。沙箱里绝不能放长期 AK/SK,因为它执行的是模型生成的不可信代码。正确做法是沙箱向 Artifact Service 出示会话令牌,换取短期单对象 URL。这样即使 URL 泄漏,损失也被限制在一个对象和很短的时间窗内。
及格回答: 用来校验文件有没有损坏。满分回答: 完整性只是第一层。sha256 让相同内容天然去重——专家团多份报告里重复的附件只存一份;让 manifest 可以验证”下游读到的确实是上游产出的那一份”;让缓存和增量处理成为可能——hash 没变就不用重新处理;还能支撑血缘追踪,patch 可以记录它基于哪个父产物的 hash。可以说内容寻址是产物系统可验证性的基础。
及格回答: 加个锁,谁先拿到谁写。满分回答: 我不倾向用分布式锁做长期方案,而是用乐观并发加不可变版本。读的时候拿到 ETag 或 version,写的时候带 If-Match;版本对不上就返回 409,让写入方重新读取后决定合并还是上报。对象永远不原地覆盖,冲突就产生新版本,由 Lead 或规则决定哪个是当前版本。这样既避免了锁的死锁和租约问题,又保留了完整历史。
及格回答: 分块读,读一部分处理一部分。满分回答: 首先绝不 base64 内联进消息。上游把大文件提交为 artifact,下游只拿引用;需要读取时用 Range 请求做流式或分片读取,支持断点续传。文本类产物优先传 diff / patch 而不是整份文件。下游 Agent 先读 manifest 判断是否真的需要内容,很多情况下只需要摘要或元数据。上传侧用 multipart 分片并逐片校验 hash,避免大文件半途失败重传。
及格回答: 把文件改回上一版就行。满分回答: 不能覆盖,因为覆盖会丢失证据、也无法回答”当时交付的是哪一版”。正确做法是所有版本都作为不可变对象保留,manifest 记录 version 和 parentArtifactId,发布用一个指针指向当前版本。回滚就是把指针指回上一个通过的版本,而不是删改历史。这样既能快速恢复,又保留了完整的血缘和审计链,复盘时能定位是哪一级 Agent、基于什么上游产物出的问题。

延伸阅读与引用参考