OpenProgram · Runtime DAG + Chat · Visual contract

外部 Program 运行节点

定义用户从 Programs、fn-form 或其他外部入口直接运行一次函数时,DAG 视图、完成后的 summary handoff 和聊天记录应如何表现。这里只规定顶层运行、终态交付及其现有执行事件的投影,不规定 workflow 内部阶段。

设计状态:聊天窗口与 summary handoff 已实现 · DAG 投影仍为设计
核心决定

外部调用显示为 conversation layer 的圆角正方形 Program/Function 节点,由 ROOT 直接分出,不补造 User 或 LLM 节点。workflow 的实质结果默认写入文件;成功态 Conclusion 的工作交接由独立 summary 函数生成,不是 workflow 结果正文。非成功终态的 Conclusion 由前端根据状态和错误确定性生成。

端到端流程:执行、交接与聊天投影

外部 agentic_workflow 一次调用 DEFAULT: FILE ARTIFACTS + SHORT HANDOFF
agentic_workflow 从外部调用到聊天 Conclusion 的完整流程 流程分为运行与产物、summary 信任边界、聊天投影三层。完整结果正文及其在后续调用参数中的副本默认只进入文件和 workflow state,不进入 summary 输入或公共 payload;只有原始任务明确要求直接返回正文时才单独显示。 1 · 运行与产物 Programs / fn-form 外部直接调用 顶层 Program 节点 caller 为空 · code square agentic_workflow 执行 planner / SINGLE / programmed 使用当前 session provider / model capped / cancelled / interrupted / failed 跳过 LLM summary → 确定性 Conclusion 实质产物写入当前工作目录 报告 · 代码 · 表格 · 其他文件 workflow state 保留完整执行数据 raw result 与每步 result 仅内部持久化 2 · Summary 信任边界与公共 payload 允许进入 summary 的输入 • 原始 task 与 workflow status • 函数名 / 状态 • agent operational preview ≤ 240 字 • raw result 仅提供字符数 _summarize_workflow 独立 LLM 调用 · 无工具 自然概括 / 可选编号流程 / 完成判断 失败时使用保守 fallback summary 输出 summary(聊天式 Markdown) 概括 / 流程 / 完成状态 不产生 return_result 公共 payload ✓ handoff summary ✓ 安全步骤投影 默认 result = null 显式要求时才含 result 原始 task(只读) task-only guard 的唯一输入 原始 task 明确要求 在聊天返回正文? YES 从 state 读取 raw result 与 summary 分开携带 NO · result 保持 null 完整 result 正文不得进入 summary 输入 3 · 聊天消息 DOM 投影 ƒ 1. ExecutionStrip:只折叠执行树与 usage 2. Conclusion:成功显示 handoff;非成功显示确定性状态 / 错误 3. Direct result:仅 return_result=true 时存在 4. Footer:时间 / Copy / Retry / Edit / 版本导航,始终在最底部 capped / cancelled / interrupted / failed 状态 / 错误 Conclusion → footer
默认交付产物写文件;聊天自然概括做了什么、主要流程和最终完成状态,不强制引用或路径。
信任边界summary 模型和 agent preview 都不能授权返回正文,授权只读取原始 task。
失败隔离summary 调用失败只使用保守 fallback,不改变已经完成的 workflow 状态。

节点语言

ROOT · 菱形 User · 圆形 LLM · 三角形 Program / Function · 圆角正方形
空 session:直接运行 Program ROOT → PROGRAM
ROOT agentic_workflow Running...

外部动作本身就是一次可见运行。一个正方形节点已经完整表达它,不需要额外的参与者节点。

已有聊天:Program 与聊天轮次并列 ONE ROOT · TWO ACTIONS
ROOT User message LLM response agentic_workflow Running...

正常聊天仍然是圆形 User → 三角形 LLM。外部 Program 是 ROOT 下另一项显式动作,不伪装成一次聊天。

聊天记录:完全收起后的顶层 Program AVATAR + ONE LINE

专用头像区分顶层 Program 与普通助手消息。标题行沿用现有 Thinking/Functions 折叠条的字号、颜色和箭头,但信息更完整。点击展开后直接显示当前 RuntimeBlock,不重新设计内部函数调用。

聊天窗口视觉合同

只新增顶层外壳增加一个专用 Program 头像和一条压缩标题;展开区继续使用现有 RuntimeBlockTreeStep,消息 footer 保持聊天消息的独立层级。
只折叠执行过程参数、执行树和 usage 进入折叠区域;终态 Conclusion 与操作 footer 留在折叠区域之外。Conclusion 使用普通聊天正文排版,不使用 blockquote、左侧竖线或引用式缩进;footer 始终位于整条消息最底部,不随执行过程折叠。
标题摘要不调用模型压缩标题由现有结构化字段确定性生成:函数名、状态、时长,以及步骤数、输出预览或错误预览;终态 Conclusion 的 handoff 才使用独立 summary 调用。

压缩标题的四种状态

RUNNING
COMPLETED
Conclusion

这次工作流完成了资料读取、内容核对和结果整理。执行过程按任务要求保留了完整记录,没有把报告正文重复显示在聊天中。

  1. 读取并检查输入资料。
  2. 完成内容整理和一致性核对。
  3. 保存任务产物并检查执行状态。

任务已完成;没有需要用户继续处理的问题。

ERROR
Conclusion

工作流失败:Permission denied。

CANCELLED
Conclusion

工作流已取消;取消前记录了 3 个调用。

展开、收起与点击行为

用户动作或状态变化聊天窗口行为
运行刚创建立即显示专用头像和压缩标题。若用户未操作,沿用 ExecutionStrip 现有行为:Running... 时默认展开。
用户点击标题行只切换参数、执行树和 usage。终态 Conclusion 与消息 footer 均不随执行过程折叠。
展开状态内部完整复用当前函数调用展示;本设计不改变根函数行、嵌套调用、Details、Copy、Retry、Edit & re-run 或版本导航。
运行结束且用户没有操作过沿用现有 ExecutionStrip 逻辑自动收起并更新终态标题。成功完成且具有 workflow_handoff_v1 时,Conclusion 显示 summary handoff;capped、取消、interrupted 或失败态不调用 LLM summary,由前端生成确定性的状态或错误 Conclusion。footer 始终位于 Conclusion 之后。
用户已经手动展开或收起运行状态和事件更新不覆盖用户选择。
窄屏标题超过可用宽度保持单行并从尾部截断,箭头始终可见;完整标题保留为按钮的 accessible name。

运行状态只改变正方形,不替换节点

Running...分支色虚线描边
Completed分支色实线描边
Error错误色实线描边
Cancelled中性色实线描边

数据语义与可视投影

层面当前语义本设计规定
持久化手动顶层函数是一个 role=code 节点;caller 为空,predecessor 是当前 HEAD,空 session 时为 ROOT。不改变存储字段,不新增 synthetic User/LLM。
历史重载归属caller 表示调用所有权;predecessor 只保存 conversation layer 的时间顺序。caller 为空或 ROOT 时始终渲染为顶层 Program,即使 predecessor 指向 assistant。只有非空 caller 指向 assistant 时才收进该消息的 runtimeChildren;不得根据 predecessor 推断调用所有权。
DAG conversation layer顶层手动函数属于默认可见的 conversation layer;持久化 predecessor 仍指向创建调用时的 HEAD。会话概览使用派生的 ROOT → Program 投影边,把圆角正方形作为 ROOT 直接子级排版;这条概览边不写回存储,也不删除或改写 predecessor。详细图需要时间顺序时仍可读取原始 predecessor。
节点标签代码节点已有函数名、状态、参数和输出。图上至少显示函数名与现有英文状态;参数和输出进入 Details。
状态更新运行开始与结束更新同一 code 节点。节点位置与形状不变,只改变描边和状态文本。
聊天标题顶层 Runtime 已有函数名、状态、时间戳和 contextTree按“函数名 · 状态 · 时长 · 摘要”生成单行标题。状态词保持现有英文;时长由消息时间与当前时间或根节点 duration 派生。
标题摘要运行时可统计当前执行树节点数;结束后根节点已有 output 或 error。运行中显示当前可观察的执行树节点数;完成后显示单行输出预览;失败显示单行错误预览;取消显示当前可观察的执行树节点数。只压缩空白并截断,不调用 LLM。
终态结论summary 实际等于 workflow() 的完整返回值,会把报告正文误当成聊天总结。workflow 成功完成后调用一个独立的无工具 summary 函数。它读取原始任务、函数名与状态,以及执行记录中每个 function=agent 步骤最多 240 字的 operational handoff 预览;不读取调用参数、完整产物正文或任何非 agent 函数的结果摘要,避免中间结果经后续调用参数进入 summary。输出采用自然聊天结构:通常先用 2–3 句话概括,多阶段任务再用简短编号列出主要流程,最后判断任务是否完成;单阶段任务可以省略列表。引用、路径和警告只在有助于交接时出现,不作为固定字段。预览不得用于复述主题结论。完整产物默认写入当前 session 的工作目录并只保留在文件与 workflow state 中。
总结调用前端不会额外调用模型。新增的一次 LLM summary 调用只发生在后端 workflow 成功完成阶段,复用当前 session 已选择的 provider/model,禁用工具并要求 JSON 对象。调用失败或格式错误时使用不声称产物已完成的保守 fallback,不改变已完成状态,也不回退为显示完整产物。capped、取消、interrupted 和失败态不调用 LLM summary,但前端仍生成确定性的状态或错误 Conclusion。
公共 handoff schema完整 raw result、调用参数、错误正文与每步结果保存在 workflow state。summary_kind 固定为 workflow_handoff_v1summary 是简短的聊天式 Markdown,不限制为固定条数或固定字段;return_result 只由原始 task 的确定性 guard 计算,明确否定优先于直接返回措辞;result 默认是 null,只有 guard 为 true 时才读取 state 中的 raw result。公共 items 采用安全字段白名单,只保留步骤身份、状态、哈希与时间;公共 revisions 只保留版本和时间。调用参数、结果与错误正文均不进入公共 payload。
产物交付planner 示例允许 return findings 或直接 return agent(...),没有区分任务产物与 handoff。planner 和 SINGLE agent 的执行合同统一规定:报告、代码、表格等实质产物默认写入当前工作目录;最终返回描述已完成工作,以及有用的警告或后续操作,路径只在有助于交接时出现。只有任务明确要求“直接回答、返回正文、在聊天中给出”时才允许把正文作为直接结果。
展开内容函数内部调用通过 caller 形成 execution layer;聊天侧已有 RuntimeBlockTreeStep 和 Details。完整复用现有组件和交互,不增加 Planner、Agent 或 workflow 专用视觉层。
运行时选择直接运行仍属于当前 session;session picker 的 provider_override/model_override 是该 session 的模型选择,没有显式覆盖时由 session 的 agent 配置决定。父进程在创建函数子进程前解析同一选择,并把 provider/model 快照显式传入子进程。子进程不得重新使用全局自动检测覆盖 session 选择。
footer顶层 footer 已有时间、Copy、Retry、Edit & re-run 和版本导航。footer 不属于执行过程,始终放在整条消息最底部:有 Conclusion 时位于其后,无 Conclusion 时位于折叠标题后。其上方间距复用 assistant 正文到 footer 的 12px 段落间距;出现条件、按钮顺序和行为保持不变。

现状、参考与取舍

参考面已有能力缺口与决定
dag-layout-spec.htmlROOT=菱形、User=圆形、LLM=三角形、Code=正方形;场景 5 已定义手动函数。直接采用现有正方形,不增加新节点形状。
dag/overview.md区分 predecessorcaller,顶层手动调用只有一个 code 节点。保留存储中的 predecessor 时间顺序;会话概览单独派生 ROOT → Program 排版边,不补造调用者消息。
dag/rendering.md手动顶层函数属于 conversation layer,默认可见。当前看不到节点属于实现缺口,不通过修改数据模型解决。
当前 RuntimeBlock有 tree 时显示执行树,无 tree 时显示一个 running StepRow,顶层已有消息 footer。顶层外层复用 ExecutionStrip 的展开状态逻辑;只有执行内容和 usage 传入折叠区,现有 footer 在其外部原样渲染。嵌套调用的现有展示不变。
当前 ExecutionStrip运行中默认展开,结束后在用户未操作时收起,用户选择优先;标题采用小字和箭头。直接采用其状态规则和视觉密度,不另写 Program 专用折叠状态机。
新图框架无必要能力缺口;现有 SVG renderer 已支持 code 方块和状态描边。不引入 React Flow、Cytoscape 或其他依赖。

采用:现有 code 正方形、现有分支颜色、现有英文状态词、ExecutionStrip 折叠规则、RuntimeBlock 展开内容。
调整:顶层 Program 增加专用头像;压缩标题比 Thinking/Functions 更详细,包含函数名、状态、时长和结果摘要。
拒绝:虚构 User/LLM、单独新 lane、大卡片、百分比进度、workflow 专用内部时间线、用完整产物正文冒充工作总结。

本页边界:本页设计头像、顶层折叠标题和终态 Conclusion。展开后怎样画根函数、嵌套函数、参数、输出和错误,全部服从当前 RuntimeBlock;不为 agentic_workflow 增加专用内部流程设计。

已实现验收标准:summary 与聊天窗口

入口可观察结果
刷新已有聊天后的直接函数运行即使该运行的 predecessor 是上一条 assistant,空 caller 仍保持顶层 Program;具有 workflow_handoff_v1 的成功运行继续显示 Conclusion,消息 footer 始终可见。非空 caller 指向 assistant 的内部运行仍留在该 assistant 消息内。
聊天记录刚创建显示专用 Program 头像和“函数名 · Running... · 时长 · 步骤数”标题;运行中默认展开现有 RuntimeBlock
用户收起顶层运行头像、单行标题、已有的 Conclusion、可选 direct result 和消息 footer 保持可见;只有参数、执行树和 usage 不可见且不占布局空间。
聊天记录收到执行事件展开区继续由现有 TreeStep 更新;标题步骤数同步更新,用户手动展开/收起状态不被覆盖。
workflow 成功完成未手动操作时自动收起并更新为 Completed;后端独立 summary 调用生成简短的聊天式工作交接:先概括,多阶段时可用编号列出主要流程,最后判断是否完成;不强制引用、路径或固定条数,也不复述报告正文。时间与操作 footer 固定在 Conclusion 后,并与 Conclusion 保持 assistant 消息一致的 12px 段落间距。
workflow capped、取消、interrupted 或失败标题显示对应终态,不调用 LLM summary;前端根据终态、调用数和已有 error 生成确定性的状态或错误 Conclusion。footer 位于该 Conclusion 之后,二者都不进入折叠区域。
任务要求生成报告、代码或表格但未要求直接返回实质产物写入当前工作目录;Conclusion 概括完成步骤和完成状态,只有在有助于用户继续操作时才写路径,payload 不携带用于聊天渲染的完整结果。
任务明确要求直接回答或返回正文summary 函数仍生成工作总结;独立的 task-only 授权判断标记 return_result=true。Conclusion 在工作总结后显示完整直接结果。
任务明确否定在聊天中返回正文否定优先;summary 模型、agent preview 和“不写文件”等其他措辞不能把 return_result 改为 true,公共 payload 中的 result 保持 null。
summary 调用失败或返回格式错误显示保守 fallback,不声称文件已经生成;workflow 保持 Completed,完整 raw result 不进入公共 payload,错误只保存在 state。
窄屏与键盘标题保持单行、尾部截断且箭头可见;按钮支持键盘并暴露 aria-expanded,完整摘要可被辅助技术读取。
当前 session 选择了自定义 provider/model 后直接运行函数子进程使用相同 provider/model;不访问其他 session 或全局 picker,不因 provider 未列入内置 PROVIDERS 表而失败。
兼容性LLM 调用的普通内部工具仍按 execution layer 聚合;现有 User、LLM、merge、spawn 形状不变。

后续 DAG 投影验收标准

入口可观察结果
空 session 从 Programs 运行 agentic_workflowDAG 立即出现且只出现一个 ROOT 子级圆角正方形节点,标签为 agentic_workflowRunning...
已有聊天的 session 从 Programs 运行现有 User → LLM 结构不变;同一 conversation layer 增加一个由 ROOT 直接分出的 Program 节点。
概览投影处理已有 predecessor存储中的 predecessor 保持当前 HEAD;概览 renderer 根据空 caller 派生 ROOT → Program 排版边,不把 Program 误接成 assistant 的内部调用。
运行完成、失败或取消更新同一 Program 节点的描边和状态,不移动节点,不生成第二个结果节点。

本次实现任务

范围合同
生产文件agentic_workflow/__init__.py 增加独立 summary 函数、产物交付提示和结构化 handoff;runtime-summary.ts 只把带版本标记的 handoff 当作 Conclusion,并仅在 return_result=true 时暴露原始结果;runtime-block.tsx 在同一 Conclusion 中分开渲染工作总结与明确要求的直接结果。
公共入口从 Programs 或 fn-form 在会话中直接运行 agentic_workflow,刷新历史会话后也必须得到相同结论。
兼容与失败非 workflow 的 Function 行、运行中的 workflow、嵌套 LLM 工具调用保持现状;JSON 不完整、失败、取消时不得抛出渲染异常或伪造成功数字。
明确排除不新增依赖、不改变 DAG、不改变按钮内容、顺序或行为、不修改普通 assistant 消息和嵌套函数,不让 summary 函数使用工具或再次执行任务。
RED / GREENPython 公共入口测试先证明当前 SINGLE 与 programmed workflow 把完整结果放进 summary,再验证独立 summary 调用不接收完整结果、调用参数或非 agent 步骤结果,只接收 agent 的短 operational handoff;中间结果即使被后续调用参数引用,也只留在内部 state,不进入 summary prompt 或公共 payload。测试还覆盖默认不返回原始结果、明确直接返回时才携带结果、summary 失败时安全降级,以及 planner/SINGLE 的文件交付合同。npm run check:chat-ui 覆盖新 handoff、显式结果和旧 payload 不再显示完整正文;随后运行 Web typecheck、完整 Web check、文档链接与 diff 检查。

实现证据

聊天窗口实现:runtime-block.tsx 仅为顶层 Program 增加专用头像与 ExecutionStrip;执行树与 usage 作为同一折叠内容,footer 位于折叠区和 Conclusion 之后,并由 execution-strip.css 复用 assistant 消息的 12px 正文到 footer 段落间距;嵌套 LLM 工具调用保留原结构。成功态 Conclusion 只把带 workflow_handoff_v1 标记的内容当作工作总结,只有 return_result=true 时才在其后单独显示完整结果;capped、取消、interrupted 与失败态由 runtime-summary.ts 确定性生成状态或错误 Conclusion,不调用模型。旧 payload 的原始 summary 不再被当作工作总结。
后端实现:agentic_workflow/__init__.py 在 workflow 成功后调用一次独立的无工具 summary 函数。它接收任务、执行函数名、状态、原始结果长度,以及仅限 agent 步骤的 240 字 operational handoff;不接收调用参数、完整原始结果或其他函数的结果摘要。正文披露授权由只读原始 task 的确定性 guard 计算,不接受模型或 agent 输出。summary 格式错误或调用失败时生成不声称产物已完成的安全交接,并把错误只留在 state。planner 与 SINGLE agent 同时收到默认文件交付合同。调用参数、原始结果、步骤结果与错误正文继续持久化到 workflow state;公共 itemsrevisions 使用安全字段白名单,不公开这些正文。
自动检查:pytest -q tests/component/agent/test_agentic_workflow.py 的 35 项测试、完整 Web check、npm run build、Web tsc --noEmit、文档链接检查与 git diff --check 通过。测试覆盖默认隐藏原始结果、整个公共 payload 不含步骤正文或错误正文、中间结果经后续参数引用时仍不公开、agent preview 不能授权正文披露、中英文显式与否定返回措辞、明确要求时单独返回、summary 输入不含完整原始结果、调用参数与非 agent 步骤结果、summary 格式错误或调用失败时安全降级并只把错误持久化到 state、planner/SINGLE 文件交付合同、旧 payload 不再显示正文。
真实验收:历史会话中的旧 workflow payload 不具备 workflow_handoff_v1 标记,因此不再把旧的 12198 字任务结果显示为 Conclusion。新 handoff 的真实 18100 验收必须使用新建 workflow 运行,且只使用 /Applications/OpenProgram.app、默认 ~/.openprogram18100;不启动 18200。DAG 节点投影未在本次实现中改动。