← 返回 FEED
AGENT2026-04-21

生产级深度 Agent 的运行时架构

两层分离:Harness vs Runtime

构建一个好的 Agent 需要两层:

  • Harness:围绕模型搭建的支持系统,包括 Prompt、Tools、Skills,以及支持模型和工具调用循环的一切
  • Runtime:底层基础设施——持久化执行、记忆、多租户隔离、可观测性,让 Agent 在生产环境持续运行而不需要团队每次都重新发明

大多数教程停在 Harness。但生产级 Agent 失败的地方,往往是 Runtime 层面。

持久化执行:让 Agent 不怕打断

Agent 的核心循环是:给一个 Prompt,模型推理,调用工具,观察结果,重复直到任务完成。这个循环可能横跨几分钟甚至几小时——一个研究 Agent 可能花二十分钟搜集来源、合成发现,中途进程崩溃不能让它从头来过。

两个核心需求:

  • 长时间运行需要能承受基础设施故障:Agent 已经支付了 Token 费用、执行了工具调用,崩溃后应该从最后一个完成的步骤恢复,所有之前状态完好
  • Agent 需要能够停止和等待:等待人工审批时不可能持续占用工作进程,Agent 需要真正停止,释放资源,之后从中断的地方继续

两个需求由同一件事解决:Durable Execution(持久化执行)

Agent 运行在一个托管任务队列上,每个图执行的超级步骤(super-step)都会将 checkpoint 写入持久化层(默认 PostgreSQL),以 thread_id 为 key。当工作进程崩溃,run 的租约被释放,另一个 worker 从最新 checkpoint 恢复。当 Agent 等待人工输入,进程交出槽位,run 休眠,直到被恢复——可以是一天后。

两种记忆:短期的和长期的

短期记忆(Short-term Memory):Agent 在单次对话中积累的内容——交换的消息、调用的工具、跨 run 建立起来的中间状态。存储在 thread 的 checkpoint 里,thread 结束时概念上消失。

长期记忆(Long-term Memory):跨对话携带的信息——用户偏好、项目约定、最佳实践,或者每个新查询都会增强的知识库。不属于任何单一 thread,是用户级或组织级的上下文,跨每次对话持久化。Checkpoint 做不到这一点,因为 checkpoint 状态作用域是单一 thread。

LangChain Agent Server 的长期记忆是一个 Key-Value 接口,记忆按 namespace tuples 组织(例如 (user_id, "memories"))。默认由 PostgreSQL 存储,支持 embedding 相似性检索。

多租户隔离:三个问题分别解决

一旦 Agent 服务超过一个用户,三个问题同时出现:

  1. 用户 A 的数据与用户 B 隔离:Auth Handler 在每个请求上作为中间件验证凭证,返回用户身份和权限,附加到 run context;Resource Handler 在创建时打上所有权元数据,读取时返回过滤字典
  2. Agent 代表用户操作第三方服务:Agent Auth 处理 OAuth 流程和 Token 存储,用户认证一次,Agent 在后续 run 中使用用户范围的凭证
  3. 控制谁能操作系统本身:RBAC 处理运维层面的访问控制(部署 Agent、配置、查看 traces、更改 auth 策略)

三层组合:最终用户通过 Auth Handler 认证,Agent 通过 Agent Auth 调用第三方服务,团队在 RBAC 策略下运维部署。

Human-in-the-loop:中断而不是打断

有时候需要在 Agent 运行过程中插入人工判断——审批一个 consequential 的工具调用,或者 Agent 遇到无法自行解决的决策点需要向人确认。

LangChain 的方案是 interrupt() / continue():

  • interrupt() 暂停执行,将完整图状态写入持久化存储,进程释放资源并无限期等待
  • continue(resume=...) 恢复执行,恢复值成为 interrupt() 调用的返回值

与静态断点不同,interrupt() 是动态的:可以在代码中任何位置调用,可以包在条件语句里,可以嵌入工具函数内部,这样审批逻辑就跟着工具走,而不是跟着 Agent 走。

实时交互:Streaming 和 Double-texting

Streaming:Agent 花三十秒产生响应,用户盯着 spinner 不知道是卡住了还是在运行。Streaming 让部分输出在 Agent 产生时流向客户端,用户实时看到响应展开。LangChain 支持多种粒度:每步完整状态快照、仅状态更新、Token 级 LLM 输出、自定义应用事件。

Double-texting:用户在新 run 还在运行时发送了第二条消息。策略有四种:

  • enqueue(默认):新输入等待当前 run 结束,然后顺序处理
  • reject:拒绝任何新输入直到当前 run 完成
  • interrupt:停止当前 run,保留进度,用新输入从该状态继续处理
  • replace:停止并完全回滚,包括原始输入,用新消息作为全新 run

Middleware:策略必须每次都执行

有些生产需求无法表达为"持久化运行 loop",而是要塑造 loop 本身——在模型输入时拦截,在工具输出时过滤,对昂贵操作强制限制。这些策略属于代码层,不属于 Prompt。

LangChain 的 Middleware 在定义的钩子上包装 agent loop(before_model、wrap_model_call、wrap_tool_call、after_model),策略每次都确定性地执行。

内置 Middleware 包括:PIIRedactionMiddleware(脱敏)、ModelRetryMiddleware、ModelFallbackMiddleware、ToolCallLimitMiddleware、SummarizationMiddleware、HumanInTheLoopMiddleware、OpenAIModerationMiddleware。Middleware 开源,但只有跑在 Agent Runtime 里时才能覆盖所有交互模式——streaming、人机交互暂停/恢复、重试、后台 run、长生命周期 thread,每种模式下 guardrails 都一致生效。

可观测性:Traces 是改进循环的基础

Agent 的执行路径取决于模型在运行时的选择——调用什么工具、传什么参数、如何解释结果、何时放弃并尝试别的方式。出了问题,不能靠重读代码解决,需要看到实际发生了什么。

LangSmith Deployment 提供完整执行树:模型调用、工具调用、子 Agent run、中间件钩子,可按用户、时间窗口、成本、延迟、错误状态、反馈或自定义标签查询。Trace 不是只有调试用——是改进循环的基础:

  • LangSmith Assistant 分析 traces,发现常见失败模式、慢工具调用、重复模式
  • Online Evals 对生产 traces 自动运行 LLM-as-judge 或自定义评分器,回归能被即时捕获

时间穿越调试:从 Checkpoint Fork

每个 super-step 都写 checkpoint,run 历史中每个点都已经是快照。LangChain 的 client.threads.fork_from_checkpoint 让你从 thread 历史中选一个 checkpoint,可选地修改其状态,然后从那里恢复。修改后的 checkpoint fork 线程历史,原来的保持完整,新路径作为自己的分支运行。

这解锁了难以构建的模式:调试 Agent 为什么选错了工具、对比两个 Prompt 在相同上游上下文下的表现、从跑偏的 run 恢复到最后一个良好状态、跨多个 fork 探索反事实以理解模型行为。

沙箱隔离:任意代码执行

能调用预接线工具的 Agent 受限于你能想到的工具。能运行任意代码的 Agent 是通用——可以安装依赖、clone 仓库、执行测试、运行数据分析、生成文档、渲染图表。

但任意代码执行需要隔离:Agent 不能 rm -rf / 你的主机,不能读取你的环境变量 exfiltrate 你的 API keys。

LangChain 的 Sandboxing 通过 Daytona、Modal、Runloop 等实现,工作方式:配置一个实现 SandboxBackend 的后端,Agent 自动获得在沙箱中运行 shell 命令的 execute 工具,以及标准文件系统工具。没有沙箱后端,execute 工具对 Agent 不可见。

Auth Proxy 值得特别一提:Agent 需要调用经过认证的 API,但把凭证放在沙箱里有安全风险。代理作为 sidecar 运行,拦截出站请求,自动从 workspace secrets 注入凭证——沙箱代码调用 http.get("https://api.github.com/repos") 不带任何 header,代理在出站时加上正确的 Authorization header。凭证永不进入沙箱,Agent 无法 exfiltrate 它看不见的东西。

开放协议:打破 Agent 和外部系统的墙

MCP(Model Context Protocol):连接 Agent 到工具和数据源的开放标准。LangChain Agent Server 每个部署都作为 MCP 服务器暴露,使 Agent 可被任何 MCP 兼容客户端(Claude Desktop、IDE、其他 Agent)发现,无需编写适配代码。

A2A(Agent-to-Agent):Agent 间通信的对应标准。编排者 Agent 在一个部署中,可以发现并调用另一个部署中的 Worker Agent,双方使用相同理解的协议,无需手写 HTTP 契约。

Webhooks:出站场景——Agent 完成一个 run,你想触发下游操作,不需要轮询。创建 run 时传入 webhook URL,服务器在完成时 POST 载荷到该 URL。

定时 Run:Agent 也可以主动

大多数 Agent 是响应式的:用户发消息,Agent 回复。但很多有价值的 Agent 工作是主动的——按计划发生,没有人触发:

  • 空闲时计算:研究 Agent 每晚运行,追踪你领域的新论文;Prep Agent 在你开始一天前审查日历并起草简报;分类 Agent 整理隔夜支持工单
  • 健康和监控循环:Agent 定期检查,发现问题或有异常时采取行动或升级

LangChain Agent Server 内置 crons,stateful(client.crons.create_for_thread)让每次触发的 run 附加到同一对话(适合需要看到自己历史的 Agent);stateless(client.crons.create)每次执行启动一个全新 thread(适合不需要 run 间连续性的批处理工作)。

部署选择:不开源锁定

LangChain deepagents deploy 支持 VPC、BYOC(Bring Your Own Cloud)和全托管部署。关键是:Harness 是开源的,Agent 指令用 Markdown,Agent 通过开放协议暴露——无模型锁定,无沙箱锁定,Harness 不是黑箱。

默认 Harness 提供的核心能力包括:持久化执行、短长期记忆、多租户隔离、人机交互、Middleware 策略执行、可观测性 traces、时间穿越调试、沙箱代码执行、定时 runs、MCP/A2A/Webhooks。