详情

首页手游攻略 AI 工程范式演进(三):Agent 的思考-行动-观察循环:Harness 到底在忙什么?

AI 工程范式演进(三):Agent 的思考-行动-观察循环:Harness 到底在忙什么?

佚名 2026-07-25 17:42:56

AI 工程范式演进(三):Agent 的「思考-行动-观察」循环,Harness 到底在忙什么?

{"type":"doc","content":[{"type":"paragraph","attrs":{"id":null,"textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false}},{"type":"blockquote","attrs":{"id":"02497f23-2960-42c8-b75e-db93c2d4a650","textAlign":"inherit","isHoverDragHandle":false},"content":[{"type":"paragraph","attrs":{"id":"2b8d42a1-d06b-4705-b592-d9973012ad1a","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"一句话定位:Agent 不是「一次问答」,而是一个"},{"type":"text","marks":[{"type":"bold"}],"text":"由模型自己决定下一步该调用什么工具的循环"},{"type":"text","text":"。Harness 就是那个既当裁判、又当场地、又当记分牌的执行框架。"}]}]},{"type":"horizontalRule","attrs":{"id":"03219237-f66a-4b08-9553-8958f3f72fd0","isHoverDragHandle":false}},{"type":"heading","attrs":{"id":"507d8c27-f736-4464-b7e3-29f975150a7c","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"一、场景切入:查天气并推荐穿搭"}]},{"type":"paragraph","attrs":{"id":"4e71a7dc-c6b4-4b18-ae7b-33e034807759","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"先别急着讲概念,我们从一个你能直接看懂的任务开始。"}]},{"type":"paragraph","attrs":{"id":"4c90ac55-816b-4f4e-a8d6-53965819df04","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"用户问:"}]},{"type":"blockquote","attrs":{"id":"982f0d08-58d8-48e2-9ebe-fb3c28e32f35","textAlign":"inherit","isHoverDragHandle":false},"content":[{"type":"paragraph","attrs":{"id":"54ddcb88-e65c-4663-a38c-477d29980961","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"「我明天要去上海出差,帮我查一下天气,再推荐一套穿搭。」"}]}]},{"type":"paragraph","attrs":{"id":"82204188-4a13-4739-a6c8-d93ee9db70c4","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"如果是传统 REST 接口,后端会把这句话丢给 N 个硬编码步骤:"}]},{"type":"orderedList","attrs":{"id":"ca1ade90-a70c-4b1e-b280-ff1c065876f7","start":1,"isHoverDragHandle":false},"content":[{"type":"listItem","attrs":{"id":"71400e01-eeab-4d43-b769-099699d8b58a"},"content":[{"type":"paragraph","attrs":{"id":"4f0dd81c-978f-40db-8c76-708b4ba319c7","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"正则匹配城市 = 上海"}]}]},{"type":"listItem","attrs":{"id":"db8506be-39bc-4a63-a9be-56ada9ca34f7"},"content":[{"type":"paragraph","attrs":{"id":"f104ac35-c6fc-4f32-9d65-f523be7d20bf","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"正则匹配日期 = 明天"}]}]},{"type":"listItem","attrs":{"id":"ce0eb079-bdce-4845-9fff-adbcaf4fd34a"},"content":[{"type":"paragraph","attrs":{"id":"51ddd546-edd7-43de-aa6a-46909a8fef06","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"调用天气 API"}]}]},{"type":"listItem","attrs":{"id":"4cfb1dc1-51a1-425b-954c-83a0db510e3f"},"content":[{"type":"paragraph","attrs":{"id":"1e38c667-3f80-4875-a2e1-b1c5f7f42d7a","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"拿到温度后,按 if-else 推荐衣服"}]}]},{"type":"listItem","attrs":{"id":"3688d333-df77-4b54-9e55-10ed51dafc96"},"content":[{"type":"paragraph","attrs":{"id":"f02a882d-249f-42c9-a0fc-09deb6ee9346","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"拼接返回"}]}]}]},{"type":"paragraph","attrs":{"id":"337dd20f-5f22-45f5-ab5b-11a8580c81c1","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"这套逻辑能跑,但脆弱:用户说「下周三去杭州开会穿什么」,你的正则可能就跪了。"}]},{"type":"paragraph","attrs":{"id":"afd5be48-a41b-4d48-96ff-bc1dbd71b9cc","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Agent 的做法完全不同。它不会把所有步骤写死,而是让模型"},{"type":"text","marks":[{"type":"bold"}],"text":"自己决定下一步"},{"type":"text","text":"。内部发生的事情大概是这样:"}]},{"type":"codeBlock","attrs":{"id":"480e9c57-c38f-48b5-96cf-3a1d0bfeb9cc","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":""},"content":[{"type":"text","text":"用户:明天去上海出差,查天气并推荐穿搭。nn[Think 1]n→ 用户需要两个信息:上海明天的天气,以及基于天气的穿搭建议。n→ 我有 get_weather 工具,先调用它。nn[Action 1] 调用 get_weather(city="上海", date="明天")nn[Observe 1]n→ 天气 API 返回:上海明天 18~24℃,多云,有微风。nn[Think 2]n→ 温度适中,多云,不需要厚外套,但也不能穿短袖。n→ 我有 recommend_clothing 工具,把天气传给它。nn[Action 2] 调用 recommend_clothing(temperature="22℃", weather="多云", wind="微风")nn[Observe 2]n→ 穿搭建议返回:薄针织开衫 九分裤 休闲鞋。nn[Think 3]n→ 已经拿到天气和穿搭,可以直接回答用户,不需要再调用工具。nn[Final] 上海明天 18~24℃ 多云有微风,建议穿薄针织开衫 九分裤 休闲鞋。"}]},{"type":"paragraph","attrs":{"id":"9eabede6-a9c6-4ea9-b24c-21207a426768","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"注意这里的关键:"},{"type":"text","marks":[{"type":"bold"}],"text":"下一步行动不是由 if-else 决定,而是由模型每次推理后动态决定"},{"type":"text","text":"。这就是 Agent 循环的核心。"}]},{"type":"paragraph","attrs":{"id":"c0413586-8389-4c2e-b17e-3b7d7189430e","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Harness 在这里做了什么?它负责:"}]},{"type":"bulletList","attrs":{"id":"a7dfef69-cf38-4c73-a4e9-7921dd81a432","isHoverDragHandle":false},"content":[{"type":"listItem","attrs":{"id":"e72e3a23-7c9c-4ba9-8146-275d59104c10"},"content":[{"type":"paragraph","attrs":{"id":"46d54685-135a-46f9-9b7a-b714b12605df","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"把用户的 query 和工具描述组织成 Prompt;"}]}]},{"type":"listItem","attrs":{"id":"016c8128-ef84-43d6-bb98-07179865033c"},"content":[{"type":"paragraph","attrs":{"id":"b0418d14-a5be-4277-ade3-e4d4f5e4985a","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"调用 LLM;"}]}]},{"type":"listItem","attrs":{"id":"3375429a-002d-4bcd-ad57-3c9fd201b59f"},"content":[{"type":"paragraph","attrs":{"id":"7f3320c9-93b5-4cb8-9f53-2c84c585323b","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"解析 LLM 输出,判断它是「直接回答」还是「要调用工具」;"}]}]},{"type":"listItem","attrs":{"id":"20ee8b15-3457-453c-9945-f966446812c5"},"content":[{"type":"paragraph","attrs":{"id":"5e21f1c3-25b7-4621-a810-a92a592ec123","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"执行工具,捕获结果;"}]}]},{"type":"listItem","attrs":{"id":"209d341d-d9b6-4809-a72e-fb9980283bb9"},"content":[{"type":"paragraph","attrs":{"id":"9652723a-d454-431a-b293-5fcd608f4ed0","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"把结果塞回上下文,再次调用 LLM;"}]}]},{"type":"listItem","attrs":{"id":"8fcd0eae-60e4-4a00-925b-6593ccd57d20"},"content":[{"type":"paragraph","attrs":{"id":"f91754c7-4589-41da-aa1b-f58b0a4b97fe","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"判断什么时候该终止循环,把答案抛给用户。"}]}]}]},{"type":"paragraph","attrs":{"id":"fe8b6bd0-adc7-4de2-9c47-2dab9e6bbd32","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"如果把这个过程画成图,就是这样:"}]},{"type":"codeBlock","attrs":{"id":"cc4a2ef6-ec58-447a-a0aa-e6e77a476640","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":""},"content":[{"type":"text","text":"用户输入n │n ▼n[Prompt 组装] ────────────────────┐n ││n ▼│n[LLM 推理] → 输出 Thought/Action│n ││n ▼│n[输出分类] 工具调用?还是答案?│n ││n ├─ 是工具调用 → [工具执行] │n │ ││n │ ▼│n │ [Observation]│n │ ││n └───────┴──────────────────────┘n │n ▼n循环继续 or 终止"}]},{"type":"horizontalRule","attrs":{"id":"e2928d98-41e9-40c0-88c7-d5f55e87e50c","isHoverDragHandle":false}},{"type":"heading","attrs":{"id":"790a7ee3-06a1-4a9e-a112-74acffd16bd9","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"二、ReAct 范式解析:不是循环,是「循环里有决策」"}]},{"type":"paragraph","attrs":{"id":"13305473-e5cf-4767-961e-80a781089025","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"ReAct 这个词来自 Google 2022 年的论文 "},{"type":"text","marks":[{"type":"italic"}],"text":"ReAct: Synergizing Reasoning and Acting in Language Models"},{"type":"text","text":"。它把推理(Reasoning)和行动(Acting)交织在一起:模型先想,再动,再观察,再想,再动……"}]},{"type":"heading","attrs":{"id":"209b044e-1400-4421-ace1-65aab9ac87e5","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"2.1 Thought → Action → Observation 的闭环"}]},{"type":"codeBlock","attrs":{"id":"d5777446-00bd-4ae8-a098-3a63512307c5","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":""},"content":[{"type":"text","text":"Thought──►Action──►Observationn ▲│n └────────────────────────┘"}]},{"type":"bulletList","attrs":{"id":"6a8a8a31-99c9-4cb6-8fb9-220e0ec95ca0","isHoverDragHandle":false},"content":[{"type":"listItem","attrs":{"id":"b693dee4-3370-46b7-a2f4-262927f47bf3"},"content":[{"type":"paragraph","attrs":{"id":"1d62d440-b5e4-4e4a-aecb-1eb6e26986cd","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"Thought"},{"type":"text","text":":模型对当前处境的理解,以及下一步该做什么的推理。"}]}]},{"type":"listItem","attrs":{"id":"e1fb6e3b-2e72-4965-bfc5-4b2bfe256d12"},"content":[{"type":"paragraph","attrs":{"id":"c9cd4e41-8fdb-403b-9c2e-0c69e742d669","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"Action"},{"type":"text","text":":基于 Thought 产生的具体动作,通常是一个工具调用。"}]}]},{"type":"listItem","attrs":{"id":"b4f57fed-72a0-4bff-9e1b-4faea72feadd"},"content":[{"type":"paragraph","attrs":{"id":"5f824bde-a66f-4a9b-aa69-c7c85eb023da","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"Observation"},{"type":"text","text":":工具执行后的结果,回传给模型作为下一轮 Thought 的输入。"}]}]}]},{"type":"paragraph","attrs":{"id":"8018bcf2-973a-4a4f-95d2-81e0a0d1914a","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"闭环不断旋转,直到 Thought 认为「任务已完成」或达到最大步数。"}]},{"type":"heading","attrs":{"id":"fa159e21-89e6-4739-8552-5019a0817fdf","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"2.2 与传统编程循环的本质区别"}]},{"type":"paragraph","attrs":{"id":"3438ce4e-b109-49cd-ab18-b46ca335a847","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"传统循环里,循环体是"},{"type":"text","marks":[{"type":"bold"}],"text":"固定的"},{"type":"text","text":":"}]},{"type":"codeBlock","attrs":{"id":"a47feee9-c030-457f-b5d2-50041191967d","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":""},"content":[{"type":"text","text":"for city in cities:nweather = get_weather(city)nprint(weather)"}]},{"type":"paragraph","attrs":{"id":"36eecb1a-cad0-4f07-99d3-3eefe7748e30","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"每一步该调用什么函数、传什么参数,程序员在写代码时就定死了。"}]},{"type":"paragraph","attrs":{"id":"5ab4f7d2-3622-419f-89ec-d801a1431a66","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Agent 循环里,循环体是"},{"type":"text","marks":[{"type":"bold"}],"text":"动态生成的"},{"type":"text","text":":每一轮由 LLM 根据当前上下文,自己决定「接下来要调用哪个工具、传什么参数、还是直接给答案」。"}]},{"type":"paragraph","attrs":{"id":"5cd7644d-7f4d-4ac9-b3df-dcf188c363b9","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"这就好比:"}]},{"type":"bulletList","attrs":{"id":"3fe7c6bc-bff8-4ae9-9504-08414ccd8742","isHoverDragHandle":false},"content":[{"type":"listItem","attrs":{"id":"0e55d457-fa9c-456b-b232-f85355dcb7b6"},"content":[{"type":"paragraph","attrs":{"id":"477bbb24-51aa-4ea2-ac5a-c2d50cfdce93","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"传统程序是"},{"type":"text","marks":[{"type":"bold"}],"text":"火车轨道"},{"type":"text","text":",车只能按轨道走;"}]}]},{"type":"listItem","attrs":{"id":"43aa1286-e152-4bc7-841c-c42b7d53a733"},"content":[{"type":"paragraph","attrs":{"id":"b3f0706a-2439-4ae4-8605-ff6fd2b66912","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Agent 是"},{"type":"text","marks":[{"type":"bold"}],"text":"自动驾驶汽车"},{"type":"text","text":",每次看到路况后自己决定左转、右转还是直行。"}]}]}]},{"type":"heading","attrs":{"id":"0e5c19bd-874f-4a4c-8bb1-c9c59cec2162","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"2.3 用 Spring Interceptor 链类比"}]},{"type":"paragraph","attrs":{"id":"9c0fca95-e4b9-4cca-9e64-c7e68ef26079","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"如果你熟悉 Spring 的 "},{"type":"text","marks":[{"type":"code"}],"text":"HandlerInterceptor"},{"type":"text","text":",会很容易理解。"}]},{"type":"paragraph","attrs":{"id":"29989a3b-ada4-4c3a-b4c3-82d3d6b07e3d","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Spring 的拦截器链:"}]},{"type":"codeBlock","attrs":{"id":"150c5ef8-db48-4feb-aa4a-0b86e88a11a2","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":""},"content":[{"type":"text","text":"请求 → Interceptor1.preHandle() → Interceptor2.preHandle() → Controllern│n返回 false 则中断流程"}]},{"type":"paragraph","attrs":{"id":"874d075a-9e50-4a0d-937f-5ac48f5b9156","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Agent 的循环也有点像:"}]},{"type":"codeBlock","attrs":{"id":"cafcdd44-cdc3-4bb5-a9d2-77c705e71e89","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":""},"content":[{"type":"text","text":"用户输入 → 组装 Prompt → LLM 推理 → 输出分类 → 工具执行 → 结果回环n│n模型决定继续还是终止"}]},{"type":"paragraph","attrs":{"id":"66dcbf0b-f697-4825-b409-be9a5a1cc463","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"区别是:"}]},{"type":"bulletList","attrs":{"id":"d42785f7-e3a5-4eb1-9b9f-2af493ccf08b","isHoverDragHandle":false},"content":[{"type":"listItem","attrs":{"id":"5a048fee-e871-46ec-901b-51f84055ac0b"},"content":[{"type":"paragraph","attrs":{"id":"6306ff91-3923-449f-aa75-78b6aa8c7b3e","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Spring 的拦截器逻辑是"},{"type":"text","marks":[{"type":"bold"}],"text":"硬编码"},{"type":"text","text":"的;"}]}]},{"type":"listItem","attrs":{"id":"de714807-21de-41d3-841e-edc158031387"},"content":[{"type":"paragraph","attrs":{"id":"df63ec45-05c7-4b82-b282-2bf62b3ebfe1","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Agent 的「拦截/继续」决策是"},{"type":"text","marks":[{"type":"bold"}],"text":"模型动态生成"},{"type":"text","text":"的。"}]}]}]},{"type":"paragraph","attrs":{"id":"a2c13355-c99e-4683-9636-947e096d4d77","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"这也解释了为什么 Harness 不能太重:如果 Harness 把太多决策逻辑写死,就退化成传统拦截器链,失去了 Agent 的灵活性。"}]},{"type":"horizontalRule","attrs":{"id":"f927a018-ebe5-456c-9a67-11e1d791179c","isHoverDragHandle":false}},{"type":"heading","attrs":{"id":"620d2612-378d-415c-bade-fc63ab875c84","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"三、七步编排循环:从 Prompt 到终止判断"}]},{"type":"paragraph","attrs":{"id":"4966cfe4-701e-470f-b689-86631faf0198","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"下面我们拆解一个工业级 Agent 的七步循环。每一步都给出伪代码和关键注意点。"}]},{"type":"heading","attrs":{"id":"86b0670b-fd9d-461e-b26f-34423534fe7d","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"Step 1:Prompt 组装"}]},{"type":"codeBlock","attrs":{"id":"eb720d40-ad82-472b-9175-0a11c27c6a28","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":""},"content":[{"type":"text","text":"def build_prompt(system_prompt, tools, memory, history, query):nmessages = []nmessages.append({"role": "system", "content": system_prompt})nn# 把工具 schema 塞进 system prompt,让模型知道能调用什么ntool_descriptions = format_tools(tools)# JSON Schema / OpenAI function schemanmessages.append({"role": "system", "content": tool_descriptions})nn# 记忆:长期 facts、用户偏好nfor mem in memory:nmessages.append({"role": "system", "content": f"[记忆] {mem}"})nn# 历史对话nmessages.extend(history)nn# 当前用户输入nmessages.append({"role": "user", "content": query})nreturn messages"}]},{"type":"paragraph","attrs":{"id":"7793fba6-e3d2-4e6b-8fea-497c11857897","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"后端映射:这就像 Spring 的 "},{"type":"text","marks":[{"type":"code"}],"text":"Filter"},{"type":"text","text":" 在请求到达 Controller 之前,把 security context、traceId、tenantId 都封装到 "},{"type":"text","marks":[{"type":"code"}],"text":"ThreadLocal"},{"type":"text","text":" 里。"}]},{"type":"heading","attrs":{"id":"464c7d32-c95a-448f-863c-006658051251","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"Step 2:LLM 推理"}]},{"type":"codeBlock","attrs":{"id":"9c07ba26-c883-482f-9f8b-c8df02166030","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":""},"content":[{"type":"text","text":"def llm_infer(messages, model="gpt-4o"):nresponse = openai.chat.completions.create(nmodel=model,nmessages=messages,ntools=tools,nstream=Truen)nreturn stream_to_full_text(response)"}]},{"type":"paragraph","attrs":{"id":"2425062b-fbde-49c4-a1db-d40f170db86f","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"注意点:流式响应需要处理 "},{"type":"text","marks":[{"type":"code"}],"text":"delta"},{"type":"text","text":" 片段,最后聚合成完整消息。如果是本地小模型,可能还要做 token 限制和超时保护。"}]},{"type":"paragraph","attrs":{"id":"f735415f-70c4-4d62-91c8-11985995436d","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"后端映射:相当于调用一个远程 Service。要有重试、超时、熔断、降级,不能裸调。"}]},{"type":"heading","attrs":{"id":"8e928596-ec9d-4036-84b5-f18380ced440","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"Step 3:输出分类"}]},{"type":"paragraph","attrs":{"id":"48bbfd9b-86ab-4b42-b396-1e8f4dd4603b","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"LLM 返回后,必须解析它到底想干什么。通常有三种情况:"}]},{"type":"table","attrs":{"id":"96ff97c4-b826-4a2b-90c9-ae8886920b49","isHoverDragHandle":false},"content":[{"type":"tableRow","content":[{"type":"tableHeader","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"371d8b6c-1bbf-4c98-bf5d-44f25c886579","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"类型"}]}]},{"type":"tableHeader","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"0ca4ebfb-1f38-47ff-bb1d-64e914cb2b88","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"判定方式"}]}]},{"type":"tableHeader","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"dd672588-e764-45d2-b16f-e6ad067fa682","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"处理动作"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"9ff19351-7b67-465e-8528-d938add2c4e6","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"纯文本答案"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"fa0e1f37-4a59-4d22-88d5-2671f56909ab","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"没有 "},{"type":"text","marks":[{"type":"code"}],"text":"tool_calls"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"8a77475e-466f-4baf-988b-2759923c151b","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"直接返回给用户,循环终止"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"3c036e6a-88bc-42c4-9429-f17cc24ff76c","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"工具调用"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"850c44a0-b146-4d67-8867-c1e43cb16144","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"包含 "},{"type":"text","marks":[{"type":"code"}],"text":"tool_calls"},{"type":"text","text":" 字段"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"c42f6182-f2e9-40b7-87d9-3a54aa477eba","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"解析函数名和参数,进入 Step 4"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"72fc34bc-66a1-42ad-8851-d4cf337eb547","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Handoff"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"04f44b45-fb7d-483e-a396-4cae80b5f67e","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"包含 "},{"type":"text","marks":[{"type":"code"}],"text":"handoff"},{"type":"text","text":" / 特殊 token"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"308f058a-d02b-4951-b495-2e7bee5986d6","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"把对话转给另一个 Agent 处理"}]}]}]}]},{"type":"codeBlock","attrs":{"id":"a2b863c1-0d40-48f5-8ae9-4e631ee9c708","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":""},"content":[{"type":"text","text":"def classify_output(llm_output):nif llm_output.get("tool_calls"):nreturn "tool_call", llm_output["tool_calls"]nif llm_output.get("handoff"):nreturn "handoff", llm_output["handoff"]nreturn "answer", llm_output["content"]"}]},{"type":"heading","attrs":{"id":"5fbf7376-5f02-48a5-a982-760b645297a0","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"Step 4:工具执行"}]},{"type":"paragraph","attrs":{"id":"00bf4162-05c1-4e08-8d7a-eab4c92dc552","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"工具执行是 Agent 循环里最危险的一步,必须严谨。"}]},{"type":"codeBlock","attrs":{"id":"2f9c93dd-268e-43e5-96fc-889de71575a6","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":""},"content":[{"type":"text","text":"def execute_tool(tool_name, arguments, tool_registry):ntool = tool_registry.get(tool_name)nif not tool:nreturn f"错误:未找到工具 {tool_name}"nn# 参数校验:JSON Schema 校验nvalidate(arguments, tool.schema)nn# 权限检查:该工具是否允许当前用户/会话调用nif not permission_check(tool, context):nreturn f"错误:没有权限调用 {tool_name}"nn# 沙箱执行,捕获所有异常ntry:nresult = tool.run(**arguments)nreturn resultnexcept Exception as e:nlogger.error(f"工具 {tool_name} 执行失败", exc_info=True)nreturn f"工具执行失败:{type(e).__name__}: {str(e)}""}]},{"type":"paragraph","attrs":{"id":"219728c8-40c3-4d1e-921c-ae48f58ea274","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"后端映射:工具调用 ≈ Service 层方法调用。参数校验像 JSR-303,权限检查像 Spring Security,异常处理像全局 "},{"type":"text","marks":[{"type":"code"}],"text":"@ControllerAdvice"},{"type":"text","text":"。"}]},{"type":"heading","attrs":{"id":"c0c73027-70fd-42a2-865c-b06a5faa6bad","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"Step 5:结果打包"}]},{"type":"paragraph","attrs":{"id":"ffcb8eb3-9573-4c0f-9de6-e3ab5af857e4","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"工具返回的结果五花八门:JSON、字符串、图片 URL、错误信息。必须统一格式化成 LLM 能读懂的 "},{"type":"text","marks":[{"type":"code"}],"text":"ToolMessage"},{"type":"text","text":"。"}]},{"type":"codeBlock","attrs":{"id":"8d00a3e9-9405-4277-a53f-27ff1af0fb21","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":""},"content":[{"type":"text","text":"def pack_observation(tool_call_id, tool_name, result):nreturn {n"role": "tool",n"tool_call_id": tool_call_id,n"name": tool_name,n"content": json.dumps(result, ensure_ascii=False) if not isinstance(result, str) else resultn}"}]},{"type":"paragraph","attrs":{"id":"1ee2761c-c2c1-4ce0-ab79-e996f6318e71","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"注意:如果结果很长,还要做截断或摘要,否则上下文会爆。"}]},{"type":"heading","attrs":{"id":"3d42aaf1-9dd9-4ce2-89fa-3953a33a60d5","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"Step 6:上下文更新"}]},{"type":"paragraph","attrs":{"id":"ea790626-e7ef-4612-8ebb-d45bb8d44078","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"把 Observation 追加到历史消息里,为下一轮 LLM 推理做准备。"}]},{"type":"codeBlock","attrs":{"id":"bfecb455-0b45-4373-a7a9-7d406bdf0726","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":""},"content":[{"type":"text","text":"history.append(llm_output)nhistory.append(observation)nn# 上下文压缩:超过阈值时触发摘要或截断nif token_count(history) > MAX_CONTEXT_TOKENS:nhistory = compress_history(history)"}]},{"type":"paragraph","attrs":{"id":"bf8c0a7f-9141-450e-8916-5e7415faa809","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"后端映射:这像 "},{"type":"text","marks":[{"type":"code"}],"text":"ThreadLocal"},{"type":"text","text":" 的上下文传递,或者像微服务链路中的 trace 上下文。每个 Agent 步骤都在同一个「请求上下文」里读写。"}]},{"type":"heading","attrs":{"id":"112561d2-0c98-4f40-bde2-60a884420b2d","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"Step 7:循环继续 or 终止判断"}]},{"type":"codeBlock","attrs":{"id":"6972f07f-039f-4b7e-827d-c2cc43e54574","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":""},"content":[{"type":"text","text":"while True:nif step_count > MAX_STEPS:nreturn "达到最大步数,终止循环"nnmessages = build_prompt(system, tools, memory, history, query)nllm_output = llm_infer(messages)ncategory, payload = classify_output(llm_output)nnif category == "answer":nreturn payloadnnif category == "tool_call":nfor tool_call in payload:nresult = execute_tool(tool_call["name"], tool_call["arguments"])nobservation = pack_observation(tool_call["id"], tool_call["name"], result)nhistory.append(llm_output)nhistory.append(observation)ncontinuennif category == "handoff":nreturn handoff_to_agent(payload, history)"}]},{"type":"paragraph","attrs":{"id":"b1c52b35-57c5-4594-bad2-fe13437c7c05","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"终止条件通常有:"}]},{"type":"orderedList","attrs":{"id":"36775d4e-75f5-442d-bcee-538c1dd1dfc9","start":1,"isHoverDragHandle":false},"content":[{"type":"listItem","attrs":{"id":"a95da21a-5888-4495-937b-11b9b98d949a"},"content":[{"type":"paragraph","attrs":{"id":"91d23b34-5ae8-425d-ac5a-6290646d5bd9","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"模型输出最终答案(没有工具调用);"}]}]},{"type":"listItem","attrs":{"id":"744dc142-76ab-4b96-a3a9-f117ab00be47"},"content":[{"type":"paragraph","attrs":{"id":"745d46a1-5c79-43a3-8b69-7593135932db","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"达到最大循环步数(防止死循环);"}]}]},{"type":"listItem","attrs":{"id":"ae577cf4-1e40-40d9-94dd-e2d56b5cfecc"},"content":[{"type":"paragraph","attrs":{"id":"179e3304-d03a-4236-917b-46e1cc366694","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"工具连续失败多次;"}]}]},{"type":"listItem","attrs":{"id":"a9e55dce-a79a-4b7c-bc08-184b3381dcce"},"content":[{"type":"paragraph","attrs":{"id":"931261e8-b324-43c7-9a90-ef4d0c0dd21b","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"用户主动中断;"}]}]},{"type":"listItem","attrs":{"id":"faac6191-2e09-4f3f-835c-e20ebd65f41d"},"content":[{"type":"paragraph","attrs":{"id":"8a103f1d-a211-466f-97a8-9f2d3898f29a","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Handoff 到其他 Agent。"}]}]}]},{"type":"horizontalRule","attrs":{"id":"34214ff2-2c62-4218-a27b-8eda706dac30","isHoverDragHandle":false}},{"type":"heading","attrs":{"id":"866374c6-3a42-4d54-9fb9-5777215b7ebf","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"四、Dumb Loop vs Thick Harness:哲学辩论"}]},{"type":"paragraph","attrs":{"id":"dae58ee4-b9fe-4fd0-a148-638c1e2d44d7","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Agent 循环到底应该多「笨」?Harness 应该多「厚」?这个行业里有两派观点。"}]},{"type":"heading","attrs":{"id":"21984afc-4d3c-41b8-a67d-4bc4bceef00f","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"4.1 Anthropic 立场:Harness 越薄越好,智能在模型"}]},{"type":"paragraph","attrs":{"id":"72de10b6-a634-41a7-9094-581da99bb2b3","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Anthropic 在 "},{"type":"text","marks":[{"type":"italic"}],"text":"Building effective agents"},{"type":"text","text":"(2024)里明确提出:"},{"type":"text","marks":[{"type":"bold"}],"text":"Agent 的智能应该来自模型,而不是来自复杂的框架控制流"},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"id":"92eb0169-cf4b-42d3-8d91-f491a200f30b","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"他们认为:"}]},{"type":"bulletList","attrs":{"id":"ad468973-dde8-4623-a0f5-7c11f669b2fe","isHoverDragHandle":false},"content":[{"type":"listItem","attrs":{"id":"fc1c490e-439a-4938-b077-6bb9038f83af"},"content":[{"type":"paragraph","attrs":{"id":"f915ef34-b4d8-4774-9bb9-666012dd9682","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"过多的状态机、分支、Retry 逻辑会掩盖模型的推理能力;"}]}]},{"type":"listItem","attrs":{"id":"7f9024e2-5117-453b-9dcc-8312444c4f89"},"content":[{"type":"paragraph","attrs":{"id":"f4df7e52-f4d5-4b55-9162-7ab334d83146","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"复杂的 Harness 容易变成「硬编码的智能」,难以维护;"}]}]},{"type":"listItem","attrs":{"id":"cd3087c6-552c-45c5-8dae-2baa40aa6977"},"content":[{"type":"paragraph","attrs":{"id":"c25ddd08-e66d-47f2-a9eb-52901e3d4406","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"薄 Harness 强模型 = 更通用、更灵活的系统。"}]}]}]},{"type":"paragraph","attrs":{"id":"5b3d3a24-f1eb-448f-9844-b637ad8edbcf","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"简单理解:Harness 只要做好 Prompt 组装、工具执行、上下文更新三件事,剩下的交给模型。"}]},{"type":"heading","attrs":{"id":"385a5a08-0d9c-4a1f-88b2-1d797346880a","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"4.2 LangGraph 立场:显式控制才能可靠"}]},{"type":"paragraph","attrs":{"id":"c298ef80-da53-427c-a8fc-f1f0265674de","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"LangGraph 的思路是:把 Agent 的每一步都变成图里的节点和边。"}]},{"type":"bulletList","attrs":{"id":"fa3e89d7-fce4-48fa-bddb-7255df83f84e","isHoverDragHandle":false},"content":[{"type":"listItem","attrs":{"id":"88ea4bc8-a350-4297-a457-44857af39fb1"},"content":[{"type":"paragraph","attrs":{"id":"67d9b821-e3ae-4c23-b4b0-827cb8b23b03","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"每个节点是一个 Agent 或工具;"}]}]},{"type":"listItem","attrs":{"id":"1d8f7ed8-fc6a-47c9-88e9-5d0df273d496"},"content":[{"type":"paragraph","attrs":{"id":"5d523752-40f1-48fe-b358-ceb7ae733b77","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"每条边是明确的条件跳转;"}]}]},{"type":"listItem","attrs":{"id":"852cc430-0ec6-4e33-b4df-e6d7a0bf903d"},"content":[{"type":"paragraph","attrs":{"id":"a42b9411-20b3-40dd-a380-1a6c78f1ae0b","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"你可以看日志、打断点、重放。"}]}]}]},{"type":"paragraph","attrs":{"id":"20b34733-a714-4705-9ba9-f75d458fa1d2","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"这种「 Thick Harness 」适合:"}]},{"type":"bulletList","attrs":{"id":"5e9b845e-705c-4cb0-9988-01901828731f","isHoverDragHandle":false},"content":[{"type":"listItem","attrs":{"id":"d2ae9d4a-1aac-499a-b3e7-4c2a1fb76c0b"},"content":[{"type":"paragraph","attrs":{"id":"f06a3d8d-93f4-42b3-ae47-871165e61b12","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"多 Agent 协作系统;"}]}]},{"type":"listItem","attrs":{"id":"b6038e35-b367-4b1b-a3a4-ff6ec587d3e4"},"content":[{"type":"paragraph","attrs":{"id":"8f83a2de-b543-4950-84c3-07ae0be8c123","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"需要严格审计的金融、医疗场景;"}]}]},{"type":"listItem","attrs":{"id":"b1da560e-3277-4650-8bdc-996b33df25bc"},"content":[{"type":"paragraph","attrs":{"id":"6faeafa7-c18c-4d8b-89ad-39fcd88f6792","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"长期运行、可能跨会话的任务。"}]}]}]},{"type":"heading","attrs":{"id":"06cec032-0392-40f1-a878-eb545c9bfc7a","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"4.3 我的判断:不同场景不同选择"}]},{"type":"table","attrs":{"id":"944845a0-9d7f-4022-aff5-369feb2b56f5","isHoverDragHandle":false},"content":[{"type":"tableRow","content":[{"type":"tableHeader","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"4ec1cbcd-85bf-48b1-b3c8-cadab216e1d4","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"场景"}]}]},{"type":"tableHeader","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"caee60ce-d26e-418d-8cd0-2d3d4dc1a494","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"推荐模式"}]}]},{"type":"tableHeader","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"ac28756d-2923-4c2d-a55a-b055b77663af","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"原因"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"d27d31e6-93cf-4dbe-b775-2eba5173cd92","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"单轮工具调用(查天气、算公式)"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"a1cc7ccd-2a46-4d79-a7ca-25d74ef5866b","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Dumb Loop"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"4680c021-c3b3-4d73-8d44-722a4ecbbcf4","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"简单、可控、易调试"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"e368bf30-e12a-4139-b405-36be2eca7f4b","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"多 Agent 协作(客服、运维排障)"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"17ba5034-a342-4da1-87a8-06e6775e6de5","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Thick Harness"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"2b5545af-3f41-4156-85c1-af17f01a66e6","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"需要状态机、路由、审计"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"b2ce66a3-3a93-4254-85ae-6aee90fe8eda","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"长周期任务(代码生成、数据处理)"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"546571cd-ebb0-47e7-9431-7baa54245906","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Ralph Loop 门控"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"ffe26413-36dc-4e2d-9b05-02cbcfc2d0f3","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"跨会话、可恢复、有背压"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"90a2563f-8a2b-4d3d-8ac0-fd719365e15a","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"高并发服务接口"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"d4098e08-1091-456c-a372-1281449e5bcc","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"不要当 Agent 用"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"6f4f3570-30e3-4aae-b800-e13605b493c6","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Agent 循环 latency 高,不适合高并发"}]}]}]}]},{"type":"paragraph","attrs":{"id":"7824d5dd-95b1-44fe-9e7d-bde7fb683dd1","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"一句话总结:"},{"type":"text","marks":[{"type":"bold"}],"text":"模型越强,Harness 可以越薄;流程越关键、越复杂,Harness 越要厚。"}]},{"type":"horizontalRule","attrs":{"id":"db7470b9-bd1c-4ad8-a854-5d06cacad463","isHoverDragHandle":false}},{"type":"heading","attrs":{"id":"9623de68-f3af-47ba-8ac3-7303be5f8d04","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"五、Ralph Loop 模式:跨会话的连续性"}]},{"type":"paragraph","attrs":{"id":"cba6ee51-7a9d-47ac-b77e-cacc0c44de84","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Ralph Loop 是 Claude Code 团队早期提出的一种模式,名字来自 Ralph,核心思想是:"},{"type":"text","marks":[{"type":"bold"}],"text":"把 Agent 变成一个可以跨会话持续运行的循环"},{"type":"text","text":"。"}]},{"type":"heading","attrs":{"id":"e500d984-4497-41c6-840c-6985d6203a9a","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"5.1 为什么需要跨会话记忆"}]},{"type":"paragraph","attrs":{"id":"b7a1d3ea-8bf2-4018-a509-aa31c6ece724","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"很多任务不是一次对话能完成的。比如:"}]},{"type":"bulletList","attrs":{"id":"01be0377-2cab-4825-b957-cdd20cb23159","isHoverDragHandle":false},"content":[{"type":"listItem","attrs":{"id":"0db63f99-8c2a-42c3-96a7-b11cf011f41f"},"content":[{"type":"paragraph","attrs":{"id":"34401193-7fc3-4d10-98ef-6b01b8f083a5","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"生成一个完整项目的代码,需要几十轮工具调用;"}]}]},{"type":"listItem","attrs":{"id":"3c588013-bb6d-49ad-bdde-9dec046721a2"},"content":[{"type":"paragraph","attrs":{"id":"2c1e3e92-58fe-4fc3-80d5-930952a25de5","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"数据分析任务要跑多个 SQL、画图、写报告;"}]}]},{"type":"listItem","attrs":{"id":"fd5e6d66-359c-4a2e-b3aa-a649c03c4cd9"},"content":[{"type":"paragraph","attrs":{"id":"d0db8186-b454-4c88-85b3-4c660c3d832f","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"运维排障要在多个系统里查日志、执行命令。"}]}]}]},{"type":"paragraph","attrs":{"id":"3e3ec419-5a95-4277-887d-32c42db84180","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"如果每次重启会话都清空上下文,前面的推理就白费了。Ralph Loop 解决的就是「会话重启后的连续性」问题。"}]},{"type":"heading","attrs":{"id":"9a582052-c3c4-4357-a24f-6243ee558ef7","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"5.2 两阶段架构:Initializer Agent Coding Agent"}]},{"type":"codeBlock","attrs":{"id":"d3216515-d01b-492d-b555-755c1461a872","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":""},"content":[{"type":"text","text":"[Initializer Agent]n │n ├── 读取 PROMPT.md / 任务描述n ├── 检查环境、拉仓库、读历史状态n └── 生成一份「当前任务上下文」n │n ▼n [Coding Agent]← 持续运行,循环执行n │n ├── 读上下文n ├── LLM 推理n ├── 工具执行n ├── 更新状态文件n └── 决定继续还是终止"}]},{"type":"paragraph","attrs":{"id":"2bf8a4dc-b000-4804-a077-17a41e6592dc","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Initializer Agent 负责「开局」,Coding Agent 负责「持久战」。"}]},{"type":"heading","attrs":{"id":"f4e726e7-dcae-4498-be2c-ad71efb11e7f","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"5.3 核心实现:一个 while true 循环"}]},{"type":"codeBlock","attrs":{"id":"bc8193dc-d6fb-4b36-8d3d-fb56a83513bf","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":""},"content":[{"type":"text","text":"#!/bin/bashn# run_agent.shnnwhile true; doncat PROMPT.md | claude-code --continuen# 如果上一次失败或没完成,循环会继续n# 通过退出码或状态文件判断何时停止nif [[ -f STOP_FLAG ]]; thennbreaknfindone"}]},{"type":"paragraph","attrs":{"id":"236991f7-da2a-48cc-a03b-07078addb892","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"这个 shell 循环看起来简陋,但威力在于:它让 Agent 可以跨会话「接力跑」。每次 "},{"type":"text","marks":[{"type":"code"}],"text":"claude-code --continue"},{"type":"text","text":" 都会从上一次状态恢复,继续执行未完成的任务。"}]},{"type":"heading","attrs":{"id":"fd504fca-a79c-46f2-86d7-08eeb6510e6f","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"5.4 背压门控:测试/Lint 不通过时不推进"}]},{"type":"paragraph","attrs":{"id":"c912949e-db6d-4d76-9d2e-dc9159c0847a","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Ralph Loop 最关键的不是循环,而是"},{"type":"text","marks":[{"type":"bold"}],"text":"门控"},{"type":"text","text":"。它不是无条件继续,而是根据检查结果决定是否推进:"}]},{"type":"codeBlock","attrs":{"id":"f392d084-45a6-4310-92e9-18b8cfc0cec1","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":""},"content":[{"type":"text","text":"while True:n# 执行一轮 Agentnagent.run_step()nn# 背压门控:检查测试、Lint、类型nif not run_tests():nlogger.error("测试未通过,停止推进,等待修复")nbreaknnif not run_lint():nlogger.error("Lint 未通过,停止推进")nbreaknn# 状态文件判断任务是否完成nif task_finished():nbreak"}]},{"type":"paragraph","attrs":{"id":"0453e1d3-2448-4098-97c5-9c1af6b27675","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"后端映射:这就像一个带状态的 Cron Job 条件门控。Cron Job 负责定时拉起,条件门控决定是否进入下一步。失败的步骤不会继续,而是等待人工或 Agent 自我修复。"}]},{"type":"horizontalRule","attrs":{"id":"8555d7eb-cf61-4a64-88ea-448cc84e6f7b","isHoverDragHandle":false}},{"type":"heading","attrs":{"id":"f2fe69af-0aea-4177-97a0-945eb0aa3cf5","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"六、后端视角映射:把抽象概念落地"}]},{"type":"paragraph","attrs":{"id":"ae2fb189-39ac-4265-856a-b7aba91c739a","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"把 Agent 循环映射到后端熟悉的概念,有助于设计自己的 Agent 系统。"}]},{"type":"table","attrs":{"id":"70ce6904-d961-4074-9731-aaac5108f1a4","isHoverDragHandle":false},"content":[{"type":"tableRow","content":[{"type":"tableHeader","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"5d6732e0-01ec-4a00-80b1-c9301066f5dc","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Agent 概念"}]}]},{"type":"tableHeader","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"b38ecb0e-e40a-4af9-ace3-5da8af555664","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"后端映射"}]}]},{"type":"tableHeader","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"f9632a0d-47c0-482e-91ce-d9a5b988dd45","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"备注"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"6703fdc9-910b-4029-a5e1-e3d1d04f326b","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Prompt 组装"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"d63ef8bb-e7b1-4991-a542-0226ecb612c1","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Servlet Filter Chain"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"f0725d16-c521-4e2c-a430-021ef6029292","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"每层 Filter 加料:安全上下文、工具 schema、记忆"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"702105f3-ee6b-40f9-bf69-3164bfc4052e","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"LLM 推理"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"cfd45323-d2a4-430f-91c4-01d8b17bbe70","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"远程 RPC 调用"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"8dd45b88-cc9e-4a8e-816e-385cd4778237","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"需要超时、重试、熔断、流式处理"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"835a89bf-3ddf-4f97-b693-0ef518ffccb1","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"输出分类"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"23b32a10-d0a2-4c59-aeb8-d9db744d1a1c","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"消息路由/分发器"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"6c386ae7-71fa-4522-b7db-2977c550ac90","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"根据消息类型分发到不同处理器"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"7ece2626-e1ca-431d-ac76-eda9a982d187","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"工具执行"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"22868335-9962-4d44-aaa3-e65a62ab401a","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Service 层方法 AOP 拦截"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"4fd22551-f25c-47ca-9393-dfb23b22881b","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"参数校验、权限检查、异常捕获、日志记录"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"e04ba50b-5d75-4de7-ac32-b332292b14b3","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"结果打包"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"f4aef6f3-62e8-4d27-a833-69f49bd36a21","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"统一响应体封装"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"a226828b-2e1d-4e59-adb5-5290e7470f61","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"把工具结果格式化为 LLM 可读的 ToolMessage"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"5dabde12-4334-43aa-92b9-382ca6d7eb12","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"上下文更新"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"0f7a5a4f-c51f-4ff9-97ef-e48a5d243260","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"ThreadLocal 上下文传递"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"081a5e9a-87e3-40dd-928b-fb1220338642","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"每一步在同一个请求上下文里读写"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"2009c09f-1606-4e97-a24a-2df1cd013e5a","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"循环终止"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"9cd151a7-0edc-4191-9932-154feb2f1b5c","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"状态机终态判断"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"a6c73303-f675-42da-8cd3-c8194a7dd0b6","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"达到终态、最大步数、失败次数、用户中断"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"9a90872b-89bd-4d9b-b2d8-965ef5afd7dc","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Ralph Loop"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"b34a842f-31fc-4e7d-bea2-8ad1105bf0eb","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"带状态 Cron Job 条件门控"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"fccc858a-e5b6-4b1f-9f82-b8ebbce39e29","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"跨会话运行,失败时停止推进"}]}]}]}]},{"type":"paragraph","attrs":{"id":"36d384b9-cc45-4bd9-9da3-df7da39462db","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"这个映射不是生搬硬套。它提醒我们:Agent 系统虽然新,但底层的工程问题——"},{"type":"text","marks":[{"type":"bold"}],"text":"并发、超时、异常、状态、上下文、可观测性"},{"type":"text","text":"——和后端系统一模一样。"}]},{"type":"horizontalRule","attrs":{"id":"81ed3dce-98da-42b7-a65d-951e5944fa90","isHoverDragHandle":false}},{"type":"heading","attrs":{"id":"0967e587-da8c-4613-a52c-64e9a9370eb4","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"七、代码实战:最小化 Agent Loop(Python)"}]},{"type":"paragraph","attrs":{"id":"33276e9f-57b5-437b-a19f-dfba1337b6a2","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"下面是一个能直接跑通的 100 行左右 Python 示例。它模拟了一个 LLM,支持「思考 → 调用工具 → 观察 → 继续或终止」的完整循环。"}]},{"type":"codeBlock","attrs":{"id":"c06aeeec-6b59-4c8f-9cf3-dfc32f24e9e2","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":""},"content":[{"type":"text","text":"import jsonnimport renn# ======================== 工具注册表 ========================nndef get_weather(city: str, date: str = "今天") -> str:n"""模拟天气查询工具"""nreturn f"{city}{date}天气:18~24℃,多云,微风。"nnndef recommend_clothing(temperature: str, weather: str, wind: str) -> str:n"""模拟穿搭推荐工具"""nreturn f"根据{temperature}、{weather}、{wind},推荐:薄针织开衫 九分裤 休闲鞋。"nnnTOOL_REGISTRY = {n"get_weather": get_weather,n"recommend_clothing": recommend_clothing,n}nnn# ======================== 工具 schema 描述 ========================nnTOOLS_SCHEMA = """n可用工具:n1. get_weather(city: str, date: str = "今天") -> 返回城市天气n2. recommend_clothing(temperature: str, weather: str, wind: str) -> 返回穿搭建议nn请按以下格式输出你的决策:n- 如果需要调用工具:THINK: 你的推理过程。ACTION: 工具名。参数:{"key": "value"}n- 如果可以直接回答:THINK: 你的推理过程。ANSWER: 最终答案n"""nnn# ======================== 模拟 LLM 推理 ========================nndef mock_llm(messages, history_len):n"""用一个简单的规则模拟 LLM 的推理和工具调用。n真实系统这里应调用 OpenAI/Claude/本地模型 API。n"""nlast_user = Nonenfor m in reversed(messages):nif m["role"] == "user":nlast_user = m["content"]nbreaknn# 第一轮:没有天气信息,调用 get_weathernif history_len == 0:nreturn {n"think": "用户需要天气和穿搭。我应先查天气。",n"action": "get_weather",n"arguments": {"city": "上海", "date": "明天"},n}nn# 第二轮:已有天气信息,调用 recommend_clothingnif history_len == 2:nreturn {n"think": "已拿到天气信息,现在调用穿搭推荐工具。",n"action": "recommend_clothing",n"arguments": {n"temperature": "22℃",n"weather": "多云",n"wind": "微风",n},n}nn# 第三轮:直接回答nreturn {n"think": "已拿到天气和穿搭,可以给出最终答案。",n"answer": "上海明天 18~24℃ 多云有微风,建议穿薄针织开衫 九分裤 休闲鞋。",n}nnn# ======================== Prompt 组装 ========================nndef build_prompt(system_prompt, tools_schema, history, query):n"""把系统提示、工具 schema、历史对话、用户输入组装成消息列表。"""nmessages = [n{"role": "system", "content": system_prompt},n{"role": "system", "content": tools_schema},n]nmessages.extend(history)nmessages.append({"role": "user", "content": query})nreturn messagesnnn# ======================== 输出解析 ========================nndef parse_llm_output(output):n"""解析模拟 LLM 的输出,判断是工具调用还是最终答案。"""nif "answer" in output:nreturn "answer", output.get("answer")nif "action" in output:nreturn "tool_call", outputnreturn "unknown", Nonennn# ======================== 工具执行 ========================nndef execute_tool(action, arguments):n"""执行工具调用,用 try-catch 包裹,返回 Observation。"""ntool = TOOL_REGISTRY.get(action)nif not tool:nreturn f"错误:未找到工具 {action}"ntry:nreturn tool(**arguments)nexcept Exception as e:nreturn f"工具执行失败:{type(e).__name__}: {e}"nnn# ======================== Agent 主循环 ========================nndef agent_loop(query, max_steps=5):n"""Agent 的 Think-Action-Observe 循环。"""nsystem_prompt = "你是一个 helpful 的助手,会根据用户需求调用工具。"nhistory = []nnfor step in range(max_steps):nprint(f"n=== Step {step 1} ===")nn# Step 1: 组装 Promptnmessages = build_prompt(system_prompt, TOOLS_SCHEMA, history, query)nn# Step 2: LLM 推理nllm_output = mock_llm(messages, len(history))nprint(f"THINK: {llm_output.get('think', '')}")nn# Step 3: 输出分类ncategory, payload = parse_llm_output(llm_output)nnif category == "answer":n# 终止循环nprint(f"ANSWER: {payload}")nreturn payloadnnif category == "tool_call":naction = payload["action"]narguments = payload["arguments"]nprint(f"ACTION: {action}({arguments})")nn# Step 4: 工具执行nobservation = execute_tool(action, arguments)nprint(f"OBSERVATION: {observation}")nn# Step 5 & 6: 结果打包并更新上下文nhistory.append({"role": "assistant", "content": json.dumps(payload, ensure_ascii=False)})nhistory.append({"role": "tool", "content": observation})nnelse:nprint("未知输出类型,终止循环")nreturn Nonennprint("达到最大步数,终止循环")nreturn Nonennn# ======================== 运行 ========================nnif __name__ == "__main__":nresult = agent_loop("我明天要去上海出差,帮我查一下天气,再推荐一套穿搭。")nprint(f"n最终结果: {result}")"}]},{"type":"paragraph","attrs":{"id":"89d5503d-4ed8-4efc-b7d7-39ce3ef32422","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"运行结果:"}]},{"type":"codeBlock","attrs":{"id":"2c559715-f8c9-4716-b41b-ff61d7da60dc","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":""},"content":[{"type":"text","text":"=== Step 1 ===nTHINK: 用户需要天气和穿搭。我应先查天气。nACTION: get_weather({'city': '上海', 'date': '明天'})nOBSERVATION: 上海明天天气:18~24℃,多云,微风。nn=== Step 2 ===nTHINK: 已拿到天气信息,现在调用穿搭推荐工具。nACTION: recommend_clothing({'temperature': '22℃', 'weather': '多云', 'wind': '微风'})nOBSERVATION: 根据22℃、多云、微风,推荐:薄针织开衫 九分裤 休闲鞋。nn=== Step 3 ===nTHINK: 已拿到天气和穿搭,可以给出最终答案。nANSWER: 上海明天 18~24℃ 多云有微风,建议穿薄针织开衫 九分裤 休闲鞋。nn最终结果: 上海明天 18~24℃ 多云有微风,建议穿薄针织开衫 九分裤 休闲鞋。"}]},{"type":"paragraph","attrs":{"id":"5879c73b-d5c3-4397-a606-50e6048e1f18","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"这个例子虽然用了一个 mock LLM,但骨架是真实的:Prompt 组装、工具执行、上下文更新、循环终止,一个都不少。把 "},{"type":"text","marks":[{"type":"code"}],"text":"mock_llm"},{"type":"text","text":" 替换成真正的 OpenAI/Claude API 调用,就是一个生产可用的最小 Agent。"}]},{"type":"horizontalRule","attrs":{"id":"6cfb0bcf-fcf5-4e9f-8f59-c6043e203aea","isHoverDragHandle":false}},{"type":"heading","attrs":{"id":"3a60c502-74b2-4e9f-9216-f65297671bff","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"八、总结:Harness 不是「壳」,是「循环的导演」"}]},{"type":"paragraph","attrs":{"id":"825e1ad7-7556-4a7e-9708-60bd5e5c55da","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"回到文章开头的问题:Harness 在循环中扮演什么角色?"}]},{"type":"paragraph","attrs":{"id":"63aeaec8-0d85-447a-9e93-65d94dcb30e7","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"它不是简单的包装壳,而是整个循环的导演:"}]},{"type":"bulletList","attrs":{"id":"663f85f3-f701-45d0-a541-6f4d93685328","isHoverDragHandle":false},"content":[{"type":"listItem","attrs":{"id":"178593c3-1b61-4d6b-af57-c190eae3ae2e"},"content":[{"type":"paragraph","attrs":{"id":"346df925-78c0-4557-9104-2be9eb35bfe9","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"组织舞台"},{"type":"text","text":":把 Prompt、工具、记忆、历史拼装成模型能理解的输入;"}]}]},{"type":"listItem","attrs":{"id":"c06c9a27-d1b3-497e-80bf-af6a936bcaa9"},"content":[{"type":"paragraph","attrs":{"id":"21a04cc9-2877-451a-abbc-f080cb3b806a","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"调度演员"},{"type":"text","text":":让 LLM 上场推理,然后按输出把任务分发给工具;"}]}]},{"type":"listItem","attrs":{"id":"9ca278c5-a5e0-4347-8000-baf96a36b8bd"},"content":[{"type":"paragraph","attrs":{"id":"6ab2f590-3678-4a00-a876-726a554899ed","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"实时反馈"},{"type":"text","text":":把工具结果回收、格式化,再送回给模型;"}]}]},{"type":"listItem","attrs":{"id":"b0ea358f-29fc-4d33-ab74-b7f3d4c303f9"},"content":[{"type":"paragraph","attrs":{"id":"8bb1b4a0-588f-4ba5-a36d-0d8056fef934","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"控制节奏"},{"type":"text","text":":决定什么时候继续、什么时候终止、什么时候 handoff;"}]}]},{"type":"listItem","attrs":{"id":"e9533b99-18a8-4a01-b116-dfb57962198b"},"content":[{"type":"paragraph","attrs":{"id":"ae2ddce3-5551-47dc-b6f8-e2a9363cd8bb","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"兜底保障"},{"type":"text","text":":参数校验、权限检查、异常捕获、最大步数限制。"}]}]}]},{"type":"paragraph","attrs":{"id":"46bb913f-b666-4e79-a2a0-9f22050e836a","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"优秀的 Harness 既不能让模型觉得束手束脚(Dumb Loop 的价值),也不能完全放任自流( Thick Harness 的必要性)。"}]},{"type":"paragraph","attrs":{"id":"a969e639-ab2e-4e73-a1e4-5403d36a72c3","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"理解了这一点,你就不会再把 Agent 看作「一个会调 API 的大模型」,而是会把它看作一个"},{"type":"text","marks":[{"type":"bold"}],"text":"由模型驱动的、带状态反馈的循环控制系统"},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"id":"f2224d8d-8230-45fe-9a63-87e3d23c4c14","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"下一篇,我们会继续深入:当 Agent 需要调用多个工具、走错路还要回退时, Harness 又该如何设计状态机和错误恢复机制?"}]},{"type":"horizontalRule","attrs":{"id":"cd8930ad-7ef5-47a1-b018-bfe6c1222e01","isHoverDragHandle":false}},{"type":"paragraph","attrs":{"id":"a251640a-045a-44c2-802d-bec47eb2d6c7","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false}},{"type":"paragraph","attrs":{"id":"56bf2aa9-0042-4f74-a991-e5b2c08679f8","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false}},{"type":"blockquote","attrs":{"id":"f39106cc-f0f9-4420-ad21-d5645ff1673e","textAlign":"inherit","isHoverDragHandle":false},"content":[{"type":"paragraph","attrs":{"id":"7808d3ba-ef1d-4513-a1d0-e4eadeb0ade8","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"本文是「Agent 架构师」系列第 3 篇。如需转载或讨论,欢迎留言。"}]}]},{"type":"paragraph","attrs":{"id":"3649364d-4124-4499-8833-fcc04f9a3e80","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false}}]}","createTime":1782651991,"ext":{"closeTextLink":0,"comment_ban":0,"description":"","focusRead":0},"favNum":1,"html":"","isOriginal":0,"likeNum":1,
点击查看更多
推荐专题
热门阅读