返回文章
架构与边界·约 10 分钟·Kain

企业级 Agent OS 控制平面技术架构

在真实场景中试过不同 Agent SDK 后,整理控制平面、最小闭环与选型边界。

企业级 Agent OS 控制平面技术架构的封面
文章目录

这段时间在探索 Agent 如何在企业内部落地。开源框架层出不穷:AgentScope、LangGraph、Claude SDK、Agno……每个都有自己的优缺点。看文档看得眼花缭乱,不如动手试试。

借助 AI,我用不同的 Agent SDK 把内部几个场景跑了一遍。跑的过程中,需求和关键技术点慢慢澄清,方向也逐渐清晰。这篇文章就是在这个过程中梳理出来的。还比较粗糙,但大方向应该差不多了,后续就是技术细节的澄清和实践。


一、定位:从助手到控制平面

很多人一开始把 Agent 系统定位成"智能助手"。听起来很美好,但这个定位有个致命问题:助手是服务个人的,企业要的是可控的系统。

我们做 POS 助手项目时,一开始也是这个思路。后来发现,如果只定位成"销售查询助手",架构就会往"能用就行"的方向走。权限随便传,SQL 让模型生成,审计日志可有可无。等要接入第二个业务场景,整个架构就得重来。

所以我们把定位改了:

平台中立型企业 Agent OS 控制平面
宗旨:脑可换、身可控、身份随、安全合规

这四句话,每一句都是踩过坑才总结出来的。

脑可换:去年我们用 GPT-4,今年用 Claude,明年可能用 Gemini。模型供应商说变就变,业务架构不能跟着变。Prompt、工具定义、业务逻辑,这些不能绑死在某一个模型上。

身可控:Agent 调数据库、调 API、调遗留系统,这些操作必须走受控通道。不能让模型直接生成 SQL,不能让工具绕过权限层,不能让 RPA 在后台乱跑。

身份随:用户是谁、在哪个门店、有什么权限,这些信息必须从头到尾跟着请求走。不能在模型调用环节丢失,不能靠 Prompt 来传递,不能存到 conversationData 里。

安全合规:权限校验、审计追踪、数据脱敏,这些是控制平面的能力,不是模型的自觉。指望模型"自己知道不该查什么数据",是在赌运气。

二、五平面架构:不是分层,是分责

传统架构喜欢分层:展示层、业务层、数据层。Agent 系统不能这么分,因为每一层都有"控制"的职责。

我们把架构拆成五个平面:

平面 核心职责 一句话理解
Product Protocol & Experience 前端协议、流式交互、artifact 别让前端从 Markdown 里猜图表
Interaction & Orchestration 会话、任务、记忆、多代理协作 Agent 怎么持续工作
Model Abstraction 模型网关、协议适配、身份注入 模型供应商随便换
Security & Governance IAM、RBAC、审计、脱敏 出了问题能追责
Resource & Execution MCP、工具、数据库、知识库 Agent 怎么操作企业系统

这五个平面,不是从上到下的调用链,而是五个独立的职责域。每个平面都有自己的边界和约束。

Product Protocol & Experience Plane

这个平面最容易被忽视。

很多团队直接把模型的文本输出返回给前端。前端拿到一串 Markdown,里面可能夹着代码块、表格、图表描述。前端工程师得写解析逻辑,从 Markdown 里猜这是什么类型的内容。

我们踩过这个坑。前端问:"图表数据在哪个代码块里?"后端说:"你找找 chart 关键字。"前端说:"找到了,但格式不统一。"后端说:"那我们改 Prompt。"改了 Prompt,旧数据又解析不了了。

后来我们定了一个硬规则:前端协议必须结构化。

{
  "content": "用户可读 Markdown",
  "artifacts": [],
  "conversationData": {}
}

content 只放用户可读的文本。图表、按钮、文件,这些增强信息放 artifacts。多轮任务状态放 conversationData。

前端不需要解析 Markdown,不需要猜格式。拿到 artifacts 里的 application/vnd.echarts+json,直接渲染图表。拿到 actions,直接渲染快捷操作按钮。

这个规则看似简单,但它把前后端的边界划清楚了。模型输出什么,是后端的责任;前端怎么渲染,是前端的责任。不要混在一起。

Interaction & Orchestration Plane

这个平面负责 Agent 怎么持续工作。

会话、任务理解、状态维护、记忆管理、多代理协作,这些都在这里。

我们一开始用 LangGraph 做 runtime。后来发现,LangGraph 的状态机太重了。每个节点都要定义,每条边都要显式声明。业务逻辑一变,状态图就得改。团队花了大量时间在调试状态流转上,而不是在解决业务问题上。

后来我们换了个思路:让 Claude Agent SDK 承担 agent loop,LangGraph 只在强一致流程里做局部引擎。

会话管理也是这个平面的大坑。

很多团队直接把 Claude session 当成业务会话。问题是,Claude session 是模型上下文的连续性,不是业务状态的连续性。用户换了门店、换了角色,Claude session 不会自动感知。

我们用两层会话来解决:

  • Claude session:模型上下文连续性。
  • conversationData:业务状态连续性。

conversationData 里存的是当前任务的状态、上次查询的结果、用户选择的门店。这些信息每次请求都要重新校验,不能依赖模型"记得"。

Model Abstraction Plane

这个平面的核心是:别绑死在一个模型上。

我们首期用 Claude Agent SDK,但业务代码不直接依赖 Claude SDK。我们定义了一个 AgentRuntime 抽象,所有业务代码通过这个抽象调用模型。

这样做的好处是:换模型时,只需要换 runtime 实现,业务代码不用改。

Prompt 也要解耦。业务规则不要写在 Prompt 里,要写在 MCP 工具和权限层里。

举个例子:店铺数据范围校验。如果写在 Prompt 里,模型"知道"要校验,但它可能忘,可能被绕过,可能在不同模型上表现不一致。写在 MCP 工具里,每次调用都强制校验,模型绕不过去。

身份跟随也在这个平面。

用户身份、租户、门店、角色,这些信息用 PermissionContext 对象传递。Python 用 contextvars,Node 用 AsyncLocalStorage。不要把 token 放进 Prompt,不要把 token 写进 conversationData,不要在日志里输出 token。

Security & Governance Plane

这个平面是企业的底线。

权限体系的核心是:PermissionContext 是唯一可信来源。

Authorization
    -> Permission Provider
    -> PermissionContext
    -> ClaudeAgentOptions.user
    -> MCP headers/env
    -> MCP tool enforcement

用户能查哪些门店的数据,来自 PermissionContext.shop_scope。用户在自然语言里说"查门店 A001 的数据",这个编码只能作为 requested_shop_no。requested_shop_no 必须和 shop_scope 做交集校验。权限不足,直接拒绝,不能降级为无过滤查询。

工具授权也是这个平面的事。

我们用 Claude SDK 的 allowed_tools 和 disallowed_tools 来控制工具可见性。高危工具(Bash、Write、Edit)不开放。通用数据库 MCP 不开放。MCP 工具白名单按角色动态生成。

审计追踪不能省。

每个请求有 X-Request-Id,透传到 Claude runtime、MCP、数据库。工具调用用 hooks 记录。SQL 在服务端日志里打印,但 token、API key 必须脱敏。用户看到的回复里,不能暴露 SQL、原始 JSON、内部状态。

Resource & Execution Plane

这个平面负责 Agent 怎么操作企业系统。

MCP 是核心。我们用 pos MCP server,工具命名 mcp__pos__query_sales。

数据访问有几个硬约束:

  • Claude 不生成 SQL。
  • MCP 工具接收业务参数,SQL 由代码构建。
  • SQL 必须只读校验。
  • 查询必须执行 PermissionContext.shop_scope 过滤。
  • 销售查询时间范围不超过 31 天。

这些约束写在 MCP 工具里,不是写在 Prompt 里。模型调用工具时,约束自动生效。

遗留系统和 RPA,首期不引入。没有 API 的系统,后续通过独立 RPA MCP server 接入。RPA 工具必须强制人工审批。

三、最小闭环:先跑通,再扩展

架构设计容易陷入一个误区:想得太全,做得太少。

我们定了一个原则:P0/P1 不做大平台,只做可验证闭环。

最小闭环是什么?

Frontend
  -> HTTP/SSE Protocol
  -> PermissionContext
  -> Claude Agent SDK
  -> Skill 领域知识
  -> MCP 业务能力
  -> {content, artifacts, conversationData}

验证场景就一个:

上周销售量按天统计,使用饼图显示

这个场景要验证五件事:

  • Claude 能用 Skill 理解领域任务。
  • Claude 能调用 MCP 业务能力。
  • MCP 能基于 PermissionContext 执行权限过滤。
  • 图表返回 artifact,不塞进 Markdown 代码块。
  • 多轮数据写入 conversationData。

这五件事跑通了,架构就立住了。然后再扩展第二个场景、第三个场景。

四、技术选型:立即用、预留接口、暂不引入

技术选型要分三类:

立即采用:Claude Agent SDK、MCP、PermissionContext、SSE、ECharts artifact。这些是首期必须有的。

预留接口:LiteLLM、OPA、OpenTelemetry、Milvus、Presidio。这些是中期可能引入的,先定义接口,不急着实现。

暂不引入:通用数据库 MCP、RPA、LangGraph 全局 runtime、复杂多模型路由。这些是首期不需要的,引入会增加复杂度,拖慢闭环验证。

五、关键决议:踩坑后的总结

最后,几个关键决议:

POS 助手是验证场景,不是架构边界来源。架构要服务企业级 Agent OS,不是服务一个助手。

Skill 是领域知识,不是业务执行层。业务执行在 MCP 工具里。

MCP 是业务能力,不是权限策略层。权限策略在 PermissionContext 和 OPA 里。

PermissionContext 是身份和数据权限的唯一可信来源。不要相信 Prompt,不要相信模型记忆。

Claude 负责推理和工具选择,不负责授权和 SQL。授权在权限层,SQL 在 MCP 工具里。

前端协议是独立平面,不从模型文本里反向解析业务结构。结构化协议,前后端各司其职。

平台化能力分阶段引入,先闭环,再扩展。别一上来就做大平台,先跑通一个场景。


做企业级 Agent 系统,技术不是最难的。最难的是守住边界:模型做什么、工具做什么、权限层做什么、前端做什么。边界不清,迟早失控。

把控制平面想清楚,代码写得慢一点,但心里踏实。出了问题能追责,换了模型能适配,加了场景能扩展。这才是企业级系统该有的样子。

继续阅读同主题文章架构与边界