如何设计和构建基于你自己业务的自定义Agent Harness?
从业务所需的上下文、潜在故障、强制策略和运行环境出发,借助 create_agent 与 middleware,把八类能力组合成真正适配任务的 Agent Harness。
在构建面向具体业务的 AI Agent 时,开发者真正要决定的关键问题,往往并不是“选哪个最强模型”,而是厘清当前任务的具体运行诉求:它究竟需要哪些上下文(context it needs)、会遇到哪些潜在失败(failures it'll encounter)、必须执行哪些策略(policies it must enforce),以及运行在怎样的真实环境(environment it operates in)之中。这四个维度,正是原文在定义 Task-Harness Fit(任务与底座适配度) 时明确指出的核心衡量标准。
构建真正实用的智能体,本质上是关于定制化(Customization)——如何让智能体在特定任务中连接到所需的上下文、数据与运行环境。包裹在模型外部的 Agent Harness(智能体运行底座/脚手架),正是实现这种连接的工程实体。需要交代的是,原文并未给出开箱即用的完整业务实施教程,而是系统阐明了如何以极简原语为核心、利用中间件为业务量身设计和定制 Harness 的架构路径。

概念解耦:什么是 Harness?为什么说 Agent = Model + Harness?
在最本质的层面上,智能体就是一个模型在循环中不断调用外部工具,直到任务完成并返回结果:

这一运行机制可以用一个核心公式清晰表达:
Agent = Model + Harness
这里的 Harness,就是包裹在大模型外部、负责将其与真实世界连接起来的整套脚手架工程。

这一架构认知建立在两项前提之上:
- 智能体的实际表现,取决于提供给模型的上下文质量(An agent is only as good as the context provided to the model);
- Harness 的核心职责,就是在循环的每一步为模型精准提供所需的上下文(The job of a harness is to provide context to the model at every step)。
因此,要构建出真正可用的智能体,就必须打造一套善于为特定任务按时、按需向模型输送正确上下文的 Harness。
极简原语与预组装底座的分水岭:为什么选择 create_agent?
在 LangChain 体系中,构建自定义 Harness 的基础原语正是 create_agent。只需传入模型、工具集和系统提示词,就能得到一个正常运转的智能体:
from langchain.agents import create_agent
agent = create_agent(
model="anthropic:claude-sonnet-4-6",
tools=tools,
system_prompt="you are a helpful assistant..."
)
在工程选型中,市面上存在两种截然不同的底座构建思路:
- 预组装 Harness(Pre-assembled Harnesses):如 Deep Agents 或 Claude Agent SDK。它们出厂即带有一套有明确取向的中间件技术栈,包含记忆、上下文管理、沙箱等组件。这类底座旨在帮助团队快速得到生产可用的 Agent,适用于大多数场景。然而,许多 Agent 仍需要比预装底座更细粒度的定制控制,例如专属提示词、业务逻辑以及护栏。
- 极简原语路线(Purposefully Minimalistic Primitive):
create_agent采取了不同的方式,这一理念类似于高可配置的代码智能体 Harness Pi。create_agent只实现最核心的智能体循环,并把中间件(Middleware)暴露为定制原语。
中间件机制:如何通过四类杠杆精细定制 Harness?
中间件是深度定制 Harness 的核心手段。中间件能够直接挂载到 Agent 运行循环的各个阶段:模型调用前后、工具调用前后,以及智能体启动和终止时。每个中间件独立处理单一关注点,并能与其他中间件自由组合拼装:

通过中间件,开发者可以借助以下四类常常协同起效的“工程杠杆”按业务需求精细定制底座:
- 确定性逻辑(Deterministic Logic):
- 解决的设计问题:业务规则、策略强制执行以及动态运行时控制,需要在运行循环的特定节点触发,不适合完全塞进提示词(Prompt)中。
- 机制与原文示例:用于在循环特定节点触发的确定性代码。原文明确指出的关键场景是对智能体运行时的动态控制:根据任务复杂度动态切换模型(swapping the model based on task complexity)、动态调整提示词(adjusting the prompt),以及在上下文压缩时更新消息历史(updating the agent's message history, during compaction, for example)。凡是不能或不应写在提示词里的逻辑,都属于此类。
- 工具生命周期治理(Tools):
- 解决的设计问题:当工具带有外部依赖、需要初始化或结束时清理,仅仅把工具直接注册到 Agent 上,会让配置与治理逻辑分散。
- 机制与原文示例:不再将工具生硬地直接注册在智能体上,而是由中间件全权接管工具的完整生命周期——初始化设置(setup)、运行结束清理与卸载(teardown)以及动态注册(registration),并妥善管理工具依赖,最终交付给智能体一套干净规整的可用工具集。这保证了工具配置与其背后的控制逻辑紧密内聚,避免配置散落。
- 自定义状态(Custom State):
- 解决的设计问题:中间件需要在不同生命周期钩子之间持续记录并共享业务状态。
- 机制与原文示例:通过自定义属性扩展智能体的状态对象(extend the agent's state with custom properties)。原文明确指出,这使得中间件能够在整个执行周期内维护计数器(counters)、状态标志(flags)或其他持久值,并在不同的钩子之间无缝共享数据。
- 流处理器(Stream Handlers):
- 解决的设计问题:智能体输出流中的不同事件,需要交给界面、审计和监控等不同消费者处理。
- 机制与原文示例:中间件可以拦截并重塑输出流——过滤事件(filtering events)、注入元数据(injecting metadata),并将不同类型的事件路由给不同的消费者。原文给出的典型业务场景包括:前端 UI 消费 Token 增量(token deltas)实现实时打字渲染、审计日志系统捕获工具调用(tool calls)完成合规留痕、监控系统追踪延迟(latency)保障服务稳定性。
中间件机制的核心工程价值在于:
- 允许在智能体生命周期的任意拦截点进行无缝定制;
- 将关联工程逻辑封装为独立解耦、可自由组装并在多项目间复用的代码单元。
LangChain 提供了覆盖常见模式的预置中间件(Prebuilt Middleware);若存在专有需求,也可以编写自定义中间件(Custom Middleware)。由于每个中间件彼此隔离,同一个中间件可以在组织内复用,使新 Agent 继承已经验证过的行为。
从业务任务倒推 Harness:八大能力需求与中间件映射
Harness 的终极使命,是在循环的每一步为模型递送精准匹配当前任务的上下文。
构建 Harness 不是把所有中间件全量装上。原文明确指出,智能体最终采用哪些中间件组合,取决于具体任务的核心需求:是否需要长周期运行(is it long running?)、任务本身有多复杂(how complex are the tasks?),以及智能体执行动作的敏感程度如何(how sensitive are the agent's actions?)。一个客服 Agent 与一个长运行编程 Agent 所需的 Harness 会明显不同,但原文没有替这两类业务规定固定组合。
业务设计方法:从任务需求倒推 Harness 装配
围绕“如何设计和构建基于你自己业务的自定义 Harness”,把原文关于 Task-Harness Fit 的四个维度与官方能力映射表结合起来,可以提炼出一套面向业务开发者的倒推设计方法(注:这是把原文的 Task-Harness Fit 考量与能力表合并后的读者用法,而非 LangChain 官方给出的固定四步规范):
- 写清任务使命(Mission):先明确智能体要完成的核心业务目标、执行边界与期望交付物。
- 按四大维度盘点特征(Context / Failures / Policies / Environment):
- 上下文(Context):会话是多轮长交互还是一次性问答?需不需要记忆模块在启动时加载外部知识、在结束时沉淀经验?
- 潜在故障(Failures):模型或工具会遇到哪些不可预测的瞬态失败?
- 策略红线(Policies):是否存在用户隐私脱敏(PII)、合规检查,或者哪些高敏感操作必须获得人工审批批准?
- 运行环境(Environment):智能体是在受限数据环境还是需要获得文件系统、命令行或代码解释器等更广阔的执行环境?
- 从八项核心能力中按需筛选:根据盘点出的特征,在下方八项能力中挑出当前业务真正需要的项,避免无谓堆砌。
- 映射到具体中间件组合:将选定的能力直接对应到 LangChain 预置中间件或编写自定义中间件,组合挂载到
create_agent的循环中。
TASK → CAPABILITY → MIDDLEWARE
用业务条件拼出你的 Harness
勾选当前业务真实存在的条件,右侧会把对应 middleware 自动去重组合。未选择时,下方八项能力仍完整可读。
下表展示了原文梳理的八项核心生产能力需求、其背后的关键价值,以及官方对应的预置中间件映射关系:
| 能力维度(Capability) | 为什么重要(Why it Matters) | 对应中间件(Middleware) |
|---|---|---|
| 防止上下文溢出(Prevent context overflow) | 长时间运行的会话会迅速积累消息历史。若不加干预,将导致上下文窗口溢出。 | SummarizationMiddleware、ContextEditingMiddleware |
| 访问与更新记忆(Access and update memory) | 在启动时加载相关知识,在运行结束时写回更新。使智能体能够从真实使用中随时间持续进化。 | FilesystemMiddleware、MemoryMiddleware、SkillsMiddleware |
| 在环境中执行动作(Take actions in an environment) | 固定的工具集限制了智能体的能力边界。获得文件系统和执行环境的访问权限,能解锁更具创造性的解决方案,且往往具备更高的 Token 效率。 | ShellToolMiddleware、FilesystemMiddleware、CodeInterpreterMiddleware |
| 委托任务(Delegate tasks) | 子智能体(Subagents)使用独立的干净上下文窗口处理复杂子任务。待办清单(Todo list)则用于追踪长运行周期中的整体任务进度。 | SubAgentMiddleware、AsyncSubAgentMiddleware、TodoListMiddleware |
| 处理瞬态故障(Handle transient failures) | 模型与工具的调用故障具有不可预测性。生产级智能体需要具备退避重试逻辑,并在主模型不可用时自动启用回退方案。 | ToolRetryMiddleware、ModelRetryMiddleware、ModelFallbackMiddleware |
| 执行策略与合规(Enforce policies) | PII(个人身份信息)脱敏、合规检查、审批关卡——无论模型输出什么内容,这些检查都必须在每次调用时强制触发,它们绝不能只写在提示词里。 | PIIMiddleware、HumanInTheLoopMiddleware |
| 引导与控制智能体(Steer the agent) | 完全自主并不总是合适。在执行具有重大影响的动作前暂停执行,等待人类审核批准、拒绝或重定向指令。 | HumanInTheLoopMiddleware |
| 控制运行成本(Control costs) | 提示词缓存(Prompt caching)能降低长运行任务的 Token 开销。调用上限控制则能防止成本无节制累积。 | ModelCallLimitMiddleware、ToolCallLimitMiddleware、PromptCachingMiddleware |
完整的预置中间件定义与说明可查阅官方的 Prebuilt Middleware 参考文档。
任务与底座适配(Task-Harness Fit):检验你的自定义 Harness
Task-harness fit(任务与底座适配度),衡量的是 Harness 对业务任务真实需求的匹配程度:它需要的具体上下文(the context it needs)、可能遭遇的故障类型(the failures it'll encounter)、必须强制执行的安全合规策略(the policies it must enforce),以及它赖以运转的宿主环境(the environment it operates in)。正如前文所述,一个客服 Agent 与一个长周期运行的编程 Agent,其 Harness 构造截然不同。
LangChain 在文章中列举的三个自建 Agent,都基于 create_agent 并为各自任务装配中间件栈:
好的智能体不只依赖能力强大的模型,也依赖与具体任务高度契合的 Harness。LangChain 给出的直接做法,是使用 create_agent 配合中间件打造这种自定义底座。
自定义 Harness 最小设计自查清单
在将这些原理带回你的业务场景时,可以通过以下源自原文四个维度与能力图谱的问题进行快速自查:
- 上下文与记忆(Context & Memory):
- 任务是否涉及长运行会话?是否需要配置上下文总结或编辑中间件防止窗口溢出?
- 智能体是否需要在启动时加载外部知识/技能,并在运行结束时将新经验写回记忆?
- 故障容错与成本(Failures & Costs):
- 当外部模型或工具发生不可预测的瞬态故障时,是否配有退避重试与回退模型中间件?
- 是否配置了提示词缓存以降低长任务 Token 成本?是否设置了模型与工具的调用次数限制,避免成本持续累积?
- 策略约束与人工控制(Policies & Steering):
- 业务中是否有 PII 脱敏或合规审查等规则?它们是否已通过中间件在每次调用中强制执行?
- 面对高影响或敏感动作,是否配置了暂停并等待人类批准、拒绝或重定向的人在回路机制?
- 运行环境与任务协同(Environment & Delegation):
- 智能体是否需要突破固定工具集,接入文件系统、命令行或代码解释器环境以提高行动与 Token 效率?
- 面对复杂的长任务,是否需要将其拆解并委托给具备独立干净上下文的子智能体或由待办列表跟踪?
- 工具的依赖、初始化设置(setup)与结束清理(teardown)是否已交由中间件治理?
- 输出流是否需要分别处理:让前端消费 Token 增量、审计留存工具调用、监控追踪耗时延迟?
拓展资源与参考链接
官方指南与文档
如何设计和构建基于你自己业务的自定义Agent Harness?
让模型调用工具,是业务智能体的起点。任务需要长时间运行时,消息历史会不断增长;模型或工具可能出现调用故障;涉及隐私和高影响动作时,还要执行规则、保留人工审核。
这些需求需要模型外部的工程系统承接。Harness,就是把模型连接到业务数据、工具与运行环境的“运行底座”。LangChain 这篇文章讨论的,是怎样根据具体任务设计这层底座。
模型决定下一步,底座提供运行条件
智能体在运行中反复调用工具,工具的结果又成为模型下一步判断的信息。它的实际表现与每一步得到的上下文有关;Harness 的核心职责,就是在循环中按需提供这些上下文。
因此,设计前要先问:任务需要哪些信息、可能在哪里失败、必须执行哪些策略,以及能在什么环境中行动。这四个维度,构成 Task-Harness Fit(任务与底座适配度)的判断依据。
可以用预装底座,也可以从核心循环开始搭
已有方案能帮助团队快速起步。若业务需要更细地控制提示词、业务逻辑或护栏,就需要考虑相应的定制能力。选择取决于任务要求。
从已有能力组合起步
Deep Agents、Claude Agent SDK 提供有明确取向的组件组合,包含记忆、上下文管理、沙箱等能力,帮助团队较快获得可用的智能体。
围绕核心循环按需装配
LangChain 的 create_agent 提供核心工具调用循环,通过中间件开放定制入口。传入模型、工具和系统提示词,即可构建基础智能体。
agent = create_agent(
model=..., tools=..., system_prompt=...
)
上面只示意基础调用参数;完整业务仍需补齐具体工具与运行逻辑。
中间件把业务逻辑接进每一轮循环
中间件,是可挂在运行节点上的功能模块。它可以在智能体启动和终止时、模型调用前后、工具调用前后介入。每个模块处理一个关注点,多个模块可以组合,也能跨项目复用。
有了这些介入点,业务逻辑就能在需要的时候执行。正文将定制能力归为下面四类:它们共同改变底座的行为,不能只靠把要求写进提示词来替代。
在节点上执行规则确定性逻辑
根据任务复杂度切换模型、动态调整提示词,或在上下文压缩时更新消息历史。代码在对应节点执行,承接运行时控制。
管理工具的全过程工具生命周期
将工具的初始化、结束清理、动态注册和依赖管理放在一起,向智能体提供准备好的工具集,避免配置与治理逻辑散落各处。
让不同节点共享信息自定义状态
扩展智能体的状态对象,在整个执行周期中维护计数器、状态标志或其他持久值,让不同节点能共享这些数据。
把事件送到需要它的地方流处理器
过滤事件、注入元数据,并将不同输出分发给各自的消费者。
按任务挑能力,再找到对应的中间件
先写清业务目标、行动边界与期望产出,再盘点上下文、故障、策略和环境。任务是否长时间运行、子任务是否复杂、动作是否敏感,会影响最终的组合。下面八项按需选择,并非全部必装。
“任务使命 → 特征 → 能力 → 中间件”是解读结合原文提炼的使用方法,并非 LangChain 官方固定四步规范。
防止上下文溢出
长会话不断积累消息,需要总结或编辑历史,防止超出上下文窗口。
SummarizationMiddlewareContextEditingMiddleware访问与更新记忆
启动时加载相关知识,结束时写回更新,让运行之间能保留记忆。
FilesystemMiddlewareMemoryMiddlewareSkillsMiddleware在环境中执行动作
按任务需要提供文件系统、命令行或代码执行环境,扩展行动空间。
ShellToolMiddlewareFilesystemMiddlewareCodeInterpreterMiddleware委托任务
子智能体用独立上下文处理复杂子任务,待办清单追踪整体进度。
SubAgentMiddlewareAsyncSubAgentMiddlewareTodoListMiddleware处理瞬态故障
为模型和工具调用提供退避重试;主模型不可用时采用回退方案。
ToolRetryMiddlewareModelRetryMiddlewareModelFallbackMiddleware执行策略与合规
个人身份信息(PII)脱敏、合规检查和审批关卡,需要在调用中强制执行。
PIIMiddlewareHumanInTheLoopMiddleware引导与控制智能体
在高影响动作前暂停,由人批准、拒绝或重新指明方向。
HumanInTheLoopMiddleware控制运行成本
利用提示词缓存降低开销,并用模型或工具的调用上限控制累计成本。
ModelCallLimitMiddlewareToolCallLimitMiddlewarePromptCachingMiddleware判断底座是否合适,要回到任务本身。客服智能体与长运行编程智能体的需求不同,正文没有为它们规定固定组合。LangChain 列出的 GTM Agent、Open-SWE 和 Fleet,也都是围绕各自任务使用 create_agent 和中间件。
这篇提供架构路径与能力映射,并未交付可以直接上线的完整业务实现代码。
How to Build a Custom Agent Harness
Effective agents are built with harnesses that are tightly coupled with the task at hand. The easiest way to build a custom harness is with LangChain's create_agent plus middleware. This guide covers the core agent loop and how you can customize it for your agent's use case.
Building useful agents is largely about customization: connecting your agent to the right context, data, and environment(s) for the task at hand.
At its core, an agent is a model calling tools in a loop until it completes a task and returns a result:

You can also define an agent as:
agent = model + harness
The harness is the scaffolding around the model that connects it to the real world.

The remainder of this post assumes the following:
- An agent is only as good as the context provided to the model
- The job of a harness is to provide context to the model at every step
So, to build a useful agent, you need a harness that’s great at delivering the right context for the given task to the model.
The base harness
create_agent is LangChain's primitive for building a harness. Pass in a model, tools, and a system prompt, and you have a working agent:
from langchain.agents import create_agent
agent = create_agent(
model="anthropic:claude-sonnet-4-6",
tools=tools,
system_prompt="you are a helpful assistant..."
)Harnesses like Deep Agents and the Claude Agent SDK come pre-assembled with an opinionated middleware (explained below) stack: memory, context management, sandboxing, and more. They're designed to get you to a production-ready agent fast, and they work well for most cases. But many agents need finer grained customization than these harnesses support: custom prompting, business logic, guardrails, etc.
create_agent takes a different approach: it’s purposefully minimalistic. Our philosophy is similar to that of Pi, a highly configurable coding agent harness. create_agent just implements the core agent loop, and it exposes middleware as a primitive for customization.
Middleware: how you customize the harness
Middleware hooks into the agent loop at each step: before and after model calls, before and after tool calls, at agent startup and teardown. Each piece handles one concern and composes freely with any other:

Middleware allows you to add capabilities to your agent via a few levers that often work together:
Deterministic Logic. Business logic, policy enforcement, dynamic agent control — anything that needs to fire at a specific point in the loop. This includes runtime control over the agent itself: swapping the model based on task complexity, adjusting the prompt, and updating the agent’s message history (during compaction, for example). The right place for anything that can't (or shouldn't) live in a prompt.
Tools. Rather than registering tools directly on the agent, middleware can handle the full lifecycle — setup, teardown, registration — and hand the agent a clean set of tools to work with. This matters when tools have dependencies, require initialization, or need to be torn down cleanly at the end of a run. It also keeps tool configuration close to the logic that governs it, rather than scattered across the agent definition.
Custom state. If your middleware needs to track state across hooks, middleware can extend the agent’s state with custom properties. This enables middleware to track state throughout execution (maintain counters, flags, or other values that persist throughout agent runs) and share data between hooks.
Stream handlers. Middleware can intercept and transform the agent's output stream — filtering events, injecting metadata, routing different event types to different consumers. Useful when different parts of your stack need to react to different things the agent does: a UI consuming token deltas, an audit log capturing tool calls, a monitoring system tracking latency.
The beauty of middleware is that it:
- Enables customization at any point in the agent loop
- Bundles related logic in composable, sharable units of code
LangChain ships prebuilt middleware for the most common patterns. Anything bespoke to your use case is one custom middleware away. Because each piece is isolated, the same middleware can be reused across every agent in an organization so that new agents inherit battle-tested behavior without rebuilding it.
Harness capabilities
The job of a harness is to get the model the right context at the right time for the given task.
The table below maps common capabilities to middleware that support them. Most production agents end up using several together, depending on the agent’s needs (is it long running? how complex are the tasks? how sensitive are the agent’s actions?, etc):
| Capability | Why it Matters | Middleware |
|---|---|---|
| Prevent context overflow | Long-running sessions accumulate message history fast. Without intervention, it overflows the context window. | SummarizationMiddleware, ContextEditingMiddleware |
| Access and update memory | Load relevant knowledge at startup, write it back at the end of a run. Lets the agent improve over time from real usage. | FilesystemMiddleware, MemoryMiddleware, SkillsMiddleware |
| Take actions in an environment | A fixed toolset limits what an agent can do. Access to a filesystem and execution environment unlocks more creative solutions, often with greater token efficiency. | ShellToolMiddleware, FilesystemMiddleware, CodeInterpreterMiddleware |
| Delegate tasks | Subagents handle complex sub-tasks with clean context windows. A todo list tracks progress across a long run. | SubAgentMiddleware, AsyncSubAgentMiddleware, TodoListMiddleware |
| Handle transient failures | Models and tools fail unpredictably. Production agents need retry logic with backoff and fallbacks when a model is unavailable. | ToolRetryMiddleware, ModelRetryMiddleware, ModelFallbackMiddleware |
| Enforce policies | PII handling, compliance checks, approval gates — these need to fire on every call regardless of what the model does. They don't belong in a prompt. | PIIMiddleware, HumanInTheLoopMiddleware |
| Steer the agent | Full autonomy isn't always appropriate. Pause before consequential actions and wait for a human to approve, reject, or redirect. | HumanInTheLoopMiddleware |
| Control costs | Prompt caching reduces token spend on long-running tasks. Call limits prevent costs from accumulating unchecked. | ModelCallLimitMiddleware, ToolCallLimitMiddleware, PromptCachingMiddleware |
See the full list of prebuilt middleware here.
Task-harness fit
Task-harness fit is how well your harness matches the actual demands of the task: the context it needs, the failures it'll encounter, the policies it must enforce, the environment it operates in. A harness for a customer service agent looks very different from one built for a long-running coding agent.
Every agent we build at LangChain, including our GTM agent, asynchronous coding agent, and our no-code agent builder, is built on create_agent with a middleware stack tailored to that agent’s mission.
The best agents aren't just built with capable models, they're built with harnesses that tightly fit the task. The easiest way to build a custom harness is with create_agent.
References
Get Started
Acknowledgements
Thanks to @hwchase17, @huntlovell, @masondrxy, and @Vtrivedy10 for their thoughtful review and feedback.