主题色
250
壁纸模式
壁纸设置
特效设置
固定导航栏
字体选择
文章列表布局
9274 字
24 分钟
2026:Agent 基础设施七大难题
2026-08-02

飞书群里有人 @ 机器人:“帮我查一下最近几个 PR 的构建状态,把失败的总结一下发群里。” 消息不会直接喂给大模型:入口先验签、归一化、鉴权,再把事件路由到会话;会话加载上下文和记忆后,Agent 才能调用 GitHub、CI 等工具,必要时再派子 Agent 并行处理。结果还要转换成飞书支持的格式发回去。

把同一条链路换成 GitHub webhook 或定时任务,入口协议会变,后面的基础设施问题仍然存在。本文把这些问题归纳为七层,并用 Claude Code 作为参照:它在单进程、本地开发场景里做了很多“够用”的取舍,也因此把边界暴露得很清楚。

flowchart LR in([飞书消息进站]) --> ch1["触发与 Channel<br>验签 归一化 鉴权"] ch1 --> mem["记忆<br>加载上下文"] mem --> tool["工具调用<br>MCP 权限模型"] tool --> orch["多 Agent 编排<br>派子 Agent"] orch --> ch2["触发与 Channel<br>格式渲染 回发"] ch2 --> out([飞书消息出站]) obs["可观测性 成本 评估"] -.-> ch1 obs -.-> tool obs -.-> orch sec["安全 合规"] -.-> ch1 sec -.-> tool sec -.-> orch dep["部署与状态托管"] ==> ch1 dep ==> mem dep ==> tool dep ==> orch

实线是消息旅程;虚线表示可观测性和安全约束;粗线表示部署与状态托管。七层不是顺序台阶,而是一条相互牵制的链。

层要回答的问题失效时最先看到的症状
触发与 Channel谁在什么入口、以什么身份触发哪个会话?重复回复、错会话、伪造 webhook
工具调用Agent 能发现什么工具,又能以谁的权限调用?工具越权、连接器维护失控
记忆与知识哪些信息值得保存,如何在窗口有限时准确取回?答非所问、上下文膨胀、旧事实污染新任务
多 Agent 编排任务如何拆分,结果和状态如何合并?死循环、丢更新、协调者成为瓶颈
可观测性、成本与评估发生了什么、花了多少、结果是否变好?只能看日志,无法归因和回归
安全与合规哪些动作必须阻止、审批、留痕?prompt injection、敏感数据外泄、无法审计
部署与演进有状态执行如何恢复、扩容和升级?重启丢任务,版本漂移,无法水平扩展

一、触发与 Channel 层:世界怎么触达 Agent#

这条飞书消息不是直接喂给大模型的文本。它先进入 POST /api/agent/webhooks/feishu/:appId,完成验签、归一化和权限判断,再带着 trigger 标记进入 Agent 运行时。这一层解决“世界怎么触达 Agent”,和后面的工具调用是方向相反的两层。

在飞书、QQ、Telegram 里 @ 机器人,看起来只是“接一条消息”,实际包含连接维持、身份验证、消息归一化、会话路由和回包渲染。OpenClaw 把渠道做成 Gateway 下的插件,LobeHub 则用平台注册表统一各个适配器。实现形式不同,边界相同:Channel 负责把外部事件变成 Agent 能消费的输入,而不是把每个聊天平台直接耦合进运行时。

触发层与工具层为什么必须分开#

LobeHub 的 IM 渠道位于 apps/server/src/services/bot/platforms/,MCP 工具则在另一套目录中。这个分层不是代码洁癖:触发层回答“谁、何时、在哪个会话里让 Agent 开始工作”,工具层回答“工作开始后允许做什么”。触发到达时,模型通常还没有进入推理,因此验签、路由、去重和限流必须由运行时完成。

协议异质性:这层最显性的工作量#

各家 IM 的连接方式天然不同。LobeHub 在 bot/platforms/types.ts 里定义了三种 ConnectionMode:

  • polling:平台不提供 webhook 时主动轮询,需要处理限频和断线恢复。
  • webhook:平台主动推送事件,接收端可以保持无状态。
  • websocket:依赖常驻长连接,需要连接保活和水平扩展策略。

连接方式会直接改变部署拓扑,消息能力也不能假定一致。以表情回应为例,有的平台支持原子替换,有的平台要先添加再删除,还有的平台没有对应 API;线程、附件、Markdown 和用户语言同样存在差异。统一接口只能定义最小公分母,平台特性仍要留在适配器内部。Dify 进一步把触发器外推给插件生态,换来更干净的主仓库,也把接入和升级成本交给了插件维护者。

被动触发的鉴权与幂等#

被动触发的入口天然暴露在外。除了按平台规则验签,还要把调用方身份绑定到执行上下文,避免所有请求共用一套高权限凭证。n8n 的 establishTriggerIdentity(token, resource) 就是在触发阶段建立这层身份关系。

投递还要处理重复、遗漏和突发流量。常见做法分别是幂等键、补偿扫描、去抖或退避。再往前一步是会话绑定:同一用户从飞书和微信发来的两条消息,是否共享上下文并没有通用答案,但系统必须把这个产品决策落实为稳定的路由规则。这里的状态机与 LLM 无关,却决定了 Agent 会不会重复执行、串错会话。

Claude Code 的触发机制#

Claude Code 最初以终端输入为主,后来也补上了多种 harness 级触发。/loop 和 cron 工具负责会话内定时任务,/goal 在每个回合后用独立评估器判断是否达到停止条件;Channels 则允许 MCP server 把 webhook、告警或聊天消息推入正在运行的会话。

这组能力再次说明触发和工具必须分层。模型可以请求创建定时任务,也可以调用 Channel 暴露的回复工具,但真正的计时、事件接收、发送者校验和权限转发都由运行时完成。Claude Code 的 Channels 仍处于 research preview,且桥接服务运行在本机进程中;它证明了统一契约可行,还没有消除各平台适配和长期托管的成本。

二、工具调用层:MCP 标准与权限模型的落差#

飞书消息过了验签、进了会话,Agent 要查 PR 构建状态,得先有工具可调。这一层就是 Agent 伸出手去碰外部世界的那只手。要理解它的难处,得先看清楚 MCP 解决了什么、没解决什么。

MCP(Model Context Protocol)在 2024 年底由 Anthropic 发起,2025 年 12 月捐入 Linux Foundation 新成立的 AAIF(Agentic AI Foundation),成了事实标准。它统一了工具发现、参数序列化和 JSON-RPC 调用等协议契约,但没有统一业务语义:GitHub 的 create_issue 和 Slack 的 post_message 仍然有不同的参数、鉴权、错误码和分页方式。MCP 解决了“怎么调”,没有解决“调什么”。

“调什么”背后是 SaaS 生态的碎片化。一个企业 Agent 要接 GitHub、Slack、Jira、Notion、飞书十几个 SaaS,每个服务的鉴权方式、权限粒度、错误码和分页协议都不同。更麻烦的是这些连接散在各处:哪个连接器今天失败了、哪个令牌过期了、哪个 SaaS 的调用成本异常,往往没有一处能看清。连接器(connector)要填的正是这些坑:它解决的不只是语义鸿沟,还包括跨 SaaS 的鉴权、权限和调用观测。

连接器的两种哲学:代码还是数据#

标准有了,生态仍然很碎。连接器到底应该是代码还是数据,背后是一个实际取舍:API 的异质性,是交给编程语言处理,还是用声明式配置覆盖。

open-connector(oomol-lab 出品)走的是 code-first 的路子,是这条哲学最有代表性的实现。它的每个 provider 是一个纯静态的 TypeScript 对象。看 GitHub provider 的定义:

下面是源码节选,只保留能说明结构的字段,不能直接运行。

// src/providers/github/definition.ts(节选)
export const github: ProviderDefinition = {
service: 'github',
displayName: 'GitHub',
categories: ['developer-tools', 'productivity'],
authTypes: ['oauth2', 'api_key'],
auth: {
oauth2: {
authorizationUrl: 'https://github.com/login/oauth/authorize',
tokenUrl: 'https://github.com/login/oauth/access_token',
scopes: [...],
tokenEndpointAuthMethod: 'client_secret_post',
},
api_key: { label: '...', placeholder: '...', description: '...' },
},
actions: githubActions,
oauthScopes: githubOAuthScopes,
}

新增一个 provider 需要把定义、actions 和 scopes 写进源码,再运行 npm run generate:catalog 生成目录。连接器因此是编译期产物,不能在运行时热注册;换来的则是类型安全和构建期校验。这是用灵活性换可靠性。

为什么 code-first 在这里站得住脚。SaaS 的 API 不是稳定的数据,它是有版本、有怪癖、有边界条件的代码契约。用 TypeScript 写连接器,等于把 “处理这些怪癖” 的逻辑交给了编程语言,遇到 GitHub 的分页是 Link header、Slack 的分页是 cursor 这种异质问题,写几行 if-else 就解决了,声明式配置反而要发明一套 DSL 来覆盖所有情况,最后 DSL 比代码还复杂。open-connector 选这条路,是因为它赌的是 “provider 数量可控、正确性比灵活性好” 的场景。

另一头是数据派。Truto 的官方原话是 “Every connector is data, not code”,标准 CRUD 操作用 JSONata 映射就能搞定,连一行代码都不用写。这条路赌的是 “大多数 SaaS API 在剥掉鉴权后,本质都是 RESTful 的 CRUD”,只要映射好字段就能通用,接入门槛极低,但碰到非标准接口(多步编排、状态机、重试逻辑)就得回退到写代码。Nango 处在中间偏 code 的一侧,主打 Zero YAML:用 TypeScript 的 createSync/createAction/createOnEvent 写集成函数,集成代码 commit 在用户自己的 Git 仓库里,它把鉴权、轮询、重试、Webhook 这些公共难题打包好,连接器逻辑交给用户自己维护,灵活性最高,维护成本也一并交了出去。

三条路线对应三种取舍:

  • open-connector 要改源码重新发布,适合 provider 数量可控、对正确性要求高的场景。
  • Truto 的 JSON 配置上手快,但碰到非标准接口就得回退到写代码。
  • Nango 把集成代码交给用户自己维护,灵活性最高,也把维护成本一并交了出去。

选择取决于 API 的异质性和维护边界:异质性低时声明式配置足够,异质性高时业务代码不可避免。复杂度不会消失,只会被放在连接器作者、平台维护者或使用团队身上。

权限模型:从全有或全无到分层授权#

连接器解决了 “怎么连”,权限解决 “连上之后允许做什么”。大部分 MCP 客户端的权限模型还很粗,要么全有要么全无:接上一个 GitHub MCP server,整个仓库的读写权限就都敞开了。这在个人工具里无所谓,到了企业场景就是事故源头。

为什么粗粒度权限在企业里行不通。企业场景里,权限决策依赖三个运行时变量:谁在调用(哪个员工)、何时调用(工作时间还是凌晨)、调用时的业务上下文(是日常操作还是紧急救火)。一个静态的 “授予 repo 读写权限” 表达不了 “工作时间内允许、工作时间外要审批” 这种策略。所以企业级权限必然走向 “静态声明加运行时策略” 的分层结构。

Arcade 展示了一种分层授权管道。第一层是 resource server 这个前门,每个工具用装饰器静态声明自己需要的 OAuth scope。下面是示意代码,省略了认证对象的定义:

@app.tool(requires_auth=GitHub(scopes=["repo", "read:org"]))
def list_my_repos() -> list[dict]:
...

scope 是每个工具静态声明的,运行时做的是断言,确认用户实际授予的 scope 是工具所需 scope 的超集(required_set.issubset(granted)),而不是动态计算可用工具集。这一层解决的是 “最小权限” 问题:每个工具只声明自己需要的 scope,用户授权时能看清楚这个工具到底要什么。

第二层是 Contextual Access,由三个 webhook 组成管道:Access Hook 在请求进入时拦截,Pre-Execution Hook 在工具执行前再过一道,Post-Execution Hook 在执行后审计。为什么是 webhook 管道而不是一个静态策略引擎。因为前面说的三个运行时变量(谁、何时、上下文)是策略引擎没法静态穷举的,必须把决策权交给企业的运行时系统,让它在调用前后插入自己的业务逻辑。比如 “工作时间外禁止转账”“敏感操作要二次审批” 这类策略,写死在配置里维护不动,交给 webhook 让企业的 IAM 系统实时判断才合理。它的 engine 是闭源的,但 arcade-mcp 是完整的开源实现,驱动着数千个工具和上百个 MCP server,并不是只暴露接口没有实现。

Claude Code 走了哪条路#

连接器和权限是工具层的两个维度。Claude Code 可以通过 stdio 运行本地 MCP server,也可以连接远程服务。独立进程增加了进程间通信开销,却换来故障隔离:一个第三方 server 崩溃或卡死,不必拖垮主进程。要注意,进程隔离本身不是授权模型;子进程仍可能继承过多的文件和网络权限。

权限侧采用 allow、ask、deny 规则与多种权限模式。默认模式适合有人值守的本地开发,因为写文件、执行命令等有副作用的动作可以逐次确认;无人值守时可以用 dontAsk 只执行预先允许的工具,也可以把审批委托给外部策略系统。auto 会在后台安全检查后执行,bypassPermissions 则跳过权限层;后者不存在“最后再问一次”的兜底,只应在已经由容器或虚拟机完成强隔离的环境中使用。

这揭示了本地 Agent 与企业 Agent 的分界:前者可以把人当作实时策略引擎,后者必须把最小权限、身份传递、审批和审计写进系统。

三、记忆与知识:上下文不是硬盘,是 RAM#

Agent 调工具前,需要知道之前查过哪些 PR、项目约定使用哪个分支。这些信息不会在推理过程中自动写回模型权重,只能来自当前上下文或外部存储。

上下文更像工作内存,不是持久存储。真正困难的也不是把内容存下来,而是在正确的时机取回正确的片段:漏取会遗忘,错取会误导,多取则增加 token 成本并稀释注意力。

检索的精度:Mem0 的三层评分#

Mem0 的思路是把记忆拆成原子化的事实存进向量库,用的时候检索回来。它的检索不是简单的一次向量相似度,而是三层评分叠加。下面是 _search_vector_store 的逻辑骨架,不是可直接运行的实现:

mem0/main.py
def _search_vector_store(self, query, vectors, filters, limit):
# internal_limit = max(limit * 4, 60) # 多捞再裁
# 省略候选召回与过滤逻辑
# 1. semantic: 向量余弦相似度
# 2. bm25: 稀疏检索,用 query 长度自适应的 sigmoid 归一化
# (normalize_bm25, get_bm25_params)
# 3. entity boost: 命中实体集合的额外加权
# score_and_rank 按 max_possible 动态除数(1.0/2.0/2.5/1.5)加权合并

向量相似度擅长语义召回,却容易漏掉专有名词的精确匹配;BM25 补足字面匹配,实体加权再利用人名、产品名等显式关系。internal_limit = max(limit * 4, 60) 先扩大候选集再重排,是用额外计算换召回率。这里值得保留的不是某组固定权重,而是“多路召回、统一归一化、最后重排”的结构。

成本出现在写入侧。Mem0 的 add() 会调用 LLM 提取原子事实,再判断新增、更新或删除。记忆因此不是廉价数据库写入,而是一条带推理成本、冲突处理和失败补偿的管道。开源版与商业版的时序、衰减能力也不同,选型时必须按实际版本验证,不能只看产品能力列表。

知识库的规模:WeKnora 的工程化#

Mem0 解决的是 “记住关于用户的事”,WeKnora(腾讯出品)解决的是 “管理一大堆文档”。两者的分野本身就是个洞察:记忆和知识库是两类不同的问题。记忆是 “写一次读多次、小规模、需精确”,知识库是 “批量摄入、大规模、需召回率”。前者重检索精度,后者重摄入吞吐和检索广度,工程难题完全不同。

WeKnora 的工程重点是批量摄入:切分、向量化和建图都是慢操作,需要任务队列削峰、死信队列隔离失败。检索侧的父子分块则解决另一组矛盾:小块有利于精确命中和节省 token,大块有利于保留完整语境,因此可以命中子块、返回父块。知识库规模化不只是换一个更大的向量库,还包括摄入调度、失败恢复、分块策略和检索成本。

Claude Code 的文件记忆#

Claude Code 的自动记忆 没有引入向量库,而是使用项目级 Markdown 文件:MEMORY.md 是每次会话加载的精简索引,主题文件按需读取;CLAUDE.md 则承载需要稳定执行的项目指令。两类文件都可由人直接审阅和修改。

这适合“项目约定、调试结论、常用命令”这类小规模、高置信信息。优势是零额外服务、内容可审计;代价是缺少语义检索,记忆又是机器本地的,不能天然跨机器共享。换成需要保存海量用户事实的客服 Agent,仍要回到带租户隔离和检索能力的存储系统。

上下文压缩:不是丢弃,是摘要替换#

上下文接近上限时,Claude Code 会先清理旧工具输出,再把早期对话压缩成摘要,完整 transcript 仍保留在磁盘。/context 用于查看空间占用,/compact 可以手动压缩;项目根目录的 CLAUDE.md 会在压缩后重新注入。

摘要必然有损。只在对话中出现的安全约束和业务规则可能被遗漏,因此需要长期成立的约束不应依赖摘要,而应写进可重新加载、可审计的指令文件。这里的设计原则比具体压缩阈值更重要:工作上下文可以压缩,安全边界和持久事实必须另存。

四、多 Agent 编排:消息传送与共享状态#

查 PR 时如果一次拿不全,Agent 可以派几个子 Agent 并行查不同仓库。难点不在“多开几个模型”,而在两件事:任务约束如何完整传递,多个执行者的结果和状态如何合并。

社区大致形成两类方案。消息传送让每个 Agent 保持独立上下文,通过显式消息交换结果;共享状态让节点读写统一的数据结构,通过合并规则协调并发。它们确实借用了分布式系统的思想,但不能直接套用 CAP:是否存在网络分区、系统要求何种一致性,需要结合具体部署才能讨论。

消息传送派:CrewAI 与 AutoGen#

CrewAI 的 Process 以 sequential 和 hierarchical 为主,并行通过异步任务或更上层的 Flow 组织。hierarchical 模式把任务分配与结果汇总交给 Manager,结构清楚,但 Manager 会同时成为上下文和决策瓶颈。

AutoGen 让 Agent 通过消息协作,发言顺序和最大轮数由编排策略控制。事件驱动的 actor 底座解决了同步轮次阻塞,却没有消除语义损失:如果 Agent A 只把结论摘要发给 Agent B,遗漏的证据不会自动恢复。消息协议因此不该只传自然语言结论,还应携带来源、结构化结果、完成状态和错误信息。

共享状态派:LangGraph#

LangGraph 走的是另一条路:把整个工作流建模成一张图,节点是 Agent 或函数,边是控制流,所有节点共享一份全局状态字典。它的状态不是无类型的字典,而是用 TypedDict 加 Annotated 声明,每个字段可以挂一个 reducer 函数:

from typing import Annotated, TypedDict
from langgraph.graph import StateGraph
from langgraph.graph.message import add_messages
class AgentState(TypedDict):
messages: Annotated[list, add_messages] # reducer: 追加而非覆盖
count: int
graph = StateGraph(AgentState)

add_messages 是 reducer,声明多个节点写入 messages 时如何合并:新消息会追加,带有相同 ID 的消息则更新原值。reducer 把隐式的“最后写入者获胜”改成显式合并规则,避免 fan-out 后出现丢失更新。

共享状态简化了节点通信,也扩大了污染范围。任何节点都可能写坏全局字段,因此状态 schema、checkpoint 和逐步回放缺一不可。即便如此,工程上仍要限制每个节点可写的字段,不能把“有 checkpoint”当成全局可变状态的免责卡。

Claude Code 的同进程编排#

Claude Code 的多 Agent 采用第三种范式:同进程函数调用。AgentTool 把任务 prompt 交给新的 query(),子 Agent 使用独立上下文运行,不需要网络 RPC 或跨进程序列化。

它的隔离边界很明确:子 Agent 可以使用独立工作树,父 Agent 取消时子 Agent 也会收到取消信号;子 Agent 不会自动继承父会话的全部对话和已加载能力,任务所需的约束必须显式写入定义或 prompt。这用少量重复换取了上下文可控和父子状态隔离。

fork 是一个有意的例外:它复制父会话的上下文和工具前缀,再只在末尾追加不同的任务指令。这样多个 fork 可以复用相同的 prompt cache,代价是它们共享了更大的上下文前缀,也更容易把无关历史带入任务。后台子 Agent 还可以通过 resume 从 transcript 恢复,说明“派出去就忘掉”并不是唯一的生命周期模型。

持续运行有两种驱动。/loop 是定时器,到点重新注入 prompt;/goal 则在每个回合后用独立评估器判断是否满足条件。前者适合轮询,后者适合有明确完成标准的任务,二者都受会话生命周期和权限设置约束。

当子 Agent 数量上升,Claude Code 会把编排计划移出模型上下文:脚本负责循环、分支和中间结果,模型只接收必要的输入输出。再往上是实验性的 agent teams,由多个独立会话通过共享任务列表和 mailbox 协作。这个光谱的核心不是“同进程还是分布式”,而是把协调状态放在哪一层:上下文、脚本,还是专门的协作服务。

把这几层摆在一起,能看清 Claude Code 编排的完整光谱,从底到顶按协调规模递增:

flowchart TD L1["AgentTool 同进程子 Agent<br>可见状态:文件系统<br>规模:少量分工"] --> L2["fork 子 Agent<br>继承状态:可复用上下文前缀<br>规模:并行探索"] L2 --> L3["脚本化工作流<br>协调状态:脚本变量<br>规模:较多任务"] L3 --> L4["agent teams<br>协调状态:task list 与 mailbox<br>规模:跨 session 协作"]

这张图的要害在协调复杂度:小规模把状态留在进程和文件系统,中规模交给脚本,大规模才引入跨会话通信。编程任务可以沿这条路径渐进扩展;换成没有共享文件系统的客服或交易场景,就必须更早引入显式状态和消息协议。

五、可观测性、成本与评估:黑盒里的三个洞#

Agent 的执行路径由模型临场决定,必须同时回答三个问题:发生了什么、花了多少、结果是否变好。传统 APM 能回答前两个的一部分,却无法直接判断开放式输出是否完成任务,因此需要把 trace、成本和评估数据放在同一条执行链上。

Trace 的层级:Langfuse 的 Observation 模型#

Langfuse 用 Observation 表示一次执行中的观测,SPAN 记录可嵌套的步骤,EVENT 记录不可嵌套的瞬时事件,GENERATION 专门记录模型调用。后者带有 prompt、模型、token 和成本字段,能够按模型或步骤聚合,而不必从自由文本日志里反查。这个数据模型的价值不在名词,而在于让一次 Agent 执行可以被拆成可查询的因果链。

评估:概率输出怎么判对错#

可观测性记录“发生了什么”,评估判断“结果是否可接受”。评估通常组合基准数据集、规则检查、LLM-as-judge、轨迹评估和对抗样例,并在每次修改 prompt、模型或工具后回归。评估本身也会消耗模型调用,因此要记录评估成本和评估器版本,避免把评分变化误当成业务质量变化。

开源工具的定位可以这样区分:

方案更适合解决的问题典型抽象
Phoenix在线观测与基础评估Observation、span、评估信号
Braintrust数据集与评估实验Dataset、Evaluator、Scorer
DeepEval把评估接入 CIassert_test 与模块化 metric

选型先看工作流:线上排查优先观测平台,比较 prompt 或模型优先评估平台,希望每次提交都阻断回归则优先测试框架。三者可以组合,不必强行二选一。

Claude Code 的可见与不可见#

Claude Code 在成本可见性上提供了 /cost、/usage 和状态栏统计,适合开发者观察单会话消耗。但“看见成本”不等于“控制成本”,后者仍需要网关、配额和并发限制。

它也已经支持可选的 OpenTelemetry 导出:指标和事件可以发往 OTLP,分布式 trace 则按需要开启。这样可以接入 Langfuse、Phoenix 或企业自己的 Collector。交互界面和本地 transcript 仍然有价值,但不应再把它描述成唯一的观测手段。

真正的边界在于职责分工:Claude Code 只输出原始遥测,跨会话聚合、异常检测、告警和长期成本预算要交给后端系统。生产化时需要先定义事件字段和脱敏策略,再决定保留哪些 prompt、工具参数和文件内容;否则“导出了 trace”也无法用于审计。

六、安全与合规:自主执行的双刃剑#

入口验签只能解决“谁能触发”。Agent 继续调用工具、读写文件和执行代码后,prompt injection、第三方 MCP 服务、记忆投毒和长任务中的约束丢失都会扩大影响面。因此这一层要把运行时安全控制、合规留痕和持久记忆的来源放在同一个威胁模型里看。

Claude Code 的安全模型#

Claude Code 的安全模型不是单一开关,而是权限规则和操作系统沙箱的组合。/permissions 管理 allow、ask、deny 规则;权限模式从只读的 plan、需要确认的 default,到自动接受编辑的 acceptEdits、带后台安全检查的 auto、只执行预授权工具的 dontAsk,以及跳过权限层的 bypassPermissions,分别对应不同的监督强度。

/sandbox 开启后,Linux 使用 bubblewrap 限制 Bash 子进程的文件系统和网络访问。沙箱不可用时,默认行为是提示警告后继续执行;需要把 sandbox.failIfUnavailable 设为 true,才能把沙箱当成生产安全门。这个默认值很容易被忽略。

命名空间主要隔离文件和网络,不自动提供 CPU、内存配额,也不替你抵御共享内核漏洞。需要资源隔离或更强的租户边界时,仍要叠加 cgroup、容器或 microVM。bypassPermissions 会跳过权限层,因此只能在这些外部边界已经建立时使用。

Claude Code 的企业边界也需要更新:它可以把指标、工具事件和权限决策通过 OpenTelemetry 发往 Collector 或 SIEM,但跨用户的策略、告警、数据留存和租户隔离仍由部署方负责。本地 CLI 提供了安全原语,不等于提供完整的企业治理平面。

合规:法规的真实时间线#

企业还要把技术控制映射到适用法规。以 EU AI Act 为例,2026 年 8 月 2 日起透明度义务和执法框架开始适用;特定高风险场景的规则延至 2027 年 12 月 2 日,嵌入受监管产品的高风险系统延至 2028 年 8 月 2 日。具体日期会随修订变化,部署时应以欧盟委员会和 EUR-Lex 的最新文本为准。

对 Agent 基础设施更有操作性的要求是:保留可追溯的事件记录,能说明使用了哪个模型、哪些工具、谁批准了高风险动作,以及发生异常后如何回放。GDPR 的数据保护影响评估(DPIA)与 AI Act 的基本权利影响评估(FRIA)不是同一个流程,合规清单里应分别处理。

协议生态:谁在治理什么#

协议的职责也应分层理解:MCP 解决 Agent 与工具之间的发现和调用,A2A 解决 Agent 间通信,ANP 等协议尝试处理 Agent 身份。它们不是同一层的替代品,采用时应先明确要解决的是工具接入、跨 Agent 协作,还是身份与信任。

记忆中毒#

记忆也是攻击面:攻击者可以把伪造事实写入持久化层,让后续会话反复引用。防护重点不是某个特定数据库,而是写入前的来源和权限校验、按用户与 Agent 隔离、版本化保留变更记录,以及对高风险记忆设置人工确认。Graphiti 的时序事实模型能帮助事后追溯“何时有效、何时失效”,但它不能自动判断一条事实是否被投毒,实时检测仍需要独立的策略或评估链路。

七、部署与演进:从 Jupyter 到生产#

原型阶段只要一次任务能跑通,生产阶段则要保证重试不会重复产生副作用、进程重启后任务能继续、模型或 prompt 升级后效果没有悄悄退化。部署问题的核心不是“把 Python 脚本放到服务器”,而是把一条概率性、有副作用的执行链变成可恢复的服务。

先把三类状态拆开#

Agent 状态并非都不能结构化,混在一起才难以恢复。生产系统至少要拆成三类:

  • 控制状态:任务 ID、当前步骤、重试次数、审批状态和幂等键,适合放进关系数据库或工作流引擎。
  • 语义状态:对话、文档、摘要和向量,适合对象存储、搜索引擎或向量数据库。
  • 执行状态:临时文件、工作树、沙箱进程和网络连接,应当可丢弃、可重建。

恢复的关键是控制状态。工具调用前写入意图和幂等键,调用后记录结果引用;进程重启时才能判断“尚未执行”“执行成功但未回写”还是“可以安全重试”。只保存聊天 transcript,不足以恢复一条产生了外部副作用的任务。

推理底座:vLLM 与 Firecracker#

推理服务和工具执行是两套底座。vLLM 解决模型推理的吞吐与调度,Firecracker 这类 microVM 解决不可信代码的隔离。Firecracker 官方给出的启动时间低于 125 毫秒,但这是精简内核和设备配置下的指标,不能直接当成所有业务镜像的冷启动承诺。

部署时应分别评估模型实例和执行沙箱:前者关心批处理、KV cache、显存和限流,后者关心文件与网络边界、CPU/内存配额、镜像预热和销毁策略。把两者都塞进同一组 Pod 指标,会掩盖真正的瓶颈。

Claude Code 的伪无状态#

Claude Code 已支持非交互调用、云端任务、Channels、团队协作和 OpenTelemetry,不能再简单概括为“只有本地单进程”。但它的自动记忆仍默认保存在本机,项目 transcript、工作树和沙箱也依赖具体执行环境。它更像一套可嵌入工作流的开发者 Agent,而不是通用的多租户 Agent 服务。

这条边界对架构设计很有价值:本地文件系统足以支撑个人编程任务,团队或无人值守服务则必须额外解决状态迁移、集中密钥、租户隔离、队列调度和故障恢复。不要因为入口已经支持云端或 CI,就误以为状态层也自动完成了服务化。

从原型到生产:七关如何逐层浮现#

七道关卡不会同时成为主要矛盾,可以用四个准入阶段控制建设顺序:

阶段先解决什么进入下一阶段前的最低条件
原型单 Agent 与少量只读工具任务集可重复运行,失败能定位到具体步骤
集成Channel、连接器、记忆入口可鉴权和去重,工具按身份授权,记忆可删除和纠错
工作流多步骤或多 Agent 编排有 checkpoint、超时、重试上限和逐步 trace
生产无人值守、多人或多租户有预算、评估回归、沙箱、审计、恢复演练和版本回滚

这个顺序有三个直接结论。入口身份和幂等没有做好,不要急着扩渠道;单 Agent 的 trace 与评估没有建立,不要急着上多 Agent;任务状态不能恢复、工具执行没有隔离,不要开启无人值守。

Claude Code 的参照价值也在这里。小规模编程任务可以用文件系统记忆、交互确认和同进程子 Agent 解决,不必预先引入分布式编排和向量数据库。跨出本地、单用户、可监督的边界后,再按真实压力补齐网关、持久状态、策略与观测系统。基础设施的成熟度,不由采用了多少组件决定,而由失败之后能否解释、停止和恢复决定。

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

赞助
2026:Agent 基础设施七大难题
https://blog.souloss.cn/posts/ai/agent/agent-infra-challenges-2026/
作者
Tsukimi
发布于
2026-08-02
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时