首页/Agent 核心/循环、图与骨架工程
Agent 核心 · 第 14 章

循环、图与骨架工程

第 13 章经营的是模型"看到什么"——窗口里装什么、裁掉什么、留下什么。这一章换个视角:模型之外的所有工程结构。同一个模型,装进不同的骨架,表现可以天差地别;循环怎么跑怎么停、复杂流程怎么编排、整套骨架怎么分层搭起来—…

约 32 分钟12,863 字20 个代码示例

第 13 章经营的是模型"看到什么"——窗口里装什么、裁掉什么、留下什么。这一章换个视角:模型之外的所有工程结构。同一个模型,装进不同的骨架,表现可以天差地别;循环怎么跑怎么停、复杂流程怎么编排、整套骨架怎么分层搭起来——这些模型"看不见"的工程决策,才是可靠性的真正来源。本章位于"第五章 怎么做得可靠"的核心位置,分三部分展开:先讲最具体的循环工程(让循环该停时停、偏航时正、失控时刹),再讲图工程(复杂流程的显式编排),最后用骨架工程(Harness)收官——把前两部分所做的一切升华成体系化的总纲。

1. 循环工程:让循环安全地跑

Agent 的本质是循环(第 8 章),而循环的本质是风险——没有循环,错误止于一次调用;有了循环,一个错误会被放大成整个任务的失败。第 8 章给了四道闸门做应急处理,这一部分把它扩展成系统的循环工程学:怎么让循环该停时停、偏航时正、失控时刹。

1.1 循环的三种死法

先病理分析。Agent 循环的失败模式归为三类(第 8 章见过前两类):

死法一:打转(oscillation)
  search[天气] → 结果不满意 → search[天气] → ……   ← 第 8 章的重复检测

死法二:发散(drift)
  任务:写周报 → 中途开始"优化模板" → 又开始"调研工具" → 忘了初衷
  每步都"合理",整体离题万里——目标漂移

死法三:滚雪球(cascade)
  轮次↑ → 上下文↑ → 注意力稀释 → 判断质量↓ → 更多无效调用 → 轮次↑
  正反馈循环,越跑越糟

死法一有现成解药(重复检测)。死法二和三更隐蔽:每一步单看都没毛病,是宏观行为坏了——这就是循环工程要处理的核心难题:微观合理性与宏观失控的矛盾。

1.2 终止工程:什么时候该停

终止不止"达到上限就砍"(第 8 章的粗暴版本)。完整的终止设计分三层:

成功终止

模型不再调用工具、给出最终答案——这是自然出口。但自然出口 ≠ 正确出口:模型可能在证据不足时提前"自信作答"(第 9 章见过:搜一次就作答)。对策是在系统提示词里定义完成标准("必须交叉验证两个来源才能回答"),而不是任由模型自己感觉"差不多了"。

资源终止(硬止损)

第 8 章的四道闸门完整版。这里补一个关键的工程细节——各级闸门的关系应该是嵌套的软硬结合:

# 软闸门:先警告,给模型自纠的机会
if self.tokens_used > self.budget * 0.7:
    if not self._warned:
        self.messages.append({"role": "user",
            "content": "提示:token 预算已使用 70%。请尽快总结当前成果并收尾。"})
        self._warned = True

# 硬闸门:无情切断
if self.tokens_used > self.budget:
    return self._partial_result()   # 带着部分成果退出,而不是空手

_partial_result 值得展开:硬闸门触发时,让模型基于已有信息输出一个"目前最佳答案",比直接抛"任务失败"有价值得多——已消耗的成本换点残值回来:

def _partial_result(self) -> str:
    resp = client.chat.completions.create(
        model=self.model,
        messages=self.messages + [{
            "role": "user",
            "content": "预算已用尽。请基于已收集到的信息,"
                       "给出当前最佳的不完整答案,并注明局限。",
        }],
    )
    return resp.choices[0].message.content

语义终止(质量止损)

资源闸门防的是"跑太久",语义闸门防的是"跑着跑着没意义":

def _goal_check(self, original_task: str) -> bool:
    """每 N 轮做一次目标对齐检查"""
    resp = client.chat.completions.create(
        model=self.model, temperature=0,
        messages=[
            {"role": "system",
             "content": "判断当前进度是否仍在服务原始任务。"
                        "只输出 ALIGNED 或 DRIFTED。"},
            {"role": "user",
             "content": f"原始任务:{original_task}\n\n"
                        f"最近的行动:{self.recent_actions_summary()}"},
        ],
    )
    return resp.choices[0].message.content.strip() == "ALIGNED"

对准的是死法二(目标漂移):每 5 轮花一次廉价调用检查"还在正道上吗"。发现 DRIFTED 时的处置不是杀掉重来,而是注入纠偏消息("你正在偏离任务,请回到:{original_task}")——下一节的纠偏机制。

1.3 纠偏工程:偏航时怎么正

终止是最后手段,纠偏是日常操作。核心思想:循环里要有"负反馈"——不是让模型一直往前跑,而是持续校准它。

三类纠偏信号(按介入强度):

# ① 结果型纠偏:工具返回了错误信息(第 7 章的既有模式)
#    模型看到 "参数校验失败:..." 通常下一轮自己修正

# ② 提示型纠偏:框架检测到模式问题,注入 user 消息
def _inject_correction(self, issue: str, guidance: str):
    self.messages.append({
        "role": "user",
        "content": f"[系统提示] 检测到问题:{issue}。{guidance}",
    })
# 用例:重复调用后 → "你已连续3次做相同调用,请更换策略"
#      目标漂移后 → "当前行动偏离了原始任务,请回到:{task}"

# ③ 结构型纠偏:重置部分状态(最重)
def _structural_reset(self):
    """保留任务和关键结论,丢弃失败过程"""
    self.messages = [
        self.messages[0],                      # system
        {"role": "user", "content": self.original_task},
        {"role": "assistant",
         "content": f"已完成部分:{self.achieved_summary}。"
                    f"失败尝试:{self.failed_summary}(避免重复)。"},
    ]

③ 是第 12 章"干净上下文"思想在单 Agent 内的应用:与其在污染的上下文里挣扎,不如带着摘要重开。"重启"不是失败,是循环工程的正常工具。

1.4 循环形状的设计:不是所有循环都该一样

第 8 章的循环是"自由循环"(模型全权决定下一步)。实际上不同任务适合不同形状:

形状 结构 适合 风险
自由循环(ReAct 式) 模型每轮自选动作 探索型任务(调研) 死法一二三
阶段循环 固定阶段(分析→执行→验证),阶段内自由 流程明确的复杂任务 阶段间信息损耗
双层循环 外层规划、内层执行(Plan-Execute) 长任务 计划赶不上变化

阶段循环的实现骨架(第二部分图工程的雏形):

PHASES = ["analyze", "execute", "verify"]

def run_phased(self, task: str):
    context = {"task": task, "findings": []}
    for phase in PHASES:
        phase_prompt = self.phase_prompts[phase].format(**context)
        self.messages.append({"role": "user", "content": phase_prompt})
        # 阶段内跑第 8 章的标准循环(限更小轮次)
        result = self._bounded_loop(max_rounds=3)
        context["findings"].append(result)
        # 阶段间质量控制:verify 不过可以折返
        if phase == "verify" and self._failed(result):
            return self.run_phased(task)   # 或定向折返 execute
    return context["findings"][-1]

自由度是资源,不是越多越好:确定性强的部分用结构锁定,探索性的部分留给模型(第三部分原则四的又一次应用)。verify 阶段的存在本身是重要的循环设计——Agent 的循环里要有"自我验证"的环节,让"完成"是验证过的判断而非模型的自我感觉。

1.5 失控保险丝:最后的防线

汇总成一张保险丝配置表(生产前自查):

保险丝 阈值 动作
轮次上限 任务复杂度 + 2(如 8~10) 软警告 → 硬止损+部分结果
token 预算 70% 警告 / 100% 止损 同上
重复检测 连续 3 次相同调用 注入纠偏 → 重置状态
目标漂移 每 5 轮检查 注入纠偏 → 终止
副作用频率 单轮写操作 > N 次 熔断(第 15 章 fail-closed)
壁钟时间 任务级超时(如 10 分钟) checkpoint + 终止

最后一条"壁钟时间"单独强调:它是唯一不属于模型维度的保险丝。LLM 推理的延迟波动大(第 4 章:prefill 随输入长度变化),没有任务级超时的 Agent,一次 API 卡顿就能挂住你的整条流水线。框架层的 timeout 必须存在,哪怕设得很宽松。

第一部分小结

  • 三种死法:打转(有解药)、发散(目标漂移)、滚雪球(质量正反馈恶化)——后两个是微观合理宏观失控
  • 终止三层:成功终止(要定义完成标准)、资源终止(软硬闸门+部分结果)、语义终止(目标对齐检查)
  • 纠偏三层:结果型(工具错误自纠)→ 提示型(注入系统消息)→ 结构型(带摘要重启)
  • 循环形状按任务选:自由/阶段/双层——自由度是资源,确定性部分用结构锁定
  • 保险丝六条:轮次/预算/重复/漂移/副作用/壁钟时间——最后一条与模型无关但必须有

循环解决了"步骤间的动力",但当整个任务有复杂的阶段依赖和分支走向时,需要把循环进一步结构化——状态图。

2. 图工程:把流程变成代码里的一等公民

自由循环(第 8 章)像即兴爵士,模型随手发挥;阶段循环(第一部分)像固定曲目单;而当任务有复杂的状态依赖、条件分支、并行汇合——你需要的是一张显式的图。这一部分讲图工程(Graph Engineering):把工作流从"模型的即兴发挥"变成"代码里的一等公民",以及什么时候该做(和不该做)这个转变。

2.1 从代码顺序到图

先看熟悉的代码形态(第一部分的阶段循环):

result = analyze(task)
result = execute(result)
if not verified(result):
    result = execute(result)      # 折返重试
return report(result)

它隐含了一张图,但图埋在控制流里——想改流程(比如 verify 失败要回到 analyze 而不是 execute),得改代码结构。图工程的主张:把流程本身升为显式数据结构:

        ┌──────────┐
        │ analyze  │
        └────┬─────┘
             ▼
        ┌──────────┐
   ┌───▶│ execute  │
   │    └────┬─────┘
   │         ▼
   │  ┌──────────┐   fail
   └──│ verify   │────────┐
      └────┬─────┘        ▼
           │ pass    ┌────────┐
           ▼         │ retry  │──┐
      ┌────────┐    └────────┘  │(计数)
      │ report │       ……
      └────────┘

显式化的收益:

维度 代码控制流 显式图
看懂流程 读代码+脑内模拟 看图
改流程 改代码结构 改边/节点配置
并行分支 手写线程/异步 声明式
状态追溯 散落各处 图执行引擎统一记录
人机协作 难 图可以直接给产品/客户看

LangGraph、Dify、n8n 这些"工作流/编排"产品,本质都是在做同一件事:图结构的 Agent 编排。

2.2 图的三个基本要素

节点(Node):做一件事的单位

节点是最小的执行单元,内容可以是任何东西:

from dataclasses import dataclass, field

@dataclass
class Node:
    name: str
    execute: callable                    # 执行函数:state → state
    kind: str = "agent"                  # agent / tool / human / logic

关键认知:节点不等于 Agent。一个节点可以是一次 LLM 调用(轻)、一个完整的第 8 章 Agent(重)、一段纯代码(判定逻辑)、甚至一次人工介入(第 15 章的确认门)。图是编排层,节点内容自选粒度——这正是第三部分"复杂度搬家"的应用:把流程逻辑从模型搬到图结构,把每个节点内的自由留给模型。

状态(State):贯穿全局的记事本

图执行时,所有节点共享一份状态:

from typing import TypedDict

class WorkflowState(TypedDict):
    task: str                    # 原始任务
    findings: list[str]          # 各节点产出的累积
    attempt_count: int           # 重试计数
    verified: bool               # 验证结论
    current_node: str            # 执行位置

状态的收敛性设计很重要:图里流动的是"结论"而非"过程"。节点内部(比如一个子 Agent)可以跑得轰轰烈烈,但对外只写关键结论进 state——第 13 章上下文管理的图级版本:每个节点只消费和产出必要信息。

边(Edge):转移规则

@dataclass
class Edge:
    source: str
    target: str
    condition: callable = None    # 条件边:state → bool

边的两种形态:直边(无条件转移)和条件边(路由函数决定去向)。条件边是图的智慧所在——verify 之后去 report 还是回 execute,由 condition(state) 的代码逻辑决定,确定性路由留在代码,不确定性留给节点内的模型。

2.3 实现一个最小的图引擎

一个能跑的迷你引擎(麻雀虽小,五脏俱全——节点/边/状态/条件路由/循环):

from typing import Callable

class Graph:
    def __init__(self):
        self.nodes: dict[str, Callable] = {}
        self.edges: list[Edge] = []

    def add_node(self, name: str, fn: Callable):
        self.nodes[name] = fn

    def add_edge(self, source: str, target: str,
                 condition: Callable | None = None):
        self.edges.append(Edge(source, target, condition))

    def run(self, initial_state: dict, start: str,
            max_steps: int = 20) -> dict:
        state = initial_state
        current = start
        for step in range(max_steps):              # 第一部分的保险丝
            state["current_node"] = current
            state = self.nodes[current](state)     # 执行节点

            # 找下一个节点:优先匹配条件边
            next_node = None
            for e in self.edges:
                if e.source != current:
                    continue
                if e.condition is None or e.condition(state):
                    next_node = e.target
                    break
            if next_node is None:                  # 没有出边 = 自然终点
                return state
            current = next_node
        raise RuntimeError("图执行超过步数上限(疑似环死循环)")

用它搭第一部分那个"分析→执行→验证"流程的完整版:

g = Graph()

def analyze(state):
    state["findings"].append(f"分析结果: {state['task'][:20]}...")
    return state

def execute(state):
    state["findings"].append("执行结果: ...")
    return state

def verify(state):
    state["verified"] = len(state["findings"]) >= 2    # 演示用判断
    return state

def report(state):
    state["final"] = "\n".join(state["findings"])
    return state

g.add_node("analyze", analyze)
g.add_node("execute", execute)
g.add_node("verify", verify)
g.add_node("report", report)

g.add_edge("analyze", "execute")
g.add_edge("execute", "verify")
g.add_edge("verify", "report", condition=lambda s: s["verified"])
g.add_edge("verify", "execute",
           condition=lambda s: not s["verified"] and s["attempt_count"] < 3)

result = g.run({"task": "写周报", "findings": [],
                "attempt_count": 0}, start="analyze")
print(result["final"])

对照第一部分的阶段循环代码:流程逻辑从 if/for 里浮到了边的声明里。verify→execute 的折返重试从"递归调用"变成了"一条带条件的边"。改流程 = 改图,不碰节点实现。

2.4 图上的高级模式

引擎之上,三个常用的图模式:

并行扇出/扇入(fan-out / fan-in)

        ┌→ research_A ─┐
analyze ┤              ├→ synthesize
        └→ research_B ─┘

research_A 和 B 无依赖可并行跑,synthesize 等齐了再动(第 12 章子代理的图化表达)。实现上扇出节点返回多个后继、扇入节点做 barrier 计数——生产引擎(LangGraph 的 Send API 等)都内置了这个模式。

人工门(human gate)

draft → [human_review] → publish
              │ reject
              ▼
          revise → draft

把第 15 章的 human-in-the-loop 做成一个节点:执行时暂停图、通知人、等人回复、带着决定继续。图的持久化状态让"暂停等几天"成为可能(第三部分 checkpoint 的图级版)——审批流这种天然跨天的工作流,只有图结构能优雅承接。

动态图(边由模型决定)

固定图之外,还可以让模型在运行时选择下一条边(路由节点:模型看 state 决定去向)——这其实就是把第 8 章的"模型自选下一步"压缩成单个节点的内部逻辑。固定图和自由循环不是对立的,是同一光谱的两端:

纯代码流程 ── 固定图 ── 混合图(部分边动态)── 路由循环 ── 纯自由循环
(n8n 工作流)  (审批流)      (客服分流+处理)      (第8章ReAct)

2.5 什么时候不该上图

图工程最大的陷阱是过度工程。不该上图的信号:

  • 流程只有三步且不会变:if-else 写完五分钟的事,上图是自找复杂度
  • 探索性主导的任务:调研类任务下一步做什么取决于上一步发现什么,预定义的图反而限制模型发挥——该用自由循环(第 8 章)
  • 流程还在剧烈变化:图结构适合"已知的确定性",摸索期用自由循环收集行为模式,稳定后再固化成图(和第 12 章"Skill 是 MCP 的孵化器"同一思想:自由循环是图的孵化器)
  • 团队没有图运维能力:图引擎是个新依赖,调试、监控、版本管理都要学——工具链的账要算

一个可用的决策标准:当你在自由循环里反复写"如果又发生 X 就……"的补丁时,就到了该上图的时候——那说明流程的结构已经从实践中浮现出来了,值得显式固化。

第二部分小结

  • 显式图的收益:流程可视、改流程不改代码、声明式并行、状态统一追溯
  • 三要素:节点(任意粒度:LLM 调用/完整 Agent/纯代码/人工门)、状态(流动结论不流过程)、边(条件路由,确定性归代码)
  • 迷你引擎 60 行:节点执行 + 条件边路由 + 步数保险丝
  • 高级模式:扇出扇入(并行)、人工门(跨天暂停)、动态边(模型路由)——固定与自由是光谱不是对立
  • 不该上图的四个信号;自由循环是图的孵化器

循环让系统动起来,图让复杂流程有了形状——但它们都只是骨架的一部分。第三部分收官:把模型之外的一切工程结构收进一个体系,看骨架如何决定同一个模型的表现上限。

3. 骨架工程:模型之外的体系(收官)

同一个模型,放进不同的工程骨架,表现天差地别——这层骨架就叫 Harness(脚手架/马具)。第 8 章的 Agent 循环就是一个最小 Harness,本章前两部分做的循环控制与图编排,都是骨架的组成部分。这一部分收官升维:把模型之外的一切工程要素系统化——为什么骨架比模型更能决定成败,好的 Harness 长什么样。它是本章前两部分所做之事的理论升华与体系化总纲。

3.1 模型 × 骨架 = 表现

先看一个思想实验(综合前面各章的知识就能推出来):

同一个 qwen3:4b,装进不同的骨架:

骨架 表现
裸调用(一次问答) 能聊天,复杂任务必挂
+ 工具 + 循环(第 8 章) 能查证、能计算、能多步执行
+ 工具 + 循环 + 重试 + 校验(第 6/7 章防御) 可靠度大幅上升
+ 记忆 + 权限 + 预算(第 13、15 章) 可以托付真实工作

模型没变,表现天差地别。这个加法链条就是骨架工程(Harness Engineering)的内容——它不是新概念,是第 7 章到第 13 章所有工程决策的统称,也是本章前两部分(循环工程、图工程)的理论升华。

一个流传很广的判断(源自 Claude Code 等产品的实践观察):模型能力的下限由模型决定,上限由 Harness 决定。前沿团队花在骨架上的工程量,远超 prompt 本身。

3.2 Harness 的解剖图

把第 8 章的 Agent 类按职责重新分层:

┌─────────────────────────────────────────┐
│              Agent Harness                │
│                                           │
│  ┌─────────┐  模型接口层                  │
│  │ 模型调用 │  超时、重试、降级、备用模型    │
│  └─────────┘                              │
│  ┌─────────┐  工具执行层                   │
│  │ 工具系统 │  权限、沙箱、超时、结果截断    │  ← 第 7/11/15 章
│  └─────────┘                              │
│  ┌─────────┐  循环控制层                   │
│  │ 主循环   │  轮次、预算、卡死检测         │  ← 第 8 章
│  └─────────┘                              │
│  ┌─────────┐  上下文层                     │
│  │ 上下文   │  组装、裁剪、预算分配           │  ← 第 13 章
│  └─────────┘                              │
│  ┌─────────┐  反馈层                       │
│  │ 校验重试 │  输出校验、失败重试、自纠错     │  ← 第 6 章
│  └─────────┘                              │
│  ┌─────────┐  观测层                       │
│  │ 事件审计 │  轨迹、日志、熔断              │  ← 第 8/15 章
│  └─────────┘                              │
└─────────────────────────────────────────┘

六层每层都独立可测、可换。分层的价值在此刻兑现:换模型只动接口层(第 5 章的"模型当配置")、加安全只动执行层、调上下文策略不碰循环。

3.3 三层最容易被低估的骨架能力

有些骨架组件的重要性常被低估,单独展开。

错误恢复:失败是常态

第 6 章的校验-重试是单次调用的恢复。任务级的恢复更粗粒度:

def run_with_recovery(self, task: str, max_retries: int = 2) -> str:
    for attempt in range(max_retries + 1):
        try:
            result = self.run(task)
            if not self._looks_failed(result):        # 启发式检查结果质量
                return result
            failure_reason = "结果质量可疑"
        except Exception as e:
            failure_reason = str(e)

        if attempt < max_retries:
            # 带着教训重试:失败原因进入下一轮的系统提示词
            self.messages.append({
                "role": "user",
                "content": f"上次尝试失败({failure_reason})。"
                           f"请换一种策略重新完成任务。",
            })
            self._cleanup_partial_work()              # 回滚半成品副作用
    return self._fallback_answer(task)                 # 优雅降级

两个关键设计:失败原因要进入重试的上下文(不带教训的重试是重复撞墙);有副作用要回滚(写了半个文件的任务重试,先清掉残留——否则下次运行环境已脏)。

中断与恢复:长任务的存档点

Agent 跑 20 分钟的任务,中途崩了怎么办?——checkpoint 机制:

def checkpoint(self, task_id: str):
    """把当前状态序列化——messages + 关键中间产物"""
    state = {"messages": self.messages,
             "round": self.current_round}
    Path(f".checkpoints/{task_id}.json").write_text(
        json.dumps(state, ensure_ascii=False), encoding="utf-8")

def resume(self, task_id: str) -> bool:
    """从最近的存档点恢复"""
    p = Path(f".checkpoints/{task_id}.json")
    if not p.exists():
        return False
    state = json.loads(p.read_text(encoding="utf-8"))
    self.messages = state["messages"]
    self.current_round = state["round"]
    return True

每轮循环末尾存一次档。这是长任务生产化的分水岭——不能断点续跑的 Agent 只能处理玩具任务。

流式反馈:可感知的进展

第 5 章说过流式不省时间只省焦虑。对 Agent 加倍成立:多轮任务动辄几分钟,黑盒等待会杀死用户的信任。第 8 章的事件系统在这里再兑一次现——把 TOOL_CALL 事件实时推给用户("正在查询天气…""正在读取文件…")。工程含义:Harness 的观测层同时是 UX 层,一份数据两个消费者。

3.4 Harness 的设计原则

收拢成四条(全部来自前文的实践):

原则一:模型不可靠,骨架要可靠。所有"模型应该会做对"的地方都要问:它做错了,谁来兜底?——校验(第 6 章)、闸门(第 8 章)、确认(第 15 章)。骨架的存在意义就是把概率行为约束在安全轨道上。

原则二:每层可独立替换。模型会升级(接口层)、工具会增删(执行层)、策略会调整(上下文层)——耦合了任何两层的代码都会在未来某天让你重写整个系统。

原则三:可观测优先于聪明。一个平庸但全轨迹可见的 Agent,好过一个聪明但黑盒的 Agent——前者可调试可改进,后者出问题时你只能盯着结果发呆(第 15 章的根基)。

原则四:复杂度守恒,只是搬家。把决策从模型搬到代码(确定性增强),或从代码搬到模型(灵活性增强),复杂度没有消失只是换了地方。Harness 设计的艺术在于把确定性要求高的复杂度搬进代码,把探索性的复杂度留给模型。

3.5 实例:从第 8 章的 Agent 到完整 Harness 的差距

盘点第 8 章的 Agent 类距离生产 Harness 还缺什么(也是自查清单):

缺口 解法 状态
模型调用无重试/超时 接口层加 retry + timeout + 备用模型 本章 3.3
无 checkpoint 每轮存档 本章 3.3
无流式反馈 事件转发到用户界面 本章 3.3
无成本核算 第 8 章有预算闸门,缺分项记账(模型/工具/记忆各花多少) 第 15 章
无评测基线 改动无从验证好坏 第 15 章
并行能力 子代理(第 12 章)已在架构上就绪 ✓

这个表也解释了骨架工程为什么能担纲本章收官:它是本章前两部分所做之事的理论升华与体系化总纲,也是通往第 15 章的地基——度量的对象不是模型,是整个 Harness。

3.6 收官:五个工程层次的全景

至此五个 Engineering 讲完,用一张全景图收束(也是第 13 章与本章的复习):

┌────────────────────────────────────────────────┐
│                  Agent 系统                      │
│                                                  │
│   Prompt Eng.    怎么把一件事说清楚(13 章)     │
│        ↓ 每条指令进入                             │
│   Context Eng.   窗口里装什么(13 章)           │
│        ↓ 每轮组装成                               │
│   Harness Eng.   系统骨架怎么搭(本章)           │
│        ↓ 骨架的运行时是                           │
│   Loop Eng.      循环怎么跑怎么停(本章)          │
│        ↓ 复杂流程结构化为                         │
│   Graph Eng.     流程怎么编排(本章)              │
└────────────────────────────────────────────────┘

五个层次从微观(一句话)到宏观(整个系统),每一层解决不同粒度的问题——它们不是竞争关系,是同一个人在不同抽象高度看同一个系统。

第三部分小结

  • 模型能力下限由模型决定,上限由 Harness 决定——骨架工程量远超 prompt 本身
  • 六层解剖:模型接口 / 工具执行 / 循环控制 / 上下文 / 校验重试 / 观测审计——每层独立可换
  • 三个易低估的骨架能力:任务级恢复(带教训重试+副作用回滚)、checkpoint 续跑、流式反馈(观测层即 UX 层)
  • 四原则:模型不可靠骨架可靠、每层可换、可观测优先、复杂度搬家艺术
  • 第 8 章的 Agent + 本部分缺口清单 = 一个真实可用的 Harness 全貌
  • 五个 Engineering 全景:说清楚 → 装对东西 → 搭好骨架 → 控制循环 → 编排流程

至此,三大工程的全貌齐了:循环负责"怎么跑、怎么停",图负责"复杂流程怎么编排",Harness 把它们连同上下文、工具、校验一起收进可替换、可观测、可托付的体系。只剩最后一件事:把它送上生产,并用数据证明它做得好。

下一篇:15 · 记忆、权限与评测