1. 结论与边界
这次重构不新增第三个 Agent 抽象,也不把 session Job API 包装成另一个公共函数。公共语义保持在 agent();持久化和分支属于运行环境,不属于 Workflow 编写接口。
共用执行入口
agent() 与配置化 Agent 调用使用同一自主工具循环。
普通 Agentic Function 不调用它,只允许一次 llm();完整分类合同见编程模型与分类。Workflow 内的 agent() 在当前 Runtime 中运行并形成父子 Call 关系。
内部 session 适配
run_agent_turn() 只服务于 Chat、CLI、后台 Job 和真正独立的 sub-agent。它负责创建会话分支、抢占 worker、恢复 Job 和移动 session head,不得被 Programs 直接导入。
2. 当前实现:已核对的事实
agent() 已使用当前 Runtimeopenprogram/agentic_programming/agent.py 调用 runtime.exec(..., execution_kind="agent"),因此本来就适合在 Workflow DAG 内运行。
run_agent_turn() 是持久 Job 入口它创建或恢复 session Job,处理 worker claim、branch、head、archive、chain depth 等会话生命周期。
create_workflow 的编写经 _run_planner_turn() → agent() 执行,归属当前 Workflow 的 public Agent Call;run_agent_turn() 仍仅供 Chat/CLI/Job。
agent() 已支持结构化结果公共 agent() 已把 response_format 透传到当前 Runtime,并原样返回经过验证的 JSON value;Workflow 规划器仍解析 JSON 文本。
| 位置 | 当前职责 | 问题 | 目标 |
|---|---|---|---|
agentic_programming.agent | 当前 Runtime 内工具循环 | 参数能力不完整,DAG 标签不够明确 | 扩展为唯一公共 Agent 合同 |
agent.sub_agent_run | 会话分支和 durable Job | 被 Workflow 内部规划直接调用 | 只保留为内部生命周期适配层 |
| Workflow 管理与入口 | search_workflows、create_workflow、revise_workflow,以及 workflows/auto_workflow.py | 旧复合入口曾混合不同副作用 | 前三项保留为可复用管理函数;完整自动流程位于 workflows/ 并保持独立注册 |
Runtime.exec | 统一 LLM/工具循环底层 | 公共参数未完全上浮 | 继续作为唯一 Agent loop 内核,不公开 session 语义 |
3. 目标架构:两个适配入口,一个执行内核
差异只存在于执行前后的生命周期:Program 路径复用当前 Runtime;session 路径先创建 durable Job。模型循环、工具选择和错误语义保持相同。
4. 四个运行原语的固定层级
Workflow 位于最高层,可以直接选择 llm()、agent()、goal() 或普通 Python Functions。goal() 基于 agent();agent() 基于 llm()。这是依赖关系,不要求每个 Workflow 都经过全部层级。
| 原语 | 公开语义 | 是否持久 session | DAG 记录 |
|---|---|---|---|
llm() | 恰好一次逻辑模型请求;允许结构化输出 | 否,继承当前 Runtime | 一个 LLM Call |
agent() | 同一任务内的模型—工具循环;返回最终文本或结构化结果 | 否,继承当前 Runtime | 一个 Agent Call,内部含 LLM 与 Function Calls |
goal() | 用 Agent 尝试,再用独立 judge 判断是否满足目标;Programs 默认隔离调用前历史,/goal 显式传入当前 session 视图 | 是,写入所属 session 的同一 GoalState | Goal → Agent → Goal judge |
run_agent_turn() | 内部会话生命周期适配,不是 Program 原语 | 是 | session/branch 关联的独立 Agent Call |
目标公开签名
def agent(
prompt: str | list[dict],
*,
description: str = "",
agent_id: str = "",
model: str = "",
effort: str = "",
tools: Sequence[str] | None = None,
response_format: dict | JsonSchemaOutput | None = None,
max_iterations: int = 20,
timeout_s: float | None = None,
) -> str | dict | list | int | float | bool | None:
...
description 只影响可见标签和 Call metadata;agent_id 复用 Agents 页面已有 profile resolver;显式 model/tools 覆盖 profile 对应字段。公开签名不加入 session_id、branch_from、advance_head、archive_when_done 或 run_in_background。
5. Self Programming Workflow 的目标流程
公共行为已经拆为 search_workflows、create_workflow、revise_workflow 和用户手动入口 auto_workflow(task)。Chat Agent按需直接调用前三类能力或具体Workflow;只有用户手动运行完整流程时才进入 auto_workflow。本节只描述它们如何使用公共 agent();完整合同以发现、创建与自动执行为准。
create_workflow 的author与确定性validator生成并发布多文件Python package;显式修改由 revise_workflow 独立负责。| 阶段 | 允许能力 | 明确输出 | 可观测性 |
|---|---|---|---|
| 搜索与选择 | 只读catalog与候选元数据 | 固定 revision,或 create 决策 | search函数与一个selection Agent节点 |
| 验证与发布 | 纯 Python 校验和文件操作 | revision、依赖清单、验证诊断 | Function Call 节点 |
| 创建重试 | 同一未发布candidate、明确诊断、有限轮数 | 通过门禁的新candidate | create_workflow 下的Agent节点 |
| 执行 | Workflow 声明的 Programs | 文件交付物或明确 return_result | 完整嵌套 DAG |
| 总结 | 运行事件和交付物元数据 | 过程性 summary,不复制完整正文 | Conclusion 区域 |
6. DAG 与聊天显示合同
重构后的首要验收不是“函数返回了 JSON”,而是用户能看到 Workflow 如何选择、如何创建、实际调用了哪些 Programs,以及错误发生在哪一层。
| 界面层级 | 默认显示 | 展开后显示 |
|---|---|---|
| 顶层 Workflow | 名称、状态、耗时、步骤数、完整 Conclusion | 选择/编写 Agent、校验、实际 Workflow、summary |
| Agent | 描述标签、状态、迭代数 | 模型输出摘要和真实 Programs 调用;不展示隐藏 chain-of-thought |
| Program Call | 名称、参数摘要、状态 | 输入、输出、错误和 side panel 详情 |
| sub-agent session | 单独的可跳转行 | 切换到子 session;返回后仍保持同一行,不变成另一套卡片 |
7. 失败、恢复与状态一致性
| 失败点 | 处理规则 | 用户可见状态 |
|---|---|---|
| provider/model 不支持结构化输出 | 能力探测后使用文本 JSON + 本地 schema 校验;不得把内部 LLM 错误覆盖成 Workflow completed | 对应 Agent/LLM Call error,顶层 Workflow failed |
| 候选 Workflow 校验失败 | 把确定性诊断交给有限次数的 public agent() 修复;达到上限则失败 | 每次 repair 是可展开 Agent 节点 |
| worker 重启 | 只有 session/Job 路径使用 durable recovery;Program 内 Agent 随父 Call 终止并由父 Workflow 重试策略处理 | 不把旧 running 状态永久保留 |
| 用户取消 | 同一个 cancellation token 传到 Runtime、provider 与工具执行;子调用先终止,再关闭父 Workflow | cancelled/interrupted 一致,不显示 completed |
| 工具或子 Workflow 失败 | 保留原始 error payload、caller 和 partial artifacts;summary 不宣称完成 | 失败节点与 Conclusion 状态一致 |
| 历史 run 恢复 | 旧的 SINGLE/code.py 状态仅用于旧 run 恢复;任何新 task 必须进入项目选择/创建流程 | 旧记录可读,新记录不再产生 legacy project |
8. 分阶段迁移计划
每个阶段先添加能复现当前缺口的测试,再修改对应层。禁止在同一阶段同时改公共 API、session lifecycle、Workflow 文件布局和聊天视觉样式。
冻结执行合同
- 记录当前
agent()、run_agent_turn()和 Runtime 调用图。 - 增加架构测试:Programs 不得导入
agent.sub_agent_run。 - 增加真实注册 schema 测试,固定四个Workflow管理函数的公开参数。
补全 public agent()
- 透传
response_format、content blocks、description 和 agent profile。 - 复用现有 profile/tool resolver,不新建配置格式。
- 增加 Agent wrapper Call,使 LLM 和工具节点稳定归属。
拆分 Workflow 公共行为
search_workflows保持确定性只读。auto_workflow的selection Agent只决定reuse/create,不写文件、不自动revise。- author、写入与发布前验证分别属于
create_workflow和revise_workflow。
收紧 session 适配层
run_agent_turn()保持内部,继续支持 branch、Job、recovery、archive。- 确认 dispatcher 最终调用与 public agent 相同的 Agent loop 内核。
- 去除重复的模型默认值、工具解析和错误规范化。
迁移所有 Programs
- 扫描
openprogram/programs/对内部 Agent API 和直接 loop 的调用。 - Workflow 与 Application 统一使用 public
agent();普通 Agentic Function 只允许一次llm()。 - 保留 vanilla sub-agent 工具作为 session adapter 的产品入口。
DAG 与聊天展示
- 后端事件补充 execution_kind、label、caller、iteration 和 artifact metadata。
- 前端按同一 Runtime hierarchy 渲染,不推断独立结构。
- Conclusion、footer 和折叠逻辑沿用现有统一组件。
兼容清理与发布
- 旧 run 只读恢复;新 run 禁止 legacy SINGLE。
- 删除失去调用方的 planner helper 和重复测试 fixture。
- 更新设计导航、API 文档和 Programs 依赖图。
受控上线
- 先运行 focused component tests,再运行必要的完整套件。
- 用一个 reuse、一个 create、一个 repair、一个 cancel 的真实会话验收。
- 保留旧恢复读取器一个兼容周期,不再写旧格式。
9. 兼容、保留与删除项
| 对象 | 处理 | 原因 | |
|---|---|---|---|
agent() | 保留并扩展;旧参数继续工作 | 已经是 ambient Runtime 内的正确公开原语 | |
run_agent_turn() | 保留但标记 internal;禁止 Programs 导入 | Chat/CLI/background 的 durable session 需求真实存在 | |
_run_planner_turn() | Workflow selection/authoring 调用 public agent() | Programs 内规划不再 import run_agent_turn | 保留为 agent(tools=PLANNER_TOOLS) 薄包装;后续可删除 |
_request_project_decision() | 用单一编排 Agent 的实际工具行为替代 | 先输出 selection JSON 再编写造成两次 Agent 语义和断裂 DAG | |
legacy SINGLE / code.py | 只读恢复,禁止新建 | 保留历史记录但不继续产生不可维护单文件 Workflow | |
| 工作流项目包 | 继续使用标准 Python package 和显式 Agent 方法或函数导出 | 支持多文件维护、Git revision、静态依赖图和直接 Python 调用 | |
| Agents profile | 复用现有 Agents 配置与 resolver | 避免 Program 内出现第二套模型/工具配置 |
10. 验收矩阵
API 与注册
- Registry只包含
search_workflows、create_workflow、revise_workflow与auto_workflow;分类目录不注册。 agent()的 model/tools/profile 覆盖顺序稳定。- 结构化输出在支持和不支持原生 schema 的 provider 上都可验证。
调用结构
- selection属于
auto_workflow;author与发布前重试属于create_workflow或revise_workflow。 - Workflow 调用的 Programs 均出现在 DAG。
- direct/manual Workflow 不因 predecessor 被误归到上一条 assistant。
生命周期
- 父取消会终止 Agent、LLM 与工具。
- session Job 重启后只恢复 session 路径。
- 新 run 不生成 SINGLE;旧 run 仍能恢复或给出明确不兼容错误。
界面
- 折叠态显示 Workflow 标题、Conclusion、footer。
- 逐级展开,不一次展开全部子节点。
- App/Web/TUI 读取同一默认 profile 和 18100 worker。
建议的定向检查
pytest -q tests/component/agent/test_agentic_workflow.py
pytest -q tests/unit/programs/dag/test_runtime_exec_dag.py
pytest -q tests/unit/agent/workflows/test_agentic_programming_goal.py
pytest -q tests/component/agent/jobs/test_async_job_recovery.py
pytest -q tests/unit/agent/jobs/test_spawn_caller_invariant.py
pytest -q tests/component/webui/abilities/test_programs_explorer.py
npm --prefix web run check:chat-ui
npx --prefix web tsc --noEmit
python -m scripts.docs_site.checklinks
git diff --check
11. 框架对照与取舍
这里只比较与本次架构决策直接相关的能力。OpenProgram 不引入新的第三方编排运行时。
| 参考 | 采用 | 不采用 |
|---|---|---|
| OpenAI Agents SDK · 运行 agent | Runner 维护一个逻辑 turn 的模型—工具循环;max turns、session、hooks 分开表达。 | 不把 Runner 作为 OpenProgram 的第二个运行时;继续使用现有 Runtime/dispatcher。 |
| OpenAI Agents SDK · 工具 | Python function tool 和 agent-as-tool 都是明确调用,父级可观察子执行。 | 不把 Workflow 隐式转换为 handoff;Workflow 仍是 Python package。 |
| OpenAI Agents SDK · 编排 | 区分 manager 调用子 agent 与把控制权 handoff 给另一 agent。 | Program 内 agent() 不自动创建 session 分支;只有产品级 sub-agent 操作才切 session。 |
| LangGraph · 工作流与 agent | Workflow 是预定代码路径,Agent 在局部动态决定工具调用。 | 不新增图 DSL;静态调用图从 Python imports 与显式入口身份 生成。 |
| LangGraph · 持久化 | 持久化、thread、checkpoint 和中断恢复应是显式生命周期能力。 | 不把所有 Program 内 Agent 强制变成持久 thread;仅 session adapter 使用 durable Job。 |
12. 实现状态
llm()、agent()、goal()三者已经以 ambient Runtime 为基础,层级方向可保留。
response_format、tools、model、effort、timeout、execution_kind 等底层能力已经存在。
agent()workflow._run_planner_turn() 调用 openprogram.agentic_programming.agent()(受限 PLANNER_TOOLS);auto selection 有 AUTO_DECISION_ATTEMPTS 上限。四个注册入口与源码分类的权威合同见authoring设计页。
agent() 仍用 session adapter旧版 code.py 执行路径的 _agent_function() 仍绑定 session turn;项目 snapshot 执行已使用 public agent()。
组件测试已覆盖 reuse/create/revise/pin/resume;默认 App 中 selection Agent 节点、Conclusion 与 reload 行为仍待验收。
agent() 结构化输出透传公共 agent() 已接受裸 JSON Schema 或 JsonSchemaOutput,并原样返回 Runtime 验证后的 object、array、scalar 或 null。未请求结构化输出时继续保留文本和 legacy {"text": ...} 兼容行为;Workflow 规划器迁移不属于这项实现。