跳到主要内容

crewai — 本课题摘录

读了哪几篇: 01-agent-loop(Agent 执行循环)。 其余三篇(Crew 编排、Flow 引擎、横切设施)本轮没读——属多 agent 与工作流课题。

这一家在本课题里的位置:它是"怎么认出模型要调工具"这一问的双轨方案代表。

它对本课题回答了什么

决定二:怎么认出模型要调工具 —— 两条路,开循环前二选一

路径模型怎么表达"我要调工具"什么时候走这条
原生工具调用直接返回结构化的调用对象模型声明自己支持,且确实挂了工具
文本 ReAct输出 Thought: … / Action: … / Action Input: … 纯文本,框架正则解析模型不支持,或原生调用被拒绝时降级

(依据:前沿库 · CrewAI · Agent 执行循环 —— 开循环前按 supports_function_calling 且有工具二选一,走 _invoke_loop_native_tools 或 _invoke_loop_react)

决定二的关键:运行时降级,而不是启动时判断

这是最值得抄的一条。 模型声称支持不等于真支持——网关可能不支持、模型版本可能变。它的做法是:

选了原生路径 → 真跑起来报「不支持原生工具调用」的错


往历史里塞一句「请改用文本格式调工具」的说明


当场切回文本 ReAct,这次执行不失败

(依据:前沿库 · CrewAI · Agent 执行循环 —— 原生路径捕获到 is_native_tool_calling_unsupported_error 时,先往历史追加「请用文本格式调工具」的说明,再改走 _invoke_loop_react,不让整次执行失败)

这条对我们直接有用。 换厂商这件事本课题不管,但"同一个模型在运行时才暴露出不支持某个能力"是循环必须处理的——它给的答案是能力探测放在运行时、降级路径事先备好

决定二补充:文本协议的解析要能容忍半残的 JSON

文本路径下,工具输入是模型手写的 JSON,经常是半残的。它先过一道自动修复。 (依据:前沿库 · CrewAI · Agent 执行循环 —— 文本 ReAct 路径下工具输入先过 _safe_repair_json 用 json_repair 容错修复,因为 LLM 经常吐出半残 JSON)

既没有动作也没有最终答案时,抛解析错误,循环捕获后把格式说明喂回让模型重试——又一次"报错即教学"。

停用词是文本路径的配套件: ReAct 靠 Observation 这类停用词截断模型输出,免得模型自己把观测也编出来。用不用取决于模型支不支持停用词。 (依据:前沿库 · CrewAI · Agent 执行循环 —— ReAct 模式靠 Observation 之类停用词截断输出,是否使用取决于模型 supports_stop_words())

跟 smolagents 的"把代码闭合标签加进停止序列"是同一招:让模型在该停的地方停,而不是让它把系统该说的话也编出来。

决定三:结果怎么回填 —— 原生路径每轮只执行第一个调用

一个明确的取舍:即使模型一次返回多个工具调用,也只执行第一个,然后让模型看着结果再想。 (依据:前沿库 · CrewAI · Agent 执行循环 —— _handle_native_tool_calls 每轮只执行第一个 tool call,注释说明这是为了「每个工具后都能反思」,让 LLM 基于结果再决定下一步)

执行完还会主动塞一条"请基于刚才的结果继续推理"的提示再进下一轮。

这跟 vercel-ai-sdk / openai-agents-js 的"并行执行这一轮的所有调用"是直接对立的选择。 对立点在于:并行省时间,串行 + 反思省错误。这是本课题一个要自己拍板的地方。

决定四:什么时候停 —— 三个兜底 + 一条硬契约

情况处理
迭代超过上限强制收尾,逼出一个"最终答案"
上下文长度超限裁剪历史后继续重试
解析失败把格式说明喂回让模型改正

(依据:前沿库 · CrewAI · Agent 执行循环 —— 三处保护分别是 handle_max_iterations_exceeded 强制收尾、respect_context_window 时 handle_context_length 裁剪后 continue、handle_output_parser_exception 把格式说明喂回)

硬契约:循环只在拿到"最终答案"时退出;否则末尾直接抛错说"没能给出最终答案"。

这一条比 cline 的"抛错兜底"更明确:它不允许循环悄悄结束——要么有答案,要么明确失败。

它的做法(可以抄的部分)

工具执行前后各留一个钩子,钩子返回"假"可以直接拦掉这次工具调用。 结果还可以进缓存。 (依据:前沿库 · CrewAI · Agent 执行循环 —— 工具执行前后跑 before/after_tool_call 钩子,钩子返回 False 可拦截工具调用,结果可进 tools_handler.cache)

它没回答什么

  • 历史怎么压——只说"裁剪历史后重试",没讲怎么裁。要看 headroomopencodedexter
  • 工具清单怎么给——工具是固定挂上去的,没有每轮变化的机制。看 beeai-frameworkdeepagents
  • 状态怎么存、崩了怎么续——没有这一层。看 openai-agents-jsriglanggraph

坑与代价

  • 这一章讲的执行器已经被标为弃用。 新默认执行器逻辑同构,但它本身继承自框架的流程图引擎——"Agent 的多步循环"被重新表达成一张事件驱动的流程图。 (依据:前沿库 · CrewAI · Agent 执行循环 —— CrewAgentExecutor 构造时发 DeprecationWarning,新默认执行器 AgentExecutor 继承自 Flow,把 Agent 多步循环表达成事件驱动流程图)

    判断(无锚): 我们读的是旧执行器,因为它的循环最直白。但要记住业界有把循环重写成图的倾向(LangGraph、CrewAI 新执行器都是)。 如果错,会错在: 如果我们的原型很快就需要"人在中途插手 + 崩了续跑",裸 while 会很快撑不住,那时图式引擎的价值就出来了。

  • 文本 ReAct 这条路把解析成本转移给了自己。 半残 JSON、缺 Action、编出观测,每一种都要单独兜。原生路径没有这些问题,但挑模型。