Harness Engineering的落地实践
摘要:Harness Engineering 最近很火,但我翻了数十篇文章大部分都在讲它的概念,极少人去讲解它的落地实践。今天这篇文章我将大致讲解什么是 Harness Engineering,并讲解一个采用 Harness Engineering 架构设计、基于 LangChain Deep Agents 框架实现的项目落地核心代码实现,以及我们日常如何将这个概念运用到日常开发中。
三个阶段的演进
Prompt Engineering(提示词工程)主要优化单次交互的质量,重点是"一句提示词该怎么写,模型才更容易给出想要的结果"。
Context Engineering(上下文工程)则动态构建知识、记忆、RAG,解决"模型看什么"的问题,减少幻觉、提高检索命中率。
Harness Engineering(驾驭工程)重点构建整个运行环境,解决"模型怎么把长链路任务稳定做完"的系统级问题。
核心定义
Harness 原意是马具、缰绳。放到 Agent 里,它指除模型本身之外的所有东西——工具、记忆、规划、安全护栏、执行循环、状态管理。LangChain 团队将其精炼为公式:
Agent = Model + Harness
模型提供"思考"能力,Harness 负责"让它真的能干活,而且别出大事"。
传统 Agent 在应对长周期、多步骤任务时,常面临上下文窗口爆炸、状态丢失、工具调用混乱、缺乏规划、无法从失败中恢复等工程难题。Harness Engineering 正是为了解决这些"工程上的’稳’的问题"而生的。模型决定能力的上限,Harness 决定它能不能把能力变成可交付的结果。
DeepAgents 中的七大能力模块
在 DeepAgents 框架中,Harness Engineering 被拆成一组可组合的能力模块:
| 模块 | 核心能力 | Harness 价值 |
|---|---|---|
| Planning | write_todos维护结构化任务清单 | 将非结构化思考转为可追踪、可恢复的确定性工作流 |
| Virtual Filesystem | 读、写、编辑、搜索、执行文件 | 对抗 Context Rot,扩展有效上下文窗口 |
| Subagents | 主 Agent 委派专项任务给子 Agent | 上下文隔离 + 算力分配,引入"多线程"和"微服务"架构 |
| Context Management | 内容卸载、摘要压缩、长期记忆 | 自动执行上下文工程,让模型注意力集中在核心决策 |
| Code Execution | 沙箱内执行 shell 命令 | "Trust the LLM"但隔离执行环境 |
| Human-in-the-Loop | interrupt_on在关键操作前暂停 | 在高风险操作前插入确定性的人工控制点 |
| Skills | 渐进式披露,按需加载领域知识 | 知识模块化,让 Agent 具备领域专长 |
五个核心原理
- 配置优于编码:所有复杂能力被封装为可配置的中间件栈,通过声明式方式组合,而非编写底层控制流。开箱即用,分钟级定制。(对应第 1~7 节的所有模块配置)
- 中间件架构:每个核心能力都是独立的
AgentMiddleware,在 Agent 生命周期的各阶段插入钩子,动态注入工具、修改提示、管理上下文。(对应第 1、3、5 节的 Planning、Subagents、Skills) - 后端协议抽象:统一的
BackendProtocol抽象了文件存储和执行环境。内存、本地磁盘、云存储还是沙箱,对 Agent 而言都是统一的ls、read、write接口。(对应第 2 节的 Sandbox) - 上下文工程自动化:Harness 自动执行摘要压缩、内容卸载、按需加载等策略,确保模型在任何时刻看到的都是最相关、最精炼的信息。(对应第 6 节的 Context Engineering)
- 从智能到系统:通过规划管理目标,通过文件系统管理状态,通过子 Agent 管理复杂度,通过安全沙箱管理风险,通过人在回路管理不确定性。最终,将一个"聪明的对话者"转变为一个"可靠的操作者"。
范式转变
这套思路意味着开发范式的根本转变:
- 从前:手动编写任务分解逻辑、管理上下文窗口、实现子 Agent 通信、构建安全机制。
- 现在:通过组合规划、文件系统、子 Agent、上下文管理和人工审批等能力,可以快速搭建具备长任务执行基础的 Agent Harness;真正进入生产前,仍需围绕权限、幂等、审计、失败恢复、评测与观测补齐业务级保障。
这不是另一套抽象名词,而是一条具体实现路径。下面从一个真实项目看它怎样落地。
1. Planning:先把复杂任务拆成可追踪的待办
简单任务不必每次都规划;但只要目标包含调研、查询、生成报告、调用多个系统这类步骤,就应该先把任务外置为结构化清单。这样做的重点不是给用户展示进度,而是让 Agent 自己始终知道:当前做到哪里、下一步是什么、哪些任务还没有完成。
我们这里通过write_todos做长任务分步规划:
它将任务 ID、内容、状态、依赖关系和合并策略都变成明确字段。代码中的装饰器和导入路径取决于你的具体封装与框架版本。
fromdeepagentsimporttool,ToolParameter@tool(name="write_todos",description=("创建并管理一个结构化的任务清单,用于规划复杂目标。""可以一次性创建完整列表,或者增量更新现有列表。""每一步执行完成后必须更新对应任务的状态。"),parameters={"todos":ToolParameter(type="array",description="要应用的任务列表。如果提供空数组则清空所有任务。",items={"type":"object","properties":{"id":{"type":"string","description":"唯一标识符"},"content":{"type":"string","description":"任务描述"},"status":{"type":"string","enum":["pending","in_progress","completed","cancelled"],},"depends_on":{"type":"array","items":{"type":"string"},"description":"前置依赖的任务ID列表",},},"required":["id","content","status"],},),"merge":ToolParameter(type="boolean",description="是否与现有列表合并(默认True),否则全量替换",default=True,),})defwrite_todos(todos:list[dict],merge:bool=True)->str:# 实际逻辑将由框架自动接入,这里只是占位函数体...这段代码里有三个很关键的点。
- 第一,
status被限制为固定枚举值,模型不能随手写一个"快完成了"之类的自然语言状态。 - 第二,
depends_on让任务顺序可以被显式表达,例如"生成图表"必须等待"数据调研"完成。 - 第三,
merge让 Agent 可以增量更新计划,而不是每做一步就丢掉已有任务。
Harness 在这里真正做的,是校验模型传来的结构是否合理,并把更新后的清单写回运行时状态。计划一旦外置,模型就不必把全部进度硬记在对话里;中断后也能从最近状态继续。
任务跑到最后一步时,Agent 看到的应该是这样的状态,而不是一长串失效的聊天记录:
Updated todo list to [ {'content': '扫描技能目录并加载分析操作手册', 'status': 'completed'}, {'content': '收集产品规格与技术参数(web_search + ERP查询)', 'status': 'completed'}, {'content': '市场价格调研(爬取竞品B2B页面)', 'status': 'completed'}, {'content': '供应商渠道对比(supplier_query + part_search)', 'status': 'completed'}, {'content': '执行综合分析并生成图表', 'status': 'completed'}, {'content': '输出最终报告到 /analysis/ 目录', 'status': 'in_progress'} ]这份清单不是"任务完成后的汇报",而是 Agent 执行过程中的工作内存。真正容易出问题的不是模型不会列计划,而是计划只写在提示词里,没有被工具、状态管理和验收流程约束住。
2. Sandbox:允许执行,但不要把宿主机直接交出去
Agent 要完成真实任务,往往需要读写文件、执行命令、安装依赖甚至访问外部服务。我们可以用到 OpenSandbox 或 Cube Sandbox,这一步不能省。
沙箱的意义不只是防止"删错文件"。更重要的是把代码执行、依赖安装、临时文件和高风险工具放进受控环境,让 Agent 有执行能力,但没有无限制的系统权限。读操作、写操作、网络访问、密钥使用和生产资源都应该按最小权限拆开配置。
对 Harness 来说,安全不是在系统提示词里写一句"请谨慎操作",而是让危险动作在架构上根本没有越界的机会。
下面是 OpenSandbox 的核心配置代码。OpensandboxBackend将其适配为 DeepAgents 的沙箱后端;文件操作走BackendProtocol,execute则是沙箱后端提供的扩展能力。该适配包独立于 DeepAgents 主包,生产使用时应锁定与 DeepAgents、OpenSandbox 兼容的版本。
importosfromopensandbox.sync.sandboximportSandboxSyncfromopensandbox.sync.connection_configimportConnectionConfigSyncfromdatetimeimporttimedeltafromdeepagents_opensandboximportOpensandboxBackend# ---------- 方式一:通过环境变量配置(推荐生产环境) ----------# os.environ["OPEN_SANDBOX_API_KEY"] = "your-secret-api-key"# os.environ["OPEN_SANDBOX_DOMAIN"] = "sandbox.example.com:8080"# ---------- 方式二:直接创建沙箱实例 ----------# use_server_proxy=True 适用于 Server 在 Docker、Client 在宿主机的场景config=ConnectionConfigSync(use_server_proxy=True)sandbox=SandboxSync.create("python:3.11",# 指定 Docker 镜像timeout=timedelta(seconds=600),# 沙箱最大存活时间ready_timeout=timedelta(seconds=120),# 等待沙箱就绪的超时connection_config=config,)# 将沙箱包装为 DeepAgents 后端,Agent 通过 BackendProtocol 访问backend=OpensandboxBackend(sandbox=sandbox)print(f"Sandbox ID:{backend.id}")# Agent 可以在沙箱内执行命令,宿主机不受影响result=backend.execute("pip install pandas && python -c 'import pandas; print(pandas.__version__)'")print(f"Exit code:{result.exit_code}")# 0print(f"Output:{result.output}")# pandas 版本号# 错误命令也能被捕获,不会影响宿主机result=backend.execute("exit 42")print(f"Exit code:{result.exit_code}")# 42# ---------- 清理 ----------sandbox.kill()sandbox.close()在实际项目中,backend会被传入create_deep_agent的backend=参数。对 Agent 来说,它通过统一的文件工具操作后端;当后端实现沙箱执行协议时,才可以调用execute。实际隔离边界取决于你部署的 OpenSandbox 配置。这就是"后端协议抽象"的价值——切换沙箱、本地磁盘或云存储时,业务 Agent 的调用方式可以保持一致。
3. Subagents:把专项任务隔离出去,主 Agent 只收结论
当一个任务涉及多个专业领域(比如订单创建流程里既有物料调研、又有价格比对、又有合规检查),如果全部塞给一个 Agent,上下文会迅速膨胀,工具列表也会越来越长,模型注意力被稀释。
Subagents 的思路类似微服务:主 Agent 是编排者,负责拆任务和收结果;每个子 Agent 在独立的上下文中完成专项工作,只返回压缩后的结论。这样主 Agent 的上下文窗口始终保持在可控范围。
内联定义子 Agent
最直接的方式是在create_deep_agent时通过subagents参数传入:
fromdeepagentsimportcreate_deep_agent# 定义一个物料调研子 Agentresearch_sub_agent={"name":"researcher","description":"负责产品规格、技术参数和市场价格的调研,返回结构化结论","model":"anthropic:claude-haiku-4-5-20251001",# 子 Agent 可用更轻量的模型"system_prompt":("你是一个专业的物料调研助手。""根据给定的物料名称,搜索产品规格、技术参数和市场价格。""返回 JSON 格式的调研结论,不要返回冗长的原始数据。"),"tools":[web_search,supplier_query,part_search],}# 定义一个合规检查子 Agentcompliance_sub_agent={"name":"compliance_checker","description":"检查采购订单是否符合合规要求(供应商资质、预算上限、审批层级)","model":"anthropic:claude-sonnet-4-20250514","system_prompt":("你是一个采购合规审核助手。""检查订单的供应商资质、预算上限和审批层级是否满足要求。""返回 pass/fail 及具体原因。"),"tools":[erp_query,budget_check],}# 将子 Agent 接入主 Agentagent=create_deep_agent(model="anthropic:claude-sonnet-4-20250514",tools=[order_create,order_update],system_prompt=SYSTEM_PROMPT,subagents=[research_sub_agent,compliance_sub_agent],backend=backend,# 接入第 2 节的 OpenSandbox 后端checkpointer=CHECKPOINTER,interrupt_on={"order_create":{"allowed_decisions":["approve","reject"]},"order_update":{"allowed_decisions":["approve","reject"]},},)YAML 配置子 Agent
如果子 Agent 较多,也可以用 YAML 文件管理;当前 DeepAgents 不提供load_subagents,需要由应用自己把 YAML 解析为SubAgent列表:
# subagents.yamlresearcher:description:负责产品规格、技术参数和市场价格的调研model:anthropic:claude-haiku-4-5-20251001system_prompt:|你是一个专业的物料调研助手。 根据给定的物料名称,搜索产品规格、技术参数和市场价格。 返回 JSON 格式的调研结论。tools:-web_search-supplier_query-part_searchcompliance_checker:description:检查采购订单是否符合合规要求model:anthropic:claude-sonnet-4-20250514system_prompt:|你是一个采购合规审核助手。 检查供应商资质、预算上限和审批层级。 返回 pass/fail 及具体原因。tools:-erp_query-budget_checkimportyamlfromdeepagentsimportcreate_deep_agent TOOL_REGISTRY={"web_search":web_search,"supplier_query":supplier_query,"part_search":part_search,"erp_query":erp_query,"budget_check":budget_check,}withopen("subagents.yaml",encoding="utf-8")asf:raw_subagents=yaml.safe_load(f)subagents=[{"name":name,**config,"tools":[TOOL_REGISTRY[tool_name]fortool_nameinconfig["tools"]],}forname,configinraw_subagents.items()]agent=create_deep_agent(model="anthropic:claude-sonnet-4-20250514",tools=[order_create,order_update],system_prompt=SYSTEM_PROMPT,subagents=subagents,backend=backend,checkpointer=CHECKPOINTER,)主 Agent 如何委派任务
配置好子 Agent 后,主 Agent 会自动获得一个task工具。当它判断某个子任务应该交给专家处理时,会调用task并指定subagent_type:
主 Agent 接收:"帮我创建一张采购订单,物料是 X" → write_todos 拆解任务 → 调用 task(description="调研物料X的规格和市场价格", subagent_type="researcher") └─ researcher 子 Agent 在独立上下文中执行调研 └─ 返回结构化结论给主 Agent(原始搜索结果不进入主上下文) → 调用 task(description="检查此订单的合规性", subagent_type="compliance_checker") └─ compliance_checker 子 Agent 执行审核 └─ 如果发现违规,触发 interrupt 等待人工确认 → 主 Agent 拿到两个结论,继续执行 order_create这里的关键是上下文隔离:researcher 搜索到的几十条原始网页数据、compliance_checker 查到的 ERP 记录,都不会进入主 Agent 的上下文。主 Agent 只收到一句"调研完成,物料X规格如下…“和"合规检查通过”。这就是 Subagents 对抗上下文膨胀的核心价值。
4. Human-in-the-Loop:信息不够时,暂停,不要瞎猜
订单创建、文件修改、付费调用、生产数据更新这类场景,最怕 Agent 缺字段还继续往下跑。正确做法是暂停,展示已收集的信息和缺失字段,等待人补充后从原状态恢复。
fromlanggraph.typesimportinterruptimportjsondefrequest_missing_info(missing_fields:list[str],collected_data:dict)->str:"""当工具调用时发现必要字段缺失,暂停执行并向用户展示 缺失字段,等待人类补充输入后继续执行。 Args: missing_fields: 缺失的字段列表,格式如 "partId (物料ID, 必填)" collected_data: 当前已收集到的数据 Returns: 用户补充的字段数据(JSON 字符串) """response=interrupt({"type":"order_info_request","missing_fields":missing_fields,"collected_data":collected_data,})returnjson.dumps(response,ensure_ascii=False)这里的interrupt不是普通报错。它把当前任务停在一个可恢复点,把缺失项和已收集的数据一起交给人。前提是 Agent 创建时传入了checkpointer;用户补完partId后,要用同一个thread_id和Command(resume=...)恢复,系统才会继续原任务,而不是让用户从头再说一遍需求:
fromlanggraph.typesimportCommand config={"configurable":{"thread_id":"order-20260723-001"}}# 首次调用在 request_missing_info() 处暂停agent.invoke({"messages":[{"role":"user","content":"创建采购订单"}]},config=config)# 人工补齐字段后,从同一个 checkpoint 恢复agent.invoke(Command(resume={"partId":"P-10086"}),config=config)下面的 YAML 则把人工确认放在订单创建和更新这两个关键节点上:
interrupt_on:order_create:allowed_decisions:["approve","reject"]order_update:allowed_decisions:["approve","reject"]人不必盯住每一步,但必须控制不可逆或高风险的那一步。
5. Skills:把能力拆成模块,按需加载
这里体现了两个 Harness 原则:
渐进式披露。Agent 启动时只读取SKILL.md的元数据部分,根据用户请求匹配到相关技能后,才加载完整内容。这大幅减少了初始上下文的 Token 消耗。已配置/skills/order/作为技能来源后,新增技能只需放进该目录,无需再改 Agent 代码——这就是"配置优于编码"。
角色边界。system_prompt不是写一篇百科全书,而是明确告诉 Agent:你是谁、在哪里运行、核心流程是什么。订单相关的详细规则不塞在全局 Prompt 里,而是拆进技能目录按需加载。
fromdeepagentsimportcreate_deep_agent agent=create_deep_agent(model="anthropic:claude-sonnet-4-20250514",backend=backend,# /skills/order/ 下的每个子目录均可作为一个技能被扫描skills=["/skills/order/"],system_prompt=("你是一个专业的 ERP 采购订单管理助手,运行在隔离的 OpenSandbox 沙箱环境中。""你的核心职责是:理解订单操作需求 → 调用 MCP 工具执行操作 → 验证结果 → 返回确认。"),)这几行配置把"技能发现"和"职责边界"写得很清楚:订单相关的详细规则不需要塞在全局 Prompt 里;Agent 匹配到订单任务后,再去读取/skills/order/下的资料。
这个项目的 skills 实现了自我进化:自动下载、自动创建、功能测试与自动分配。
6. Context Engineering:Token 爆了,别硬塞
一条复杂任务跑久了,上下文一定会越来越大。检索原文、工具返回、运行日志、代码片段都堆在对话里,模型真正需要记住的计划反而被淹没。
这四种处理方式,基本就是长任务的常用组合:
- 自动 Offloading:一次读取内容过多时,将大结果拆分或落到文件系统,需要时再读取;
- 自动 Summarization:上下文接近上限时,把历史压缩为结构化摘要;
- 手动
compact_conversation:在适当节点主动收缩历史,保留结论、约束、文件路径和未完成任务; - Isolation:让多个子 Agent 在独立上下文中完成专项工作,主 Agent 只接收压缩结果。
下面是一个手动压缩上下文的示例。当前 DeepAgents 通过create_summarization_tool_middleware注册compact_conversation;该工具不接收手写摘要,而是由中间件生成摘要、更新状态并将原始历史按 backend 配置落盘:
fromdeepagentsimportcreate_deep_agentfromdeepagents.middleware.summarizationimport(create_summarization_tool_middleware,)model="anthropic:claude-sonnet-4-20250514"agent=create_deep_agent(model=model,backend=backend,middleware=[create_summarization_tool_middleware(model,backend),],)Context Engineering 不是拼命扩大 Token,而是管理模型注意力。一个好的 Harness 会让模型每一轮只看到"此刻必须知道的内容",而不是把整段历史原封不动再发一遍。
7. Checkpoint:人工介入后,任务还能接着跑
当 Agent 接入 SSE 事件流、异步子 Agent、用户偏好和多轮审批后,内存里的状态远远不够。任务中断、服务重启、人工补字段后,都需要 checkpoint 把它带回原来的执行位置。
importosfromdeepagentsimportcreate_deep_agentfromlanggraph.store.memoryimportInMemoryStorefromlanggraph.checkpoint.mongodbimportMongoDBSaver# ---------- MongoDB 配置(用于 Agent 短期记忆 / checkpoint) ----------MONGODB_URI=os.environ["MONGODB_URI"]# ---------- 持久化存储 ----------STORE=InMemoryStore()# 仅开发环境使用# MongoDB 持久化:用于 Agent 对话状态 checkpointing。# checkpointer 的生命周期应覆盖 Agent 的调用和恢复过程。withMongoDBSaver.from_conn_string(MONGODB_URI)asCHECKPOINTER:agent=create_deep_agent(model="anthropic:claude-sonnet-4-20250514",tools=[order_create,order_update],backend=backend,checkpointer=CHECKPOINTER,store=STORE,)# 使用同一个 thread_id 调用 agent,并在 interrupt 后以 Command(resume=...) 恢复。这里要分清三类信息:当前任务状态放 checkpoint;会话中间结果放工作区或会话存储;长期偏好可以沉淀到preferences.md或受控数据库。不要把三类东西混成一个"记忆库",否则很难排查权限、更新来源和过期数据。
对应的项目目录可以保持简单:
/agent.md /prompts.py /persisted-skills /preferences.mdagent.md放总规则和索引,prompts.py放可测试的提示词构造,persisted-skills放经过审核的可复用技能,preferences.md只记录允许跨会话复用的偏好。不要把一切都塞进agent.md,控制在一两百行的规范通常更容易维护。
8. 完整链路:七层如何协同
把上面的代码连起来看,一次完整的订单创建流程是这样的:
用户:"帮我创建一张采购订单,供应商是华为,物料是..." ↓ Agent 启动 → 加载 system_prompt → 匹配 /skills/order/ 技能(渐进式披露) ↓ write_todos → 拆任务:收集字段 → 调研物料 → 合规检查 → 创建订单 → 验证结果 ↓ task(subagent_type="researcher") → 子 Agent 在独立上下文中调研物料规格和市场价格 ↓ task(subagent_type="compliance_checker") → 子 Agent 执行合规审核 ↓ 调用 order_create → 发现 partId 缺失 ↓ interrupt() 暂停 → CHECKPOINTER 把状态写入 MongoDB ↓ 人类补充 partId → 从 MongoDB checkpoint 恢复 ↓ Agent 拿到数据继续执行 → order_create 调用 MCP 工具 ↓ interrupt_on 触发 → 人类 approve ↓ 执行完成 → 验证结果 → 返回确认每一层各司其职:system_prompt定义角色,skills按需加载领域知识,write_todos管理规划,task委派子 Agent 隔离上下文,interrupt()实现暂停,MongoDBSaver保证状态可恢复,OpenSandbox隔离执行环境。这就是 Harness Engineering 的"配置优于编码"——不是手写控制流,而是组合模块。
三、日常开发中如何运用 Harness 思路
先从当前项目最容易失控的地方补起。
1. agent.md 不要写成百科全书
首页只放角色、边界、启动流程和目录索引,控制在两百行以内。详细规则拆进 skills、prompts、验收规范等子目录,按需加载。新增能力时改的是对应模块,不是把主提示词越堆越长。
2. 每接一个工具,都补齐契约
明确输入字段、权限范围、失败类型、幂等性和返回格式。特别是写操作,必须定义"执行成功后怎么验收"——不能只返回一段自然语言说"已完成"。
3. 把中间结果落盘
调研原文、代码修改记录、测试输出、待办状态都应能被重新读取。不要只存在模型的短期上下文里。大文件写入工作区,对话中只保留摘要和路径,需要时再读取。
4. 给 Agent 验收能力
浏览器、日志查询、单元测试、接口检查都可以成为最终确认的一部分。Agent 调完工具不能只看返回一句"success",而要检查文件是否真的生成、接口状态是否符合预期、测试是否通过。Harness 的交付标准不是模型说"我做完了",而是系统能验证"结果确实在"。
5. 高风险操作设人工闸门
涉及删除、提交、付费、外发、生产数据时,先展示影响范围,再由人批准。人不需要盯住每一步,但必须在风险真正发生前拥有控制权。
一句话总结
按这个顺序补:多步骤任务就接一个结构化待办;工具有写操作就加校验和审批;工具结果很长就落到文件系统;任务会跨会话或等待人工输入,就加 checkpoint。
结语
本文讲解了一个基于 Harness 架构实现的 Agent 项目,包含了 Planning、Sandbox、Subagents、Human-in-the-Loop、Skills、Context Engineering 和 Checkpoint 七个核心模块的代码实现。这种思维架构值得我们去学习、去运用到日常开发中。
Harness Engineering 不替模型思考,却把模型的思考接进一个可以规划、执行、校验和恢复的系统。它不替代 Prompt 或 Context,而是把它们放进一个可持续运行的闭环里。Prompt 决定模型如何理解任务,Context 决定模型看到什么,Harness 决定它如何规划、执行、校验、恢复,并最终完成交付。
当 Agent 开始真正操作文件、调用系统、完成多步骤工作时,工程重点就已经从"怎样让它回答得更漂亮",转向"怎样让它可靠地做完,而且出了问题能被看见、能被拦住、能继续恢复"。这才是 Harness 最有价值的地方。
项目参考
【Harness Engineering 企业级多 Agent 协同项目实战!Multi-Agent+SandBox+自我进化的 Skill+人工介入-码士集团 AI 大模型】https://www.bilibili.com/video/BV1Cs7h6MEsX?p=31&vd_source=0d5a4d32633eb45ba20dd7e06a8a4604