
在企业级 AI 应用中,用户附件是最一手的业务资料。一份专利审查文档、一张 Excel 员工花名册、一份 Figma 设计稿——这些文件的格式之广泛、内容之丰富,远超纯文本对话所能承载的信息密度。
传统聊天式 LLM 交互将附件视为"附属品":先上传,再提取文本,最后拼接到 prompt 中。这种简单策略在面对以下场景时迅速失效:
OODER 的解决方案是:将附件提升为一等公民,通过 Workflow 驱动 Harness 工程实现其完整生命周期管理。本文将深入剖析这一机制的设计哲学与工程实现。
核心设计原则
附件不是对话的"附加信息",而是驱动流程编排的语义源头。每一个附件的上传都是一个 HUMAN 节点的暂停事件,每一次解析都是一个 Skill 的执行活动,每一次甄别都是一次人机协同确认。
附件处理不是孤立的"上传→解析"管道,而是嵌入在 Workflow-Harness-LLM 三层架构中的完整闭环:

图 1:Workflow-Harness-LLM 三层架构 — 附件处理贯穿全层
在这三层架构中,附件的旅程是:
OODER 不会为附件创建独立的"上传事件"——附件推送复用 SSE human_confirm 事件体系,通过 confirmType 字段区分交互类型。这是一个关键的设计决策:
设计哲学:统一交互模型

图 2:附件推送机制 — human_confirm 事件驱动前端渲染上传区域
SSE 事件通过 SseEventEmitter.emitHumanConfirmRequiredEvent() 发射,经由 ContextEventBus → SseEventPushListener 桥接转发到前端。前端有两条渲染路径,通过 _renderHumanConfirm 主入口自动选择:流程面板活跃时注入到 activity-body 层内,否则渲染到主窗体。
附件上传的完整链路涉及前端、后端、VFS 和流程引擎四个维度,下图展示了从用户拖拽文件到流程恢复的完整数据流:

图 3:附件上传全链路 — 从前端 XHR 到 VFS 存储再到流程恢复
关键设计:signalConfirm 原子操作
GenericAttachmentController.uploadBatch() 在完成所有文件处理后,一次性调用 signalConfirm 唤醒阻塞线程。前端无需二次发送 confirm 请求,避免了上传完成与流程恢复之间的竞态条件。
用户附件场景之广泛,要求解析层必须具备格式感知的多策略分派能力。当前系统支持 7 种基础格式和 5 种设计源格式:
格式类型 | 扩展名 | 解析策略 | 输出数据 | 典型场景 |
|---|---|---|---|---|
Word | .docx .doc | Apache POI → 纯文本 | 字段列表 + 段落结构 | 法律文档、合同模板 |
Excel | .xlsx .xls | Apache POI → 行列结构 | 字段列表 + TREEGRID 建议 | 员工花名册、财务报表 |
PDFBox → 纯文本提取 | 全文 + 页码结构 | 专利文档、学术论文 | ||
HTML | .html .htm | Jsoup → Axure/通用解析 | 组件树 + 布局 + 样式 | Axure/Mockplus 原型 |
CSV | .csv | OpenCSV → 表格结构 | 字段列表 + TREEGRID 建议 | 数据导入、批量配置 |
Figma JSON | .json | FigmaDesignReader → 组件映射 | 组件树 + 样式 Token | Figma 设计稿导出 |
纯文本 | .txt .md | 直接读取 | 全文 | 配置文件、说明文档 |
设计源 | 输入形式 | 解析器 | 输出 |
|---|---|---|---|
Figma URL | https://figma.com/... | FigmaDesignReader | 组件树 + 样式 Token |
Lanhu URL | https://lanhuapp.com/... | LanhuDesignReader | 页面结构 + 样式 |
Axure 导出 | .html (含 Axure 标记) | AxureWidgetParser → AxureComponentMapper | 组件映射 + 样式转换 |
格式检测通过 AttachmentParseSkill.detectFormat() 实现,采用三级检测策略:
这是本次改造的核心命题。在改造前,附件保存使用 java.io.tmpdir/ooder-attachments 本地临时目录,存在三个严重问题:
改造前的三大风险
1. 重启丢失:临时目录在 JVM 重启后可能被清理,导致附件引用失效 2. 部署不兼容:绝对路径 e:\xxx 在 Linux 部署环境无效 3. 违反 VFS 约束:项目硬约束要求"所有文件读取必须使用 VFS 路径"

图 4:VFS 归一改造 — 从临时目录到版本化虚拟文件系统
改造后的 GenericAttachmentController 在文件保存后立即执行三步 VFS 归一操作:
附件不是一次性消费——它是场景编排的语义源头。系统中 4 大编排场景以不同方式消费附件数据:

图 5:附件场景消费 — 4 大编排场景的数据流与 SSE 事件链
HUMAN 节点暂停后,系统需要处理"用户不响应"的容错场景。改造后的超时策略已从三选一扩展为四选一:
策略 | 代码 | 行为 | 适用场景 | 优先级 |
|---|---|---|---|---|
P0跳过 | SKIP | 跳过当前活动,路由到下一活动 | 附件可选的场景 | 默认 |
P1重试 | RETRY | 重新触发 human_confirm 事件 | 网络不稳定场景 | 低 |
P1失败 | FAIL | 流程失败终止 | 附件必填的场景 | 低 |
P1部分成功继续 | AUTO_ACCEPT_PARTIAL | 部分上传成功则继续流程 | 多文件批量上传场景 | 新增 |
改造前,FILE_UPLOAD 复用 CONFIRM 的 confirmTimeoutMs(默认 300s),但附件上传耗时远超普通确认。改造后在 HumanOperationConfig 中新增独立配置:
// HumanOperationConfig — FILE_UPLOAD 子配置
fileUploadTimeoutMs = 600000 // 10分钟(vs 确认的5分钟)
fileUploadMaxCount = 20 // 最大文件数
fileUploadAcceptTypes = ".xlsx,.docx,.pdf,.csv,.json,.html"
fileUploadMaxFileSize = 10485760 // 10MB这些配置通过 @BpmField 注解驱动,BPM Designer 属性面板自动渲染配置表单,无需额外前端开发。
同一个文件可能被多次上传(不同对话、不同时间),VFS 版本管理通过内容哈希去重实现:

图 6:附件去重与版本管理 — SHA-256 内容哈希 + VFS 版本历史
附件处理涉及多个 SSE 事件的前后端交互,事件链完整性是系统可靠性的关键保证。以下是对现有实现的审计结果:
检查项 | 状态 | 说明 |
|---|---|---|
human_confirm 有独立监听器 | PASS | NlpChatInlineNetwork.js L2828: addEventListener('human_confirm') |
attachment_analysis 有独立监听器 | PASS | NlpChatInlineNetwork.js L2793: addEventListener('attachment_analysis') |
field_suggestion 有独立监听器 | PASS | NlpChatInlineNetwork.js L2807: addEventListener('field_suggestion') |
事件无消费者冗余 | PASS | 每个事件仅一处消费 |
事件命名符合六层分类 | WARN | attachment_analysis/field_suggestion 未用 FLOW_ 前缀 |
事件时序正确 | PASS | ATTACHMENT_ANALYZED → FIELD_SUGGESTION → human_confirm |
场景与主流程交互合规 | PASS | 通过 extensions 传递数据,不直接修改主流程 context |
VFS 路径归一 | PASS | 改造后所有附件通过 VFS 路径引用 |
signalConfirm 残留清理 | PASS | Loop修复#15: 超时/错误时清理残留 |

图 7:附件处理演进路线 — 从 VFS 归一到智能预处理
总结
附件在 OODER 系统中不是对话的附属品,而是驱动 Workflow 编排的语义源头。通过 VFS 归一、SHA-256 去重、独立超时策略和 SSE 事件链审计,我们构建了一个完整、可靠、可审计的附件生命周期管理体系。这个体系的核心是:每一个附件都有确定的 VFS 身份(vfsPath)、可追溯的内容指纹(contentHash)、与流程绑定的生命周期(human_confirm → signalConfirm → resumeActivity),以及面向未来的版本管理能力。
OODER Architecture Series — Workflow 驱动 Harness 工程实现
Copyright © 2026 ooder.ai — All rights reserved
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。