第一章:系统架构设计

企业内部建设 Agent 平台,最容易出现两个问题:一开始就拆出很多服务,系统看起来完整但无法快速上线;或者只实现一个模型调用页面,缺少权限、版本、任务恢复和审计,无法进入真实业务环境。

本章给出一个可以开发、部署和上线的精简方案。它同时支持多租户、单 Agent 和多 Agent,但只保留生产运行需要的模块。

1. 系统定位

这个系统是一个支持多租户隔离,同时支持单 Agent 和多 Agent 协作的企业内部应用。

  • 多租户解决数据和权限属于谁:不同租户的用户、Agent、知识、任务、密钥、日志和用量必须隔离。
  • 单 Agent用于多数简单任务:一个 Agent 直接调用模型和工具,链路短、成本低、容易排查。
  • 多 Agent用于需要分工的复杂任务:主 Agent 拆分任务,成员 Agent 分别执行,最后统一汇总。

多租户和多 Agent 是两个维度。一个租户可以只有一个 Agent,也可以维护多个 Agent 团队。平台不强制所有任务都使用多 Agent。

2. 建设范围

2.1 直接建设的功能

  1. 统一 Web 控制台和 OpenAPI。
  2. 租户、成员和角色权限。
  3. Agent 与 Agent Team 配置、版本发布和回滚。
  4. 单 Agent 执行,以及主 Agent 调度成员 Agent。
  5. 在线调试、固定用例回放和版本对比。
  6. 任务状态、运行轨迹、工具审批、审计和 Token 用量。

2.2 采用简单实现的部分

  • 审批只支持单级人工确认。
  • 用量按 Token 汇总,暂不建设复杂计费系统。
  • 编排只支持顺序、并行和主 Agent 分派。
  • 模型适配和工具适配作为 Worker 内部模块。
  • 所有 Agent 共用 Worker 池,不为每个 Agent 单独部署服务。
  • 复用公司现有网关、SSO、消息队列、密钥和监控系统。

3. 核心概念

概念含义关键关系
Tenant数据与权限的隔离边界拥有用户、Agent、团队、任务和密钥引用
Agent包含提示词、模型、知识和工具权限的执行角色发布后生成不可修改的 Agent Version
Agent Team多个 Agent 的协作定义指定主 Agent、成员、调用关系和运行上限
Task用户提交的一次完整请求绑定 Agent Version 或 Team Version
Run某个 Agent 在任务中的一次运行子 Run 通过 parent_run_id 关联父 Run
Step一次模型调用、工具调用或任务委派属于 Run,按 step_no 保存输入和输出

任务开始后必须固定 Agent 或团队版本。管理员随后修改提示词或工具时,新任务使用新版本,已经开始的任务仍使用原版本。这是任务可复现和版本可回滚的基础。

4. 总体架构

系统只有两个主要部署单元:模块化平台后端和 Agent Worker。中心编排器、Agent Loop、模型适配和工具适配都运行在 Worker 中。

flowchart TB
    subgraph ACCESS[接入]
        WEB[统一 Web 控制台]
        API[OpenAPI]
        AUTH[公司 SSO / API Key]
    end

    subgraph BACKEND[模块化平台后端 · 两个副本]
        TENANT[租户与权限]
        CONFIG[Agent 与团队配置]
        RELEASE[测试、发布与回滚]
        TASK[任务、审批与审计]
    end

    subgraph RUNTIME[Agent Worker 池]
        ORCH[中心编排器]
        LOOP[Agent Loop]
        ADAPTER[模型与工具适配]
        ORCH --> LOOP --> ADAPTER
    end

    subgraph DATA[数据与基础设施]
        PG[(PostgreSQL)]
        MQ[(公司消息队列)]
        REDIS[(Redis)]
        STORE[(对象存储 / pgvector)]
    end

    WEB --> BACKEND
    API --> BACKEND
    AUTH --> BACKEND
    BACKEND --> MQ
    MQ --> RUNTIME
    BACKEND --> PG
    BACKEND --> REDIS
    RUNTIME --> PG
    RUNTIME --> REDIS
    RUNTIME --> STORE

创建任务时,平台后端会把以下信息保存为运行快照:

  • tenant_id 和当前用户;
  • 已发布的 Agent Version 或 Team Version;
  • 当前角色权限和工具白名单;
  • 最大步骤数、最大并发数、超时时间和 Token 上限。

运行快照一旦生成就不能被后续配置修改影响。

5. 模块职责

模块必须实现的职责部署方式
Web 控制台Agent/团队配置、在线测试、发布回滚、任务查询和审批一个前端,按角色显示菜单
平台后端认证、租户权限、配置版本、任务 API、运行查询、审计一个模块化应用,至少两个副本
中心编排器创建子 Run、分派、并行控制、结果汇总和退出判断Worker 内的一种任务处理器
Agent Loop上下文组装、模型调用、工具调用、步骤保存和终止所有 Agent 共用同一套执行内核
模型适配统一请求格式、超时、重试、并发限制和 Token 统计Worker 内部模块
工具适配参数校验、权限、审批、幂等、密钥引用和调用审计Worker 内部模块

平台后端采用模块化单体,主要原因是租户、版本、任务和审批之间存在明确事务关系。早期拆成多个微服务会增加分布式事务、部署和排障成本。

6. 一次任务怎样执行

sequenceDiagram
    participant U as 用户或业务系统
    participant B as 平台后端
    participant Q as 消息队列
    participant W as Agent Worker
    participant M as 模型
    participant T as 企业工具

    U->>B: 提交任务
    B->>B: 校验租户、版本和权限
    B->>Q: 写入任务消息
    Q->>W: Worker 领取任务
    W->>W: 加载运行快照并创建 Run
    W->>M: 发送上下文
    M-->>W: 最终回答或工具调用
    alt 需要工具
        W->>W: 校验白名单、审批和参数
        W->>T: 使用幂等键执行工具
        T-->>W: 返回工具结果
        W->>M: 带工具结果进入下一轮
    end
    W->>B: 保存结果、轨迹和 Token 用量
    B-->>U: 返回状态和最终结果

具体步骤如下:

  1. 平台后端校验租户、用户、目标版本和权限,生成 task_id。
  2. 任务写入消息队列,Worker 使用消息确认和任务租约领取任务。
  3. 单 Agent 任务直接创建根 Run;团队任务先运行主 Agent。
  4. 主 Agent 可以直接回答,也可以创建子 Run 委派给成员 Agent。
  5. Worker 保存每一步模型输入、模型输出、工具调用和 Token 用量。
  6. 任务最终进入成功、失败或取消状态;需要审批时暂停并释放 Worker。

7. Agent Loop

Agent Loop 重复执行“组装上下文、调用模型、执行工具、保存结果”,直到满足退出条件。

while task.is_running():
    check_cancel_timeout_and_budget()
    context = build_context(task_snapshot, run_steps)
    response = model_adapter.call(context)

    if response.is_final_answer():
        return succeed(response.answer)

    for tool_call in response.tool_calls:
        check_tool_permission(tool_call)
        result = execute_with_timeout_and_idempotency(tool_call)
        save_step(tool_call, result)

    if reached_limits() or repeated_same_action():
        return fail(reason)

退出条件必须由运行时强制执行,不能只依赖模型自己判断。

退出原因判断方式
正常完成模型返回最终答案,或主 Agent 判断必要子任务已经完成
达到上限达到 max_steps、max_depth、最大并发、超时或 Token 上限
用户取消Worker 在每次模型或工具调用边界检查取消状态
失败终止模型连续失败、工具重试耗尽或必要子任务失败
等待审批保存运行快照,释放 Worker,审批通过后恢复
循环检测相同 Agent、输入和工具参数连续重复超过阈值

建议初始默认值:

{
  "max_steps": 12,
  "max_depth": 3,
  "max_parallel_agents": 3,
  "timeout_seconds": 300,
  "token_budget": 30000,
  "same_action_limit": 3
}

这些限制应该允许租户管理员在平台范围内调整,但不能允许普通用户无限放大。

8. 多 Agent 编排

默认采用主 Agent 负责分派和汇总的方式:

flowchart LR
    INPUT[用户任务] --> SUPERVISOR[主 Agent 判断]
    SUPERVISOR --> A[成员 Agent A]
    SUPERVISOR --> B[成员 Agent B]
    SUPERVISOR --> C[成员 Agent C]
    A --> JOIN[汇总必要结果]
    B --> JOIN
    C --> JOIN
    JOIN --> FINAL[主 Agent 生成最终结果]

首个版本只需要三种编排节点:

  1. Agent 节点:运行指定的 Agent Version,返回结构化结果。
  2. 并行节点:同时派发多个 Agent,并限制最大并发数量。
  3. 汇总节点:等待必要分支结束,把结果交给主 Agent 整理。

Agent 之间不直接建立私有通信。委派请求、子任务结果和共享事实统一写入 Run 和 Step,由编排器传递。这样才能支持回放、审计和故障恢复。

9. 租户隔离和权限

数据隔离采用一个明确方案:共享 PostgreSQL、共享表、所有租户业务表包含 tenant_id,并启用数据库行级策略。

租户标识的传递过程:

  1. SSO 用户通过成员关系确定当前租户;API Key 在创建时绑定租户。
  2. 客户端不能通过请求参数任意切换 tenant_id。
  3. 平台后端把 tenant_id、user_id、task_id 和 trace_id 写入任务快照和消息。
  4. 数据访问层自动追加 tenant_id 查询条件。
  5. PostgreSQL 行级策略再次验证租户上下文。
  6. 缓存键、消息、对象路径、向量索引和日志字段都包含 tenant_id。

工具最终权限按照交集计算:

最终权限 = 租户允许的工具
         ∩ Agent Version 工具白名单
         ∩ 当前用户角色权限

高风险工具在权限校验通过后,还需要单级人工确认。密钥保存在公司的密钥系统中,平台数据库只保存密钥引用。

10. 核心数据表

表用途关键字段
tenant租户信息和状态id, name, status, quota
tenant_member用户在租户中的角色tenant_id, user_id, role
agent_version不可修改的 Agent 配置tenant_id, agent_id, version, prompt, model, tool_policy
team_version主 Agent、成员和协作图tenant_id, team_id, version, supervisor_id, graph
task用户的一次完整请求tenant_id, task_id, agent_version_id/team_version_id, status, limits
agent_run一个 Agent 的一次运行tenant_id, run_id, parent_run_id, agent_version_id, status
run_step模型、工具或委派步骤tenant_id, run_id, step_no, type, input_ref, output_ref, idempotency_key
approval高风险工具审批tenant_id, tool_call_id, status, approver, decided_at
usage_recordToken 和模型调用用量tenant_id, task_id, run_id, model, input_tokens, output_tokens
audit_log配置、发布、权限和工具操作tenant_id, actor, action, resource, trace_id, created_at

所有租户业务表的索引和唯一约束都必须包含 tenant_id。大文本、附件、模型原始响应和任务产物放入对象存储,数据库只保存引用。知识向量存入 pgvector,并在索引元数据中保存 tenant_id。

11. 状态与故障恢复

stateDiagram-v2
    [*] --> PENDING
    PENDING --> RUNNING
    RUNNING --> WAITING_APPROVAL: 需要人工审批
    WAITING_APPROVAL --> RUNNING: 审批通过
    WAITING_APPROVAL --> FAILED: 审批拒绝
    RUNNING --> SUCCEEDED: 正常完成
    RUNNING --> FAILED: 重试耗尽或超限
    PENDING --> CANCELLED: 用户取消
    RUNNING --> CANCELLING: 用户取消
    CANCELLING --> CANCELLED
    SUCCEEDED --> [*]
    FAILED --> [*]
    CANCELLED --> [*]
故障场景处理方式
Worker 进程退出任务租约到期后重新入队,新 Worker 从已保存 Step 恢复
消息重复投递使用 task_id、run_id 和 step_no 组成幂等键
工具有副作用工具调用携带 idempotency_key,由连接器记录执行结果
模型调用超时只对可重试错误进行有限次数重试,并记录每次尝试
审批等待较长保存运行快照并释放 Worker,通过消息重新唤醒
用户取消先进入 CANCELLING,Worker 在安全边界停止后变为 CANCELLED

12. 测试与发布

测试能力放在平台后端中,不单独建设大型评测平台。

  • 在线调试:选择草稿版本运行,查看模型输入输出和工具结果。
  • 固定用例回放:保存少量代表性输入和检查项,发布前批量执行。
  • 版本对比:比较成功率、人工评分、耗时和 Token 用量。
  • 发布回滚:发布生成不可修改的新版本;回滚只把线上别名重新指向旧版本。

发布检查至少包含:固定用例全部执行完成、没有越权工具调用、Agent Loop 没有异常循环、Token 和响应时间没有明显失控。

13. 生产部署

flowchart TB
    subgraph K8S[公司 Kubernetes 集群 · 单命名空间]
        GW[公司网关 / SSO]
        APP[平台后端 × 2]
        WORKER[Agent Worker × N]
        GW --> APP
        APP --> WORKER
    end

    APP --> PG[(PostgreSQL 主备)]
    APP --> MQ[(公司消息队列)]
    APP --> REDIS[(Redis)]
    WORKER --> MQ
    WORKER --> PG
    WORKER --> REDIS
    WORKER --> STORE[(对象存储)]
    WORKER --> SECRET[公司密钥系统]
    WORKER --> EGRESS[模型与工具固定出口]
    APP --> OBS[公司日志、指标与告警]
    WORKER --> OBS

生产部署的最低要求:

  • 平台后端至少两个副本,保持无状态,配置和任务状态写入 PostgreSQL。
  • Agent Worker 至少两个副本,根据队列积压扩缩容。
  • PostgreSQL 使用主备部署并每日备份,上线前执行一次恢复验证。
  • 消息队列开启确认、有限重试和死信队列。
  • Worker 禁止直连业务生产数据库,工具通过受控连接器访问。
  • 日志和指标包含 tenant_id、task_id、run_id 和 agent_version_id。

14. 示例:经营分析任务

用户提交:“分析昨天各区域的销售变化,找出异常原因并生成简报。”

Agent职责允许使用的工具
主 Agent理解问题、分派任务、检查结果并生成最终简报任务委派、知识检索
数据 Agent通过受控查询接口获取销售汇总数据经营数据查询 API
分析 Agent计算环比、识别异常并整理可能原因Python 沙箱、知识检索
写作 Agent把结构化结果整理成固定格式的简报模板读取、文档生成

主 Agent 可以同时派发“获取销售数据”和“检索异常背景”,收到结果后再启动分析 Agent,最后交给写作 Agent。任一必要分支失败,主 Agent 返回明确的缺失项,而不是猜测业务数据。

15. 建议开发顺序

  1. 完成单 Agent 闭环:租户认证、Agent Version、Task/Run/Step、模型调用、任务查询和审计。
  2. 补齐工具边界:工具白名单、参数校验、密钥引用、超时、幂等和单级审批。
  3. 增加可靠执行:消息队列、任务租约、重试、取消、审批等待和故障恢复。
  4. 增加多 Agent:Team Version、父子 Run、主 Agent 分派、并行上限和结果汇总。
  5. 完成上线能力:固定用例回放、版本回滚、监控告警、数据备份和恢复验证。

先把单 Agent 运行内核做稳定,再增加多 Agent。多 Agent 复用同一套 Task、Run、Step、权限和工具执行机制,不应重新实现一套运行系统。

16. 上线验收清单

  • [ ] 两个租户无法读取对方的 Agent、知识、任务和日志。
  • [ ] 单 Agent 任务不需要经过团队编排。
  • [ ] 任务固定使用已发布版本,历史任务可以复现。
  • [ ] 子任务支持并行、超时、重试、取消和失败汇总。
  • [ ] Worker 重启后,任务可以重新领取并继续执行。
  • [ ] 有副作用的工具不会因消息重复而重复执行。
  • [ ] 高风险工具需要审批,全部调用可以追溯。
  • [ ] 可以按租户、任务、Agent 和模型查询 Token 用量。
  • [ ] 版本可以回滚,数据库备份完成恢复验证。
  • [ ] 日志能够通过 tenant_id、task_id 和 run_id 定位。

17. 本章小结

这套架构的关键不是模块数量,而是边界清晰:

  • 租户负责数据和权限隔离;
  • Agent Version 和 Team Version 负责固定可执行配置;
  • Task、Run 和 Step 负责记录完整运行过程;
  • Agent Loop 负责模型与工具循环;
  • 中心编排器负责多 Agent 分派和汇总;
  • 消息队列、任务租约和幂等机制负责故障恢复;
  • 测试、审计、监控、备份和回滚保证系统可以上线运行。

在这个基础上继续增加 Agent 类型、工具连接器和业务场景,不需要改变系统的核心执行模型。