Skip to content

L6 · 如何将 Agent 能力提供给用户和其他系统? - Application ​

所属知识库:Agent 全栈技术地图
所属领域:03 · Agent System
所属章节:02 · Agent System 是如何构建和运行的? - Technical Architecture
文档类型:应用架构、交互协议与工程实践研究
版本:v1.1
更新日期:2026 年 10 月 28 日
核心问题:Agent System 如何将 L1 - L5 的模型、执行、编排和治理能力封装为稳定、可理解、可操作的应用接口,使用户与外部系统能够安全地提交任务、查看进度、接收增量反馈、参与审批、控制执行、获取结果,并在异步运行、断线重连、重复请求、权限变化与故障条件下保持交互和交付的一致性?

专题导读 ​

本篇属 Technical Architecture。Agent System 的技术能力并不会自动转化为可使用的产品。即使 L4 Agent Engine 能够驱动模型与工具、L5 Orchestration 能够协调复杂任务,用户仍需要一种稳定方式表达意图、了解执行过程、干预关键操作、确认最终成果;其他软件也需要可靠的 API、事件和数据契约。L6 Application(应用层)研究的就是系统能力如何对外呈现、如何被调用,以及用户与业务系统如何在任务的整个生命周期中持续参与。

传统同步 API 往往以一次请求和一次响应为中心;Agent 任务可能运行数分钟乃至更久,期间会调用工具、生成中间产物、请求审批、等待外部事件、失败重试或被用户取消。因此,L6 不能只设计一个“聊天输入框”,也不能把内部 Token 流直接当成产品协议。它需要同时解决命令提交、任务资源、状态查询、事件订阅、人工决策、权限验证、产物管理、失败解释和版本兼容等问题。

本篇承接 L1 Infrastructure、L2 Platform Services、L3 Model Services、L4 Agent Engine、L5 Orchestration & Collaboration 的研究成果,以“技术研究报告 Studio”为贯穿案例,建立应用层的边界、接口模型、用户交互状态、异步通信、审批与取消、产物交付、外部集成和可验证的工程设计。重点区分内部执行事件与对外应用事件、命令接受与任务完成、界面显示状态与服务端权威状态、用户身份与 Agent 执行权限。文中 API 和事件 Schema 属于中立参考设计,不是任何框架的标准接口;资料来源与实际验证范围在文末说明。

一、研究定位:L6 的职责、边界与交付对象 ​

1.1 L6 在六层技术架构中的位置 ​

text
用户 / 浏览器 / 移动 App / 企业系统 / 外部 API 客户端
                          │
              L6 Application
     ┌────────────┼────────────┐
   任务 API      实时事件接口     审批与产物接口
     └────────────┼────────────┘
                          │ 受控命令与查询
              L5 Orchestration & Collaboration
                          │ 子任务 / 协作 / 汇总
                    L4 Agent Engine
                          │ 决策循环 / 工具执行
                    L3 Model Services
                          │
            L2 Platform Services / L1 Infrastructure

这里的分层是职责划分,不是要求部署六个服务。小型 Agent 应用完全可以将 API、执行器与数据库放在一个进程中;大型系统则可以拆分 API Gateway、Application Backend、事件推送服务和异步 Worker。L6 的边界在于对外契约:它不应把模型供应商协议、内部状态机实现、消息队列拓扑直接暴露为长期稳定的客户端接口。

层次核心责任对 L6 的主要供给
L1 基础设施计算、网络、隔离应用服务的运行条件
L2 平台服务数据、消息、身份、存储任务索引、事件、鉴权、产物
L3 模型服务模型协议、路由、计量模型能力与成本信息
L4 Agent Engine单个 Run 的执行运行状态、工具事件、终态
L5 编排协作跨任务协调工作流状态、审批节点、成果
L6 应用外部访问与交互契约用户可操作的产品能力

1.2 L6 应提供的六类对外能力 ​

  1. 任务入口:接收目标、输入材料、配置选择、预算与执行约束;验证请求并返回可追踪标识。
  2. 任务控制:允许查看、取消、暂停、恢复或重试,但操作是否可用取决于系统状态与权限。
  3. 状态与反馈:提供快照、进度、结构化事件和必要的实时更新。
  4. 人工参与:将审批、补充信息、修改要求和最终确认建模为有审计记录的操作。
  5. 产物交付:管理报告、数据、文件、引用、版本及下载权限。
  6. 外部集成:提供稳定 API、Webhook 或事件订阅,并处理重试、签名、版本与限流。

这六类能力不要求每个最小 Agent System 都具备。例如本地 CLI 只需任务输入和结果输出;若产品承诺长任务、审批和恢复,就必须提供相应契约。应用层的完整程度应由用户任务和风险决定,不由界面复杂程度决定。

1.3 应用层不等于 Agent Platform ​

L6 负责某个 Agent System 的能力如何被消费;Agent Platform 则研究多个 Agent 或 Agent System 如何被统一创建、注册、配置、治理和运营。一个研究报告 Studio 的任务页、审批页和结果页属于 L6;跨团队的 Agent 注册中心、租户管理、构建器和平台运营控制台则更接近 Agent Platform。两者可能共享 UI 组件和 API,但研究对象不同。

二、从用户意图到任务资源:应用契约的基本模型 ​

2.1 命令、查询、事件与产物必须区分 ​

**命令(Command)**请求系统改变状态,例如提交、取消、批准;**查询(Query)**读取当前权威状态;**事件(Event)**描述已经发生的事实;**产物(Artifact)**是可以独立访问、版本化和验收的输出。它们不能互相替代。收到 run.accepted 不意味着执行成功;看到 progress=90% 不意味着报告可交付;客户端发送 cancel 不意味着所有外部操作立即停止。

建议的外部资源模型:

text
Workspace / Project
  └── Task             用户目标与输入契约
       ├── Run         一次实际执行实例
       │    ├── Events  对外可见的状态与进度事件
       │    └── Approvals 待处理的人类决策
       ├── Artifacts   版本化输出
       └── Feedback    用户评价与修订请求

Task 与 Run 分离具有实际意义:用户可以对同一 Task 重新运行或比较不同配置,保留每次运行的结果与成本。若系统只支持单次运行,可以在实现中合并,但 API 最好不要让“任务定义”和“执行尝试”概念永久混淆。

2.2 创建任务的参考接口 ​

http
POST /v1/tasks
Authorization: Bearer <access_token>
Idempotency-Key: client-generated-unique-key
Content-Type: application/json
json
{
  "workspace_id": "ws-17",
  "task_type": "research_report",
  "input": {
    "question": "比较两种 Agent 工作流的恢复机制",
    "source_refs": ["artifact://input-17"]
  },
  "constraints": {
    "max_cost_usd": 5,
    "deadline_seconds": 1800,
    "require_publish_approval": true
  },
  "config_version": "research-studio@3"
}

参考响应:

http
HTTP/1.1 202 Accepted
Location: /v1/tasks/task-203
json
{
  "task_id": "task-203",
  "run_id": "run-001",
  "status": "QUEUED",
  "status_url": "/v1/runs/run-001",
  "events_url": "/v1/runs/run-001/events"
}

202 Accepted 表示服务器接受了异步处理请求,不承诺最终成功。对非法输入应返回明确的 4xx;对于已经存在的幂等键,服务器应根据其契约返回原请求结果或冲突,而不是默默创建第二个 Run。请求幂等键需要绑定调用身份、操作和请求摘要,设置保留期,并由可信存储原子保证去重。仅在内存里维护字典不具备跨实例可靠性。

2.3 API 资源与最小操作集合 ​

资源操作目的
/tasksPOST创建任务
/tasks/{id}GET查看任务定义
/runs/{id}GET查看运行快照
/runs/{id}/cancelPOST请求取消
/runs/{id}/eventsGET查询或订阅事件
/approvals/{id}GET/POST查看并提交审批决定
/artifacts/{id}GET查看产物元数据
/artifacts/{id}/downloadGET获取授权下载入口

这是教学用资源划分,不是必须采用的 REST 路由。实际设计可以使用 RPC、GraphQL 或其他协议,但必须保留等价的身份、资源、状态与错误语义。对重试、恢复、审批和产物版本的约束比 URL 命名更重要。

三、应用层状态模型:用户看到什么、系统实际处于什么状态 ​

3.1 不要将内部 Step 状态直接暴露为产品状态 ​

L4 可能拥有 MODEL_REQUESTED、TOOL_RUNNING、WAITING_TOOL_RESULT 等细粒度状态;L5 可能管理多个节点的 PENDING、BLOCKED 和 READY。如果前端直接依赖所有内部枚举,内部执行器一旦升级就会破坏 UI。因此应设计稳定的对外状态投影(Public State Projection)。

对外状态含义用户可执行动作
QUEUED已接受,等待执行查看、请求取消
RUNNING正在执行查看、请求取消
WAITING_INPUT需要补充信息提交信息、取消
WAITING_APPROVAL等待授权决定审批、拒绝、取消
PAUSED已暂停,等待恢复恢复或取消(按权限)
SUCCEEDED达到约定成功条件查看产物、反馈
FAILED无法按约定完成查看原因、重试
CANCELLED取消已生效查看历史

状态集由产品契约决定,不能机械套用;例如不支持暂停的系统不应暴露 PAUSED。取消请求应与取消完成分离:可以使用 CANCELLING 中间状态,或 cancel_requested=true 与当前运行状态组合表达。不能在用户点击取消的瞬间就声称外部副作用全部停止。

3.2 任务进度不一定可以量化为百分比 ​

Agent 任务会动态发现新子任务,分母可能变化。随意把工具调用次数映射为“完成 73%”容易误导。更稳妥的进度表示包括:当前阶段、已完成/总计的已知工作单元、最近活动时间、待处理阻塞、预计等待范围及不确定性。只有当工作量基准稳定且计算口径明确时才展示百分比。

json
{
  "run_id": "run-001",
  "status": "WAITING_APPROVAL",
  "phase": "evidence_review",
  "completed_nodes": 3,
  "known_nodes": 5,
  "progress_is_estimate": true,
  "pending_approval_ids": ["approval-4"],
  "updated_at": "2026-10-28T14:00:00Z",
  "version": 19
}

3.3 版本与并发控制 ​

应用快照应带 version 或 ETag。审批、编辑和恢复操作可以通过 If-Match 或请求中的 expected_version 做乐观并发检查:如果用户依据旧状态提交决定,服务器返回冲突并要求刷新,而不是覆盖后来发生的状态。客户端显示的状态是投影,服务端持久化状态才是授权与状态转换的依据。

四、实时反馈:轮询、SSE、WebSocket 与事件重放 ​

4.1 三种通信方式的适用条件 ​

方式优点局限与注意事项
轮询简单,兼容性好延迟与请求开销的权衡
SSE单向事件流,浏览器友好连接中断后需补齐事件
WebSocket双向、低延迟交互会话、鉴权、重连更复杂

对于研究报告生成、阶段进度、工具活动和审批提示,HTTP 命令 + GET 快照 + SSE 事件流通常是值得优先评估的组合。实时协同编辑、语音双向流或高频控制才更可能需要 WebSocket。SSE 并不保证业务事件恰好处理一次;WebSocket 连接成功也不意味着消息已经持久化。

4.2 外部事件必须是稳定的产品协议 ​

内部追踪事件可能包含 Prompt、工具参数、凭据、原始检索内容和模型中间信息,不能直接广播。应先经过权限检查、脱敏、归一化和可见性过滤,生成Public Event:

json
{
  "event_id": "evt-00042",
  "run_id": "run-001",
  "sequence": 42,
  "type": "run.phase_changed",
  "occurred_at": "2026-10-28T14:00:00Z",
  "schema_version": 1,
  "payload": {
    "phase": "drafting",
    "message": "已进入报告撰写阶段"
  }
}

对外事件应具备可排序的游标或序列号,但不应假设跨多个 Run 存在全局严格顺序。生产环境还要定义事件保留期、重复投递行为、缺失事件处理、快照同步和敏感字段过滤。

4.3 断线重连与快照校准 ​

推荐流程:客户端先读取权威快照和当前游标;再订阅后续事件;若服务端支持从游标恢复,则重放遗漏事件;如游标过期或出现序列缺口,重新读取快照。要避免“先读快照、后建立订阅”之间丢失事件,可采用服务端提供的一致性游标,或在订阅后进行二次快照校准。

text
GET /runs/{id} ─────► status + cursor=41
GET /runs/{id}/events?after=41
                     ├─ evt 42
                     ├─ evt 43
网络中断 ─────────────┤
重新连接 after=43 ────► evt 44, 45...
若游标过期 ──────────► 410/专用错误 → 重新拉取快照

SSE 的 Last-Event-ID 是传递恢复游标的一种机制;是否支持重放、重放多长时间由服务端应用实现决定。客户端需要以 event_id 去重,并且不能把消息到达顺序自动等同于任务因果顺序。

4.4 流式模型输出与最终交付 ​

模型 Token 流可以改善交互感受,但流式文本是过程性内容,不一定是最终产物。在工具调用、证据审查或报告修订中,前面显示的草稿可能被推翻。应区分 draft.delta、draft.replaced、artifact.ready 和 run.succeeded;对于需要引用和审查的报告,正式下载入口只应指向经过相应验收的版本。

五、人类参与:审批、澄清、修改与发布 ​

5.1 审批是持久化的业务对象 ​

不能只在前端弹出一个“允许/拒绝”按钮。审批应拥有独立 ID、关联的 Run/Step、请求操作、风险摘要、有效期、允许决策人、版本、状态与审计记录。L4/L5 进入等待态;L6 展示审批对象;用户提交决定;可信服务层验证身份与当前状态;执行器再恢复。

json
{
  "approval_id": "approval-4",
  "run_id": "run-001",
  "action": "publish_report",
  "target": "workspace:ws-17",
  "risk_summary": "将研究报告发布到团队共享空间",
  "request_digest": "sha256:...",
  "status": "PENDING",
  "expires_at": "2026-10-28T15:00:00Z",
  "version": 2
}

审批提交示例:

http
POST /v1/approvals/approval-4/decisions
If-Match: "2"
Content-Type: application/json
json
{
  "decision": "APPROVE",
  "comment": "仅允许发布已审核的 v3 报告",
  "artifact_version": "v3"
}

审批必须绑定具体操作与内容版本,否则“批准发布 v3”可能被错误地复用为“发布 v4”。高风险操作需要执行前再次验证审批、目标资源和权限。审批界面提供的是人的决策入口,真正的授权必须由服务端执行。

5.2 人类输入的不同语义 ​

  • 澄清(Clarification):补足任务必要信息,不应默认修改原始目标。
  • 审批(Approval):对某项明确操作授权或拒绝,必须绑定范围。
  • 修订(Revision):要求重新处理某个成果,通常创建新版本或新执行尝试。
  • 取消(Cancellation):请求终止后续工作,不能自动回滚已经发生的外部操作。
  • 最终确认(Acceptance):对交付物进行业务验收,不等同于执行器的技术成功状态。

在研究报告 Studio 中,“审核 Agent 通过”是自动质量门禁,“用户确认选题”是人类业务决策,“允许公开发布”是具有外部副作用的授权,三者不应合并成一个布尔字段。

5.3 审批失效与竞态 ​

审批请求可能在用户打开页面后已被撤销、过期、替换或执行。服务器应对重复决定返回幂等结果或冲突,并记录操作者、时间、目标版本及授权依据。客户端可以禁用按钮改善体验,但不能用按钮禁用替代后端检查。对等待时间很长的任务,还应定义超时后的默认行为,通常不应把“未响应”解释为自动批准。

六、任务控制:取消、暂停、恢复与重试 ​

6.1 取消是请求,不是瞬时事实 ​

取消可能跨越 API、编排器、Worker、模型服务和外部工具。典型流程是:L6 记录取消意图;L5 停止分配新子任务并传播取消;L4 尝试中断当前操作;工具网关处理可中断操作;系统最终记录 CANCELLED、FAILED 或其他合法终态。外部已经提交的邮件、付款或发布行为不能因为用户点击取消就自动撤销。

应明确取消的传播范围:仅当前 Run、当前子任务、整个 Workflow,还是所有子孙任务。取消必须检查权限、记录审计事件,并防止旧 Worker 在取消后继续提交结果。

6.2 暂停与恢复的前提 ​

暂停能力依赖 L4/L5 的可持久化状态与安全检查点;不是 UI 增加按钮就能获得。恢复时应重新检查任务配置、工具权限、审批有效性、输入资料可用性与执行版本。对模型调用中途的暂停,可能只能在下一个安全点生效,而不能从任意 Token 位置精确恢复。

6.3 重试与重新运行不是同一个操作 ​

内部重试处理同一执行尝试中的暂时性故障,必须有预算和副作用控制;用户重新运行通常创建新的 Run,允许使用新配置或新输入,并保留历史对照。对 FAILED 的 Run 不应简单把状态改回 RUNNING,否则事件历史、费用和版本难以审计。需要区分“从检查点恢复”与“从头创建新 Run”。

七、产物交付:从临时输出到可验收的结果 ​

7.1 Artifact 是独立资源,不是聊天文本的附件 ​

研究报告、数据集、代码文件、图像、引用清单和测试记录,应拥有可独立访问的元数据:artifact_id、task_id、run_id、version、content_type、size、checksum、status、provenance、created_at、retention_policy。文件内容通常放在对象存储或文件系统,数据库保存索引和访问控制信息。

json
{
  "artifact_id": "report-203",
  "run_id": "run-001",
  "version": 3,
  "content_type": "text/markdown",
  "status": "READY_FOR_REVIEW",
  "checksum_sha256": "...",
  "source_manifest_id": "sources-11",
  "created_at": "2026-10-28T14:20:00Z"
}

7.2 产物状态与运行状态分离 ​

run.succeeded 表示执行契约完成,但产物可能处于 DRAFT、READY_FOR_REVIEW、APPROVED 或 PUBLISHED。例如研究助理完成报告草稿后,Run 可以成功结束,但发布仍需要用户审批。反过来,某个 Run 失败时也可能保留有价值的中间资料;应允许按权限访问部分成果,并明确其未验收状态。

7.3 下载、安全与生命周期 ​

下载应由应用服务授权,可使用短期签名 URL 或代理流;签名 URL 是临时访问凭证,需要控制有效期、对象范围与泄露风险。不能因为客户端知道对象存储路径就允许任意下载。上传材料应进行大小、类型、内容与恶意文件风险检查;HTML、Markdown、脚本和富文本预览需要防止 XSS 与内容注入。数据删除、版本保留、法律保留与审计要求应与 H9 Data Governance 对齐。

7.4 来源可追溯性 ​

研究类 Agent 的最终报告应将关键结论映射到来源记录。来源至少包含原始地址或文档标识、访问时间、版本/摘要、引用片段定位及使用许可信息。引用链接存在不等于证据支持主张;L6 可以提供证据面板和来源跳转,但证据正确性仍需由相应的评估与审查机制判断。

八、面向外部系统的 API 与 Webhook 集成 ​

8.1 外部集成的典型模式 ​

  • 同步请求:适合短小、确定性、响应时间可控的操作;不应无限延长 HTTP 连接等待复杂任务。
  • 异步任务 API:创建任务返回 ID,客户端轮询或订阅状态,适合长任务。
  • Webhook:服务端主动通知外部系统任务状态变化;接收方需验证签名和处理重复事件。
  • 事件总线集成:适合内部多服务协作,但不应把内部消息格式直接当成公共 API。

8.2 Webhook 的安全与可靠性 ​

Webhook 应采用 HTTPS、端点验证、签名与时间戳、重放窗口、超时、重试上限、失败记录和必要的死信处理。至少一次通知是常见的工程选择,因此消费者必须按 event_id 幂等处理;发送端不能把 HTTP 200 自动解释为对方已经完成业务动作。签名验证需要使用原始请求体,不能在 JSON 重新序列化后直接比较摘要。

json
{
  "event_id": "evt-00046",
  "event_type": "artifact.approved",
  "schema_version": 1,
  "occurred_at": "2026-10-28T14:25:00Z",
  "resource": {
    "task_id": "task-203",
    "artifact_id": "report-203",
    "version": 3
  }
}

8.3 API 版本与兼容性 ​

公开 API 应明确版本策略、字段可选性、错误码、废弃周期和兼容窗口。新增枚举值可能破坏采用穷举匹配的客户端;应为未知状态提供安全回退。内部工作流可以频繁演进,但对外事件 Schema 和资源标识不宜随内部实现同步频繁变动。重大破坏性修改应采用新版本并提供迁移说明。

九、身份、权限与信任边界 ​

9.1 四种身份不可混同 ​

  1. 终端用户身份:谁提交任务、查看成果或批准操作。
  2. 工作空间/租户身份:资源归属与数据隔离范围。
  3. 服务身份:哪个 API、Worker 或后台服务正在调用其他服务。
  4. Agent 执行身份:某个 Run 被授予哪些工具与资源权限。

用户登录成功不意味着 Agent 可以继承用户所有权限。尤其是浏览器侧的 Access Token 不应被原样注入模型上下文。服务端应将用户授权转换为最小权限、可撤销、可审计的执行能力,并在实际工具调用前重新检查。

9.2 资源级授权 ​

访问 /runs/{id}、/artifacts/{id}、/approvals/{id} 时必须校验资源归属,而不是只验证 Token 是否有效。顺序 ID、可猜测 URL、跨租户任务引用都是典型风险。审批还需要额外校验角色、操作范围和目标版本。L6 的前端隐藏按钮不构成安全边界。

9.3 不可信内容进入应用层的风险 ​

Agent 输出可能包含恶意 Markdown、HTML、外链或诱导操作文本;工具返回可能夹带提示注入。应用层应把模型生成内容视为数据而非可信 UI 指令,使用安全渲染、URL 协议白名单、内容安全策略和必要的人工确认。任何会触发发布、支付、删除等高风险动作的交互,都必须走可信 API 的授权与审批流程。

十、可靠性与用户体验:应用层的故障模型 ​

10.1 区分四类失败 ​

失败类别例子对外处理
请求失败输入非法、未授权明确 4xx 与修正建议
受理失败服务暂不可用有界重试与幂等
执行失败工具超时、预算耗尽Run 终态、原因与可恢复性
展示失败事件断线、UI 崩溃重连、快照校准

前端断线不意味着 Agent 停止运行;API 返回 500 也不一定意味着任务没有创建。当创建请求的响应丢失时,客户端应使用同一个幂等键重试,而不是直接提交一个新任务。

10.2 对外错误结构 ​

json
{
  "error": {
    "code": "APPROVAL_VERSION_CONFLICT",
    "message": "审批对象已发生变化,请刷新后重试",
    "retryable": false,
    "request_id": "req-98",
    "resource_id": "approval-4"
  }
}

错误码应稳定、可文档化,避免向用户泄露内部堆栈、供应商密钥或敏感工具参数。对外错误要区分可重试、需人工处理、权限拒绝、预算终止和证据不足等语义。FAILED 不应被笼统翻译成“模型出了问题”。

10.3 超时、限流与背压 ​

应用层应有请求体大小限制、认证速率限制、并发任务配额、事件连接数限制、上传/下载带宽控制和排队反馈。队列拥堵时,明确返回排队状态、预计等待范围或 429/503 与 Retry-After(按具体语义),比静默接受无限任务更可靠。预算硬限制需要由服务端执行,不能只在前端显示预估费用。

10.4 可观测性与隐私 ​

应用层应为每个请求分配 request_id,并关联 task_id、run_id、workflow_id 和必要的 trace_id。建议观察创建成功率、任务受理延迟、事件推送延迟、审批等待时间、用户取消率、产物下载成功率、前端重连率及授权拒绝事件。日志不应默认保存完整 Prompt、用户文件和审批敏感内容;保留与访问策略需与 H1/H9 对齐。

十一、贯穿案例:技术研究报告 Studio 的应用架构 ​

11.1 用户旅程与后端契约 ​

text
创建 Studio / 选择研究模板
           │
填写研究问题、材料、预算、发布约束
           │ POST /tasks + Idempotency-Key
           ▼
     任务已接受(QUEUED)
           │
     选题 Agent → 审核 Agent
           │ 事件:phase_changed / approval_requested
           ▼
       用户确认选题
           │ POST /approvals/{id}/decisions
           ▼
    研究 → 分析 → 写作 → 审核
           │
    产物 v1 / v2 / v3 + 来源清单
           │
    用户验收与发布审批(可选)
           ▼
     已批准产物 / 下载 / 分享

用户在一个界面中可以看到:左侧阶段进度、中间 Agent 工作记录和审批、右侧产物版本、底部任务控制。但这些 UI 区域不应直接读写内部 Worker 数据库;它们消费的是 L6 提供的快照、事件、审批与产物 API。

11.2 关键时序:审批后恢复 ​

text
浏览器          L6 API          L5 Orchestrator       L4 Engine / L2
  │                │                    │                    │
  │ GET run        │                    │                    │
  │◄─ WAITING_APPROVAL + approval_id ───│                    │
  │ POST decision  │                    │                    │
  │───────────────►│ 校验身份/版本/范围 │                    │
  │                │──持久化决定────────►│                    │
  │◄─ 202/200 ────│                    │──恢复被阻塞节点─────►│
  │◄─ event: RUNNING ──────────────────│                    │
  │◄─ artifact.ready ──────────────────│◄──执行结果─────────│

应避免审批 API 直接同步执行耗时模型任务。更稳妥的方式是先原子提交审批决定,再通过可靠事件或任务队列恢复编排;浏览器随后观察状态变化。若 API 在决定提交后断线,重复请求应返回同一审批结果,而不是重复触发发布。

11.3 前后端职责划分 ​

前端:表单校验、状态展示、可访问性、重连提示、草稿与正式产物区分、确认操作、错误提示。L6 后端:身份与资源授权、命令校验、幂等、状态投影、事件过滤、审批记录、下载签发。L5/L4:真正的任务编排与执行。L2:可靠存储、消息、身份与产物底座。

前端可用乐观 UI 表示“取消请求已发送”,但最终状态必须由服务端事件或快照确认。不要让客户端自行推导“审核通过即可发布”等跨权限规则。

11.4 最小可行版本与演进 ​

阶段 A:个人原型。 单用户、单机执行、POST /tasks + GET /runs + 文件下载;简单轮询即可,重点先保证任务标识、终态和结果可追溯。

阶段 B:可交付 Studio。 增加持久化、审批对象、产物版本、SSE 事件、幂等创建、取消、权限校验和可诊断错误。

阶段 C:团队协作。 增加工作空间隔离、角色授权、共享审查、Webhook、审计、配额、任务历史和跨用户通知。

阶段 D:规模化运行。 在真实负载和风险要求下评估多实例 API、事件分发、租户配额、数据保留、灾难恢复与协议兼容。并非所有项目都需要走到 D。

十二、技术选型:协议、前端与后端如何组合 ​

12.1 不要从框架品牌开始选型 ​

应先回答:任务是否超过单次 HTTP 超时?是否需要双向实时通信?是否需要人工审批?用户是否会跨设备恢复?产物是否需要版本与审计?是否存在多租户?这些问题决定 API、存储、事件和 UI 的基本架构,然后再选择实现框架。

需求优先考虑额外成本
简单短任务同步 HTTP超时与阻塞
长任务异步 Task/Run API状态与持久化
阶段实时反馈SSE + 快照游标与重连
双向实时交互WebSocket会话管理
企业集成Webhook / API签名、重试、版本
高风险操作持久审批资源权限与审计

12.2 代表性技术的定位 ​

  • FastAPI / Starlette:可用于 Python HTTP API、异步处理和流式响应;是否具备可靠长任务执行取决于外部任务系统与持久化设计,不能把 Web 框架的后台任务功能当成生产级工作流引擎。
  • Next.js / React:可用于研究 Studio 的交互界面、表单、状态视图与产物展示;不能依赖浏览器作为权威任务状态存储。
  • OpenAPI:适合描述 HTTP API 契约、Schema 和客户端生成;不自动定义业务幂等、审批语义和异步任务生命周期。
  • CloudEvents:可作为事件封装的参考规范,但具体 Agent 事件类型、授权和交付保证仍需自行定义。
  • OpenTelemetry:适合跨请求与执行链路的观测关联;Trace 不是可直接供用户重放的持久业务事件日志。

上述属于技术定位而非最新版本兼容性认证;真实实现需核对框架文档、版本和部署环境。

十三、工程实践:最小应用契约实验与验证计划 ​

13.1 实验目标与范围 ​

本篇提供一个纯 Python 标准库的可运行契约实验,用于说明任务创建幂等、状态转换、事件游标、审批版本冲突和产物就绪判定。它是内存中的确定性模型,不包含 HTTP 服务器、真实 Agent、数据库、身份服务或分布式 Worker。实验结果只能支持这些模拟不变量,不能证明生产安全性。

配套文件 L6-Agent-System-Application-v1.1-demo.py,Python 3 标准库(含 3.9)。运行:python3 L6-Agent-System-Application-v1.1-demo.py。

python
from __future__ import annotations

from dataclasses import dataclass, field


@dataclass
class Run:
    run_id: str
    status: str = "QUEUED"
    version: int = 0
    events: list = field(default_factory=list)

    def change(self, new_status):
        allowed = {
            "QUEUED": {"RUNNING", "CANCELLED"},
            "RUNNING": {"WAITING_APPROVAL", "FAILED", "SUCCEEDED", "CANCELLED"},
            "WAITING_APPROVAL": {"RUNNING", "CANCELLED"},
            "FAILED": set(), "SUCCEEDED": set(), "CANCELLED": set(),
        }
        if new_status not in allowed[self.status]:
            raise ValueError("illegal transition")
        self.status = new_status
        self.version += 1
        self.events.append((self.version, "run.status_changed", new_status))

    def after(self, cursor):
        return [event for event in self.events if event[0] > cursor]


class App:
    def __init__(self):
        self.requests = {}
        self.runs = {}

    def create(self, principal, key, digest):
        identity = (principal, key)
        if identity in self.requests:
            old_digest, run_id = self.requests[identity]
            if old_digest != digest:
                raise ValueError("idempotency key reused with different request")
            return self.runs[run_id]
        run_id = f"run-{len(self.runs) + 1}"
        run = Run(run_id)
        self.runs[run_id] = run
        self.requests[identity] = (digest, run_id)
        return run


def decide_approval(run, expected_version, approve):
    if run.version != expected_version:
        raise ValueError("approval version conflict")
    if run.status != "WAITING_APPROVAL":
        raise ValueError("approval not pending")
    run.change("RUNNING" if approve else "CANCELLED")


def test_contract():
    app = App()
    run = app.create("user-a", "key-1", "digest-1")
    assert app.create("user-a", "key-1", "digest-1") is run
    assert len(app.runs) == 1
    try:
        app.create("user-a", "key-1", "different")
        assert False
    except ValueError:
        pass
    run.change("RUNNING")
    run.change("WAITING_APPROVAL")
    assert len(run.after(1)) == 1
    try:
        decide_approval(run, expected_version=1, approve=True)
        assert False
    except ValueError:
        pass
    decide_approval(run, expected_version=2, approve=True)
    run.change("SUCCEEDED")
    assert run.status == "SUCCEEDED"
    assert len(run.after(0)) == 4
    print("PASS: idempotency, conflict, cursor, approval, terminal state")


if __name__ == "__main__":
    test_contract()

本地执行通过:输出 PASS: idempotency, conflict, cursor, approval, terminal state。

13.2 实验不覆盖的关键生产条件 ​

内存字典无法在进程崩溃后保留幂等记录;没有并发锁就不能保证跨线程/实例原子性;Run.version 不是数据库事务;示例没有鉴权、审批对象签名、事件持久化、真实网络断线或外部副作用。因此不能直接将其用作生产 API。真实系统需要把幂等表、任务状态、审批决定和事件 Outbox 置于明确的事务与一致性策略之下。

13.3 建议的集成验收矩阵 ​

场景故障注入必须验证的结果
创建请求重试丢失响应同一幂等键不重复创建
并发审批两人同时决定至多一个有效状态变更
SSE 断线断网后恢复不丢关键状态、可校准
取消传播Worker 正在调用工具终态与副作用如实记录
越权下载跨租户对象 ID服务端拒绝
Webhook 重试接收方超时重复通知可去重
产物覆盖并发生成 v2/v3版本与校验和不混乱
发布审批审批后替换产物旧批准不能授权新版本

13.4 实施步骤 ​

首先明确 Task/Run/Artifact/Approval 的资源契约与状态机;其次定义身份和资源授权;再实现幂等创建、快照查询、事件游标与产物元数据;随后接入 L5/L4 的真实执行结果;最后加入审批、取消、Webhook、限流、观测和故障测试。建议从单体应用开始,只有在并发、组织边界或独立扩缩容需求明确时再拆分服务。

十四、常见设计误区与修正 ​

误区风险修正
聊天流就是任务状态断线后无法恢复独立 Run 快照与事件
202 等于任务成功过早交付明确受理与终态
取消按钮可立即终止一切外部副作用仍存在取消请求与生效分离
模型输出可以直接驱动 UI 操作注入与越权可信命令 API
前端角色判断就是授权可被绕过服务端资源级鉴权
审批一个布尔值就够版本错配与重放持久审批对象
SSE 自动保证不丢事件断线缺口游标、重放与快照
产物就是最后一条消息无版本与证据独立 Artifact 资源
Webhook 只会投递一次重复业务动作事件 ID 幂等
Trace 可以直接展示给用户泄露敏感数据事件投影与脱敏

十五、研究结论与下一专题 ​

L6 Application 的核心职责,是把 Agent System 内部复杂、异步且可能不确定的执行过程,转化为稳定、可信、可恢复、可理解的外部交互契约。它不只是用户界面,也包括 API、任务资源、事件协议、审批、控制操作、产物版本、身份权限和外部系统集成。

本篇形成五项关键工程判断。第一,任务接受、执行状态、审批状态与产物交付必须分别建模,不能由聊天消息推断;第二,长任务优先考虑异步资源模型,实时流是体验增强而非唯一事实来源;第三,取消、审批和重试都是需要持久化与权限校验的状态转换;第四,外部产物应版本化、可追溯、可独立授权;第五,应用层的稳定协议应隔离内部 Agent Engine、编排框架和模型供应商的变化。

至此,「02 · Agent System 是如何构建和运行的? - Technical Architecture」 的 L1 - L6 六层技术研究形成完整闭环:从基础设施、基础软件、模型服务、Agent 执行、任务编排到应用交付。下一章节应先研究 「03 · 如何让 Agent System 稳定、安全、可控地运行? - Engineering & Governance」 的章节概述与研究导读,再进入 H1 Observability 等专题,而不直接跳过章节总纲。

附录 A:参考文献与原始资料入口 ​

以下为本篇涉及的官方规范和技术文档入口。它们用于说明协议语义和工程实践的来源;本篇未实时逐页核验各资料在 2026 年 10 月 28 日的最新版本,也未开展外部框架源码审计。实施时需确认所用规范版本、供应商部署环境和具体 API 行为。

  1. HTTP Semantics - RFC 9110:www.rfc-editor.org/rfc/rfc9110。HTTP 状态码、方法和条件请求语义。
  2. HTTP Conditional Requests - RFC 9110:同上,ETag 与 If-Match 的条件请求机制。
  3. Server-Sent Events - WHATWG HTML Living Standard:html.spec.whatwg.org/multipage/server-sent-events.html。EventSource、事件 ID 和重连机制。
  4. WebSocket Protocol - RFC 6455:www.rfc-editor.org/rfc/rfc6455。双向连接与协议基础。
  5. OpenAPI Specification:spec.openapis.org/oas/latest.html。HTTP API 描述与契约。
  6. CloudEvents Specification:cloudevents.io。事件封装格式与上下文属性。
  7. OAuth 2.0 Authorization Framework - RFC 6749:www.rfc-editor.org/rfc/rfc6749。授权框架基础;实际部署还需核对后续安全最佳实践。
  8. OWASP API Security Top 10:owasp.org/API-Security。对象级授权、认证与 API 风险。
  9. OWASP Cross Site Scripting Prevention Cheat Sheet:cheatsheetseries.owasp.org/cheatshee...n_Cheat_Sheet.html。不可信内容安全渲染。
  10. OpenTelemetry Documentation:opentelemetry.io/docs。请求追踪、日志与指标关联。
  11. FastAPI Documentation:fastapi.tiangolo.com。Python Web API 与流式响应实现参考。
  12. Next.js Documentation:nextjs.org/docs。React 应用与服务端能力参考。
  13. PostgreSQL Documentation - Transactions:www.postgresql.org/docs/current/tutorial-transactions.html。状态与审批事务实现参考。
  14. Amazon S3 - Presigned URLs:docs.aws.amazon.com/AmazonS3/latest/...tPreSignedURL.html。临时授权对象访问的典型机制。
  15. LangGraph - Persistence:docs.langchain.com/oss/python/langgraph/persistence。Agent 执行状态与检查点的衔接。
  16. OpenAI Agents SDK - Running Agents:openai.github.io/openai-agents-python/running_agents。执行循环与运行控制参考。

附录 B:研究证据、实现与验证声明 ​

研究定位。 本篇是 Agent System L6 应用层的技术架构研究。Task、Run、Approval、Artifact、Public Event 等数据结构、路由、状态枚举、Studio 时序和工程检查表属于中立参考设计,并非某个官方 Agent 协议或行业统一规范。具体产品可按任务范围调整,但应保持状态、权限、事件和产物语义清晰。

资料边界。 HTTP、SSE、WebSocket、OpenAPI、CloudEvents、OAuth、对象存储和 Agent 框架的技术定位参照公开规范与官方资料。文中关于“优先考虑 HTTP + 快照 + SSE”的表述是条件化的工程建议,不是对所有应用的性能基准结论。未实时核验最新文档版本或特定产品的兼容性。

实验边界。 第十三节的 Python 示例是内存中的确定性契约实验,不使用真实 Agent、数据库、HTTP 服务、SSE、Webhook 或权限系统。它只能检查有限的状态与幂等不变量。即使本地运行通过,也不证明生产级并发安全、跨进程恢复、网络重连、越权隔离或实际审批可靠性。

尚待验证。 多实例幂等创建、审批事务竞态、事件持久化与重放、SSE 断线恢复、Webhook 签名与重复投递、跨租户授权、对象存储下载权限、取消传播和发布副作用,需要在具体技术栈中进行集成测试、故障注入和安全审查。所有上线结论都必须附带环境、版本、任务分布、权限模型和验收证据。