想象一家经营得井井有条的餐厅。经理站在前厅,观察着客流、物资和人员状况,决定菜单如何设计、服务员如何调配、打烊时间如何确定。后厨的流水线则完全不同——厨师们按照标准作业流程,一个接一个地处理订单:读单、配菜、烹饪、摆盘、出餐。经理不会经常跑进后厨颠勺,厨师也不会擅自更改菜单。正是这样的分工,让餐厅既能灵活应对突发状况,又能稳定高效地批量出餐。 AI Agent架构中的Harness层与Loop层,恰好对应这对角色。Harness是“经理”,负责整体任务编排、做出流程决策、管理全局状态;Loop是“后厨流水线”,负责重复运行“大模型推理→调用工具→观察结果”的执行循环。本节将深入拆解两者的职责边界,帮你掌握分层原则、接口契约与协作机制,在真实系统中避免职责重叠造成的维护灾难。

岗位关联

学会划分Harness与Loop的边界,你就能设计出结构清晰、易于测试和维护的多Agent系统,这是AI应用架构师的核心能力。

目录
  1. 可视化演示
  2. 层级定位
  3. 控制流编排
  4. 状态管理
  5. 错误处理
  6. 接口契约
  7. 可测试性
  8. 性能维护
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示AI Agent架构中Harness工程脚手架层与Loop推理循环层的职责边界划分、控制流归属、以及多Agent共享Harness独立Loop的分层实践,通过交互切换理解架构分层原则。

本节配有交互动效(进入视口后自动加载,约 3KB)。

Harness层与Loop层:工程脚手架与推理循环分离 Harness层:输入清洗/安全过滤/输出格式化,不参与业务推理 Loop层:编排控制流/状态管理/工具调用,掌控推理决策 边界划分:数据经Harness清洗后进入Loop,推理结果经Harness格式化输出 Input → Harness(clean) → Loop(reason) → Harness(format) → Output 分层隔离工程职责与推理逻辑,降低耦合提升可维护性

层级定位

经理站在餐厅门口,目光扫过整个大厅——今天客流如何、库存还够不够、服务员排班是否合理。他思考的是“整体”:这家餐厅要往哪个方向走。而走进后厨,厨师们正沿着流水线作业,每个订单来了就按固定流程处理:读订单、配菜、下锅、摆盘、喊服务员上菜。他们在意的是“当前这一步”:这道菜做好了没?

在AI Agent架构中,这种分工被清晰地划分为两个层次。Harness层就像那位经理,它是整个任务执行的编排者——定义任务目标、选择执行策略、管理生命周期、协调多组件协作。Loop层则像后厨流水线,它以循环方式驱动Agent执行:让大模型生成下一步决策,调用工具获取结果,观察环境反馈,然后再次进入推理。这个循环会一直持续,直到任务完成或Harness下令停止。

划分两者的边界,核心在“职责”而不在“代码量”。我们可以用系统总复杂度的分配来理解:

经理管方向、后厨管执行,这句话翻译成架构语言就是:Harness定义“做什么”,Loop负责“怎么做”。当你在代码评审中看到Harness里出现了“这一轮调用哪个工具”的硬编码,或者Loop里出现了“任务是否应该继续”的判断,就该意识到——越界了。

Ctotal=Charness+CloopC_{total} = C_{harness} + C_{loop}
系统总复杂度由Harness复杂度与Loop复杂度相加构成,关键约束是“不重叠”——Harness不做Loop的执行细节,Loop不做Harness的流程决策。
  1. 总复杂度$C_{total}$ 表示整个Agent系统的总体设计复杂度,包括逻辑分支、状态流转和异常处理。
    Ctotal=Charness+CloopC_{total} = C_{harness} + C_{loop}
  2. Harness复杂度$C_{harness}$ 是编排层所承载的复杂度——流程决策、全局调度、生命周期管理。
    Charness=流程决策+全局调度+生命周期C_{harness} = \text{流程决策} + \text{全局调度} + \text{生命周期}
  3. Loop复杂度$C_{loop}$ 是执行层所承载的复杂度——单次迭代的推理、工具调用、结果观察。
    Cloop=推理+工具调用+观察C_{loop} = \text{推理} + \text{工具调用} + \text{观察}
  4. 零重叠约束若Harness掺入Loop细节,公式会多出一个交叉项 $C_{overlap}$,意味着系统开始腐化。

控制流编排

餐厅经理每天要做很多决策:今天是否开启午市套餐?客流量大时是让顾客排队还是开放预订?后厨的出菜顺序先后如何?这些决策有一个共同特征——它们发生在“动作之前”,属于流程级别的控制。而后厨并不会思考“今天该推什么套餐”,它只关心手上这道菜怎么做。

控制流的归属,是Harness与Loop分工的第一条分界线。Harness负责所有流程级决策:任务启动与终止条件、分支路由(走工具调用还是走人工确认)、并发策略(多个Loop并行还是串行)、重试与退出逻辑。Loop负责迭代级决策:当前这一步调用哪个工具、大模型生成的参数是什么、观察到的结果如何暂存。

为了看清这种分工的数学本质,我们可以把一次任务执行建模为状态转移与动作选择的分离:

$f$ 写在Loop里,$g$ 写在Harness里,这就是控制流的归属原则。一个良好的系统,其流程决策应该是可预测、可审计的——就像一家有标准作业手册的餐厅,任何一位厨师长上任都能保持出品稳定,因为“什么菜先上、什么情况插单”由经理的制度决定,而不是由某个厨师的临场发挥决定。

st+1=f(st,at),at=g(st,H)s_{t+1} = f(s_t, a_t), \quad a_t = g(s_t, \mathcal{H})
第一个式子说状态如何推进,第二个式子说动作由谁决定——循环体归Loop,方向盘归Harness。
  1. 状态变量$s_t$ 表示第 $t$ 次迭代时系统的运行状态,例如当前答案草稿、已调用过的工具列表。
    st=⟨答案草稿,已用工具,步骤计数⟩s_t = \langle \text{答案草稿}, \text{已用工具}, \text{步骤计数} \rangle
  2. 动作变量$a_t$ 表示Harness在第 $t$ 次迭代时做出的流程决策,例如“调用搜索工具”或“结束循环”。
    at=HarnessDecision(st)a_t = \text{HarnessDecision}(s_t)
  3. 状态转移函数$f$ 是Loop内部的执行逻辑——根据当前状态和动作,执行一步并产生新状态。
    st+1=f(st,at)s_{t+1} = f(s_t, a_t)
  4. 决策函数$g$ 是Harness的决策逻辑,输入当前状态与全局历史 $\mathcal{H}$,输出动作。
    at=g(st,H)a_t = g(s_t, \mathcal{H})

状态管理

经理的办公桌上有一本全局账本,上面记录着餐厅的库存、销售额、人员考勤;而每位厨师面前只有一张小小的订单小票,上面写着这道菜的要求。经理和后厨都在“记录”,但记录的范围和生命周期截然不同。账本要保存三个月以便复盘,小票在出餐后就被扔掉。

Harness持有的状态包括:用户会话、多轮对话历史、任务级配置、可用工具列表、用户偏好。这些状态的共同点是——跨越多次Loop迭代而存在,需要全局可见。Loop持有的状态包括:当前迭代的大模型输出、工具调用参数、上一步的观察结果、本轮的错误信息。这些状态在迭代结束时就完成了使命,不需要全局保留。

状态管理分工有一条黄金法则:只有需要跨迭代共享的数据才上提给Harness,其余一律留在Loop内部。用集合的视角来看:

这和餐厅的账本逻辑完全一致:经理不需要知道某一盘菜里葱花是怎么切的,但必须知道整个厨房的库存水平。当你在代码里看到Loop把某一轮的模型输出写进了全局状态,或者在Harness里查不到任何关于任务进度的记录,那一定是状态管理出了偏差。

Sharness=Sglobal∖⋃i=1nSloopiS_{harness} = S_{global} \setminus \bigcup_{i=1}^{n} S_{loop_i}
从全局状态里刨掉各Loop手里的局部状态,剩下的才是Harness应当保管的状态;这个差集运算保证了“状态不越级、数据不重叠”。
  1. 全局状态集合$S_{global}$ 表示任务运行期间系统涉及的全部状态总和,既包括跨迭代的,也包括迭代内的。
    Sglobal={会话历史,任务进度,当前输出,⋯ }S_{global} = \{\text{会话历史}, \text{任务进度}, \text{当前输出}, \cdots\}
  2. 局部状态并集$\bigcup_{i=1}^{n} S_{loop_i}$ 表示所有Loop实例(编号 $i$ 从1到 $n$)各自持有的局部状态的并集。
    ⋃i=1nSloopi=Sloop1∪Sloop2∪⋯∪Sloopn\bigcup_{i=1}^{n} S_{loop_i} = S_{loop_1} \cup S_{loop_2} \cup \cdots \cup S_{loop_n}
  3. 差集运算$S_{harness}$ 是两者的差集——从全局状态中剔除所有局部状态后,余下的跨迭代数据才属于Harness。
    Sharness=Sglobal∖⋃i=1nSloopiS_{harness} = S_{global} \setminus \bigcup_{i=1}^{n} S_{loop_i}

错误处理

某天,后厨火候没掌握好,把一份招牌菜做糊了。厨师不会沉默地自己重新做——万一食材不够呢?更不会直接给顾客换菜。他会立刻报告经理,由经理根据情况决策:食材充足就重做;食材不够就换一道同等价位的菜;如果顾客已经在投诉了,可能直接免单并送一份甜点。错误处理从来不是执行者一个人的独角戏。

AI Agent场景中,错误处理是Harness与Loop协作最密集的环节。Loop负责“检测与上报”:发现工具调用失败、模型输出格式异常、超时等情况,收集剩余上下文并向上抛出。Harness负责“决策与恢复”:评估错误的严重程度,选择重试、换工具、降级方案或终止任务。

重试策略是错误处理的核心。假设单次执行成功的概率为 $p$,系统最多重试 $k$ 次,那么最终成功的概率为:

Harness需要决定 $k$ 的取值:$k$ 太小,错误恢复的概率不够;$k$ 太大,可能浪费算力甚至放大损害(比如重复扣款)。关键原则是:Loop把错误原样上报,重试和降级的决策留在Harness。那些“在Loop里悄悄重试三次”的做法,就像厨师自己把做糊的菜重新炒一遍——经理根本不知道发生了什么。

Psuccess(k)=1−(1−p)kP_{success}(k) = 1 - (1-p)^k
单次成功率越低,越需要重试来兜底;但重试多少次、每次间隔多久,是Harness的策略问题,Loop无权自行决定。
  1. 单次成功率$p$ 表示单次执行成功的概率,例如调用某个外部API的成功率是95%。
    p=P(单次工具调用成功)p = P(\text{单次工具调用成功})
  2. 连续失败率$(1-p)^k$ 表示连续 $k$ 次都失败的概率,这是“重试了也没用”的坏情况。
    (1−p)k=(1−p)×(1−p)×⋯⏟k 次(1-p)^k = \underbrace{(1-p) \times (1-p) \times \cdots}_{k\text{ 次}}
  3. 至少一次成功$1 - (1-p)^k$ 是重试 $k$ 次后至少成功一次的概率,也是Harness评估策略收益的依据。
    Psuccess(k)=1−(1−p)kP_{success}(k) = 1 - (1-p)^k

接口契约

菜单是餐厅里最神圣的文件。后厨按菜单做菜,服务员按菜单下单,顾客按菜单点餐。菜单上写着“宫保鸡丁”,后厨不会做成“番茄炒蛋”,服务员也不会拿它去哄客人。菜单就是一份契约,它让各方不需要了解彼此的内部细节就能顺畅协作。

Harness与Loop之间同样需要一份“菜单”——接口契约。契约定义了三个核心维度。第一是协议定义:Loop向Harness注册自己的输入输出Schema,Harness通过Schema向Loop下发任务。第二是数据边界:哪些数据由Harness传入Loop,哪些由Loop返回Harness,哪些数据Loop严禁修改(如只读配置)。第三是事件通知:Loop执行中需要向Harness发送事件,如“步骤完成”“遇到错误”“需要人工确认”,这些事件的类型、载荷和时序要提前约定。

契约的稳定程度直接决定系统的可维护性,可以用兼容率来衡量:

维护好接口契约后,Harness更换大模型供应商、Loop增加新工具,双方都能像餐厅换食材供应商一样无感。一个反例是:Harness直接读取Loop内部的数据结构字段,或者Loop在没通知Harness的情况下改动了返回格式——这就像服务员绕过菜单直接向后厨喊“今天做点你拿手的吧”,短期方便,长期灾难。

Cratio=NcompatibleNtotalC_{ratio} = \frac{N_{compatible}}{N_{total}}
兼容率越接近1,说明Harness与Loop之间的契约越稳定,双方各自演进就越轻松——菜单不变,换供应商也无人察觉。
  1. 兼容变更数$N_{compatible}$ 表示在接口演进过程中不破坏现有调用方的变更数量,例如新增一个可选字段。
    Ncompatible=兼容变更次数N_{compatible} = \text{兼容变更次数}
  2. 总变更数$N_{total}$ 表示一段时间内接口发生的全部变更数量,包括破坏性变更和非破坏性变更。
    Ntotal=Ncompatible+NbreakingN_{total} = N_{compatible} + N_{breaking}
  3. 兼容率$C_{ratio}$ 越接近1,说明契约越稳定;越接近0,说明每次迭代都在“拆桥”。
    Cratio=NcompatibleNtotal⟶1C_{ratio} = \frac{N_{compatible}}{N_{total}} \longrightarrow 1

可测试性

餐厅出新品时,后厨会在操作台上单独试做几份,让内部试吃专员评价——这叫单元测试。在正式上线新菜单前,餐厅会组织一次全员模拟演练:服务员、厨师、经理甚至收银员全部到场,按真实营业流程走一遍——这叫集成测试。这样就不用等到真实营业时才发现“这道菜要15分钟,可菜单承诺10分钟上菜”。

Harness与Loop的测试策略同样可以分离。测试Harness时,将Loop替换为Mock对象——就像试菜时让一位经验固定的替班厨师上场,保证后厨行为可控。测试Loop时,不依赖Harness的具体实现,只给它标准的测试输入,就像给厨师一份拿手的菜单让他发挥。除了这两类测试,可观测性(日志、追踪、指标)贯穿始终,相当于给餐厅装监控摄像头,出了问题能回放到底哪一步出了岔子。

用成本来评估测试策略是否健康:

一个架构是否健康,可以看 $T_{mock}$ 的占比:如果Mock成本高得离谱,往往说明契约耦合太深,测试时不得不伪造大量状态。反之,当你能轻松地用Mock替换掉Loop来测试Harness的决策逻辑,就像用替班厨师试菜一样,说明两者的边界非常干净。

Ttotal=Tunit+Tintegration+TmockT_{total} = T_{unit} + T_{integration} + T_{mock}
测试总成本由单元测试、集成测试和Mock成本三块构成;其中Mock成本高不高,直接揭示契约设计得好不好。
  1. 单元测试成本$T_{unit}$ 是分别测试Loop和Harness的成本,通常最低,因为依赖都被隔离了。
    Tunit=TunitHarness+TunitLoopT_{unit} = T_{unit}^{Harness} + T_{unit}^{Loop}
  2. 集成测试成本$T_{integration}$ 是两者联测的成本,需要准备环境、依赖和真实工具。
    Tintegration=T联调准备+T场景执行T_{integration} = T_{联调准备} + T_{场景执行}
  3. Mock成本$T_{mock}$ 是编写和维护模拟对象的成本。契约越清晰,Mock越简单,成本越低。
    Tmock=f(契约清晰度)T_{mock} = f(\text{契约清晰度})

性能维护

最糟糕的餐厅是什么样?经理心血来潮冲进后厨亲自颠勺,指令和下厨指令混杂在一起;厨师看见前厅排队太长,擅自改了菜单、换了烹饪流程。结果就是菜做乱了、账记混了、顾客投诉了。职责重叠是复杂系统腐化的第一步。

当Harness开始直接操作Loop的迭代细节(比如硬编码某一次工具调用的参数),或者Loop开始自己决定要不要重试、要不要退出循环,架构的边界就开始模糊。这种职责重叠会带来三类问题:性能瓶颈——全局状态被高频读写,每次迭代都做无谓的序列化和同步;调试困难——一个bug无法定位属于哪一层,既像Harness决策错又像Loop执行错;演进风险——改一处牵一发动全身,任何重构都要同步修改两层。

用控制流复杂度 $M$ 来量化系统的混乱程度:

为了让系统长期可维护,建议用架构评审来守住边界。每一次重构都问一句:这个决策属于Harness还是Loop?这个状态该放全局还是局部?这道菜该由经理定夺还是后厨自理?当团队里每个人都能不假思索地回答这些问题,你的Agent系统就拥有了像那家理想餐厅一样的分工美学——经理安心管大局,后厨专注炒好每一道菜。

M=E−N+2PM = E - N + 2P
控制流复杂度越高,系统越难理解、越难测试;职责重叠会让控制流图中的边数 $E$ 快速膨胀,$M$ 随之飙升。
  1. 边数$E$ 表示控制流图中边的数量,代表状态转移和函数调用关系;职责重叠会疯狂增加调用边。
    E=状态转移数+调用关系数E = \text{状态转移数} + \text{调用关系数}
  2. 节点数$N$ 表示控制流图中节点的数量,代表基本代码块。
    N=基本块数量N = \text{基本块数量}
  3. 连通分量数$P$ 表示图中连通分量的数量,规范的程序通常 $P=1$。
    P=1P = 1
  4. 复杂度含义$M$ 越高,测试覆盖难度越大,维护成本越高。业界经验认为 $M \leq 10$ 是可接受区间。
    M=E−N+2PM = E - N + 2P

AI 应用场景

多Agent保险理赔系统

阶段:任务编排与多Agent协作

解决的问题:传统理赔系统用一堆if-else串联规则,流程改动需要重写全部代码。用Harness + Loop分层后,Harness负责理赔单的全局状态和流程节点(录入→核验→定损→打款),各子Agent作为Loop循环执行自己环节的推理与工具调用。遇到单据不清晰时,Loop上报哈Harness,Harness统一决定是请求用户补充还是转人工,避免子Agent各自为政。

具体案例:某保险科技公司的理赔Agent,Harness维护理赔单状态机,OCR子Agent循环执行“识别单据→提取字段→校验置信度”,低于阈值时报Harness,Harness自动发起补充材料请求。上线后理赔处理时效提升60%,且新增险种时只需在Harness中加一条流程分支。

智能客服对话机器人

阶段:对话管理与工具调用编排

解决的问题:客服机器人最怕对话轮次一多就混乱,要么重复提问,要么检索失败后强行编造答案。用Harness管理对话轮次、意图路由和全局用户画像,Loop执行“检索知识库→生成回复→更新上下文”的循环。当检索结果为空时,Loop上报Harness,Harness决定改用大模型直接生成还是转人工坐席。

具体案例:某电商平台的售前客服机器人,Harness判断当前意图是“查物流”还是“问退换货”,将对应任务下发给专门的Loop执行。Loop每轮检索结果都会写回Harness维护的会话历史,保证多轮追问不丢失上下文,用户满意度提升20%。

自动化测试执行Agent

阶段:测试编排与失败恢复

解决的问题:传统自动化测试脚本一旦某一步失败就全部中断,排查问题时日志混乱。用Harness管理测试用例的执行顺序、超时阈值和重试策略,Loop循环执行“打开页面→模拟操作→收集断言结果”。元素定位失败这类局部错误由Loop记录上下文并上报,Harness决定跳过该用例还是整体重跑。

具体案例:某金融公司的UI回归测试Agent,Harness按矩阵调度用例,Loop每轮跑完将页面快照和网络请求回传。当某用例连续3次失败,Harness自动将故障用例隔离并生成缺陷报告,测试维护成本降低40%。

Python 演示

python51 行
"""演示 Harness 与 Loop 的职责边界:Harness 负责流程决策,Loop 负责单步执行。""" import random  class Loop:    """执行循环:负责单步执行,不关心全局策略。"""     def __init__(self):        self.step_count = 0     def run_step(self, task):        """执行一次迭代:模拟模型推理+工具调用。失败时向上抛出。"""        self.step_count += 1        if random.random() < 0.2:            raise RuntimeError("工具调用失败")        return {"step": self.step_count,                "result": "完成" + task + "的第" + str(self.step_count) + "步"}  class Harness:    """高层编排:决定循环何时停止,处理 Loop 上报的错误。"""     def __init__(self, loop):        self.loop = loop        self.max_retries = 2        self.max_steps = 5     def execute(self, task):        """执行完整任务:控制循环边界,错误重试与降级。"""        results = []        while self.loop.step_count < self.max_steps:            retry = 0            while retry <= self.max_retries:                try:                    results.append(self.loop.run_step(task))                    break                except RuntimeError:                    retry += 1            else:                print("重试耗尽,切换降级策略")                break        return results  if __name__ == "__main__":    runner = Loop()    boss = Harness(runner)    output = boss.execute("处理理赔申请")    for item in output:        print(item)
目的:用不到50行的Python清晰展示Harness与Loop的职责边界——Loop只负责执行单步并上报错误,Harness控制循环边界、决定重试与降级。
  1. self.step_count = 0Loop只维护自己的迭代次数,不保存任务全局信息,就像厨师只看订单小票。
  2. while self.loop.step_count < self.max_steps:循环何时停止由Harness判断,Loop自身没有退出机制。
  3. raise RuntimeError("工具调用失败")Loop把错误原样抛出,不自己消化,对应“检测与上报”。
  4. while retry <= self.max_retries:Harness决定重试次数上限,Loop无权修改重试策略。
  5. print("重试耗尽,切换降级策略")重试无果后Harness执行降级决策,这是编排层的专属权力。

常见误区

误区为了让Agent“更自主灵活”,我把流程决策、重试逻辑和终止判断全都写进Loop里,这样Harness就只管启动任务,多省事啊。

正解这就像让厨师自己决定换菜单。短期看灵活,长期看流程完全不可预测——同一个任务这次走A路径下次走B路径,出了问题无法复现。流程决策应留在Harness,Loop只负责迭代执行,才能保证任务可控制、可审计。

为何常见:因为大模型时代“自由发挥”被过度神化,误以为把决策权下放给模型越多越好,忽略了工程上可维护性的重要。

误区Harness应该控制一切,包括Loop内部每一步的推理细节、工具参数,这样才能保证最终质量不出偏差。

正解经理不能每一道菜都自己颠勺。Harness管得越细,Loop执行上下文就会被大量无关状态污染,同时Harness本身复杂度激增,沦为“上帝类”。正确做法是只在契约层约束Loop的输入输出,让Loop在契约范围内自主执行。

为何常见:这是从传统软件开发的“控制一切”思维迁移过来的,缺乏分层抽象的信任感,总觉得不控制就会失控。

误区既然要保证数据一致性,干脆把所有状态都放进Harness管理的全局存储里,Loop执行时想读就读、想写就写,多方便。

正解这会造成类似多线程共享可变状态的并发地狱——多个Loop并发修改同一份状态,轻则逻辑错乱,重则死锁崩溃。正确做法是“能不全局就不全局”,局部状态留在Loop内部,只有跨迭代的数据才上提给Harness。

为何常见:追求“统一入口”的直觉很强,但忽略了高频全局读写带来的性能代价和组织性代价。

误区Loop遇到错误自己重试几次就好了,不用每次都打断Harness,这样效率高、响应快。

正解Loop在Harness不知情的情况下重试可能放大损害——比如调用了扣款工具,第一次超时但其实成功了,Loop重试导致重复扣款。Harness需要知道错误上下文才能做出全局最优决策(重试、换工具还是终止),Loop的“好心”反而会酿成大错。

为何常见:把错误处理等同于局部重试,忽略了单次执行失败对整体任务目标可能产生的连锁影响。

误区为了灵活,Harness与Loop之间不定义严格接口,直接传JSON对象,字段随便加,反正都是自己团队写的代码。

正解松散的接口短期灵活,时间一长任何一方悄悄改了字段,都会破坏另一方的隐含假设,而且这种破坏在运行时才暴露。就像菜单模糊不清,后厨和服务员迟早要吵架。契约要显式定义Schema、数据边界和事件类型,变更走评审。

为何常见:小团队或小型系统阶段很难预见契约的价值,等到系统膨胀后再补契约,改造成本已是天价。

面试题

Q1. Harness层在Agent架构中的核心职责是什么?

单选题 · easy

  • A.执行单步大模型推理
  • B.编排整体流程并管理全局状态← 正确答案
  • C.调用外部工具获取结果
  • D.保存每一轮的对话历史

答案:B。Harness对应餐厅经理,负责流程决策与全局状态管理;单步推理、工具调用是Loop或具体工具的事,对话历史存储属于基础设施,不是Harness的核心职责。

Q2. 关于Loop层的描述,正确的是?

单选题 · easy

  • A.Loop负责全任务的生命周期管理
  • B.Loop定义终止条件和重试策略
  • C.Loop负责循环执行推理与工具调用← 正确答案
  • D.Loop持有用户级全局配置

答案:C。Loop是后厨流水线,负责重复执行“推理→工具→观察”的循环。生命周期、终止条件、重试策略都属于Harness的编排职责,Loop不应越权持有用户级配置。

Q3. 控制流编排的分工原则是什么?

单选题 · easy

  • A.流程归Harness迭代归Loop← 正确答案
  • B.流程和迭代都归Loop
  • C.流程和迭代都归Harness
  • D.全部交给大模型自由决策

答案:A。流程级决策(何时开始、走哪个分支、何时终止)由Harness负责,迭代级决策(当前调哪个工具、参数是什么)由Loop负责。全部下放会让流程不可控,全部上提会让Harness膨胀,全交给大模型则失去工程保障。

Q4. 一个理赔任务的状态中,哪些应由Harness持有?

单选题 · mid

  • A.当前OCR返回的文本内容
  • B.本次工具调用的超时时间
  • C.全任务的处理阶段和会话历史← 正确答案
  • D.上一步大模型的原始输出

答案:C。OCR文本、超时时间、单次模型输出都是迭代级局部状态,用完即弃;任务处理阶段与会话历史需要跨迭代存在,归Harness全局管理,对应经理账本上的经营数据。

Q5. 某次工具调用失败,Loop应该怎么做?

单选题 · mid

  • A.无视错误继续下一步
  • B.自行无限重试直到成功
  • C.收集错误并上报给Harness← 正确答案
  • D.直接终止整个任务

答案:C。Loop检测并上报错误上下文,Harness决定重试、降级还是终止。Loop自行无限重试可能放大损害(如重复扣款),直接终止又可能误杀整个任务,无视错误更危险。

Q6. 重试成功率公式中,若单次成功率p=0.8,重试3次后至少成功一次的概率约为?

单选题 · extreme

  • A.0.512
  • B.0.992← 正确答案
  • C.0.800
  • D.0.896

答案:B。代入公式 $P=1-(1-0.8)^3=1-0.008=0.992$。0.512是三次全部成功的概率,0.896是简单把三次成功率相加的错觉,0.800忽略了重试的叠加收益。

Q7. 接口契约中“数据边界”的含义是?

单选题 · mid

  • A.限定哪些字段可以传给大模型
  • B.规定两层之间数据如何流转← 正确答案
  • C.限制用户输入的最大长度
  • D.设置API调用的并发数上限

答案:B。数据边界明确哪些数据由Harness传给Loop、哪些由Loop回传、哪些是只读全局配置禁止修改,是菜单式契约的重要组成部分,与模型字段、用户输入长度、并发控制无关。

Q8. 哪些做法能提高系统的可测试性?

多选题 · mid

  • A.用Mock替换Loop以测Harness← 正确答案
  • B.将测试环境的数据写死
  • C.为Loop提供标准化的测试输入← 正确答案
  • D.跳过集成测试直接上线

答案:AC。Mock让Harness测试不依赖Loop真实实现,标准化输入让Loop测试可重复、可断言。将测试数据写死会掩盖真实边界条件,跳过集成测试则失去了验证两层协作的机会,均不可取。

Q9. 以下哪些属于职责重叠的反模式?

多选题 · hard

  • A.Harness硬编码单次工具参数← 正确答案
  • B.Loop自行决定退出循环← 正确答案
  • C.Harness管理任务的启动终止
  • D.Loop统一上报错误上下文

答案:AB。Harness硬编码迭代细节、Loop自己决定退出循环,都跨越了职责边界。启动终止由Harness管理、错误上报由Loop执行,这是正确的分工,不属于反模式。

Q10. 符合状态管理分工原则的做法是?

多选题 · hard

  • A.会话历史由Harness全局维护← 正确答案
  • B.单次模型输出仅保留在Loop内部← 正确答案
  • C.全局配置允许任意Loop直接修改
  • D.跨迭代的任务进度由Harness记录← 正确答案

答案:ABD。跨迭代数据(会话历史、任务进度)归Harness,迭代内数据(单次输出)留Loop。全局配置是只读契约的一部分,绝不允许Loop随手改写——这就像后厨不能擅自修改菜单。