track_crewai 集成深度解析:Opik 如何追踪 CrewAI 的多智能体工作流
2026/9/13 15:12:44 网站建设 项目流程

track_crewai 集成深度解析:Opik 如何追踪 CrewAI 的多智能体工作流

【免费下载链接】comet-llmDebug, evaluate, and monitor your LLM applications, RAG systems, and agentic workflows with comprehensive tracing, automated evaluations, and production-ready dashboards.项目地址: https://gitcode.com/GitHub_Trending/co/comet-llm

本文以opik.integrations.crewai.track_crewai这一集成入口为核心,完整讲解如何在 Opik(Comet 团队的 LLM 可观测平台)中追踪 CrewAI 的多智能体活动:包括 API 签名与参数含义、一次调用背后实际打补丁(monkey-patch)了哪些 CrewAI 方法、每个 span 会记录哪些 input/output 字段,以及针对 CrewAI v1.0.0+ 的 Flow 与 LLM 客户端追踪机制。读完后,你可以直接在生产代码中启用 CrewAI 追踪,并能从源码层面解释平台上看到的 span 结构与 token 数据来源。

1. track_crewai 是什么:API 签名与参数语义

CrewAI 集成文档页 track_crewai.rst 通过 Sphinx 的autofunction指令直接渲染 opik_tracker.py 中track_crewai的 docstring,因此官方文档与源码保持逐字一致。该函数的完整签名为:

def track_crewai( project_name: Optional[str] = None, crew: Optional[crewai.Crew] = None, ) -> None: """ Tracks CrewAI activities by enabling tracking decorators for various critical methods. The function applies tracking decorators to key CrewAI components and methods, enabling logging or monitoring of activities. Tracking is enabled globally and can only be initialized once. If you use this tracker - please avoid using of OpenAI tracker to prevent duplicate logging of LLM calls and token usage. Parameters: project_name: The name of the project to associate with the tracking. crew: The Crew instance to track. Required for CrewAI v1.0.0+ to properly track LLM calls. """

两个参数的语义要点:

参数类型说明
project_nameOptional[str]追踪数据归属的 Opik 项目名;为None时使用默认项目。
crewOptional[crewai.Crew]要追踪的Crew实例。在 CrewAI v1.0.0+ 中必须传入,否则无法正确追踪底层的 LLM 调用(见第 5 节)。

docstring 同时强调了两个关键约束,在接入前务必理解:

  • 全局生效、仅可初始化一次:"Tracking is enabled globally and can only be initialized once"。该函数通过替换 CrewAI 类的方法实现,是进程级全局副作用,重复调用没有意义。
  • 避免与 OpenAI tracker 同时使用:"please avoid using of OpenAI tracker to prevent duplicate logging of LLM calls and token usage"。因为 CrewAI 集成本身已经接管了 LLM 调用层的埋点,再叠加opik.integrations.openai会导致同一次 LLM 调用被记录两次(token 用量重复计入成本统计)。

track_crewai仅由模块的__init__.py导出(见init.py 中__all__ = ["track_crewai"]),因此标准导入方式为:

from opik.integrations.crewai import track_crewai

2. 快速上手:完整可运行的接入示例

CrewAI 集成索引页 index.rst 给出了官方的最小接入示例:在应用入口调用一次track_crewai(project_name=...),随后按正常方式构建并运行Crew,所有活动即自动上报 Opik。完整示例如下:

from opik.integrations.crewai import track_crewai from crewai import Agent, Crew, Task, Process class YourCrewName: def agent_one(self) -> Agent: return Agent( role="Data Analyst", goal="Analyze data trends in the market", backstory="An experienced data analyst with a background in economics", verbose=True, ) def agent_two(self) -> Agent: return Agent( role="Market Researcher", goal="Gather information on market dynamics", backstory="A diligent researcher with a keen eye for detail", verbose=True ) def task_one(self) -> Task: return Task( name="Collect Data Task", description="Collect recent market data and identify trends.", expected_output="A report summarizing key trends in the market.", agent=self.agent_one() ) def task_two(self) -> Task: return Task( name="Market Research Task", description="Research factors affecting market dynamics.", expected_output="An analysis of factors influencing the market.", agent=self.agent_two() ) def crew(self) -> Crew: return Crew( agents=[self.agent_one(), self.agent_two()], tasks=[self.task_one(), self.task_two()], process=Process.sequential, verbose=True ) track_crewai(project_name="crewai-integration-demo") my_crew = YourCrewName().crew() result = my_crew.kickoff() print(result)

使用前提是已配置好 Opik 的连接(API key / 服务地址)与对应 LLM 提供商的 key(如OPENAI_API_KEY)。示例中track_crewaikickoff()之前调用;由于它是全局补丁,放在应用启动阶段(任何 Crew 执行之前)即可。

3. 一次 track_crewai 调用背后打了哪些补丁

理解集成的关键在于:track_crewai并不是装饰某个固定函数,而是对 CrewAI 库的类与方法做运行时替换。在 opik_tracker.py 中,一次调用按顺序完成以下动作:

analytics.track_event("integration", "crewai") # 上报集成使用事件 decorator_factory = crewai_decorator.CrewAITrackDecorator() crewai_wrapper = decorator_factory.track(project_name=project_name) # ① 核心三类对象的四个方法被替换为带追踪的包装 crewai.Crew.kickoff = crewai_wrapper(crewai.Crew.kickoff) crewai.Crew.kickoff_for_each = crewai_wrapper(crewai.Crew.kickoff_for_each) crewai.Agent.execute_task = crewai_wrapper(crewai.Agent.execute_task) crewai.Task.execute_sync = crewai_wrapper(crewai.Task.execute_sync) # ② 补丁 LiteLLM(CrewAI v0.x 的底层 LLM 通道) patchers.patch_litellm_completion(project_name=project_name) # ③ 补丁 Flow 类(v1.0.0+ 才有) patchers.patch_flow(project_name=project_name) # ④ 补丁 Agent 持有的 LLM 客户端(v1.0.0+,且必须传入 crew) if crew is not None and is_crewai_v1(): patchers.patch_llm_client(crew, project_name)

逐项说明:

  • ① 结构层追踪(Crew / Agent / Task)Crew.kickoffCrew.kickoff_for_eachAgent.execute_taskTask.execute_sync四个方法被CrewAITrackDecoratortrack装饰器包装。这对应 CrewAI 工作流的三层结构——Crew 执行、Agent 执行任务、Task 同步执行——在 Opik 上会形成嵌套的 span 树。注意kickoff_for_each(批量执行多组输入)同样被覆盖,因此批量任务也会逐组生成追踪。
  • ② LiteLLM 层追踪:patchers/litellm_completion.py 将litellm.completionlitellm.acompletion分别替换为opik.integrations.litellm.track_completion(project_name=...)的包装版本。CrewAI v0.x 内部经由 LiteLLM 发起 LLM 请求,因此这两个补丁保证了 v0.x 下 LLM 调用(含模型、token 用量)也能进入 Opik。
  • ③ Flow 追踪(v1.0.0+):见第 5 节。
  • ④ LLM 客户端追踪(v1.0.0+):见第 5 节。

此外,函数体开头会调用analytics.track_event("integration", "crewai")记录一次集成使用事件,属于遥测性质,不影响追踪数据本身。

4. Span 的数据采集规则:记录什么、叫什么名字

span 的字段装配逻辑集中在 crewai_decorator.py 中的CrewAITrackDecorator(继承自 Opik 通用BaseTrackDecorator,见 base_track_decorator 体系)。

4.1 开始 span 时(_start_span_inputs_preprocessor)

每个被追踪方法开始执行时,都会创建一个type="general"的 span,统一打上:

  • metadata["created_from"] = "crewai"—— 标识数据来源框架;
  • tags = ["crewai"]—— 便于在 Opik 前端按 tag 过滤;
  • 按方法名区分的metadata["object_type"]与差异化 input:
被追踪方法object_typespan 名称input 内容
Crew.kickoff/kickoff_for_eachcrew函数原名(kickoffkickoff(inputs=...)传入的inputs字典
Agent.execute_taskagentAgent 的role(如"Data Analyst"{"context": ..., "agent": {backstory, goal, role, tools}}
Task.execute_synctaskTask: {task.name}(如"Task: Collect Data Task"{"task": {config, context, description, expected_output, name, prompt_context, tools}}

其中 Agent / Task 的 input 并非把整个对象序列化,而是由白名单过滤——crewai_decorator.py 定义了三组常量,经jsonable_encoder.encode+dict_utils.split_dict_by_keys(见_encode_dict_and_keep_keys,crewai_decorator.py)保留指定键:

  • AGENT_KWARGS_KEYS_TO_LOG_AS_INPUTSbackstorygoalroletoolsllmmax_itercache等其余参数被有意排除,避免把不可 JSON 化或敏感的内部字段写入 span);
  • TASK_KWARGS_KEYS_TO_LOG_AS_INPUTSconfigcontextdescriptionexpected_outputnameprompt_contexttools
  • TASK_KWARGS_KEYS_TO_LOG_AS_OUTPUTnamerawsummary

这种白名单设计意味着:调整 span 中记录哪些字段,只需要改这三组常量列表,而不必动埋点流程。

4.2 结束 span 时(_end_span_inputs_preprocessor)

输出侧同样按object_type分流(crewai_decorator.py):

  • crew:对整个输出(CrewOutput)做jsonable_encoder.encode,并output_dict.pop("token_usage", None)—— 从 crew 级 span 的 output 中剥离 token 用量。因为 token 数据会由 LLM 层(LiteLLM / provider 客户端)以规范的 usage 字段单独记录,避免在结构 span 里重复冗余;
  • agent:输出统一包装为{"output": output}
  • task:仅按白名单保留namerawsummary三个字段。

另外,object_type键在结束 span 时通过metadata.pop("object_type")从 metadata 中取出使用,不会残留到最终上报的 metadata 里。

从 span 层级上看:kickoff作为本次运行的根 span,Agent.execute_taskTask.execute_sync嵌套其下,LLM 调用 span 又嵌套在 agent 执行之下(由第 3 节 ②/④ 的补丁保证),从而在 Opik 前端呈现一棵完整的执行树。

5. CrewAI v1.0.0+ 的增强机制:版本探测、Flow 与 LLM 客户端

CrewAI v1.0.0 重构了 LLM 抽象,不再一律走 LiteLLM,因此集成提供了版本感知的增强路径。

5.1 版本探测

is_crewai_v1() 通过importlib.metadata.version("crewai")读取已安装版本,并用opik.semantic_version.SemanticVersion.parse(version) >= "1.0.0"判断;读取失败(如元数据缺失)时静默返回False,退化到 v0.x 的埋点路径。这也解释了 docstring 中 "crew: Required for CrewAI v1.0.0+ to properly track LLM calls" 的由来——v1 下 LLM 调用追踪依赖patch_llm_client,而它的输入正是这个crew实例。

5.2 Flow 补丁(patchers/flow.py)

CrewAI v1.0.0+ 引入的Flow类(状态机式编排)在 patchers/flow.py 中被打了两处补丁,均有幂等保护(_patched标记)与"类不存在则跳过"的容错(CrewAI 旧版本下crewai.Flow不存在,直接return并打 debug 日志):

  1. Flow.__init__包装:在 Flow 构造完成后,遍历其注册的方法字典self._methods,对每个尚未标记opik_tracked的方法动态套用opik_tracker.track(project_name=..., tags=["crewai"], metadata={"created_from": "crewai"})。也就是说,用户在 Flow 中声明的每个@start/@listen/@router方法都会自动成为独立 span,无需逐个手动装饰;重复 patch 由opik_tracked属性短路。
  2. Flow.kickoff_async包装:用一个名为"Flow.kickoff_async"的 span 包裹异步入口。代码注释解释了为什么只包异步版本:"the sync version calls it internally"——同步kickoff内部会调用kickoff_async,包一处即可避免重复 span。

5.3 LLM 客户端补丁(patchers/llm_client.py)

patch_llm_client(crew, project_name) 遍历crew.agents,对每个agent.llm做 provider 探测与替换:

provider 探测目标复用的 Opik 集成
OpenAICompletionopik.integrations.openai.track_openai
AnthropicCompletionopik.integrations.anthropic.track_anthropic
GeminiCompletionopik.integrations.genai.track_genai
BedrockCompletionopik.integrations.bedrock.track_bedrock

实现细节值得注意的两点:

  • 探测本身是防御式的:每个_is_*_llm函数在对应 provider 模块ImportError时返回False_patch_*_client整体再包一层try/except并仅LOGGER.warning——某个 provider 库缺失或 patch 失败不会中断应用运行
  • 客户端属性名有版本兼容处理:_get_client_attribute_name注释说明 "CrewAI >= 1.13.0 converted LLM classes to Pydantic BaseModel, moving the SDK client from a publicclientattribute to a Pydantic PrivateAttr_client",因此会先探测_client、不存在再取client(llm_client.py)。patch 完成后,用 provider 集成返回的patched_client回写到 LLM 实例,之后 Agent 发起的所有补全请求(模型名、usage、token 成本)都会由对应 provider 集成规范记录。

5.4 v0.x 与 v1.x 的埋点差异小结

从源码结构看,两条 LLM 追踪路径是并行的:v0.x 依赖 ②(LiteLLM 补丁),v1.x 依赖 ④(provider 客户端补丁);①(结构层)与 ③(Flow,可选)对所有版本生效。因此在 v1.0.0+ 环境中调用track_crewai(project_name=...)而不传crew时,Crew/Agent/Task 层级 span 仍然生成,但 LLM 调用 span 会缺失——这正是 docstring 把crew标注为 v1 "Required ... to properly track LLM calls" 的原因。

6. 使用注意事项与常见问题

  1. 只调用一次,且尽早调用。补丁作用于类定义(crewai.Crew.kickoff等),必须在任何kickoff/ Flow 实例化之前执行;Flow 的方法装饰发生在Flow.__init__内,晚于track_crewai创建的 Flow 才能被追踪。
  2. 不要叠加 OpenAI 集成。CrewAI 场景下 LLM 层已被本集成接管(v0.x 走 LiteLLM 补丁、v1.x 走 provider 客户端补丁),再启用opik.integrations.openai会对同一请求产生双重 span 与双重 token 统计。
  3. v1.0.0+ 请传入 crew 实例track_crewai(project_name="my-project", crew=my_crew)
  4. span 命名规则决定了前端展示:Agent span 直接以role命名、Task span 以Task: {name}命名(见 4.1 节)。如果你希望前端出现更可读的名称,应从 CrewAI 侧的role/task.name入手,而非在 Opik 侧重命名。
  5. 输入/输出字段范围由白名单控制:若需要在 span 中补充 CrewAI 对象的其他字段(例如max_iteroutput_file),修改方向是扩展 crewai_decorator.py 中的三组键列表——但这是 SDK 源码层改动,实际项目中通常通过metadata或自定义 span 补充信息。

7. 测试与进一步阅读

仓库内为 CrewAI 集成配套了三层集成测试,可用作"期望行为"的权威参照:

  • test_crewai.py —— 基础 Crew/Agent/Task 追踪;
  • test_crewai_flows.py —— Flow 场景的 span 结构验证;
  • test_crewai_built_from_config.py —— 通过配置(YAML/config)方式构建 Crew 的追踪路径。

其他值得深入的关键文件:

  • 入口与版本探测:sdks/python/src/opik/integrations/crewai/opik_tracker.py
  • Span 字段装配与白名单:sdks/python/src/opik/integrations/crewai/crewai_decorator.py
  • 通用 track 装饰器参数结构(TrackOptions/StartSpanParameters):sdks/python/src/opik/decorator/arguments_helpers.py
  • 官方文档页(本文主体来源):track_crewai.rst 与 index.rst

8. 小结

track_crewai(project_name, crew)是 Opik 对 CrewAI 的一站式追踪入口:一次调用同时完成结构层(Crew/Agent/Task 四个核心方法)、LLM 层(LiteLLM 或四大 provider 客户端)与 Flow 层(v1.0.0+)的运行时补丁;span 的命名、input/output 字段由明确的白名单常量控制,token 用量则剥离到 LLM 层统一记录。把握"全局一次性初始化、v1 必传 crew、勿叠加 OpenAI 集成"这三条约束,并对照第 4 节的字段规则理解平台上的 span 树,即可把 CrewAI 多智能体应用的可观测性完整接入 Opik。

【免费下载链接】comet-llmDebug, evaluate, and monitor your LLM applications, RAG systems, and agentic workflows with comprehensive tracing, automated evaluations, and production-ready dashboards.项目地址: https://gitcode.com/GitHub_Trending/co/comet-llm

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询