扫码
40.67M · 2026-04-17
一句话:
Harness 这个词讲透Harness 可以理解为“总控壳 + 执行骨架”:
它不是单一功能库,而是把 Agent 需要的一整套机制(文件系统、工具、子代理、上下文治理、恢复机制)组织成一个可运行框架。
你可以把它类比成:
相同点(心智接近):
区别点(定位不同):
所以组合关系是:
你用 LangChain 选部件,用 LangGraph 保证结构稳定,用 DeepAgents 快速把“可住的房子”先搭起来。
如果只会“调用模型”,那不是 Harness。
Harness 的核心是把复杂任务变成可控流程,最常见闭环是:
Plan(先规划)
先拆任务、定边界、定验收标准,再开始执行。
Act(再执行)
按计划调工具、读写文件、调用子代理,逐步推进。
Check(持续验证)
每个阶段都做验证(测试、对账、规则校验),避免一路错到底。
Recover(可恢复)
中断、超时、审批、重启后能从上一步继续,而不是重跑全流程。
一句话:
Harness = Plan-first + Tool-use + Verification + Recovery 的工程闭环。
flowchart TB
A["DeepAgents(Harness)"] --> B["LangChain(能力积木)"]
B --> C["LangGraph(运行时引擎)"]
你可以把 DeepAgents 理解成:
“把 LangChain + LangGraph 的常见 Agent 能力打包好了,你先用,再按需下沉定制。”
我们用这句用户话术贯穿全教程:
上周我买的一个耳机坏了
你会实现:
pnpm add deepagents langchain @langchain/core zod
如果你要联网搜索工具(Tavily):
pnpm add @langchain/tavily
# 二选一示例
setx OPENAI_API_KEY "your-api-key"
setx ANTHROPIC_API_KEY "your-api-key"
import { createDeepAgent } from 'deepagents'
const agent = createDeepAgent({
// provider:model 形式,便于快速切模型
model: 'openai:gpt-5.4',
systemPrompt: '你是一个专业中文客服助手,回答准确、简洁。',
})
const result = await agent.invoke({
messages: [{ role: 'user', content: '上周我买的一个耳机坏了,怎么办?' }],
})
console.log(result.messages[result.messages.length - 1]?.content)
下面这段是你可以直接改业务逻辑的骨架。
import { createDeepAgent } from 'deepagents'
import { tool } from 'langchain'
import { z } from 'zod'
// 1) 查订单工具:真实项目里这里接 OMS API
const queryOrder = tool(
async ({ orderId }: { orderId: string }) => {
// 示例:返回订单基本信息
return {
orderId,
productName: '无线蓝牙耳机',
purchaseDate: '2026-04-05',
amount: 699,
}
},
{
name: 'query_order',
description: '根据订单号查询订单详情',
schema: z.object({
orderId: z.string().describe('订单号'),
}),
},
)
// 2) 查质保工具:真实项目里这里接保修系统 API
const queryWarranty = tool(
async ({ orderId }: { orderId: string }) => {
return {
orderId,
inWarranty: true,
policy: '15天换新 + 1年质保维修',
}
},
{
name: 'query_warranty',
description: '查询订单是否在质保范围',
schema: z.object({
orderId: z.string().describe('订单号'),
}),
},
)
// 3) 创建售后工单工具
const createAfterSalesTicket = tool(
async ({ orderId, reason }: { orderId: string; reason: string }) => {
return {
ticketId: `AS-${Date.now()}`,
orderId,
status: 'created',
reason,
}
},
{
name: 'create_after_sales_ticket',
description: '创建售后工单',
schema: z.object({
orderId: z.string(),
reason: z.string(),
}),
},
)
// 4) 子代理:专门做政策判定,减少主代理上下文污染
const policySubagent = {
name: 'policy-expert',
description: '判断当前售后请求应该走退款、换货还是维修',
systemPrompt: `你是售后政策专家。
先判断信息是否齐全(订单号、购买时间、故障描述)。
信息不齐请明确指出缺失字段,不要编造。
信息齐全后,给出建议路径:refund / replace / repair。`,
}
const agent = createDeepAgent({
model: 'openai:gpt-5.4',
systemPrompt: `你是电商平台售后助手。
用户可能只说“耳机坏了”,你要主动收集必要信息后再决策。`,
tools: [queryOrder, queryWarranty, createAfterSalesTicket],
subagents: [policySubagent],
})
const result = await agent.invoke({
messages: [{ role: 'user', content: '上周我买的一个耳机坏了' }],
})
console.log(result.messages[result.messages.length - 1]?.content)
你之前一直问 checkpoint,这块就是核心用法。
import { createDeepAgent } from 'deepagents'
import { tool } from 'langchain'
import { MemorySaver, Command } from '@langchain/langgraph'
import { v7 as uuid7 } from 'uuid'
import { z } from 'zod'
const refund = tool(
async ({ orderId, amount }: { orderId: string; amount: number }) => {
return `Refund submitted: ${orderId}, amount=${amount}`
},
{
name: 'refund',
description: '发起退款',
schema: z.object({
orderId: z.string(),
amount: z.number(),
}),
},
)
const checkpointer = new MemorySaver()
const agent = createDeepAgent({
model: 'openai:gpt-5.4',
tools: [refund],
// 高风险工具启用人工审批
interruptOn: {
refund: { allowedDecisions: ['approve', 'reject', 'edit'] },
},
checkpointer, // HITL 必须有 checkpointer
})
const threadId = uuid7()
const config = { configurable: { thread_id: threadId } }
// 第一次调用:可能在 refund 前被中断
let result = await agent.invoke(
{
messages: [{ role: 'user', content: '给订单 A1001 退款 699 元' }],
},
config,
)
if (result.__interrupt__) {
// 审批系统给出决定,这里示例“批准”
const decisions = [{ type: 'approve' }]
// 关键:用同一个 thread_id 恢复
result = await agent.invoke(new Command({ resume: { decisions } }), config)
}
console.log(result.messages[result.messages.length - 1]?.content)
invoke 走到敏感工具会暂停thread_id + Command(resume)继续先记住这一句:
DeepAgents 的 5 个高频生产能力是 虚拟文件系统(VFS)/ 记忆 / 长期记忆 / Skills / 子代理。
这是最容易被低估、但生产最关键的能力之一。
通俗讲:
VFS 就是“给 Agent 一块受控工作区”。
Agent 看起来在操作文件,其实是在你划定的安全边界内操作。
更关键的是:
这个“工作区”背后可以接不同存储,不只本地硬盘。
这就是 DeepAgents 的便利点:
你上层 Agent 代码几乎不变,只换 backend,就能切换底层存储策略。
为什么重要:
代码示例 1(本地目录 VFS,开发最常用):
import { createDeepAgent, FilesystemBackend } from 'deepagents'
const backend = new FilesystemBackend({
rootDir: 'E:/agent-workspace',
virtualMode: true, // 强制沙箱:路径被约束在 rootDir 下
})
const agent = createDeepAgent({
model: 'openai:gpt-5.4',
backend,
})
代码示例 2(数据库/网络存储 VFS,生产常见):
import { createDeepAgent, StoreBackend } from 'deepagents'
import type { BaseStore } from '@langchain/langgraph-checkpoint'
// 由你的基础设施提供:可接 Redis/DB/云存储封装后的 BaseStore
declare const myStore: BaseStore
const agent = createDeepAgent({
model: 'openai:gpt-5.4',
store: myStore,
// 通过 namespace 做租户/用户隔离(长期持久化)
backend: () =>
new StoreBackend({
namespace: ['memories', 'org-001', 'user-1001', 'filesystem'],
}),
})
代码示例 2.1(PostgreSQL 持久化示例,简化版):
import { createDeepAgent, StoreBackend } from 'deepagents'
import type { BaseStore } from '@langchain/langgraph-checkpoint'
import { Pool } from 'pg'
// 1) 连接 PostgreSQL
const pool = new Pool({
connectionString: process.env.PG_DSN, // 例如: postgres://user:pass@host:5432/agentdb
})
// 2) 你需要一个实现 BaseStore 的 PG 适配器(这里用伪代码表示)
class PgBaseStore implements BaseStore {
constructor(private pool: Pool) {}
// put/get/search/delete ...(按 BaseStore 接口实现)
}
const pgStore = new PgBaseStore(pool)
// 3) 把 PG Store 接到 DeepAgents 的 VFS 后端
const agent = createDeepAgent({
model: 'openai:gpt-5.4',
store: pgStore,
backend: () =>
new StoreBackend({
store: pgStore,
namespace: ['memories', 'org-001', 'user-1001', 'filesystem'],
}),
})
这个示例的价值是:
代码示例 3(组合后端:热数据本地,长期记忆走持久化):
import { createDeepAgent, CompositeBackend, FilesystemBackend, StoreBackend } from 'deepagents'
import type { BaseStore } from '@langchain/langgraph-checkpoint'
declare const myStore: BaseStore
const agent = createDeepAgent({
model: 'openai:gpt-5.4',
store: myStore,
backend: () =>
new CompositeBackend(
new FilesystemBackend({ rootDir: 'E:/agent-workspace', virtualMode: true }),
{
'/memories/': new StoreBackend({
namespace: ['memories', 'org-001', 'user-1001', 'filesystem'],
}),
},
),
})
你可以把它类比前端:
判断标准:
“下一次开新会话还要不要用到?”
要用到,就应该进长期记忆。
如果你手写,通常要自己做这几件事:
DeepAgents 给你的便利 API:
memory: string[]:声明要加载的记忆文件路径backend:决定这些记忆来自哪里(本地/数据库/组合)store:接持久化存储(跨会话、跨线程)你不用自己每轮手拼 prompt,框架会把 memory 作为上下文注入。
代码示例(长期记忆 + 客服场景):
import { createDeepAgent, FilesystemBackend } from 'deepagents'
const backend = new FilesystemBackend({
rootDir: 'E:/after-sales-agent',
virtualMode: true,
})
const agent = createDeepAgent({
model: 'openai:gpt-5.4',
backend,
// 这些文件会在每次启动时被加载到上下文中
memory: ['/memory/user-profile.md', '/memory/after-sales-policy.md'],
})
const result = await agent.invoke({
messages: [{ role: 'user', content: '我耳机坏了,想处理售后' }],
})
这个例子里,user-profile.md 和 after-sales-policy.md 就是长期记忆载体:
下次新会话仍可复用,不需要每次重新喂给模型。
Skills 的核心价值:
DeepAgents 的优势是:
内建了文件系统语义,记忆和技能都能走统一的“文件 + 后端存储”模式。
代码示例(Skills 声明式加载):
import { createDeepAgent, FilesystemBackend } from 'deepagents'
const agent = createDeepAgent({
model: 'openai:gpt-5.4',
backend: new FilesystemBackend({ rootDir: 'E:/agent-workspace', virtualMode: true }),
skills: ['/skills/common/', '/skills/after-sales/'],
})
子代理不是“炫技”,而是“降复杂度”工具。
适用场景:
收益:
代码示例(子代理最小声明):
import { createDeepAgent } from 'deepagents'
const policySubagent = {
name: 'policy-expert',
description: '负责售后规则判定',
systemPrompt: '你是售后政策专家,只做规则判断并返回可执行结论。',
}
const agent = createDeepAgent({
model: 'openai:gpt-5.4',
subagents: [policySubagent],
})
for await (const [namespace, chunk] of await agent.stream(
{
messages: [{ role: 'user', content: '帮我处理耳机售后并给出方案' }],
},
{
streamMode: 'updates',
subgraphs: true, // 包含子代理事件
},
)) {
const source = namespace.length > 0 ? `subagent:${namespace.join('|')}` : 'main'
console.log(source, chunk)
}
你在前端里可以把这类事件渲染成“执行轨迹时间线”。
interruptOn 配了但恢复失败
原因:恢复时没用同一个 thread_id
审批后状态丢失
原因:没配置 checkpointer,或者 checkpointer 没持久化
上下文爆炸、费用升高
原因:子任务没下沉到 subagent,大量中间过程污染主上下文
技能没生效
原因:skills 路径/backend 映射错误,或技能描述太弱导致匹配不到
createDeepAgent + invokeinterruptOn + checkpointer + resumestream,把执行过程打印出来query_order / query_warranty / create_ticketrefund 加 interruptOn,打通审批恢复闭环policy-expert 子代理,让主代理只做协调