# Agent Runs Multimodal 与落库重构设计 **目标**:让 `POST /agent/runs` 支持真实多模态直传到模型(非文本化),并将 worker/tool 结果按新 metadata 协议结构化落库。 **范围**:后端 `runs/resume` 请求校验、runtime 输入转换、事件落库、history 回放一致性。 --- ## 1. 背景与问题 - 当前 `binary` 内容在运行链路中被当作普通 JSON 文本拼接进入 prompt,模型拿不到原生图像输入。 - tool 落库仍依赖旧摘要逻辑 `build_tool_content_summary`,与最新 `ToolAgentOutput` 元数据规范不一致。 - worker 落库当前只落文本内容,未确保 `WorkerAgentOutput` 结构化对象与 `content=answer` 的一致关系。 --- ## 2. 设计原则 - 协议单一信源:严格遵循 `docs/protocols/agent-chat-messages.md`,只接受 `binary` 形态,不兼容旧形态。 - 最小安全边界:仅允许本项目 Supabase 私有桶签名 URL,拒绝任意外部 URL。 - 事件驱动持久化:以 event store 作为唯一落库入口,避免双轨逻辑。 - 数据可回放:history 始终可按 metadata 重新签名并回填 user 附件。 --- ## 3. 目标数据流 1. `runs` 入参校验通过后,user message 入库(附件仅存 bucket/path/mime)。 2. runtime 执行时,将 `binary` 转为模型多模态 `image_url` content block 直传。 3. orchestrator 产出结构化事件: - worker 主响应通过 `TEXT_MESSAGE_*` 事件发送,`TEXT_MESSAGE_END` 携带 `workerAgentOutput`。 - tool 执行结果通过 `TOOL_CALL_RESULT` 事件发送,携带 `toolAgentOutput`。 4. event store 统一校验并落库: - worker:`content = answer`,metadata 写 `worker_agent_output`。 - tool:`content = result_summary`,metadata 写 `tool_agent_output`。 5. history 读取 user metadata 重新签名 URL,返回 `binary` block 给前端。 --- ## 4. 安全与错误策略 ### 4.1 URL 安全边界 - `binary.url` 必须满足: - host 为当前 Supabase 项目域名。 - path 为 `/storage/v1/object/sign/{bucket}/{path}`。 - `{bucket}` 等于 `config.storage.bucket`。 - `{path}` 前缀匹配 `agent-inputs/{user_id}/{thread_id}/uploads/`。 ### 4.2 运行失败 - 保持 AG-UI 生命周期完整:`RUN_STARTED` 后只能 `RUN_FINISHED` 或 `RUN_ERROR` 结束。 - 运行错误时不落半结构化消息,避免脏元数据。 --- ## 5. 落库契约 ### 5.1 Worker - 入库角色:`assistant` - `messages.content = worker_agent_output.answer` - `messages.metadata.worker_agent_output = WorkerAgentOutput`(完整、schema 校验后) ### 5.2 Tool - 入库角色:`tool` - `messages.content = tool_agent_output.result_summary` - `messages.metadata.tool_agent_output = ToolAgentOutput`(完整、schema 校验后) - 删除旧摘要逻辑:`build_tool_content_summary` --- ## 6. 兼容性策略 - 不兼容旧输入块形态(如 `image_url` 作为 runs 输入)。 - 历史接口输出协议保持不变,前端无需修改消费协议。 - 原有 user 附件回放路径保留,只强化入站 URL 校验。 --- ## 7. 验收标准 - runs 包含合法 `binary` 时,模型收到多模态消息(非文本化 JSON)。 - 非本项目签名 URL 返回 `422`。 - worker/tool 落库满足 `content` 与结构化 metadata 一一对应。 - history 仍能正确回放 user 附件(临时签名 URL)。