凡人AI修仙(3):Agent 的思考模式与 Harness

0 阅读26分钟

从大脑到手脚,再到一个能稳定干活的执行引擎。


课程视频: player.bilibili.com/player.html…

Agent 的思考模式

各位道友,欢迎来到《凡人AI修仙》第三课。开讲之前,先说一个前提,这个前提特别重要:今天讲的三个尴尬案例,说的都是只有大模型本身、还没有 Agent 的时候,也就是一个光秃秃的大模型,一个只会一问一答的聊天框。如果你已经用上了 Claude Code、Cursor 这类产品,可能根本没遇到过这些问题。咱们就从那个聊天框开始。

1. 今天这一课,讲五块

今天这一课,讲五块。

第一块,讲清楚大模型缺什么,Agent 又怎么把这个缺口补上。

第二块,拆开 Agent 的四件套:大脑、工具、记忆、规划,每件都给具体产品和方案。

第三块,也是今天最重的一块:四种经典思考模式,ReAct、先规划后执行、反思、多智能体,每种都配时序图和 Golang 代码。

第四块,讲几个新范式:工具调用、操作电脑、深度研究、总指挥加小兵。第五块,讲 Harness,它跟 Agent 什么关系,内部有哪些零件。

好,地图给完了,咱们开始。

2. 三个场景,全是「差一点」

第一个场景,报销单。你跟它说,帮我把这张报销单整理成一张电子表格。它特别热情,给你写了一大段建议:你应该先分类,再按时间排序,注意保留发票号。你往下翻,翻到底,表格呢?没有。它给了你一套方法论,就是没给你那张表。

第二个场景,订机票。你问它,明天北京飞上海,怎么订最便宜。它讲得头头是道:早班机便宜,周二周三便宜,提前二十一天买便宜。可你让它帮你订一张,它说,抱歉,我不能帮你下单。

第三个场景,改代码。你贴一段代码给它,说这里有个缺陷,帮我改改。它改得挺像那么回事,还给你解释了为什么这么改。可这段代码到底能不能跑通,它自己根本不知道,它也没法跑。三个场景,一个共同点:它什么都知道,就是什么都做不了。

3. 只会说,不会做

所以答案就四个字:只会说,不会做。

你可以把大模型想象成一个读遍天下书、考试门门满分的天才。

四书五经、二十四史、全世界的论文,他都读过。可这个天才,从来没下过山。他没进过菜市场,没跟人砍过价,没亲手做过一顿饭。你问他什么,他都答得上来;你让他真刀真枪去办一件事,他就傻眼了。

为什么?因为他没有实践,没有跟真实世界建立过连接,也没有一套遇到事情该怎么分析、怎么一步步推进的闭环。

他的工作方式,永远是一问一答,你问完,他答完,就结束了。

他不会主动去查、去做、去验证。所以道友们,知识再渊博,没有手脚,也只是个书呆子大脑。

4. 大模型是脑,Agent 是脑加手脚

那怎么办?这就轮到今天的主角登场了,Agent,智能体。咱们可以这么理解:大模型是大脑,知识量巨大,但它没有思想,没有做事的逻辑,没有经验。

而 Agent,就是在真实世界和大模型之间,架起一座桥梁。它去调用大模型,给这个大脑装上思想、装上经验、装上一套方法论。

Agent 越强大,就越能弥补大模型和真实世界之间那道鸿沟。

一句话,大模型是脑,Agent 是脑加手脚。

而且我要特别强调一点:Agent 真正值钱的,不是手脚,是它的思想。手脚谁都能装,接几个接口就叫有手脚了;但思考模式好不好,决定了它能把大模型的价值发挥出几成。

5. 感知 · 思考 · 行动 · 观察

那 Agent 到底怎么做事?它靠的是一个闭环,四步。

第一步,感知。先搞清楚真实世界现在是什么情况,用户要什么,环境里有什么。

第二步,思考。用大模型去分析、去决策,我接下来该干什么,先干哪一步。

第三步,行动。调用工具,真的去干,去查、去点、去写。

第四步,观察。看看干完之后结果怎么样,成功了还是失败了,拿到的是什么数据。然后,拿着这个结果,再回到第一步。你看,感知、思考、行动、观察,这四步转起来,就是一个飞轮。它不再是问一句答一句,而是一个能自己转起来、越转越接近目标的东西。这就是 Agent 的灵魂。

6. 一个 Agent 的四件套

把 Agent 拆开看,一般有四件套。

第一件,大脑,也就是大模型,负责思考和决策。

这个不是虚的,就是具体某个模型:比如 DeepSeek V4.1 Flash,便宜、快、量大管饱;比如腾讯的混元 Hy3,中文和工具调用很稳;比如 GPT 6、Claude Opus 5.5,难一点的推理更靠谱;再比如 Qwen3 系列,开源可私有化。你选哪个,直接决定了这个 Agent 的上限。

第二件,工具,这是它的手脚和感官。

工具也不是虚的,就是一个个函数:查数据库、调 HTTP 接口、读文件、跑命令、搜网页、发邮件。业界统一用 MCP 协议来描述工具,一个 MCP Server 就是一组工具。

第三件,记忆。

记忆分三层:最短的是上下文窗口,就是这一轮对话里它能看见的东西;中间的是外部存储,比如把历史对话存进数据库、把知识存进向量库做检索,也就是常说的 RAG;最长的是长期记忆,比如 Mem0 这类方案,会主动抽取事实、做成用户画像,下次直接调出来。

第四件,规划。

规划也有具体做法:最简单的是思维链,让它一步一步想;再进一步是待办清单,把任务拆成一条条 TODO,做完一条划一条;最完整的是先规划后执行,先出完整计划,再逐条落地。

这四件套里,工具代表它能接触和感知外界,而思想,其实就是它的运行模式。同样是四件套,运行模式不一样,干出来的活儿完全不一样。

7. Agent 是怎么帮你订机票的

咱们拿一个具体例子走一遍,你就彻底明白了。你说,帮我订一张明天北京飞上海的机票,下午到就行,预算一千以内。Agent 先感知:它得先确认,明天几点方便,预算到底多少,有没有行李。然后思考:调用大模型分析,先查航班,再比价格,再确认时间合不合适。接着行动:它调用订票接口,真的去查、真的去下单。最后观察:接口返回成功没有,有没有出票,订单号是多少。如果没成功,比如那个航班卖完了,它会回到思考,换个航班、换个时间,再试一次。你看,这一整套下来,是不是就像一个真正会办事的助理?而大模型自己,是做不到的,因为它没有这些手。

8. 市面上能打的 Agent

说了这么多,市面上到底有哪些能打的 Agent?我给你分四类。第一类,通用型。国外的代表是 OpenAI 的 Operator 和 ChatGPT Agent,综合能力最强,生态最完善;国内的代表是 Manus,它最大的贡献是把只给结果,变成了给过程加结果,你能看见它每一步在干什么。第二类,编程型,这也是竞争最激烈的一类。国际标杆是 Claude Code 和 Cursor,一个在终端里,一个在编辑器里;国内有腾讯的 CodeBuddy。注意,CodeBuddy 是腾讯的 AI 编程助手,装在编辑器里;腾讯还有一个 WorkBuddy,那是桌面端的 AI 办公智能体,两个不是一个东西,很多人会搞混。另外还有字节的 Trae、阿里的 Qoder。第三类,长文本和深度研究型,代表是 Kimi,几百页的文档丢进去,它能读完再回答。第四类,生态型。字节的豆包智能体,背靠抖音和飞书;腾讯的操作系统级助手,能直接接管你的桌面。我建议大家别光听我讲,自己上手玩一玩,你才会有那种,哦,原来 Agent 是这么回事的体感。

9. ReAct:边想边做

好,进入今天最重的一块:Agent 的思考模式。第一种,也是最经典的,叫 ReAct,推理加行动。它的节奏特别简单:先想一想,我该怎么办,这叫 Reason;然后动手做一步,这叫 Act;做完看看结果,这叫 Observe;然后基于结果,再想、再做、再看。咱们看一个真实案例:你让 Agent 查一下北京明天的天气。这张时序图,一共六步,我一步一步说。第一步,你说话,需求进来。第二步,Agent 把需求交给大模型,大模型想:我得调天气接口。第三步,Agent 去调 get_weather 这个工具,参数是北京、明天。第四步,工具返回:晴,二十六度。第五步,Agent 把结果再交给大模型,让它总结成人话。第六步,Agent 回你:明天北京晴,二十六度,适合出门。你看,四条线一来一回,这就是 ReAct 在跑。它特别适合那种一开始不知道怎么走、需要边做边调整的任务。

10. ReAct 的 Golang 实现

光看图不够,咱们上代码。这段是 Golang,三十行左右,就是最小的 ReAct。先看开头,导包,还有 Step 这个结构体,它记录一步:是调工具还是给最终答案,调哪个工具,参数是什么。下面进入主函数 RunReAct,注意这个 for 循环,它就是飞轮,我给它设了最多六圈。循环里第一步,把问题和已有的历史记录拼成提示词。第二步,调大模型,让它输出下一步。第三步,解析它的输出。如果解析失败,说明它没按格式来,把错误记进历史,转下一圈。第四步,判断,如果它说这是最终答案,直接 return,循环结束。第五步,如果是要调工具,就执行工具,拿到观察结果。第六步,把这次调用和结果追加进历史,然后 continue,转下一圈。最后,如果转了六圈还没答案,就返回超时提示。你注意,这个循环没有写死的退出条件,实际工程里一定要加轮数上限,不然它可能转死。这就是 ReAct 的全部秘密:想一步、做一步、看一眼,再想下一步。

package main

import (
    "context"
    "encoding/json"
    "fmt"
)

type Step struct {
    Kind   string `json:"kind"`
    Tool   string `json:"tool"`
    Args   string `json:"args"`
    Answer string `json:"answer"`
}

func RunReAct(ctx context.Context, q string) string {
    history := ""
    for round := 0; round < 6; round++ {
        prompt := q + "\n已有记录:\n" + history
        raw := CallLLM(ctx, prompt)
        var st Step
        if err := json.Unmarshal([]byte(raw), &st); err != nil {
            history += "格式错误,请只输出 JSON"
            continue
        }
        if st.Kind == "final" {
            return st.Answer
        }
        obs := RunTool(ctx, st.Tool, st.Args)
        history += fmt.Sprintf("调用 %s → %s", st.Tool, obs)
    }
    return "超过最大轮数"
}

11. Plan-and-Execute:先画地图再出发

第二种,叫 Plan-and-Execute,先规划,再执行。它跟 ReAct 正好相反。ReAct 是走一步看一步,摸着石头过河;它是先站在高处,把整件事拆成一张完整的作战地图,第一步干什么,第二步干什么,第三步干什么,全列清楚,再一步一步执行。比如你让 Agent 把一份报告做成幻灯片。它先规划:第一步读报告,第二步提炼大纲,第三步生成幻灯片,三步。然后照着地图,一步一步干。这张时序图,一共八步。第一步,用户把需求交给 Agent。第二步,Agent 让大模型做规划。第三步,大模型一次性把三步计划返回。第四步,Agent 执行第一步。第五步,工具返回完成。第六步,Agent 执行第二、第三步。第七步,工具再返回完成。第八步,Agent 把成品交付给用户。好处是全局观强,不会走偏,而且计划本身可以给人看、给人改;缺点是中途出意外,它不太会变通,往往得推倒重来。所以工程上常见的做法是:先规划,执行的时候允许局部重规划。

12. Plan-and-Execute 的 Golang 实现

上代码。这段还是 Golang。先看 Plan 和 PlanStep 这两个结构,一个计划就是一串步骤,每个步骤有编号、有描述、有状态。然后看第一步,MakePlan,它把目标丢给大模型,要求输出 JSON 数组,再解析成计划。注意这里,我让它输出 JSON,是为了后面能程序化地一步步执行,不是让它自由发挥。第二步,for 循环遍历计划,一步一步执行,每执行完一步,把结果记到这个步骤的状态上。第三步,如果某一步失败了,这里有个 replan,把失败原因和已完成的部分丢回去,让它重新规划剩下的步骤。最后一步,Summarize,把整个计划的结果汇总成一段话交付。你看,这就是先规划后执行的骨架:先出地图,再按图走,走不通就重画地图。它比 ReAct 更适合那种步骤明确、可以提前拆解的任务,比如报表生成、批量迁移、文档转换。

type PlanStep struct {
    ID     int
    Desc   string
    Status string
}

type Plan struct {
    Goal  string
    Steps []PlanStep
}

func MakePlan(ctx context.Context, goal string) Plan {
    raw := CallLLM(ctx, "输出 JSON 步骤数组:"+goal)
    var p Plan
    json.Unmarshal([]byte(raw), &p)
    return p
}

func RunPlan(ctx context.Context, goal string) string {
    plan := MakePlan(ctx, goal)
    for i := range plan.Steps {
        out, err := ExecStep(ctx, plan.Steps[i].Desc)
        if err != nil {
            plan = Replan(ctx, plan, i, err)
            continue
        }
        plan.Steps[i].Status = "done:" + out
    }
    return Summarize(ctx, plan)
}

13. Reflection:自己检查自己

第三种,叫 Reflection,反思。它会让 Agent 自己检查自己。干完一步之后,它不急着往下走,而是回过头问自己:我刚才做得对吗?有没有漏洞?能不能更好?发现问题,就自己改,改完再检查一遍。比如你让 Agent 写一段代码。它先写一版,然后自己复查,发现有个边界没处理,就改,改完再跑一遍测试。这张时序图,一共八步。第一步,Agent 让大模型生成代码。第二步,大模型返回草稿第一版。第三步,Agent 让大模型检查。第四步,大模型指出:边界没处理。第五步,Agent 让它修正。第六步,大模型返回终稿第二版。第七步,Agent 调工具跑测试。第八步,工具返回:通过。这就像咱们自己写代码,写完要自己复查、跑测试、发现缺陷再修。Reflection 让 Agent 有了自我纠错的能力,输出质量会明显更稳。但要注意,它是有代价的:每一轮反思都要多调一次模型,时间和成本都会涨,所以一般只在关键步骤上用。

14. Reflection 的 Golang 实现

上代码。这段 Golang 实现的是最朴素的 Reflection:生成、评审、修正,最多三轮。先看主函数 RunReflect。第一步,Generate,让模型根据任务先生成一版。然后进 for 循环。第二步,Critique,让模型扮演评审,专门挑毛病,要求它输出问题清单。第三步,判断,如果问题清单是空的,说明通过了,直接返回。第四步,否则进入 Revise,把原稿和问题清单一起来,让它改。改完回到循环,再评审一次。你注意这里的关键:评审和生成,必须是两次独立的模型调用,而且提示词要明确分开,一个只负责挑刺,一个只负责改。如果混在一次调用里,它就会自己夸自己,反思就失效了。这也是很多人做 Reflection 没效果的根本原因。

func Generate(ctx context.Context, task string) string {
    return CallLLM(ctx, "完成任务:"+task)
}

func Critique(ctx context.Context, task, draft string) []string {
    raw := CallLLM(ctx, "你是评审,只挑问题,一行一条:\n"+draft)
    return SplitLines(raw)
}

func Revise(ctx context.Context, task, draft string, issues []string) string {
    return CallLLM(ctx, "按问题修改:\n"+strings.Join(issues, "\n")+"\n原稿:\n"+draft)
}

func RunReflect(ctx context.Context, task string) string {
    draft := Generate(ctx, task)
    for i := 0; i < 3; i++ {
        issues := Critique(ctx, task, draft)
        if len(issues) == 0 {
            return draft
        }
        draft = Revise(ctx, task, draft, issues)
    }
    return draft
}

15. Multi-Agent:组个团队干活

第四种,叫 Multi-Agent,多智能体协作。一个人干不完的活,那就组个团队。比如你让它们做一个完整的项目:一个项目经理负责规划和拆任务,一个工程师负责写代码,一个测试员负责审查。它们之间互相沟通、互相配合,甚至互相辩论。这张时序图,一共八步。第一步,用户把项目交给项目经理。第二步,项目经理把任务拆开,分给工程师。第三步,工程师写完,回报完成。第四步,项目经理转给测试员测试。第五步,测试员发现缺陷,打回给工程师。第六步,工程师修复。第七步,测试员复测通过。第八步,项目经理交付给用户。这一来一回,就是多智能体在跑。好处是能扛特别复杂的大工程,每个角色只专注自己那一块;坏处是沟通成本高,容易开会开半天,而且 token 消耗是成倍涨的。所以用不用多智能体,得看任务复杂度,简单的活别硬上。

16. Multi-Agent 的 Golang 实现

上代码。这段 Golang 用最朴素的方式实现多智能体:不引入任何框架,就是几个角色,各自有各自的提示词。先看 Role 这个结构,有名字、有系统提示词。然后是三个角色:项目经理、工程师、测试员,它们的区别,只在系统提示词不一样。接着看 run 函数,它接收一个角色和一个输入,把这个角色的系统提示词拼在前面,调模型,返回输出。然后看主流程 RunTeam。第一步,项目经理先拆任务。第二步,把拆好的计划交给工程师实现。第三步,进入一个最多两轮的循环:测试员审查代码,如果返回 PASS,就跳出;否则把缺陷清单交回工程师修复。最后,项目经理汇总交付。你看,多智能体的本质,其实就是同一个模型,换不同的系统提示词,扮演不同的角色,然后把它们的输出串起来。框架只是帮你把这个串接做得更优雅,原理就这么简单。

type Role struct {
    Name   string
    System string
}

var PM  = Role{"项目经理", "你负责拆任务、定计划、验收"}
var Dev = Role{"工程师", "你负责按计划写代码"}
var QA  = Role{"测试员", "你负责挑毛病,没问题回 PASS"}

func Run(ctx context.Context, r Role, input string) string {
    return CallLLM(ctx, r.System+"\n\n"+input)
}

func RunTeam(ctx context.Context, task string) string {
    plan := Run(ctx, PM, "拆解任务:"+task)
    code := Run(ctx, Dev, "按计划实现:"+plan)
    for i := 0; i < 2; i++ {
        bugs := Run(ctx, QA, "审查代码:"+code)
        if bugs == "PASS" {
            break
        }
        code = Run(ctx, Dev, "修复:\n"+bugs+"\n"+code)
    }
    return Run(ctx, PM, "汇总交付:"+code)
}

17. 这几年冒出来的四种新玩法

除了这四种经典模式,这几年还冒出来不少新玩法,我给大家补四个,顺便把它们的来龙去脉讲清楚。第一个,Tool Use,工具调用。这个其实不新,2023 年 6 月 OpenAI 发布 Function Calling,模型就第一次能规范地调函数了,现在几乎是标配。第二个,Computer Use,直接操作电脑,看屏幕、点鼠标、敲键盘。这是 2024 年底 Anthropic 先做出来的,思路很野:不给它接口,直接给它一个虚拟桌面,让它像人一样操作。第三个,Deep Research,深度研究。2025 年开始火起来,你给它一个题目,它能自己上网查几十上百个网页,最后写一份带引用的报告。第四个,Orchestrator-Worker,一个总指挥带一群小兵。总指挥负责拆任务、派活、验收,小兵负责干活。这四种,本质上都还是感知、思考、行动、观察这个闭环,只是把某一步做得更深、更专。

18. 工具调用:所有 Agent 的地基

先说工具调用,这个必须上代码,因为它是所有 Agent 的地基。这段 Golang 分三块。第一块,定义工具。一个 Tool 结构,有名字、有描述、有参数 schema、有真正的执行函数。注意,描述和 schema 不是给人看的,是给模型看的,模型靠它决定调不调、怎么调。第二块,注册工具。把工具放进一个 map,按名字能查到。第三块,也是最关键的,循环。第一步,把工具清单转成 JSON schema,随请求一起发给模型。第二步,模型返回说,我要调 get_weather,参数是北京。第三步,我们按名字找到工具,执行,拿到结果。第四步,把结果作为一条工具消息追加回去。第五步,再请求一次,模型这次就能给出最终答案了。你看,所谓工具调用,就是模型输出一段结构化的 JSON,你的程序负责执行,再把结果喂回去。就这么朴素。

type Tool struct {
    Name   string
    Desc   string
    Schema map[string]any
    Fn     func(args map[string]any) (string, error)
}

var registry = map[string]Tool{}

func Register(t Tool) { registry[t.Name] = t }

func Call(ctx context.Context, q string) string {
    msgs := []Msg{{Role: "user", Content: q}}
    for {
        resp := CallLLM(ctx, msgs, Schemas())
        if resp.ToolCall == nil {
            return resp.Content
        }
        t := registry[resp.ToolCall.Name]
        out, err := t.Fn(resp.ToolCall.Args)
        msgs = append(msgs, resp.AsMsg(), ToolMsg(out, err))
        // 下一圈带着工具结果再请求
    }
}

19. Computer Use:像人一样操作电脑

Computer Use 这块,用代码讲不直观,我给你讲一个真实场景。假设你要它帮你在一家老旧的内部系统里,把一百条订单的状态导出来。这个系统没有接口,只有网页,还得登录。Computer Use 的做法是这样的。第一步,先截一张屏幕图,发给模型。第二步,模型看着这张图,说,我看到了用户名输入框,坐标大概是这里。第三步,它输出一个动作:点击,坐标 x、y。程序执行点击。第四步,再截一张图。模型说,现在看到密码框了,输入。程序输入。第五步,再截图,看到登录按钮,点击。第六步,再截图,看到订单列表了。第七步,模型说,点导出按钮。程序点。第八步,文件下载下来,任务完成。整个过程,就是截图、看图、出动作、执行、再截图,一直循环。你看,它把操作电脑这件事,也变成了感知、思考、行动、观察。难点在哪?一是坐标要准,二是页面加载要等,三是出错要能看出来。所以真正商用的 Computer Use,都会加视觉定位、加等待策略、加失败重试。

20. Deep Research:搜、记、判断、再搜

再说 Deep Research,这个是最好用代码讲清楚的。核心就是一个循环,加一个判断。你看这段 Golang。先看 Note 这个结构,一条笔记,存一次查询和一次结果。然后看主函数 DeepResearch。第一步,声明一个 notes 切片,存已经查到的资料。然后进循环,最多五轮。第二步,规划,把原始问题和已有资料一起给模型,问它:下一步该搜什么?第三步,判断,如果模型说 DONE,说明它觉得够了,直接跳出。第四步,搜索,拿它给的查询词去搜,拿到结果。第五步,把这一轮的查询和结果,追加进 notes。循环结束,最后让模型基于 notes 写一份带引用的报告。你看,Deep Research 的骨架就这么简单:搜、记、判断、再搜。它之所以厉害,不是因为算法复杂,而是因为它能转几十圈,把几十个网页的内容都读进来。

type Note struct {
    Query  string
    Result string
}

func DeepResearch(ctx context.Context, q string) string {
    var notes []Note
    for r := 0; r < 5; r++ {
        query := Plan(ctx, q, notes)
        if query == "DONE" {
            break
        }
        res := WebSearch(ctx, query)
        notes = append(notes, Note{query, res})
    }
    return WriteReport(ctx, q, notes)
}

21. Orchestrator-Worker:总指挥加小兵

最后说 Orchestrator-Worker,总指挥加小兵。这个用一张架构图讲最清楚。最上面是总指挥,它只干三件事:拆任务、派活、验收。中间是任务队列,总指挥拆出来的子任务,一条条排在这里。下面是一群小兵,可以是同一个模型的不同实例,也可以是不同模型,甚至可以是人。流程是这样的:总指挥拿到大目标,先拆成子任务,丢进队列;小兵从队列里领任务,干完把结果写回去;总指挥检查结果,合格就收,不合格就打回去重做,或者拆得更细再派。它跟多智能体的区别在哪?多智能体是平级的、互相沟通的;Orchestrator-Worker 是层级化的,所有沟通都经过总指挥。好处是可控、可观测、能并行;坏处是总指挥容易成为瓶颈。这也是很多企业级 Agent 平台的标准架构。

22. 模式会变,底层逻辑不变

讲到这儿,我想跟你聊点更深的。无论什么 Agent 模式,都是暂时的。你想想人类自己,我们的大脑,到今天还有很多地方没开发出来。但是随着人类文明的进步,我们改变现实世界的行为流程、模式、思想,一直在不断更迭,改变世界的速度也越来越快。Agent 其实在帮大模型做同一件事:一步一步地发展、构建、壮大人工智能这个智慧维度的文明。所以学这一课,你重点不是背下来有几种模式,而是理解它背后那个感知、思考、行动、观察的底层逻辑。模式会变,但这个逻辑不会变。抓住这个,你就不怕它怎么变。

23. Agent 和 Harness,到底啥区别

好,Agent 讲完了,咱们聊一个大家特别容易混淆的东西:Harness。很多人以为 Harness 就是 Agent,其实不是。咱们用一句话区分:Agent 是那个能干活的东西,Harness 是驱动它跑起来的那套执行引擎。更准确地说,Agent 等于模型,加脚手架,加 Harness。模型是大脑;脚手架是模型能感知到的东西,比如提示词、工具定义、输出格式;而 Harness,是模型感知不到、但在背后驱动它跑的那一层,负责调用循环、工具执行、什么时候停、出错怎么办。打个比方,脚手架是剧本和道具,Harness 是导演加舞台监督,把一切串起来执行。

24. 一个 Harness,内部有七个零件

光说概念还是虚,咱们把 Harness 拆开,看看它内部到底有哪些零件。一共七块。第一块,主循环。就是那个 while:调模型、看它要不要用工具、用就执行、不用就结束。这是心脏。第二块,工具调度。负责把工具清单给模型、解析模型要调哪个、执行、把结果格式化回去。第三块,上下文管理。上下文窗口是有限的,聊久了就爆,所以它要负责裁剪、摘要、压缩,还要决定哪些东西留在窗口里、哪些丢到外部存储。第四块,状态与记忆。整个任务进行到哪一步了,哪些文件改过了,这些要持久化,不然一重启就全忘了。第五块,权限与安全。哪些工具能调、哪些目录能写、要不要人工确认,这一层是防止它闯祸的。第六块,错误处理。工具报错了怎么重试,模型输出格式不对怎么纠正,循环卡住了怎么跳出。第七块,可观测性。每一步的输入输出都要记日志,出了问题能复盘,成本也要能统计。你看,这七块加起来,才是一个能干活的 Harness。模型只是其中最贵的那一块,但不是最复杂的那一块。

25. 为什么光有 Agent 还不够

那为什么光有 Agent 还不够,非要一个 Harness?因为 Agent 要真正可靠地干活,光有大脑和工具是不够的。你得有人管:这一轮该不该停?工具报错了怎么重试?上下文太长了怎么裁?权限怎么控?出了事怎么复盘?这些脏活累活,就是 Harness 在干。没有 Harness,Agent 就是个能跑但不可控的演示;有了 Harness,它才能变成可靠、可控、可用的产品。你看这个对比:左边是裸的 Agent,跑两步就乱;右边是加了 Harness 的 Agent,有循环控制、有错误处理、有可观测性,才能稳定交付。

26. 市面上有哪些主流的 Harness

那市面上有哪些主流的 Harness 呢?写代码这块,Claude Code 是终端里的标杆,Cursor 是编辑器里的标杆,Cline、Aider、OpenHands 是开源的三个代表,它们把大模型包装成一个能读项目、改文件、跑测试的编程 Agent。还有我们第一课用过的 DeepSeek Harness,也是这一类。再比如 Codex CLI、Gemini CLI,这些命令行工具,本质上都是 Harness。你记住一个判断标准:凡是帮你把大模型变成能稳定干活的产品的那个壳,就是 Harness。下一节课,咱们就专门拆开一个 Harness,看看它内部到底是怎么设计的。

27. 五句话记住这一课

好,咱们总结一下今天这五句话。第一,大模型是大脑,只会说不会做。第二,Agent 是给大脑装上手脚,补上感知、思考、行动、观察的闭环。第三,Agent 四大件:大脑、工具、记忆、规划,每一件都有具体的产品和方案。第四,运行模式有 ReAct、先规划后执行、反思、多智能体,但底层逻辑不变。第五,Agent 不等于 Harness,Harness 是驱动 Agent 可靠跑起来的执行引擎。记住这五句,你就把 Agent 这层搞清楚了。

28. 下节课:拆开一个 Harness

下一节课,咱们就专门聊 Harness。我会带你拆开一个真实的 Harness,看看它的循环控制、工具调度、上下文管理、错误处理到底是怎么设计的,然后咱们亲手写一个最小的 Harness。我是刘丹冰 Aceld,我们下节课,不见不散。