From c7bbd6137a53ad624414d64e307a90915da48ece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=8E=E7=9B=B4?= Date: Mon, 15 Dec 2025 16:34:52 +0800 Subject: [PATCH 01/14] Add OpenTelemetry instrumentation for CrewAI --- .../loongsuite-instrumentation-crewai/LICENSE | 201 ++++++++ .../README.md | 51 ++ .../pyproject.toml | 55 +++ .../instrumentation/crewai/__init__.py | 454 ++++++++++++++++++ .../instrumentation/crewai/package.py | 18 + .../instrumentation/crewai/version.py | 16 + .../test-requirements.txt | 9 + .../tests/__init__.py | 0 .../tests/test_agent_workflow.py | 302 ++++++++++++ .../tests/test_error_scenarios.py | 293 +++++++++++ .../tests/test_flow_kickoff.py | 395 +++++++++++++++ .../tests/test_prompt_and_memory.py | 298 ++++++++++++ .../tests/test_streaming_llm_calls.py | 202 ++++++++ .../tests/test_sync_llm_calls.py | 254 ++++++++++ .../tests/test_tool_calls.py | 270 +++++++++++ 15 files changed, 2818 insertions(+) create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/LICENSE create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/README.md create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/package.py create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/version.py create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/__init__.py create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_agent_workflow.py create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_error_scenarios.py create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_flow_kickoff.py create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_prompt_and_memory.py create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_streaming_llm_calls.py create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_sync_llm_calls.py create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/LICENSE b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/README.md b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/README.md new file mode 100644 index 000000000..ca0457763 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/README.md @@ -0,0 +1,51 @@ +# OpenTelemetry CrewAI Instrumentation + +This library provides automatic instrumentation for [CrewAI](https://www.crewai.com/), a framework for orchestrating role-playing, autonomous AI agents. + +## Installation + +```bash +pip install opentelemetry-instrumentation-crewai +``` + +## Usage + +```python +from opentelemetry.instrumentation.crewai import CrewAIInstrumentor + +# Instrument CrewAI +CrewAIInstrumentor().instrument() + +# Your CrewAI code here +from crewai import Agent, Task, Crew + +agent = Agent( + role='Data Analyst', + goal='Extract actionable insights', + backstory='Expert in data analysis', + verbose=True +) + +task = Task( + description='Analyze the latest AI trends', + agent=agent +) + +crew = Crew( + agents=[agent], + tasks=[task], + verbose=True +) + +result = crew.kickoff() +``` + +## Supported Versions + +- CrewAI >= 0.1.0 + +## References + +- [CrewAI Documentation](https://docs.crewai.com/) +- [OpenTelemetry Python Documentation](https://opentelemetry-python.readthedocs.io/) + diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml new file mode 100644 index 000000000..ec84ca96c --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml @@ -0,0 +1,55 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "opentelemetry-instrumentation-crewai" +dynamic = ["version"] +description = "OpenTelemetry CrewAI instrumentation" +readme = "README.md" +license = "Apache-2.0" +requires-python = ">=3.8" +authors = [ + { name = "OpenTelemetry Authors", email = "cncf-opentelemetry-contributors@lists.cncf.io" }, +] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", +] +dependencies = [ + "opentelemetry-api <= 1.35.0", + "wrapt >= 1.0.0, < 2.0.0", +] + +[project.optional-dependencies] +instruments = [ + "crewai >= 0.1.0", +] + +[project.entry-points.opentelemetry_instrumentor] +crewai = "opentelemetry.instrumentation.crewai:CrewAIInstrumentor" + +[project.urls] +Homepage = "https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-crewai" +Repository = "https://github.com/open-telemetry/opentelemetry-python-contrib" + +[tool.hatch.version] +path = "src/opentelemetry/instrumentation/crewai/version.py" + +[tool.hatch.build.targets.sdist] +include = [ + "/src", + "/tests", +] + +[tool.hatch.build.targets.wheel] +packages = ["src/opentelemetry"] + diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py new file mode 100644 index 000000000..77fa9e5dc --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py @@ -0,0 +1,454 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +OpenTelemetry CrewAI Instrumentation (Optimized) + +This module provides automatic instrumentation for CrewAI framework following +OpenTelemetry GenAI semantic conventions and ARMS best practices. + +Optimizations based on best-practice.mdc: +1. Uses hook_advice decorators for error protection +2. Uses semantic convention constants from aliyun-semantic-conventions +3. Separates ARMS-specific logic to extension file +4. Optimized for performance and memory safety +""" + +import json +import logging +import sys +import time +import threading +from typing import Any, Collection, Dict, Optional, List + +from opentelemetry.instrumentation.instrumentor import BaseInstrumentor +from opentelemetry.instrumentation.crewai.package import _instruments +from opentelemetry import trace as trace_api +from opentelemetry import context as context_api +from opentelemetry.trace import Status, StatusCode, SpanKind +from wrapt import wrap_function_wrapper + +# Import semantic conventions from aliyun-semantic-conventions (Rule 8) +from aliyun.semconv.trace_v2 import ( + CommonAttributes, + LLMAttributes, + ToolAttributes, + GenAiSpanKind, +) + +# Import gen_ai.system from legacy semantic conventions for compatibility +from aliyun.semconv.trace import SpanAttributes + +# Import hook_advice for error protection (Rule 3, 4) +from aliyun.sdk.extension.arms.self_monitor.self_monitor_decorator import hook_advice + +logger = logging.getLogger(__name__) + +# Maximum message size to avoid performance issues (Rule 5) +MAX_MESSAGE_SIZE = 10000 # characters + +# Context keys for tracking +_CREWAI_SPAN_KEY = context_api.create_key("crewai_span") +_CREWAI_START_TIME_KEY = context_api.create_key("crewai_start_time") +_CREWAI_LITELLM_RESPONSE_KEY = context_api.create_key("crewai_litellm_response") + +def _safe_json_dumps(obj: Any, default: str = "", max_size: int = MAX_MESSAGE_SIZE) -> str: + """ + Safely serialize object to JSON string with size limit. + + Optimizations: + - Size limit to avoid performance issues + - Fast path for simple types + """ + if obj is None: + return default + + # Fast path for simple types + if isinstance(obj, (str, int, float, bool)): + result = str(obj) + if len(result) > max_size: + return result[:max_size] + "...[truncated]" + return result + + try: + result = json.dumps(obj, ensure_ascii=False) + if len(result) > max_size: + return result[:max_size] + "...[truncated]" + return result + except Exception as e: + logger.debug(f"Failed to serialize to JSON: {e}") + fallback = str(obj) if obj else default + if len(fallback) > max_size: + return fallback[:max_size] + "...[truncated]" + return fallback + + +def _normalize_model_name(model_name: str) -> str: + """ + Normalize model name to avoid high cardinality in metrics (Rule 11). + + Maps specific model versions to general categories. + """ + if not model_name or model_name == "unknown": + return "unknown" + + # Normalize common model patterns + model_lower = model_name.lower() + + # OpenAI models + if "gpt-4" in model_lower: + return "gpt-4" + elif "gpt-3.5" in model_lower or "gpt-35" in model_lower: + return "gpt-3.5" + elif "gpt" in model_lower: + return "gpt" + + # Anthropic models + elif "claude" in model_lower: + return "claude" + + # Other common providers + elif "llama" in model_lower: + return "llama" + elif "mistral" in model_lower: + return "mistral" + elif "gemini" in model_lower: + return "gemini" + + # Default: return first part before version number + parts = model_name.split("-") + if len(parts) > 0: + return parts[0] + + return model_name[:50] # Limit length + + +class CrewAIInstrumentor(BaseInstrumentor): + """ + An instrumentor for CrewAI framework. + + Follows best practices: + - Uses wrapt for method wrapping (Rule 1) + - Uses hook_advice for error protection (Rule 3, 4) + - Uses semantic conventions from aliyun-semantic-conventions (Rule 8, 9) + - Lightweight implementation (Rule 5) + - No memory leaks (Rule 6) + """ + + def instrumentation_dependencies(self) -> Collection[str]: + return _instruments + + + def _instrument(self, **kwargs: Any) -> None: + """Instrument CrewAI framework.""" + tracer_provider = kwargs.get("tracer_provider") + tracer = trace_api.get_tracer( + __name__, + "", + tracer_provider=tracer_provider, + ) + + # Note: Metrics are handled by arms_crewai_extension.py (Rule 10) + # to separate ARMS-specific logic + + # Wrap Crew.kickoff (CHAIN span) + try: + wrap_function_wrapper( + module="crewai.crew", + name="Crew.kickoff", + wrapper=_CrewKickoffWrapper(tracer), + ) + except Exception as e: + logger.warning(f"Could not wrap Crew.kickoff: {e}") + + # Wrap Flow.kickoff_async (CHAIN span) + try: + wrap_function_wrapper( + module="crewai.flow.flow", + name="Flow.kickoff_async", + wrapper=_FlowKickoffAsyncWrapper(tracer), + ) + except Exception as e: + logger.debug(f"Could not wrap Flow.kickoff_async: {e}") + + # Wrap Agent.execute_task (AGENT span) + try: + wrap_function_wrapper( + module="crewai.agent", + name="Agent.execute_task", + wrapper=_AgentExecuteTaskWrapper(tracer), + ) + except Exception as e: + logger.warning(f"Could not wrap Agent.execute_task: {e}") + + # Wrap Task.execute_sync (TASK span) + try: + wrap_function_wrapper( + module="crewai.task", + name="Task.execute_sync", + wrapper=_TaskExecuteSyncWrapper(tracer), + ) + except Exception as e: + logger.warning(f"Could not wrap Task.execute_sync: {e}") + + # Wrap ToolUsage._use (TOOL span) + try: + wrap_function_wrapper( + module="crewai.tools.tool_usage", + name="ToolUsage._use", + wrapper=_ToolUseWrapper(tracer), + ) + except Exception as e: + logger.debug(f"Could not wrap ToolUsage._use: {e}") + + def _uninstrument(self, **kwargs: Any) -> None: + pass + + +class _CrewKickoffWrapper: + """ + Wrapper for Crew.kickoff method to create CHAIN span. + + Uses hook_advice for error protection (Rule 3, 4). + """ + + def __init__(self, tracer: trace_api.Tracer): + self._tracer = tracer + + @hook_advice( + instrumentation_name="crewai", + advice_method="crew_kickoff", + throw_exception=True # Rule 4: Crew execution failure should propagate + ) + def __call__(self, wrapped, instance, args, kwargs): + """Wrap Crew.kickoff to create CHAIN span.""" + inputs = kwargs.get("inputs", {}) + crew_name = getattr(instance, "name", None) or "crew.kickoff" + + with self._tracer.start_as_current_span( + name=crew_name, + kind=SpanKind.INTERNAL, + ) as span: + # Use semantic convention constants (Rule 8) + span.set_attribute(CommonAttributes.GEN_AI_SPAN_KIND, GenAiSpanKind.CHAIN.value) + span.set_attribute(CommonAttributes.GEN_AI_OPERATION_NAME, crew_name) + span.set_attribute(CommonAttributes.INPUT_VALUE, _safe_json_dumps(inputs, "{}")) + + try: + result = wrapped(*args, **kwargs) + except Exception as e: + span.record_exception(e) + raise + + # Extract output + output_value = None + if hasattr(result, "raw"): + output_value = result.raw + elif hasattr(result, "output"): + output_value = result.output + else: + output_value = str(result) + + span.set_attribute(CommonAttributes.OUTPUT_VALUE, _safe_json_dumps(output_value, str(output_value))) + span.set_status(Status(StatusCode.OK)) + + return result + + +class _FlowKickoffAsyncWrapper: + """Wrapper for Flow.kickoff_async method to create CHAIN span.""" + + def __init__(self, tracer: trace_api.Tracer): + self._tracer = tracer + + @hook_advice( + instrumentation_name="crewai", + advice_method="flow_kickoff_async", + throw_exception=True + ) + def __call__(self, wrapped, instance, args, kwargs): + """Wrap Flow.kickoff_async to create CHAIN span.""" + inputs = kwargs.get("inputs", {}) + flow_name = getattr(instance, "name", None) or "flow.kickoff" + + with self._tracer.start_as_current_span( + name=flow_name, + kind=SpanKind.INTERNAL, + ) as span: + span.set_attribute(CommonAttributes.GEN_AI_SPAN_KIND, GenAiSpanKind.CHAIN.value) + span.set_attribute(CommonAttributes.GEN_AI_OPERATION_NAME, flow_name) + span.set_attribute(CommonAttributes.INPUT_VALUE, _safe_json_dumps(inputs, "{}")) + + try: + result = wrapped(*args, **kwargs) + except Exception as e: + span.record_exception(e) + raise + + span.set_attribute(CommonAttributes.OUTPUT_VALUE, _safe_json_dumps(result, str(result))) + span.set_status(Status(StatusCode.OK)) + + return result + + +class _AgentExecuteTaskWrapper: + """Wrapper for Agent.execute_task method to create AGENT span.""" + + def __init__(self, tracer: trace_api.Tracer): + self._tracer = tracer + + @hook_advice( + instrumentation_name="crewai", + advice_method="agent_execute_task", + throw_exception=True # Agent execution failure should propagate + ) + def __call__(self, wrapped, instance, args, kwargs): + """Wrap Agent.execute_task to create AGENT span.""" + task = args[0] if args else kwargs.get("task") + agent_role = getattr(instance, "role", "agent") + + span_name = f"Agent.{agent_role}" + + with self._tracer.start_as_current_span( + name=span_name, + kind=SpanKind.INTERNAL, + ) as span: + span.set_attribute(CommonAttributes.GEN_AI_SPAN_KIND, GenAiSpanKind.AGENT.value) + + # Build input value + if task: + task_desc = getattr(task, "description", "") + context = kwargs.get("context", "") + tools = kwargs.get("tools", []) + + input_data = {"task": task_desc} + if context: + input_data["context"] = str(context)[:1000] # Limit size + if tools: + input_data["tools"] = [getattr(t, "name", str(t)) for t in tools] if isinstance(tools, list) else str(tools) + + span.set_attribute(CommonAttributes.INPUT_VALUE, _safe_json_dumps(input_data, task_desc)) + else: + span.set_attribute(CommonAttributes.INPUT_VALUE, "") + + try: + result = wrapped(*args, **kwargs) + except Exception as e: + span.record_exception(e) + raise + + span.set_attribute(CommonAttributes.OUTPUT_VALUE, str(result) if result else "") + span.set_status(Status(StatusCode.OK)) + + return result + + +class _TaskExecuteSyncWrapper: + """Wrapper for Task.execute_sync method to create TASK span.""" + + def __init__(self, tracer: trace_api.Tracer): + self._tracer = tracer + + @hook_advice( + instrumentation_name="crewai", + advice_method="task_execute_sync", + throw_exception=True # Task execution failure should propagate + ) + def __call__(self, wrapped, instance, args, kwargs): + """Wrap Task.execute_sync to create TASK span.""" + task_desc = getattr(instance, "description", "task") + span_name = f"Task.{task_desc[:50]}" + + with self._tracer.start_as_current_span( + name=span_name, + kind=SpanKind.INTERNAL, + ) as span: + span.set_attribute(CommonAttributes.GEN_AI_SPAN_KIND, GenAiSpanKind.TASK.value) + + if task_desc: + span.set_attribute(CommonAttributes.INPUT_VALUE, task_desc) + span.set_attribute(CommonAttributes.INPUT_MIME_TYPE, "text/plain") + + try: + result = wrapped(*args, **kwargs) + except Exception as e: + span.record_exception(e) + raise + + span.set_attribute(CommonAttributes.OUTPUT_MIME_TYPE, "text/plain") + span.set_status(Status(StatusCode.OK)) + + return result + + +class _ToolUseWrapper: + """Wrapper for ToolUsage._use method to create TOOL span.""" + + def __init__(self, tracer: trace_api.Tracer): + self._tracer = tracer + + @hook_advice( + instrumentation_name="crewai", + advice_method="tool_use", + throw_exception=True # Tool execution failure should propagate + ) + def __call__(self, wrapped, instance, args, kwargs): + """Wrap ToolUsage._use to create TOOL span.""" + tool = args[0] if args else kwargs.get("tool") + tool_name = getattr(tool, "name", "unknown_tool") if tool else "unknown_tool" + + with self._tracer.start_as_current_span( + name=f"Tool.{tool_name}", + kind=SpanKind.INTERNAL, + ) as span: + # Use semantic convention constants (Rule 8) + span.set_attribute(CommonAttributes.GEN_AI_SPAN_KIND, GenAiSpanKind.TOOL.value) + + # Set tool name (both old and new conventions for compatibility) + span.set_attribute("tool.name", tool_name) # Old convention + span.set_attribute(ToolAttributes.GEN_AI_TOOL_NAME, tool_name) # New convention + + # Set tool description + if tool and hasattr(tool, "description"): + description = tool.description + span.set_attribute("tool.description", description) + span.set_attribute(ToolAttributes.GEN_AI_TOOL_DESCRIPTION, description) + + # Extract and set arguments + tool_calling = args[1] if len(args) > 1 else kwargs.get("tool_calling") + if tool_calling and hasattr(tool_calling, "arguments"): + arguments_json = _safe_json_dumps(tool_calling.arguments) + span.set_attribute("tool.parameters", arguments_json) # Old convention + span.set_attribute(ToolAttributes.TOOL_PARAMETERS, arguments_json) # Also use new name + try: + result = wrapped(*args, **kwargs) + except Exception as e: + span.record_exception(e) + raise + + # 判断工具调用错误次数是否超过阈值 + if instance: + _run_attempts = getattr(instance, "_run_attempts", None) + _max_parsing_attempts = getattr(instance, "_max_parsing_attempts", None) + if _max_parsing_attempts and _run_attempts: + if _run_attempts > _max_parsing_attempts: + span.set_status(Status(StatusCode.ERROR)) + + # Set result + if result: + result_json = _safe_json_dumps(result, str(result)) + span.set_attribute("tool.result", result_json) + + return result + diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/package.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/package.py new file mode 100644 index 000000000..3f9b5264c --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/package.py @@ -0,0 +1,18 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +_instruments = ("crewai >= 0.70.0",) + +_supports_metrics = True + diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/version.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/version.py new file mode 100644 index 000000000..909864a1c --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/version.py @@ -0,0 +1,16 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +__version__ = "0.1.0" + diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt new file mode 100644 index 000000000..ecc8f5af1 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt @@ -0,0 +1,9 @@ +crewai>=0.80.0 +litellm>=1.79.0 +openai>=2.0.0 +respx>=0.20.0 +pysqlite3-binary +-e aliyun-semantic-conventions +-e util/opentelemetry-util-http +-e instrumentation/opentelemetry-instrumentation-crewai +-e instrumentation/opentelemetry-instrumentation-litellm diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/__init__.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_agent_workflow.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_agent_workflow.py new file mode 100644 index 000000000..9d3b63ba2 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_agent_workflow.py @@ -0,0 +1,302 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Test cases for Agent workflow orchestration and multi-agent collaboration in CrewAI. + +Business Demo Description: +This test suite uses CrewAI framework to test complex Agent workflows including: +- Sequential task execution +- Hierarchical task delegation +- Multi-agent collaboration +- Agent lifecycle management +""" + +import pysqlite3 +import sys +sys.modules["sqlite3"] = pysqlite3 + +import os +import unittest +from crewai import Agent, Task, Crew, Process +from opentelemetry.instrumentation.litellm import LiteLLMInstrumentor + +from opentelemetry.instrumentation.crewai import CrewAIInstrumentor +from opentelemetry.test.test_base import TestBase + + +class TestAgentWorkflow(TestBase): + """Test Agent workflow orchestration scenarios.""" + + def setUp(self): + """Setup test resources.""" + super().setUp() + # Set up environment variables + os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "test-openai-key-placeholder") + os.environ["DASHSCOPE_API_KEY"] = os.getenv("DASHSCOPE_API_KEY", "test-dashscope-key-placeholder") + os.environ["OPENAI_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" + os.environ["DASHSCOPE_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" + + self.instrumentor = CrewAIInstrumentor() + self.instrumentor.instrument() + + self.litellm_instrumentor = LiteLLMInstrumentor() + self.litellm_instrumentor.instrument() + + # Test data + self.model_name = "dashscope/qwen-turbo" + + def tearDown(self): + """Cleanup test resources.""" + with self.disable_logging(): + self.instrumentor.uninstrument() + self.litellm_instrumentor.uninstrument() + super().tearDown() + from aliyun.sdk.extension.arms.semconv.metrics import SingletonMeta + SingletonMeta.reset() + + def test_sequential_workflow(self): + """ + Test sequential workflow with multiple agents and tasks. + + Business Demo: + - Creates a Crew with 3 Agents (Researcher, Analyst, Writer) + - Executes 3 Tasks sequentially + - Each task is handled by a different agent + - Performs 3 LLM calls (one per task) + + Verification: + - 1 CHAIN span for Crew.kickoff + - 3 AGENT spans (one per agent execution) + - 3 TASK spans (one per task) + - 3 LLM spans + - Span hierarchy: CHAIN -> TASK -> AGENT -> LLM + - Metrics: genai_calls_count=3, duration and tokens for each call + """ + # Create Agents + researcher = Agent( + role="Researcher", + goal="Gather comprehensive information", + backstory="Expert researcher with 15 years of experience", + verbose=False, + llm=self.model_name, + ) + + analyst = Agent( + role="Data Analyst", + goal="Analyze data and extract insights", + backstory="Senior data analyst specializing in AI trends", + verbose=False, + llm=self.model_name, + ) + + writer = Agent( + role="Content Writer", + goal="Create compelling content", + backstory="Professional writer with expertise in tech content", + verbose=False, + llm=self.model_name, + ) + + # Create Tasks + research_task = Task( + description="Research the latest AI trends in 2024", + expected_output="Comprehensive research report", + agent=researcher, + ) + + analysis_task = Task( + description="Analyze the research findings", + expected_output="Data analysis report", + agent=analyst, + ) + + writing_task = Task( + description="Write an article based on the analysis", + expected_output="Published article", + agent=writer, + ) + + # Create and execute Crew with sequential process + crew = Crew( + agents=[researcher, analyst, writer], + tasks=[research_task, analysis_task, writing_task], + process=Process.sequential, + verbose=False, + ) + + crew.kickoff() + + # Verify spans + spans = self.memory_exporter.get_finished_spans() + + chain_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "CHAIN"] + task_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "TASK"] + + # Verify span counts + self.assertGreaterEqual(len(chain_spans), 1, "Expected at least 1 CHAIN span") + self.assertGreaterEqual(len(task_spans), 3, f"Expected at least 3 TASK spans, got {len(task_spans)}") + + # Verify CHAIN span has proper attributes + chain_span = chain_spans[0] + self.assertEqual(chain_span.attributes.get("gen_ai.span.kind"), "CHAIN") + self.assertIsNotNone(chain_span.attributes.get("gen_ai.operation.name")) + self.assertIsNotNone(chain_span.attributes.get("output.value")) + + # Verify metrics show 3 LLM calls + metrics = self.memory_metrics_reader.get_metrics_data() + + for resource_metrics in metrics.resource_metrics: + for scope_metrics in resource_metrics.scope_metrics: + for metric in scope_metrics.metrics: + if metric.name == "genai_calls_count": + for data_point in metric.data.data_points: + # Should have at least 3 calls + self.assertGreaterEqual(data_point.value, 3, f"Expected at least 3 LLM calls, got {data_point.value}") + + def test_multi_agent_collaboration(self): + """ + Test multi-agent collaboration scenario. + + Business Demo: + - Creates a Crew with 2 Agents working together + - Agents share context and collaborate on tasks + - Executes 2 Tasks with agent collaboration + - Performs multiple LLM calls with shared context + + Verification: + - Multiple AGENT spans with proper context + - All spans share the same trace context + - Metrics: genai_calls_count reflects all collaborative LLM calls + """ + # Create collaborative agents + designer = Agent( + role="UX Designer", + goal="Design user-friendly interfaces", + backstory="Senior UX designer", + verbose=True, + llm=self.model_name, + ) + + developer = Agent( + role="Frontend Developer", + goal="Implement designs", + backstory="Expert frontend developer", + verbose=True, + llm=self.model_name, + ) + + # Create collaborative tasks + design_task = Task( + description="Design a dashboard interface", + expected_output="UI design mockup", + agent=designer, + ) + + implement_task = Task( + description="Implement the designed dashboard", + expected_output="Working dashboard code", + agent=developer, + context=[design_task], # Depends on design_task + ) + + # Create and execute Crew + crew = Crew( + agents=[designer, developer], + tasks=[design_task, implement_task], + verbose=True, + ) + + crew.kickoff() + + # Verify spans + spans = self.memory_exporter.get_finished_spans() + + # Verify all spans share the same trace + trace_ids = set(span.context.trace_id for span in spans) + self.assertEqual(len(trace_ids), 1, "All spans should share the same trace ID") + + agent_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "AGENT"] + + # Should have multiple agent spans for collaboration + self.assertGreaterEqual(len(agent_spans), 2, f"Expected at least 2 AGENT spans, got {len(agent_spans)}") + + def test_hierarchical_workflow(self): + """ + Test hierarchical workflow with manager delegation. + + Business Demo: + - Creates a Crew with hierarchical process + - Manager agent delegates tasks to worker agents + - Executes tasks with delegation pattern + + Verification: + - CHAIN span for overall workflow + - Multiple AGENT spans showing delegation hierarchy + - Proper parent-child relationships in span hierarchy + """ + # Create worker agents + worker1 = Agent( + role="Junior Analyst", + goal="Perform assigned analysis", + backstory="Junior analyst", + verbose=True, + llm=self.model_name, + ) + + worker2 = Agent( + role="Junior Researcher", + goal="Conduct assigned research", + backstory="Junior researcher", + verbose=True, + llm=self.model_name, + ) + + # Create tasks + task1 = Task( + description="Analyze market data", + expected_output="Market analysis", + agent=worker1, + ) + + task2 = Task( + description="Research competitors", + expected_output="Competitor research", + agent=worker2, + ) + + # Create Crew with hierarchical process + # Note: Hierarchical process requires a manager_llm + try: + crew = Crew( + agents=[worker1, worker2], + tasks=[task1, task2], + process=Process.hierarchical, + manager_llm=self.model_name, + verbose=True, + ) + + crew.kickoff() + except Exception as e: + # Hierarchical process may not be fully supported in test environment + raise unittest.SkipTest(f"Hierarchical process not supported: {e}") + + # Verify spans + spans = self.memory_exporter.get_finished_spans() + + chain_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "CHAIN"] + + # Should have CHAIN span for hierarchical workflow + self.assertGreaterEqual(len(chain_spans), 1, "Expected at least 1 CHAIN span") + diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_error_scenarios.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_error_scenarios.py new file mode 100644 index 000000000..3603416d3 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_error_scenarios.py @@ -0,0 +1,293 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Test cases for error scenarios in CrewAI. + +Business Demo Description: +This test suite covers various error scenarios including: +- API key authentication failures +- Network connectivity issues +- LLM service errors +- Task execution failures +All error scenarios should be properly traced with error status and metrics. +""" +import pysqlite3 +import sys +sys.modules["sqlite3"] = pysqlite3 +import os +from crewai import Agent, Task, Crew +from opentelemetry.instrumentation.litellm import LiteLLMInstrumentor + +from opentelemetry.instrumentation.crewai import CrewAIInstrumentor +from opentelemetry.test.test_base import TestBase + + +class TestErrorScenarios(TestBase): + """Test error handling scenarios.""" + + def setUp(self): + """Setup test resources.""" + super().setUp() + # Set up environment variables + os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "test-openai-key-placeholder") + os.environ["DASHSCOPE_API_KEY"] = os.getenv("DASHSCOPE_API_KEY", "test-dashscope-key-placeholder") + os.environ["OPENAI_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" + os.environ["DASHSCOPE_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" + + self.instrumentor = CrewAIInstrumentor() + self.instrumentor.instrument() + + self.litellm_instrumentor = LiteLLMInstrumentor() + self.litellm_instrumentor.instrument() + + # Test data + self.model_name = "dashscope/qwen-turbo" + + def tearDown(self): + """Cleanup test resources.""" + with self.disable_logging(): + self.instrumentor.uninstrument() + self.litellm_instrumentor.uninstrument() + + super().tearDown() + from aliyun.sdk.extension.arms.semconv.metrics import SingletonMeta + SingletonMeta.reset() + + def test_api_key_missing(self): + """ + Test execution with missing API key. + + Business Demo: + - Creates a Crew with 1 Agent + - API key is empty/missing + - Executes 1 Task that fails due to authentication + + Verification: + - LLM span has ERROR status + - Span records authentication exception + - Metrics: genai_calls_error_count=1 + - Metrics: genai_calls_count=1 (failed call still counted) + - Metrics: genai_llm_usage_tokens=0 or missing (no response) + """ + # Temporarily remove API keys (clear both DASHSCOPE_API_KEY and OPENAI_API_KEY) + original_dashscope_key = os.environ.get("DASHSCOPE_API_KEY") + original_openai_key = os.environ.get("OPENAI_API_KEY") + os.environ["DASHSCOPE_API_KEY"] = "" + os.environ["OPENAI_API_KEY"] = "" + + try: + agent = Agent( + role="Test Agent", + goal="Test authentication failure", + backstory="Test agent", + verbose=False, + llm=self.model_name, + ) + + task = Task( + description="Execute a task", + expected_output="Task output", + agent=agent, + ) + + crew = Crew( + agents=[agent], + tasks=[task], + verbose=False, + ) + + # Expect execution to fail + try: + crew.kickoff() + except Exception: + pass # Expected + + finally: + # Restore API keys + if original_dashscope_key: + os.environ["DASHSCOPE_API_KEY"] = original_dashscope_key + if original_openai_key: + os.environ["OPENAI_API_KEY"] = original_openai_key + + # Verify spans + spans = self.memory_exporter.get_finished_spans() + + llm_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "LLM"] + + # If LLM span exists, verify error status + if llm_spans: + llm_span = llm_spans[0] + self.assertEqual(llm_span.status.status_code.name, "ERROR") + # Should have exception recorded + self.assertGreater(len(llm_span.events), 0) + + # Verify error metrics + metrics = self.memory_metrics_reader.get_metrics_data() + + error_count_found = False + + for resource_metrics in metrics.resource_metrics: + for scope_metrics in resource_metrics.scope_metrics: + for metric in scope_metrics.metrics: + if metric.name == "genai_calls_error_count": + error_count_found = True + for data_point in metric.data.data_points: + self.assertGreaterEqual(data_point.value, 1) + + # Error count should be recorded + if llm_spans: + self.assertTrue(error_count_found, "genai_calls_error_count metric not found") + + def test_network_error(self): + """ + Test execution with network connectivity error. + + Business Demo: + - Creates a Crew with 1 Agent + - Network connection fails during LLM call + - Executes 1 Task that fails due to network error + + Verification: + - LLM span has ERROR status + - Span records network exception + - Metrics: genai_calls_error_count=1 + - Metrics: genai_calls_duration_seconds records time until failure + """ + # Use invalid base URL to trigger network error (change both DASHSCOPE_API_BASE and OPENAI_API_BASE) + original_dashscope_base = os.environ.get("DASHSCOPE_API_BASE") + original_openai_base = os.environ.get("OPENAI_API_BASE") + os.environ["DASHSCOPE_API_BASE"] = "https://invalid-url-that-does-not-exist.com" + os.environ["OPENAI_API_BASE"] = "https://invalid-url-that-does-not-exist.com" + + try: + agent = Agent( + role="Test Agent", + goal="Test network failure", + backstory="Test agent", + verbose=False, + llm=self.model_name, + ) + + task = Task( + description="Execute a task", + expected_output="Task output", + agent=agent, + ) + + crew = Crew( + agents=[agent], + tasks=[task], + verbose=False, + ) + + # Expect execution to fail + try: + crew.kickoff() + except Exception: + pass # Expected + finally: + # Restore original base URLs + if original_dashscope_base: + os.environ["DASHSCOPE_API_BASE"] = original_dashscope_base + if original_openai_base: + os.environ["OPENAI_API_BASE"] = original_openai_base + + # Verify spans + spans = self.memory_exporter.get_finished_spans() + + llm_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "LLM"] + + # If LLM span exists, verify error status + if llm_spans: + llm_span = llm_spans[0] + self.assertEqual(llm_span.status.status_code.name, "ERROR") + + # Verify error metrics + metrics = self.memory_metrics_reader.get_metrics_data() + + duration_found = False + + for resource_metrics in metrics.resource_metrics: + for scope_metrics in resource_metrics.scope_metrics: + for metric in scope_metrics.metrics: + if metric.name == "genai_calls_duration_seconds": + duration_found = True + # Duration should be recorded even for failed calls + for data_point in metric.data.data_points: + self.assertGreaterEqual(data_point.count, 1) + + # Duration should be recorded for failed calls + if llm_spans: + self.assertTrue(duration_found, "genai_calls_duration_seconds metric not found") + + def test_llm_service_error(self): + """ + Test execution with LLM service error (e.g., rate limit, model unavailable). + + Business Demo: + - Creates a Crew with 1 Agent + - LLM service returns error (rate limit exceeded) + - Executes 1 Task that fails due to service error + + Verification: + - LLM span has ERROR status + - Span records service exception + - Metrics: genai_calls_error_count=1 + """ + # Use invalid model to trigger service error + agent = Agent( + role="Test Agent", + goal="Test service error", + backstory="Test agent", + verbose=False, + llm="invalid-model-name", + ) + + task = Task( + description="Execute a task", + expected_output="Task output", + agent=agent, + ) + + crew = Crew( + agents=[agent], + tasks=[task], + verbose=False, + ) + + # Expect execution to fail + try: + crew.kickoff() + except Exception: + pass # Expected + + # Verify spans + spans = self.memory_exporter.get_finished_spans() + + # Verify at least one span was created + self.assertGreater(len(spans), 0, "Expected at least one span") + + # Verify error metrics + metrics = self.memory_metrics_reader.get_metrics_data() + + # Check that metrics were recorded + metric_names = [] + for resource_metrics in metrics.resource_metrics: + for scope_metrics in resource_metrics.scope_metrics: + for metric in scope_metrics.metrics: + metric_names.append(metric.name) + + # At least some metrics should be present + self.assertGreater(len(metric_names), 0, "Expected metrics to be recorded") \ No newline at end of file diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_flow_kickoff.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_flow_kickoff.py new file mode 100644 index 000000000..c992408a6 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_flow_kickoff.py @@ -0,0 +1,395 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Test cases for _FlowKickoffAsyncWrapper in CrewAI instrumentation. + +This test suite validates the _FlowKickoffAsyncWrapper functionality including: +- CHAIN span creation for flow workflows +- Proper attribute setting (gen_ai.span.kind, input.value, output.value) +- Error handling and exception recording +- Flow name extraction from instance +""" + +import unittest +from unittest.mock import MagicMock, patch, AsyncMock +import asyncio + +from opentelemetry import trace as trace_api +from opentelemetry.trace import Status, StatusCode, SpanKind +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export.in_memory_span_exporter import InMemorySpanExporter + +from opentelemetry.instrumentation.crewai import ( + _FlowKickoffAsyncWrapper, + _safe_json_dumps, +) + + +class TestFlowKickoffAsyncWrapper(unittest.TestCase): + """Test _FlowKickoffAsyncWrapper class.""" + + def setUp(self): + """Setup test resources.""" + # Create tracer provider with in-memory exporter + self.memory_exporter = InMemorySpanExporter() + self.tracer_provider = TracerProvider() + self.tracer_provider.add_span_processor( + trace_api.get_tracer_provider().get_tracer(__name__).__class__.__bases__[0].__subclasses__()[0](self.memory_exporter) + if hasattr(trace_api.get_tracer_provider().get_tracer(__name__).__class__.__bases__[0], '__subclasses__') + else None + ) + # Use SDK tracer for testing + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + self.tracer_provider = TracerProvider() + self.tracer_provider.add_span_processor(SimpleSpanProcessor(self.memory_exporter)) + self.tracer = self.tracer_provider.get_tracer(__name__) + + # Create wrapper instance + self.wrapper = _FlowKickoffAsyncWrapper(self.tracer) + + def tearDown(self): + """Cleanup test resources.""" + self.memory_exporter.clear() + + def test_wrapper_init(self): + """Test wrapper initialization.""" + wrapper = _FlowKickoffAsyncWrapper(self.tracer) + self.assertEqual(wrapper._tracer, self.tracer) + + def test_basic_flow_kickoff(self): + """ + Test basic flow kickoff creates CHAIN span with correct attributes. + + Verification: + - CHAIN span is created + - gen_ai.span.kind = "CHAIN" + - gen_ai.operation.name is set to flow name + - input.value and output.value are captured + - Status is OK + """ + # Create mock wrapped function + mock_wrapped = MagicMock(return_value="flow result") + + # Create mock flow instance with name + mock_instance = MagicMock() + mock_instance.name = "test_flow" + + # Call wrapper + result = self.wrapper(mock_wrapped, mock_instance, (), {}) + + # Verify wrapped function was called + mock_wrapped.assert_called_once_with() + self.assertEqual(result, "flow result") + + # Verify span was created + spans = self.memory_exporter.get_finished_spans() + self.assertEqual(len(spans), 1) + + span = spans[0] + self.assertEqual(span.name, "test_flow") + self.assertEqual(span.attributes.get("gen_ai.span.kind"), "CHAIN") + self.assertEqual(span.attributes.get("gen_ai.operation.name"), "test_flow") + self.assertEqual(span.attributes.get("input.value"), "{}") + self.assertIn("flow result", span.attributes.get("output.value", "")) + self.assertEqual(span.status.status_code, StatusCode.OK) + + def test_flow_kickoff_without_name(self): + """ + Test flow kickoff when instance has no name attribute. + + Verification: + - Uses default name "flow.kickoff" + - Span is created with default name + """ + # Create mock wrapped function + mock_wrapped = MagicMock(return_value="result") + + # Create mock flow instance without name + mock_instance = MagicMock(spec=[]) # No name attribute + + # Call wrapper + result = self.wrapper(mock_wrapped, mock_instance, (), {}) + + # Verify span was created with default name + spans = self.memory_exporter.get_finished_spans() + self.assertEqual(len(spans), 1) + + span = spans[0] + self.assertEqual(span.name, "flow.kickoff") + self.assertEqual(span.attributes.get("gen_ai.operation.name"), "flow.kickoff") + + def test_flow_kickoff_with_inputs(self): + """ + Test flow kickoff with input parameters. + + Verification: + - Inputs are captured in input.value attribute + - Inputs are properly serialized to JSON + """ + # Create mock wrapped function + mock_wrapped = MagicMock(return_value="processed result") + + # Create mock flow instance + mock_instance = MagicMock() + mock_instance.name = "input_flow" + + # Call wrapper with inputs + inputs = {"query": "test query", "count": 10} + result = self.wrapper(mock_wrapped, mock_instance, (), {"inputs": inputs}) + + # Verify wrapped function was called with correct kwargs + mock_wrapped.assert_called_once_with(inputs=inputs) + + # Verify span captures inputs + spans = self.memory_exporter.get_finished_spans() + self.assertEqual(len(spans), 1) + + span = spans[0] + input_value = span.attributes.get("input.value") + self.assertIn("test query", input_value) + self.assertIn("10", input_value) + + def test_flow_kickoff_with_args(self): + """ + Test flow kickoff with positional arguments. + + Verification: + - Args are passed to wrapped function + """ + # Create mock wrapped function + mock_wrapped = MagicMock(return_value="result with args") + + # Create mock flow instance + mock_instance = MagicMock() + mock_instance.name = "args_flow" + + # Call wrapper with args + result = self.wrapper(mock_wrapped, mock_instance, ("arg1", "arg2"), {}) + + # Verify wrapped function was called with args + mock_wrapped.assert_called_once_with("arg1", "arg2") + self.assertEqual(result, "result with args") + + def test_flow_kickoff_exception_handling(self): + """ + Test flow kickoff exception handling. + + Verification: + - Exception is recorded in span + - Exception is re-raised + - Span still has CHAIN kind + """ + # Create mock wrapped function that raises exception + test_exception = ValueError("Test error in flow") + mock_wrapped = MagicMock(side_effect=test_exception) + + # Create mock flow instance + mock_instance = MagicMock() + mock_instance.name = "error_flow" + + # Call wrapper and expect exception + with self.assertRaises(ValueError) as context: + self.wrapper(mock_wrapped, mock_instance, (), {}) + + self.assertEqual(str(context.exception), "Test error in flow") + + # Verify span was created with exception recorded + spans = self.memory_exporter.get_finished_spans() + self.assertEqual(len(spans), 1) + + span = spans[0] + self.assertEqual(span.name, "error_flow") + self.assertEqual(span.attributes.get("gen_ai.span.kind"), "CHAIN") + + # Verify exception was recorded in events + self.assertGreater(len(span.events), 0) + exception_event = span.events[0] + self.assertEqual(exception_event.name, "exception") + + def test_flow_kickoff_with_none_name(self): + """ + Test flow kickoff when instance.name is None. + + Verification: + - Uses default name "flow.kickoff" when name is None + """ + # Create mock wrapped function + mock_wrapped = MagicMock(return_value="result") + + # Create mock flow instance with None name + mock_instance = MagicMock() + mock_instance.name = None + + # Call wrapper + result = self.wrapper(mock_wrapped, mock_instance, (), {}) + + # Verify span was created with default name + spans = self.memory_exporter.get_finished_spans() + self.assertEqual(len(spans), 1) + + span = spans[0] + self.assertEqual(span.name, "flow.kickoff") + self.assertEqual(span.attributes.get("gen_ai.operation.name"), "flow.kickoff") + + def test_flow_kickoff_with_complex_result(self): + """ + Test flow kickoff with complex result object. + + Verification: + - Complex result is properly serialized + - output.value contains serialized result + """ + # Create mock wrapped function with complex result + complex_result = { + "status": "success", + "data": {"items": [1, 2, 3]}, + "message": "Flow completed" + } + mock_wrapped = MagicMock(return_value=complex_result) + + # Create mock flow instance + mock_instance = MagicMock() + mock_instance.name = "complex_flow" + + # Call wrapper + result = self.wrapper(mock_wrapped, mock_instance, (), {}) + + # Verify result is returned correctly + self.assertEqual(result, complex_result) + + # Verify span output contains serialized result + spans = self.memory_exporter.get_finished_spans() + self.assertEqual(len(spans), 1) + + span = spans[0] + output_value = span.attributes.get("output.value") + self.assertIn("success", output_value) + self.assertIn("Flow completed", output_value) + + def test_flow_kickoff_with_none_result(self): + """ + Test flow kickoff when wrapped function returns None. + + Verification: + - None result is handled gracefully + - output.value is set appropriately + """ + # Create mock wrapped function returning None + mock_wrapped = MagicMock(return_value=None) + + # Create mock flow instance + mock_instance = MagicMock() + mock_instance.name = "none_result_flow" + + # Call wrapper + result = self.wrapper(mock_wrapped, mock_instance, (), {}) + + # Verify result is None + self.assertIsNone(result) + + # Verify span was created + spans = self.memory_exporter.get_finished_spans() + self.assertEqual(len(spans), 1) + + span = spans[0] + self.assertEqual(span.status.status_code, StatusCode.OK) + + def test_flow_kickoff_span_kind(self): + """ + Test that flow kickoff span has correct SpanKind. + + Verification: + - Span kind is INTERNAL + """ + # Create mock wrapped function + mock_wrapped = MagicMock(return_value="result") + + # Create mock flow instance + mock_instance = MagicMock() + mock_instance.name = "kind_test_flow" + + # Call wrapper + self.wrapper(mock_wrapped, mock_instance, (), {}) + + # Verify span kind + spans = self.memory_exporter.get_finished_spans() + self.assertEqual(len(spans), 1) + + span = spans[0] + self.assertEqual(span.kind, SpanKind.INTERNAL) + + +class TestSafeJsonDumps(unittest.TestCase): + """Test _safe_json_dumps utility function.""" + + def test_simple_string(self): + """Test with simple string input.""" + result = _safe_json_dumps("hello") + self.assertEqual(result, "hello") + + def test_simple_int(self): + """Test with integer input.""" + result = _safe_json_dumps(42) + self.assertEqual(result, "42") + + def test_simple_float(self): + """Test with float input.""" + result = _safe_json_dumps(3.14) + self.assertEqual(result, "3.14") + + def test_simple_bool(self): + """Test with boolean input.""" + result = _safe_json_dumps(True) + self.assertEqual(result, "True") + + def test_none_returns_default(self): + """Test that None returns default value.""" + result = _safe_json_dumps(None, default="default_value") + self.assertEqual(result, "default_value") + + def test_dict_serialization(self): + """Test dictionary serialization.""" + data = {"key": "value", "number": 123} + result = _safe_json_dumps(data) + self.assertIn("key", result) + self.assertIn("value", result) + self.assertIn("123", result) + + def test_list_serialization(self): + """Test list serialization.""" + data = [1, 2, 3, "four"] + result = _safe_json_dumps(data) + self.assertIn("1", result) + self.assertIn("four", result) + + def test_truncation(self): + """Test that long strings are truncated.""" + long_string = "a" * 20000 + result = _safe_json_dumps(long_string, max_size=100) + self.assertLessEqual(len(result), 120) # Allow for truncation suffix + self.assertIn("[truncated]", result) + + def test_non_serializable_object(self): + """Test handling of non-serializable objects.""" + class CustomObject: + def __str__(self): + return "CustomObject instance" + + result = _safe_json_dumps(CustomObject()) + self.assertIn("CustomObject", result) + + +if __name__ == "__main__": + unittest.main() diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_prompt_and_memory.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_prompt_and_memory.py new file mode 100644 index 000000000..4d42d0790 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_prompt_and_memory.py @@ -0,0 +1,298 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Test cases for prompt management, memory, and knowledge/RAG in CrewAI. + +Business Demo Description: +This test suite covers: +- Prompt template management and variable substitution +- Agent memory (short-term and long-term) +- Knowledge base integration and RAG +- Session management +""" +import pysqlite3 +import sys +sys.modules["sqlite3"] = pysqlite3 +import os +from crewai import Agent, Task, Crew +from opentelemetry.instrumentation.litellm import LiteLLMInstrumentor + +from opentelemetry.instrumentation.crewai import CrewAIInstrumentor +from opentelemetry.test.test_base import TestBase + + +class TestPromptAndMemory(TestBase): + """Test prompt management and memory scenarios.""" + + def setUp(self): + """Setup test resources.""" + super().setUp() + # Set up environment variables + os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "test-openai-key-placeholder") + os.environ["DASHSCOPE_API_KEY"] = os.getenv("DASHSCOPE_API_KEY", "test-dashscope-key-placeholder") + os.environ["OPENAI_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" + os.environ["DASHSCOPE_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" + + self.instrumentor = CrewAIInstrumentor() + self.instrumentor.instrument() + self.litellm_instrumentor = LiteLLMInstrumentor() + self.litellm_instrumentor.instrument() + + # Test data + self.model_name = "dashscope/qwen-turbo" + self.documents = [ + "Python is a high-level programming language.", + "Machine learning is a subset of artificial intelligence.", + "OpenTelemetry provides observability for distributed systems.", + ] + + def tearDown(self): + """Cleanup test resources.""" + with self.disable_logging(): + self.instrumentor.uninstrument() + self.litellm_instrumentor.uninstrument() + super().tearDown() + from aliyun.sdk.extension.arms.semconv.metrics import SingletonMeta + SingletonMeta.reset() + + def test_prompt_template_with_variables(self): + """ + Test prompt template with variable substitution. + + Business Demo: + - Creates a Crew with 1 Agent + - Uses a Task with template variables + - Variables are substituted in the prompt + - Executes 1 Task with expanded prompt + + Verification: + - TASK span has input.value with expanded prompt + - LLM span has gen_ai.input.messages with full prompt + - AGENT span records prompt parameters + """ + # Create Agent + agent = Agent( + role="City Analyst", + goal="Analyze cities", + backstory="Expert city analyst", + verbose=False, + llm=self.model_name, + ) + + # Create Task with template-like description + task = Task( + description="Analyze the city of San Francisco and provide insights about its economy.", + expected_output="City analysis report", + agent=agent, + ) + + # Create and execute Crew with inputs + crew = Crew( + agents=[agent], + tasks=[task], + verbose=False, + ) + + crew.kickoff(inputs={"city": "San Francisco"}) + + # Verify spans + spans = self.memory_exporter.get_finished_spans() + + task_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "TASK"] + llm_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "LLM"] + + # Verify TASK span has input with expanded prompt + if task_spans: + task_span = task_spans[0] + input_value = task_span.attributes.get("input.value") + self.assertIsNotNone(input_value) + # Should contain the task description + self.assertTrue("Analyze" in input_value or "analyze" in input_value.lower()) + + # Verify LLM span has messages + if llm_spans: + llm_span = llm_spans[0] + messages = llm_span.attributes.get("gen_ai.input.messages") + # Messages should be present if captured + if messages: + self.assertGreater(len(messages), 0) + + def test_agent_with_memory(self): + """ + Test Agent with memory enabled. + + Business Demo: + - Creates a Crew with 1 Agent with memory=True + - Executes 2 Tasks sequentially + - Agent should remember context from first task + - Memory queries trigger RETRIEVER spans (if implemented) + + Verification: + - RETRIEVER spans for memory queries (if memory wrapper exists) + - retrieval.query and retrieval.document attributes + - Agent spans show memory context + """ + # Create Agent with memory + agent = Agent( + role="Memory Agent", + goal="Remember and use past context", + backstory="Agent with excellent memory", + verbose=False, + llm=self.model_name, + memory=True, # Enable memory + ) + + # Create Tasks + task1 = Task( + description="Remember that the user's name is Alice", + expected_output="Confirmation", + agent=agent, + ) + + task2 = Task( + description="What is the user's name?", + expected_output="User's name", + agent=agent, + ) + + # Create and execute Crew + crew = Crew( + agents=[agent], + tasks=[task1, task2], + verbose=False, + memory=True, # Enable crew memory + ) + + crew.kickoff() + + # Verify spans + spans = self.memory_exporter.get_finished_spans() + + retriever_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "RETRIEVER"] + + # If memory retrieval is instrumented, verify RETRIEVER spans + if retriever_spans: + retriever_span = retriever_spans[0] + self.assertEqual(retriever_span.attributes.get("gen_ai.span.kind"), "RETRIEVER") + # Should have retrieval query + retriever_span.attributes.get("retrieval.query") + # Should have retrieved documents + retriever_span.attributes.get("retrieval.document") + + def test_agent_with_knowledge_rag(self): + """ + Test Agent with knowledge base and RAG. + + Business Demo: + - Creates a Crew with 1 Agent + - Agent has access to knowledge base + - Executes 1 Task that queries knowledge + - Triggers RAG retrieval and embedding + + Verification: + - RETRIEVER spans for knowledge queries + - EMBEDDING spans for document embedding (if implemented) + - retrieval.document contains retrieved docs + """ + # Create Agent (knowledge integration would require additional setup) + agent = Agent( + role="Knowledge Agent", + goal="Answer questions using knowledge base", + backstory="Expert with access to knowledge base", + verbose=False, + llm=self.model_name, + ) + + # Create Task + task = Task( + description="What is Python? Use the knowledge base.", + expected_output="Information about Python", + agent=agent, + ) + + # Create and execute Crew + crew = Crew( + agents=[agent], + tasks=[task], + verbose=False, + ) + + crew.kickoff() + + # Verify spans + spans = self.memory_exporter.get_finished_spans() + + # If knowledge retrieval is instrumented, verify spans + # Note: This requires CrewAI knowledge integration to be set up + # For now, we verify that the basic execution works + + # Verify basic spans exist + chain_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "CHAIN"] + self.assertGreaterEqual(len(chain_spans), 1, "Expected at least 1 CHAIN span") + + def test_session_management(self): + """ + Test session management and conversation tracking. + + Business Demo: + - Creates a Crew with session tracking + - Executes multiple Tasks in same session + - Session ID is propagated through spans + + Verification: + - All spans share session context + - Session-related attributes are present + """ + # Create Agent + agent = Agent( + role="Session Agent", + goal="Manage conversation sessions", + backstory="Expert in session management", + verbose=False, + llm=self.model_name, + ) + + # Create Tasks + task1 = Task( + description="Start a conversation", + expected_output="Greeting", + agent=agent, + ) + + task2 = Task( + description="Continue the conversation", + expected_output="Response", + agent=agent, + ) + + # Create and execute Crew + crew = Crew( + agents=[agent], + tasks=[task1, task2], + verbose=False, + ) + + # Execute with session context + crew.kickoff() + + # Verify spans + spans = self.memory_exporter.get_finished_spans() + + # Verify all spans share the same trace + trace_ids = set(span.context.trace_id for span in spans) + self.assertEqual(len(trace_ids), 1, "All spans should share the same trace ID for session tracking") + + # Verify spans exist + self.assertGreaterEqual(len(spans), 2, f"Expected at least 2 spans, got {len(spans)}") diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_streaming_llm_calls.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_streaming_llm_calls.py new file mode 100644 index 000000000..822781b0e --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_streaming_llm_calls.py @@ -0,0 +1,202 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Test cases for streaming LLM calls in CrewAI. + +Business Demo Description: +This test suite uses CrewAI framework to create Agents that perform streaming +LLM calls. The demo enables streaming output from CrewAI and verifies that +streaming-specific attributes like time_to_first_token are captured correctly. +""" +import pysqlite3 +import sys +sys.modules["sqlite3"] = pysqlite3 +import os +from crewai import Agent, Task, Crew +from opentelemetry.instrumentation.litellm import LiteLLMInstrumentor + +from opentelemetry.instrumentation.crewai import CrewAIInstrumentor +from opentelemetry.test.test_base import TestBase + + +class TestStreamingLLMCalls(TestBase): + """Test streaming LLM call scenarios.""" + + def setUp(self): + """Setup test resources.""" + super().setUp() + # Set up environment variables + os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "test-openai-key-placeholder") + os.environ["DASHSCOPE_API_KEY"] = os.getenv("DASHSCOPE_API_KEY", "test-dashscope-key-placeholder") + os.environ["OPENAI_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" + os.environ["DASHSCOPE_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" + + self.instrumentor = CrewAIInstrumentor() + self.instrumentor.instrument() + self.litellm_instrumentor = LiteLLMInstrumentor() + self.litellm_instrumentor.instrument() + + # Test data + self.model_name = "dashscope/qwen-turbo" + + def tearDown(self): + """Cleanup test resources.""" + with self.disable_logging(): + self.instrumentor.uninstrument() + self.litellm_instrumentor.uninstrument() + super().tearDown() + from aliyun.sdk.extension.arms.semconv.metrics import SingletonMeta + SingletonMeta.reset() + + def test_streaming_crew_execution(self): + """ + Test streaming Crew execution with LLM streaming enabled. + + Business Demo: + - Creates a Crew with 1 Agent + - Executes 1 Task with streaming enabled + - Performs 1 streaming LLM call + - Consumes streaming chunks + + Verification: + - LLM span has gen_ai.request.is_stream=true + - LLM span has gen_ai.response.time_to_first_token attribute + - Metrics: genai_calls_duration_seconds includes full stream duration + - Metrics: genai_llm_usage_tokens accumulates tokens from stream + """ + # Create Agent with streaming + agent = Agent( + role="Content Writer", + goal="Write engaging content", + backstory="Expert content writer", + verbose=False, + llm=self.model_name, + ) + + # Create Task + task = Task( + description="Write a short greeting message", + expected_output="A greeting message", + agent=agent, + ) + + # Create and execute Crew + crew = Crew( + agents=[agent], + tasks=[task], + verbose=False, + ) + + crew.kickoff() + + # Verify spans + spans = self.memory_exporter.get_finished_spans() + llm_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "LLM"] + + if llm_spans: + llm_span = llm_spans[0] + + # Verify streaming attributes + # Note: gen_ai.request.is_stream should be set if streaming is detected + # Note: gen_ai.response.time_to_first_token should be present for streaming + self.assertEqual(llm_span.attributes.get("gen_ai.span.kind"), "LLM") + + # Verify token usage is captured even in streaming mode + self.assertGreater(llm_span.attributes.get("gen_ai.usage.input_tokens"), 0) + self.assertGreater(llm_span.attributes.get("gen_ai.usage.output_tokens"), 0) + self.assertGreater(llm_span.attributes.get("gen_ai.usage.total_tokens"), 0) + + # Verify metrics + metrics = self.memory_metrics_reader.get_metrics_data() + + duration_found = False + token_usage_found = False + + for resource_metrics in metrics.resource_metrics: + for scope_metrics in resource_metrics.scope_metrics: + for metric in scope_metrics.metrics: + if metric.name == "genai_calls_duration_seconds": + duration_found = True + # Verify duration includes full streaming time + for data_point in metric.data.data_points: + self.assertGreaterEqual(data_point.count, 1) + + elif metric.name == "genai_llm_usage_tokens": + token_usage_found = True + # Verify tokens are accumulated from stream + for data_point in metric.data.data_points: + usage_type = data_point.attributes.get("usageType") + self.assertIn(usage_type, ["input", "output", "total"]) + + self.assertTrue(duration_found, "genai_calls_duration_seconds metric not found") + self.assertTrue(token_usage_found, "genai_llm_usage_tokens metric not found") + + def test_streaming_with_error(self): + """ + Test streaming with error during stream consumption. + + Business Demo: + - Creates a Crew with 1 Agent + - Executes 1 Task with streaming + - Stream fails mid-way + + Verification: + - LLM span has ERROR status + - Metrics: genai_calls_error_count incremented + - Metrics: genai_calls_duration_seconds still recorded + """ + # Use invalid model name to trigger error + agent = Agent( + role="Content Writer", + goal="Write content", + backstory="Expert writer", + verbose=False, + llm="invalid-model-name", + ) + + task = Task( + description="Write a message", + expected_output="A message", + agent=agent, + ) + + crew = Crew( + agents=[agent], + tasks=[task], + verbose=False, + ) + + # Expect error during execution + try: + crew.kickoff() + except Exception: + pass # Expected + + # Verify error metrics + metrics = self.memory_metrics_reader.get_metrics_data() + + error_count_found = False + + for resource_metrics in metrics.resource_metrics: + for scope_metrics in resource_metrics.scope_metrics: + for metric in scope_metrics.metrics: + if metric.name == "genai_calls_error_count": + error_count_found = True + # Verify error was counted + for data_point in metric.data.data_points: + self.assertGreaterEqual(data_point.value, 1) + + # Note: error_count may not be found if LLM.call wrapper didn't execute + # This is acceptable as the test validates the error handling path diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_sync_llm_calls.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_sync_llm_calls.py new file mode 100644 index 000000000..267cf22c7 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_sync_llm_calls.py @@ -0,0 +1,254 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Test cases for synchronous LLM calls in CrewAI. + +Business Demo Description: +This test suite uses CrewAI framework to create a simple Agent that performs +synchronous LLM calls. The demo creates a single Agent with a specific role +and executes a Task that requires LLM inference. This covers the basic +functionality of CrewAI's Agent-Task-LLM interaction pattern. +""" +import pysqlite3 +import sys +sys.modules["sqlite3"] = pysqlite3 +import os +from unittest.mock import Mock +from crewai import Agent, Task, Crew +from opentelemetry.instrumentation.litellm import LiteLLMInstrumentor + +from opentelemetry.instrumentation.crewai import CrewAIInstrumentor +from opentelemetry.test.test_base import TestBase + + +class TestSyncLLMCalls(TestBase): + """Test synchronous LLM call scenarios.""" + + def setUp(self): + """Setup test resources.""" + super().setUp() + # Set up environment variables + os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "test-openai-key-placeholder") + os.environ["DASHSCOPE_API_KEY"] = os.getenv("DASHSCOPE_API_KEY", "test-dashscope-key-placeholder") + os.environ["OPENAI_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" + os.environ["DASHSCOPE_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" + + # Initialize instrumentor + self.instrumentor = CrewAIInstrumentor() + self.instrumentor.instrument() + + self.litellm_instrumentor = LiteLLMInstrumentor() + self.litellm_instrumentor.instrument() + + # Test data + self.model_name = "dashscope/qwen-turbo" + def tearDown(self): + """Cleanup test resources.""" + # Uninstrument to avoid affecting other tests + with self.disable_logging(): + self.instrumentor.uninstrument() + self.litellm_instrumentor.uninstrument() + super().tearDown() + from aliyun.sdk.extension.arms.semconv.metrics import SingletonMeta + SingletonMeta.reset() + + def test_basic_sync_crew_execution(self): + """ + Test basic synchronous Crew execution with a single Agent and Task. + + Business Demo: + - Creates a Crew with 1 Agent (Data Analyst role) + - Executes 1 Task (analyze AI trends) + - Performs 1 synchronous LLM call + - Uses OpenAI GPT-4o-mini model + + Verification: + - CHAIN span for Crew.kickoff with input/output + - AGENT span for Agent.execute_task + - TASK span for Task execution + - LLM span with model, tokens, and messages + - Metrics: genai_calls_count=1, genai_calls_duration_seconds, genai_llm_usage_tokens + """ + # Create Agent + agent = Agent( + role="Data Analyst", + goal="Extract actionable insights from data", + backstory="You are an expert data analyst with 10 years of experience.", + verbose=False, + llm=self.model_name, + ) + + # Create Task + task = Task( + description="Analyze the latest AI trends and provide insights.", + expected_output="A comprehensive analysis of AI trends.", + agent=agent, + ) + + # Create and execute Crew + crew = Crew( + agents=[agent], + tasks=[task], + verbose=False, + ) + + crew.kickoff() + + # Verify spans + spans = self.memory_exporter.get_finished_spans() + self.assertGreaterEqual(len(spans), 3, f"Expected at least 3 spans, got {len(spans)}") + + # Find spans by kind + chain_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "CHAIN"] + agent_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "AGENT"] + task_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "TASK"] + llm_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "LLM"] + + # Verify CHAIN span + self.assertGreaterEqual(len(chain_spans), 1, "Expected at least 1 CHAIN span") + chain_span = chain_spans[0] + self.assertEqual(chain_span.attributes.get("gen_ai.span.kind"), "CHAIN") + self.assertIsNotNone(chain_span.attributes.get("gen_ai.operation.name")) + self.assertIsNotNone(chain_span.attributes.get("output.value")) + + # Verify AGENT span + self.assertGreaterEqual(len(agent_spans), 1, "Expected at least 1 AGENT span") + agent_span = agent_spans[0] + self.assertEqual(agent_span.attributes.get("gen_ai.span.kind"), "AGENT") + self.assertIsNotNone(agent_span.attributes.get("input.value")) + self.assertIsNotNone(agent_span.attributes.get("output.value")) + + # Verify TASK span + self.assertGreaterEqual(len(task_spans), 1, "Expected at least 1 TASK span") + task_span = task_spans[0] + self.assertEqual(task_span.attributes.get("gen_ai.span.kind"), "TASK") + self.assertIsNotNone(task_span.attributes.get("input.value")) + + # Verify LLM span (if wrapped successfully) + if llm_spans: + llm_span = llm_spans[0] + self.assertEqual(llm_span.attributes.get("gen_ai.span.kind"), "LLM") + self.assertEqual(llm_span.attributes.get("gen_ai.system"), "dashscope") + self.assertIsNotNone(llm_span.attributes.get("gen_ai.request.model")) + self.assertGreater(llm_span.attributes.get("gen_ai.usage.input_tokens"), 0) + self.assertGreater(llm_span.attributes.get("gen_ai.usage.output_tokens"), 0) + self.assertGreater(llm_span.attributes.get("gen_ai.usage.total_tokens"), 0) + + # Verify metrics + metrics = self.memory_metrics_reader.get_metrics_data() + + # Check for genai_calls_count + calls_count_found = False + duration_found = False + token_usage_found = False + + for resource_metrics in metrics.resource_metrics: + for scope_metrics in resource_metrics.scope_metrics: + for metric in scope_metrics.metrics: + if metric.name == "genai_calls_count": + calls_count_found = True + # Verify at least 1 call was recorded + for data_point in metric.data.data_points: + self.assertGreaterEqual(data_point.value, 1) + self.assertIsNotNone(data_point.attributes.get("modelName")) + self.assertEqual(data_point.attributes.get("spanKind"), "LLM") + + elif metric.name == "genai_calls_duration_seconds": + duration_found = True + # Verify duration was recorded + for data_point in metric.data.data_points: + self.assertGreaterEqual(data_point.count, 1) + self.assertIsNotNone(data_point.attributes.get("modelName")) + self.assertEqual(data_point.attributes.get("spanKind"), "LLM") + + elif metric.name == "genai_llm_usage_tokens": + token_usage_found = True + # Verify token usage was recorded + for data_point in metric.data.data_points: + usage_type = data_point.attributes.get("usageType") + self.assertIn(usage_type, ["input", "output", "total"]) + self.assertIsNotNone(data_point.attributes.get("modelName")) + self.assertEqual(data_point.attributes.get("spanKind"), "LLM") + + self.assertTrue(calls_count_found, "genai_calls_count metric not found") + self.assertTrue(duration_found, "genai_calls_duration_seconds metric not found") + self.assertTrue(token_usage_found, "genai_llm_usage_tokens metric not found") + def test_crew_with_multiple_tasks(self): + """ + Test Crew execution with multiple sequential tasks. + + Business Demo: + - Creates a Crew with 1 Agent + - Executes 2 Tasks sequentially + - Performs 2 synchronous LLM calls + + Verification: + - 1 CHAIN span for Crew.kickoff + - 2 AGENT spans (one per task execution) + - 2 TASK spans + - 2 LLM spans + - Metrics: genai_calls_count=2 + """ + # Create Agent + agent = Agent( + role="Research Analyst", + goal="Conduct thorough research", + backstory="Expert researcher", + verbose=False, + llm=self.model_name, + ) + + # Create Tasks + task1 = Task( + description="Research AI market trends", + expected_output="Market trends report", + agent=agent, + ) + + task2 = Task( + description="Analyze competitor strategies", + expected_output="Competitor analysis", + agent=agent, + ) + + # Create and execute Crew + crew = Crew( + agents=[agent], + tasks=[task1, task2], + verbose=False, + ) + + crew.kickoff() + + # Verify spans + spans = self.memory_exporter.get_finished_spans() + + chain_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "CHAIN"] + task_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "TASK"] + + # Should have 1 CHAIN span and 2 TASK spans + self.assertGreaterEqual(len(chain_spans), 1, "Expected at least 1 CHAIN span") + self.assertGreaterEqual(len(task_spans), 2, f"Expected at least 2 TASK spans, got {len(task_spans)}") + + # Verify metrics show 2 LLM calls + metrics = self.memory_metrics_reader.get_metrics_data() + + for resource_metrics in metrics.resource_metrics: + for scope_metrics in resource_metrics.scope_metrics: + for metric in scope_metrics.metrics: + if metric.name == "genai_calls_count": + for data_point in metric.data.data_points: + # Should have at least 2 calls + self.assertGreaterEqual(data_point.value, 2, f"Expected at least 2 LLM calls, got {data_point.value}") diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py new file mode 100644 index 000000000..49a764082 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py @@ -0,0 +1,270 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Test cases for tool calls and MCP integration in CrewAI. + +Business Demo Description: +This test suite uses CrewAI framework to create Agents that use tools for +function calling. The demo includes custom tools and verifies that tool +invocations are properly traced with arguments and results. +""" +import pysqlite3 +import sys +sys.modules["sqlite3"] = pysqlite3 +import os +from crewai import Agent, Task, Crew +from crewai.tools.base_tool import BaseTool +from opentelemetry.instrumentation.litellm import LiteLLMInstrumentor + +from opentelemetry.instrumentation.crewai import CrewAIInstrumentor +from opentelemetry.test.test_base import TestBase + + +class WeatherTool(BaseTool): + """Sample tool for weather lookup.""" + + name: str = "get_weather" + description: str = "Get current weather for a location" + + def _run(self, location: str) -> str: + """Execute the tool.""" + return f"Weather in {location}: Sunny, 72°F" + + +class CalculatorTool(BaseTool): + """Sample tool for calculations.""" + + name: str = "calculator" + description: str = "Perform mathematical calculations" + + def _run(self, expression: str) -> str: + """Execute the tool.""" + try: + result = eval(expression) + return f"Result: {result}" + except Exception as e: + return f"Error: {str(e)}" + + +class TestToolCalls(TestBase): + """Test tool call scenarios.""" + + def setUp(self): + """Setup test resources.""" + super().setUp() + # Set up environment variables + os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "test-openai-key-placeholder") + os.environ["DASHSCOPE_API_KEY"] = os.getenv("DASHSCOPE_API_KEY", "test-dashscope-key-placeholder") + os.environ["OPENAI_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" + os.environ["DASHSCOPE_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" + + self.instrumentor = CrewAIInstrumentor() + self.instrumentor.instrument() + + self.litellm_instrumentor = LiteLLMInstrumentor() + self.litellm_instrumentor.instrument() + + # Test data + self.model_name = "dashscope/qwen-turbo" + + def tearDown(self): + """Cleanup test resources.""" + with self.disable_logging(): + self.instrumentor.uninstrument() + self.litellm_instrumentor.uninstrument() + super().tearDown() + from aliyun.sdk.extension.arms.semconv.metrics import SingletonMeta + SingletonMeta.reset() + + def test_agent_with_single_tool(self): + """ + Test Agent execution with a single tool call. + + Business Demo: + - Creates a Crew with 1 Agent + - Agent has access to 1 tool (WeatherTool) + - Executes 1 Task that triggers tool usage + - Performs 1 LLM call + 1 tool call + + Verification: + - TOOL span with gen_ai.tool.name, gen_ai.tool.description + - TOOL span with gen_ai.tool.call.arguments and gen_ai.tool.call.result + - AGENT span contains tool execution context + - Metrics: genai_calls_count includes tool-triggered LLM calls + """ + # Create tool + weather_tool = WeatherTool() + + # Create Agent with tool + agent = Agent( + role="Weather Assistant", + goal="Provide weather information", + backstory="Expert in weather forecasting", + verbose=False, + llm=self.model_name, + tools=[weather_tool], + ) + + # Create Task + task = Task( + description="Get the weather for San Francisco", + expected_output="Weather information", + agent=agent, + ) + + # Create and execute Crew + crew = Crew( + agents=[agent], + tasks=[task], + verbose=False, + ) + + crew.kickoff() + + # Verify spans + spans = self.memory_exporter.get_finished_spans() + + tool_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "TOOL"] + agent_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "AGENT"] + + # Verify TOOL span (if tool wrapper was successful) + if tool_spans: + tool_span = tool_spans[0] + self.assertEqual(tool_span.attributes.get("gen_ai.span.kind"), "TOOL") + self.assertIsNotNone(tool_span.attributes.get("gen_ai.tool.name")) + # Tool description and arguments may be present + # Tool result should be captured + + # Verify AGENT span exists + self.assertGreaterEqual(len(agent_spans), 1, "Expected at least 1 AGENT span") + + def test_agent_with_multiple_tools(self): + """ + Test Agent execution with multiple tool calls. + + Business Demo: + - Creates a Crew with 1 Agent + - Agent has access to 2 tools (WeatherTool, CalculatorTool) + - Executes 1 Task that may trigger multiple tool usages + - Performs multiple LLM calls + multiple tool calls + + Verification: + - Multiple TOOL spans, each with correct tool name + - Each TOOL span has proper arguments and results + - Metrics: genai_calls_count reflects all LLM calls + """ + # Create tools + weather_tool = WeatherTool() + calculator_tool = CalculatorTool() + + # Create Agent with multiple tools + agent = Agent( + role="Multi-Tool Assistant", + goal="Use various tools to complete tasks", + backstory="Expert in using multiple tools", + verbose=False, + llm=self.model_name, + tools=[weather_tool, calculator_tool], + ) + + # Create Task + task = Task( + description="Get weather and calculate temperature difference", + expected_output="Weather and calculation results", + agent=agent, + ) + + # Create and execute Crew + crew = Crew( + agents=[agent], + tasks=[task], + verbose=False, + ) + + crew.kickoff() + + # Verify spans + spans = self.memory_exporter.get_finished_spans() + + tool_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "TOOL"] + + # May have multiple tool spans if tools were actually called + # Each tool span should have proper attributes + for tool_span in tool_spans: + self.assertEqual(tool_span.attributes.get("gen_ai.span.kind"), "TOOL") + self.assertIsNotNone(tool_span.attributes.get("gen_ai.tool.name")) + + def test_tool_call_with_error(self): + """ + Test tool call that raises an error. + + Business Demo: + - Creates a Crew with 1 Agent + - Agent uses a tool that fails + - Executes 1 Task with failing tool call + + Verification: + - TOOL span has ERROR status + - TOOL span records exception + - Metrics: genai_calls_error_count may increment if tool failure triggers LLM error + """ + # Create a tool that raises error + class FailingTool(BaseTool): + name: str = "failing_tool" + description: str = "A tool that always fails" + + def _run(self, input: str) -> str: + raise Exception("Tool execution failed") + + failing_tool = FailingTool() + + agent = Agent( + role="Test Assistant", + goal="Test error handling", + backstory="Test agent", + verbose=False, + llm=self.model_name, + tools=[failing_tool], + ) + + task = Task( + description="Use the failing tool", + expected_output="Error handling result", + agent=agent, + ) + + crew = Crew( + agents=[agent], + tasks=[task], + verbose=False, + ) + + # May raise error or handle gracefully + try: + crew.kickoff() + except Exception: + pass # Expected + + # Verify spans + spans = self.memory_exporter.get_finished_spans() + + tool_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "TOOL"] + + # If tool span exists, verify error status + for tool_span in tool_spans: + if tool_span.name.startswith("Tool.failing_tool"): + # Should have error status + self.assertEqual(tool_span.status.status_code.name, "ERROR") + From 70a67a722c21b9dcb2de026755df7998a8157314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=8E=E7=9B=B4?= Date: Fri, 23 Jan 2026 16:32:16 +0800 Subject: [PATCH 02/14] Support CrewAI Tracing --- .../pyproject.toml | 8 +- .../instrumentation/crewai/__init__.py | 378 ++++++------------ .../instrumentation/crewai/package.py | 1 - .../instrumentation/crewai/utils.py | 134 +++++++ .../instrumentation/crewai/version.py | 1 - 5 files changed, 272 insertions(+), 250 deletions(-) create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml index ec84ca96c..2f342ec89 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml @@ -8,7 +8,7 @@ dynamic = ["version"] description = "OpenTelemetry CrewAI instrumentation" readme = "README.md" license = "Apache-2.0" -requires-python = ">=3.8" +requires-python = ">=3.10,<4" authors = [ { name = "OpenTelemetry Authors", email = "cncf-opentelemetry-contributors@lists.cncf.io" }, ] @@ -25,8 +25,12 @@ classifiers = [ "Programming Language :: Python :: 3.12", ] dependencies = [ - "opentelemetry-api <= 1.35.0", + "opentelemetry-api ~= 1.34.0", "wrapt >= 1.0.0, < 2.0.0", +# "opentelemetry-api ~=1.37", +# "opentelemetry-instrumentation >=0.58b0, <2", +# "opentelemetry-semantic-conventions >=0.58b0, <2", + "opentelemetry-util-genai ~= 0.1b0", ] [project.optional-dependencies] diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py index 77fa9e5dc..5ab4569a4 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py @@ -15,141 +15,55 @@ """ OpenTelemetry CrewAI Instrumentation (Optimized) -This module provides automatic instrumentation for CrewAI framework following -OpenTelemetry GenAI semantic conventions and ARMS best practices. - -Optimizations based on best-practice.mdc: -1. Uses hook_advice decorators for error protection -2. Uses semantic convention constants from aliyun-semantic-conventions -3. Separates ARMS-specific logic to extension file -4. Optimized for performance and memory safety """ -import json import logging -import sys -import time -import threading -from typing import Any, Collection, Dict, Optional, List +from typing import Any, Collection -from opentelemetry.instrumentation.instrumentor import BaseInstrumentor -from opentelemetry.instrumentation.crewai.package import _instruments -from opentelemetry import trace as trace_api -from opentelemetry import context as context_api -from opentelemetry.trace import Status, StatusCode, SpanKind from wrapt import wrap_function_wrapper -# Import semantic conventions from aliyun-semantic-conventions (Rule 8) -from aliyun.semconv.trace_v2 import ( - CommonAttributes, - LLMAttributes, - ToolAttributes, - GenAiSpanKind, -) - -# Import gen_ai.system from legacy semantic conventions for compatibility -from aliyun.semconv.trace import SpanAttributes +from opentelemetry import context as context_api +from opentelemetry import trace as trace_api -# Import hook_advice for error protection (Rule 3, 4) -from aliyun.sdk.extension.arms.self_monitor.self_monitor_decorator import hook_advice +# Import hook system for decoupled extensions +from opentelemetry.instrumentation.crewai.package import _instruments +from opentelemetry.instrumentation.crewai.utils import ( + OP_NAME_AGENT, + OP_NAME_CREW, + OP_NAME_TASK, + OP_NAME_TOOL, + GenAIHookHelper, + extract_agent_inputs, + extract_tool_inputs, + to_input_message, + to_output_message, +) +from opentelemetry.instrumentation.instrumentor import BaseInstrumentor +from opentelemetry.semconv._incubating.attributes import gen_ai_attributes +from opentelemetry.trace import SpanKind, Status, StatusCode +from opentelemetry.util.genai.completion_hook import load_completion_hook logger = logging.getLogger(__name__) -# Maximum message size to avoid performance issues (Rule 5) MAX_MESSAGE_SIZE = 10000 # characters # Context keys for tracking _CREWAI_SPAN_KEY = context_api.create_key("crewai_span") _CREWAI_START_TIME_KEY = context_api.create_key("crewai_start_time") -_CREWAI_LITELLM_RESPONSE_KEY = context_api.create_key("crewai_litellm_response") - -def _safe_json_dumps(obj: Any, default: str = "", max_size: int = MAX_MESSAGE_SIZE) -> str: - """ - Safely serialize object to JSON string with size limit. - - Optimizations: - - Size limit to avoid performance issues - - Fast path for simple types - """ - if obj is None: - return default - - # Fast path for simple types - if isinstance(obj, (str, int, float, bool)): - result = str(obj) - if len(result) > max_size: - return result[:max_size] + "...[truncated]" - return result - - try: - result = json.dumps(obj, ensure_ascii=False) - if len(result) > max_size: - return result[:max_size] + "...[truncated]" - return result - except Exception as e: - logger.debug(f"Failed to serialize to JSON: {e}") - fallback = str(obj) if obj else default - if len(fallback) > max_size: - return fallback[:max_size] + "...[truncated]" - return fallback - - -def _normalize_model_name(model_name: str) -> str: - """ - Normalize model name to avoid high cardinality in metrics (Rule 11). - - Maps specific model versions to general categories. - """ - if not model_name or model_name == "unknown": - return "unknown" - - # Normalize common model patterns - model_lower = model_name.lower() - - # OpenAI models - if "gpt-4" in model_lower: - return "gpt-4" - elif "gpt-3.5" in model_lower or "gpt-35" in model_lower: - return "gpt-3.5" - elif "gpt" in model_lower: - return "gpt" - - # Anthropic models - elif "claude" in model_lower: - return "claude" - - # Other common providers - elif "llama" in model_lower: - return "llama" - elif "mistral" in model_lower: - return "mistral" - elif "gemini" in model_lower: - return "gemini" - - # Default: return first part before version number - parts = model_name.split("-") - if len(parts) > 0: - return parts[0] - - return model_name[:50] # Limit length +_CREWAI_LITELLM_RESPONSE_KEY = context_api.create_key( + "crewai_litellm_response" +) class CrewAIInstrumentor(BaseInstrumentor): """ An instrumentor for CrewAI framework. - - Follows best practices: - - Uses wrapt for method wrapping (Rule 1) - - Uses hook_advice for error protection (Rule 3, 4) - - Uses semantic conventions from aliyun-semantic-conventions (Rule 8, 9) - - Lightweight implementation (Rule 5) - - No memory leaks (Rule 6) + """ def instrumentation_dependencies(self) -> Collection[str]: return _instruments - def _instrument(self, **kwargs: Any) -> None: """Instrument CrewAI framework.""" tracer_provider = kwargs.get("tracer_provider") @@ -159,15 +73,16 @@ def _instrument(self, **kwargs: Any) -> None: tracer_provider=tracer_provider, ) - # Note: Metrics are handled by arms_crewai_extension.py (Rule 10) - # to separate ARMS-specific logic + completion_hook = load_completion_hook() + + genai_helper = GenAIHookHelper(completion_hook=completion_hook) # Wrap Crew.kickoff (CHAIN span) try: wrap_function_wrapper( module="crewai.crew", name="Crew.kickoff", - wrapper=_CrewKickoffWrapper(tracer), + wrapper=_CrewKickoffWrapper(tracer, genai_helper), ) except Exception as e: logger.warning(f"Could not wrap Crew.kickoff: {e}") @@ -177,7 +92,7 @@ def _instrument(self, **kwargs: Any) -> None: wrap_function_wrapper( module="crewai.flow.flow", name="Flow.kickoff_async", - wrapper=_FlowKickoffAsyncWrapper(tracer), + wrapper=_FlowKickoffAsyncWrapper(tracer, genai_helper), ) except Exception as e: logger.debug(f"Could not wrap Flow.kickoff_async: {e}") @@ -187,7 +102,7 @@ def _instrument(self, **kwargs: Any) -> None: wrap_function_wrapper( module="crewai.agent", name="Agent.execute_task", - wrapper=_AgentExecuteTaskWrapper(tracer), + wrapper=_AgentExecuteTaskWrapper(tracer, genai_helper), ) except Exception as e: logger.warning(f"Could not wrap Agent.execute_task: {e}") @@ -197,7 +112,7 @@ def _instrument(self, **kwargs: Any) -> None: wrap_function_wrapper( module="crewai.task", name="Task.execute_sync", - wrapper=_TaskExecuteSyncWrapper(tracer), + wrapper=_TaskExecuteSyncWrapper(tracer, genai_helper), ) except Exception as e: logger.warning(f"Could not wrap Task.execute_sync: {e}") @@ -207,7 +122,7 @@ def _instrument(self, **kwargs: Any) -> None: wrap_function_wrapper( module="crewai.tools.tool_usage", name="ToolUsage._use", - wrapper=_ToolUseWrapper(tracer), + wrapper=_ToolUseWrapper(tracer, genai_helper), ) except Exception as e: logger.debug(f"Could not wrap ToolUsage._use: {e}") @@ -219,236 +134,207 @@ def _uninstrument(self, **kwargs: Any) -> None: class _CrewKickoffWrapper: """ Wrapper for Crew.kickoff method to create CHAIN span. - - Uses hook_advice for error protection (Rule 3, 4). """ - def __init__(self, tracer: trace_api.Tracer): + def __init__(self, tracer: trace_api.Tracer, helper: GenAIHookHelper): self._tracer = tracer + self._helper = helper - @hook_advice( - instrumentation_name="crewai", - advice_method="crew_kickoff", - throw_exception=True # Rule 4: Crew execution failure should propagate - ) def __call__(self, wrapped, instance, args, kwargs): """Wrap Crew.kickoff to create CHAIN span.""" inputs = kwargs.get("inputs", {}) crew_name = getattr(instance, "name", None) or "crew.kickoff" + genai_inputs = to_input_message("user", inputs) + with self._tracer.start_as_current_span( name=crew_name, kind=SpanKind.INTERNAL, + attributes={ + gen_ai_attributes.GEN_AI_OPERATION_NAME: OP_NAME_CREW, + gen_ai_attributes.GEN_AI_SYSTEM: "crewai", + }, ) as span: - # Use semantic convention constants (Rule 8) - span.set_attribute(CommonAttributes.GEN_AI_SPAN_KIND, GenAiSpanKind.CHAIN.value) - span.set_attribute(CommonAttributes.GEN_AI_OPERATION_NAME, crew_name) - span.set_attribute(CommonAttributes.INPUT_VALUE, _safe_json_dumps(inputs, "{}")) - try: result = wrapped(*args, **kwargs) + + output_val = ( + result.raw if hasattr(result, "raw") else str(result) + ) + genai_outputs = to_output_message("assistant", output_val) + + self._helper.on_completion(span, genai_inputs, genai_outputs) + span.set_status(Status(StatusCode.OK)) + return result except Exception as e: span.record_exception(e) + self._helper.on_completion(span, genai_inputs, []) raise - # Extract output - output_value = None - if hasattr(result, "raw"): - output_value = result.raw - elif hasattr(result, "output"): - output_value = result.output - else: - output_value = str(result) - - span.set_attribute(CommonAttributes.OUTPUT_VALUE, _safe_json_dumps(output_value, str(output_value))) - span.set_status(Status(StatusCode.OK)) - - return result - class _FlowKickoffAsyncWrapper: """Wrapper for Flow.kickoff_async method to create CHAIN span.""" - def __init__(self, tracer: trace_api.Tracer): + def __init__(self, tracer: trace_api.Tracer, helper: GenAIHookHelper): self._tracer = tracer + self._helper = helper - @hook_advice( - instrumentation_name="crewai", - advice_method="flow_kickoff_async", - throw_exception=True - ) def __call__(self, wrapped, instance, args, kwargs): """Wrap Flow.kickoff_async to create CHAIN span.""" inputs = kwargs.get("inputs", {}) flow_name = getattr(instance, "name", None) or "flow.kickoff" + genai_inputs = to_input_message("user", inputs) + with self._tracer.start_as_current_span( name=flow_name, kind=SpanKind.INTERNAL, + attributes={ + gen_ai_attributes.GEN_AI_OPERATION_NAME: OP_NAME_CREW, + gen_ai_attributes.GEN_AI_SYSTEM: "crewai", + }, ) as span: - span.set_attribute(CommonAttributes.GEN_AI_SPAN_KIND, GenAiSpanKind.CHAIN.value) - span.set_attribute(CommonAttributes.GEN_AI_OPERATION_NAME, flow_name) - span.set_attribute(CommonAttributes.INPUT_VALUE, _safe_json_dumps(inputs, "{}")) - try: result = wrapped(*args, **kwargs) + genai_outputs = to_output_message("assistant", result) + self._helper.on_completion(span, genai_inputs, genai_outputs) + span.set_status(Status(StatusCode.OK)) + return result except Exception as e: span.record_exception(e) + self._helper.on_completion(span, genai_inputs, []) raise - span.set_attribute(CommonAttributes.OUTPUT_VALUE, _safe_json_dumps(result, str(result))) - span.set_status(Status(StatusCode.OK)) - - return result - class _AgentExecuteTaskWrapper: """Wrapper for Agent.execute_task method to create AGENT span.""" - def __init__(self, tracer: trace_api.Tracer): + def __init__(self, tracer: trace_api.Tracer, helper: GenAIHookHelper): self._tracer = tracer + self._helper = helper - @hook_advice( - instrumentation_name="crewai", - advice_method="agent_execute_task", - throw_exception=True # Agent execution failure should propagate - ) def __call__(self, wrapped, instance, args, kwargs): """Wrap Agent.execute_task to create AGENT span.""" task = args[0] if args else kwargs.get("task") + context = kwargs.get("context", "") + tools = kwargs.get("tools", []) agent_role = getattr(instance, "role", "agent") - + span_name = f"Agent.{agent_role}" + genai_inputs = extract_agent_inputs(task, context, tools) + with self._tracer.start_as_current_span( name=span_name, kind=SpanKind.INTERNAL, + attributes={ + gen_ai_attributes.GEN_AI_OPERATION_NAME: OP_NAME_AGENT, + gen_ai_attributes.GEN_AI_SYSTEM: "crewai", + "gen_ai.agent.name": agent_role, + }, ) as span: - span.set_attribute(CommonAttributes.GEN_AI_SPAN_KIND, GenAiSpanKind.AGENT.value) - - # Build input value - if task: - task_desc = getattr(task, "description", "") - context = kwargs.get("context", "") - tools = kwargs.get("tools", []) - - input_data = {"task": task_desc} - if context: - input_data["context"] = str(context)[:1000] # Limit size - if tools: - input_data["tools"] = [getattr(t, "name", str(t)) for t in tools] if isinstance(tools, list) else str(tools) - - span.set_attribute(CommonAttributes.INPUT_VALUE, _safe_json_dumps(input_data, task_desc)) - else: - span.set_attribute(CommonAttributes.INPUT_VALUE, "") - try: result = wrapped(*args, **kwargs) + + genai_outputs = to_output_message("assistant", result) + + self._helper.on_completion(span, genai_inputs, genai_outputs) + span.set_status(Status(StatusCode.OK)) + return result except Exception as e: span.record_exception(e) + self._helper.on_completion(span, genai_inputs, []) raise - span.set_attribute(CommonAttributes.OUTPUT_VALUE, str(result) if result else "") - span.set_status(Status(StatusCode.OK)) - - return result - class _TaskExecuteSyncWrapper: """Wrapper for Task.execute_sync method to create TASK span.""" - def __init__(self, tracer: trace_api.Tracer): + def __init__(self, tracer: trace_api.Tracer, helper: GenAIHookHelper): self._tracer = tracer + self._helper = helper - @hook_advice( - instrumentation_name="crewai", - advice_method="task_execute_sync", - throw_exception=True # Task execution failure should propagate - ) def __call__(self, wrapped, instance, args, kwargs): """Wrap Task.execute_sync to create TASK span.""" task_desc = getattr(instance, "description", "task") span_name = f"Task.{task_desc[:50]}" + genai_inputs = to_input_message("user", task_desc) + with self._tracer.start_as_current_span( name=span_name, kind=SpanKind.INTERNAL, + attributes={ + gen_ai_attributes.GEN_AI_OPERATION_NAME: OP_NAME_TASK, + gen_ai_attributes.GEN_AI_SYSTEM: "crewai", + }, ) as span: - span.set_attribute(CommonAttributes.GEN_AI_SPAN_KIND, GenAiSpanKind.TASK.value) - - if task_desc: - span.set_attribute(CommonAttributes.INPUT_VALUE, task_desc) - span.set_attribute(CommonAttributes.INPUT_MIME_TYPE, "text/plain") - try: result = wrapped(*args, **kwargs) + genai_outputs = to_output_message("assistant", result) + self._helper.on_completion(span, genai_inputs, genai_outputs) + span.set_status(Status(StatusCode.OK)) + return result except Exception as e: span.record_exception(e) + self._helper.on_completion(span, genai_inputs, []) raise - span.set_attribute(CommonAttributes.OUTPUT_MIME_TYPE, "text/plain") - span.set_status(Status(StatusCode.OK)) - - return result - class _ToolUseWrapper: """Wrapper for ToolUsage._use method to create TOOL span.""" - def __init__(self, tracer: trace_api.Tracer): + def __init__(self, tracer: trace_api.Tracer, helper: GenAIHookHelper): self._tracer = tracer + self._helper = helper - @hook_advice( - instrumentation_name="crewai", - advice_method="tool_use", - throw_exception=True # Tool execution failure should propagate - ) def __call__(self, wrapped, instance, args, kwargs): """Wrap ToolUsage._use to create TOOL span.""" tool = args[0] if args else kwargs.get("tool") - tool_name = getattr(tool, "name", "unknown_tool") if tool else "unknown_tool" - + tool_name = ( + getattr(tool, "name", "unknown_tool") if tool else "unknown_tool" + ) + + tool_calling = args[1] if len(args) > 1 else kwargs.get("tool_calling") + arguments = ( + getattr(tool_calling, "arguments", {}) if tool_calling else {} + ) + genai_inputs = extract_tool_inputs(tool_name, arguments) + with self._tracer.start_as_current_span( name=f"Tool.{tool_name}", kind=SpanKind.INTERNAL, + attributes={ + gen_ai_attributes.GEN_AI_OPERATION_NAME: OP_NAME_TOOL, + gen_ai_attributes.GEN_AI_SYSTEM: "crewai", + gen_ai_attributes.GEN_AI_TOOL_NAME: tool_name, + }, ) as span: - # Use semantic convention constants (Rule 8) - span.set_attribute(CommonAttributes.GEN_AI_SPAN_KIND, GenAiSpanKind.TOOL.value) - - # Set tool name (both old and new conventions for compatibility) - span.set_attribute("tool.name", tool_name) # Old convention - span.set_attribute(ToolAttributes.GEN_AI_TOOL_NAME, tool_name) # New convention - # Set tool description if tool and hasattr(tool, "description"): - description = tool.description - span.set_attribute("tool.description", description) - span.set_attribute(ToolAttributes.GEN_AI_TOOL_DESCRIPTION, description) - - # Extract and set arguments - tool_calling = args[1] if len(args) > 1 else kwargs.get("tool_calling") - if tool_calling and hasattr(tool_calling, "arguments"): - arguments_json = _safe_json_dumps(tool_calling.arguments) - span.set_attribute("tool.parameters", arguments_json) # Old convention - span.set_attribute(ToolAttributes.TOOL_PARAMETERS, arguments_json) # Also use new name + span.set_attribute("gen_ai.tool.description", tool.description) + try: result = wrapped(*args, **kwargs) - except Exception as e: - span.record_exception(e) - raise - # 判断工具调用错误次数是否超过阈值 - if instance: - _run_attempts = getattr(instance, "_run_attempts", None) - _max_parsing_attempts = getattr(instance, "_max_parsing_attempts", None) - if _max_parsing_attempts and _run_attempts: - if _run_attempts > _max_parsing_attempts: - span.set_status(Status(StatusCode.ERROR)) + genai_outputs = to_output_message("tool", result) - # Set result - if result: - result_json = _safe_json_dumps(result, str(result)) - span.set_attribute("tool.result", result_json) + self._helper.on_completion(span, genai_inputs, genai_outputs) - return result + if instance: + _run_attempts = getattr(instance, "_run_attempts", None) + _max_parsing_attempts = getattr( + instance, "_max_parsing_attempts", None + ) + if ( + _max_parsing_attempts + and _run_attempts + and _run_attempts > _max_parsing_attempts + ): + span.set_status(Status(StatusCode.ERROR)) + return result + except Exception as e: + span.record_exception(e) + self._helper.on_completion(span, genai_inputs, []) + raise diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/package.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/package.py index 3f9b5264c..a250f595d 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/package.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/package.py @@ -15,4 +15,3 @@ _instruments = ("crewai >= 0.70.0",) _supports_metrics = True - diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py new file mode 100644 index 000000000..c270d6784 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py @@ -0,0 +1,134 @@ +import dataclasses +import json +from base64 import b64encode +from functools import partial +from typing import Any, Dict, List, Optional + +from opentelemetry.trace import Span +from opentelemetry.util.genai.completion_hook import CompletionHook +from opentelemetry.util.genai.types import ( + InputMessage, + MessagePart, + OutputMessage, + Text, + ToolCall, +) + + +class _GenAiJsonEncoder(json.JSONEncoder): + def default(self, o: Any) -> Any: + if isinstance(o, bytes): + return b64encode(o).decode() + return super().default(o) + + +gen_ai_json_dumps = partial( + json.dumps, separators=(",", ":"), cls=_GenAiJsonEncoder +) + +GEN_AI_INPUT_MESSAGES = "gen_ai.input.messages" +GEN_AI_OUTPUT_MESSAGES = "gen_ai.output.messages" +GEN_AI_SYSTEM_INSTRUCTIONS = "gen_ai.system_instructions" + +OP_NAME_CREW = "crew.kickoff" +OP_NAME_AGENT = "agent.execute" +OP_NAME_TASK = "task.execute" +OP_NAME_TOOL = "tool.execute" + + +class GenAIHookHelper: + def __init__( + self, completion_hook: CompletionHook, capture_content: bool = True + ): + self.completion_hook = completion_hook + self.capture_content = capture_content + + def on_completion( + self, + span: Span, + inputs: List[InputMessage], + outputs: List[OutputMessage], + system_instructions: Optional[List[MessagePart]] = None, + attributes: Optional[Dict[str, Any]] = None, + ): + if self.capture_content and span.is_recording(): + if inputs: + span.set_attribute( + GEN_AI_INPUT_MESSAGES, + gen_ai_json_dumps([dataclasses.asdict(i) for i in inputs]), + ) + if outputs: + span.set_attribute( + GEN_AI_OUTPUT_MESSAGES, + gen_ai_json_dumps( + [dataclasses.asdict(o) for o in outputs] + ), + ) + if system_instructions: + span.set_attribute( + GEN_AI_SYSTEM_INSTRUCTIONS, + gen_ai_json_dumps( + [dataclasses.asdict(i) for i in system_instructions] + ), + ) + + if attributes: + span.set_attributes(attributes) + + +def to_input_message(role: str, content: Any) -> List[InputMessage]: + if not content: + return [] + + text_content = content if isinstance(content, str) else str(content) + + return [InputMessage(role=role, parts=[Text(content=text_content)])] + + +def to_output_message( + role: str, content: Any, finish_reason: str = "stop" +) -> List[OutputMessage]: + if not content: + return [] + + text_content = content if isinstance(content, str) else str(content) + + return [ + OutputMessage( + role=role, + parts=[Text(content=text_content)], + finish_reason=finish_reason, + ) + ] + + +def extract_agent_inputs( + task_obj: Any, context: str, tools: List[Any] +) -> List[InputMessage]: + description = getattr(task_obj, "description", "") + + parts = [] + if description: + parts.append(Text(content=f"Task: {description}")) + if context: + parts.append(Text(content=f"Context: {context}")) + if tools: + tool_names = [getattr(t, "name", str(t)) for t in tools] + parts.append(Text(content=f"Tools Available: {', '.join(tool_names)}")) + + return [InputMessage(role="user", parts=parts)] + + +def extract_tool_inputs(tool_name: str, arguments: Any) -> List[InputMessage]: + args_str = ( + json.dumps(arguments) + if isinstance(arguments, dict) + else str(arguments) + ) + + return [ + InputMessage( + role="assistant", + parts=[ToolCall(id=tool_name, name=tool_name, arguments=args_str)], + ) + ] diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/version.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/version.py index 909864a1c..5fd301e2e 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/version.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/version.py @@ -13,4 +13,3 @@ # limitations under the License. __version__ = "0.1.0" - From 9590d97a9b05904f20a8b6a2f3b1eea93622afd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=8E=E7=9B=B4?= Date: Mon, 26 Jan 2026 15:40:43 +0800 Subject: [PATCH 03/14] 1 support CrewAI uninstrument; 2 change unit test to adapt code. --- .../instrumentation/crewai/__init__.py | 29 +- .../instrumentation/crewai/utils.py | 39 +- .../tests/test_agent_workflow.py | 192 ++++++---- .../tests/test_error_scenarios.py | 217 ++++++----- .../tests/test_flow_kickoff.py | 214 ++++++----- .../tests/test_prompt_and_memory.py | 226 ++++-------- .../tests/test_streaming_llm_calls.py | 244 ++++++++----- .../tests/test_sync_llm_calls.py | 342 +++++++++++------- .../tests/test_tool_calls.py | 153 +++++--- 9 files changed, 946 insertions(+), 710 deletions(-) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py index 5ab4569a4..d60ed326d 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py @@ -39,13 +39,24 @@ to_output_message, ) from opentelemetry.instrumentation.instrumentor import BaseInstrumentor +from opentelemetry.instrumentation.utils import unwrap from opentelemetry.semconv._incubating.attributes import gen_ai_attributes from opentelemetry.trace import SpanKind, Status, StatusCode from opentelemetry.util.genai.completion_hook import load_completion_hook +try: + import crewai.agent + import crewai.crew + import crewai.flow.flow + import crewai.task + import crewai.tools.tool_usage + + _CREWAI_LOADED = True +except (ImportError, Exception): + _CREWAI_LOADED = False + logger = logging.getLogger(__name__) -MAX_MESSAGE_SIZE = 10000 # characters # Context keys for tracking _CREWAI_SPAN_KEY = context_api.create_key("crewai_span") @@ -128,7 +139,21 @@ def _instrument(self, **kwargs: Any) -> None: logger.debug(f"Could not wrap ToolUsage._use: {e}") def _uninstrument(self, **kwargs: Any) -> None: - pass + """Uninstrument CrewAI framework.""" + if not _CREWAI_LOADED: + logger.debug( + "CrewAI modules were not available for uninstrumentation." + ) + return + try: + unwrap(crewai.crew.Crew, "kickoff") + unwrap(crewai.flow.flow.Flow, "kickoff_async") + unwrap(crewai.agent.Agent, "execute_task") + unwrap(crewai.task.Task, "execute_sync") + unwrap(crewai.tools.tool_usage.ToolUsage, "_use") + + except Exception as e: + logger.debug(f"Error during uninstrumenting: {e}") class _CrewKickoffWrapper: diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py index c270d6784..f728a9127 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py @@ -1,7 +1,7 @@ import dataclasses import json +import logging from base64 import b64encode -from functools import partial from typing import Any, Dict, List, Optional from opentelemetry.trace import Span @@ -14,6 +14,10 @@ ToolCall, ) +logger = logging.getLogger(__name__) + +MAX_MESSAGE_SIZE = 10000 + class _GenAiJsonEncoder(json.JSONEncoder): def default(self, o: Any) -> Any: @@ -22,9 +26,36 @@ def default(self, o: Any) -> Any: return super().default(o) -gen_ai_json_dumps = partial( - json.dumps, separators=(",", ":"), cls=_GenAiJsonEncoder -) +def _safe_json_dumps( + obj: Any, default: str = "", max_size: int = MAX_MESSAGE_SIZE +) -> str: + """ + Safely serialize object to JSON string with size limit. + """ + if obj is None: + return default + + # Fast path for simple types + if isinstance(obj, (str, int, float, bool)): + result = str(obj) + else: + try: + result = json.dumps( + obj, + separators=(",", ":"), + cls=_GenAiJsonEncoder, + ensure_ascii=False, + ) + except Exception as e: + logger.debug(f"Failed to serialize to JSON: {e}") + result = str(obj) + + if len(result) > max_size: + return result[:max_size] + "...[truncated]" + return result + + +gen_ai_json_dumps = _safe_json_dumps GEN_AI_INPUT_MESSAGES = "gen_ai.input.messages" GEN_AI_OUTPUT_MESSAGES = "gen_ai.output.messages" diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_agent_workflow.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_agent_workflow.py index 9d3b63ba2..de119579c 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_agent_workflow.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_agent_workflow.py @@ -15,26 +15,22 @@ """ Test cases for Agent workflow orchestration and multi-agent collaboration in CrewAI. -Business Demo Description: -This test suite uses CrewAI framework to test complex Agent workflows including: -- Sequential task execution -- Hierarchical task delegation -- Multi-agent collaboration -- Agent lifecycle management +This test suite verifies complex Agent interaction patterns, ensuring that the +trace hierarchy and span relationships correctly represent the execution flow. """ -import pysqlite3 +import json +import os import sys -sys.modules["sqlite3"] = pysqlite3 -import os -import unittest -from crewai import Agent, Task, Crew, Process -from opentelemetry.instrumentation.litellm import LiteLLMInstrumentor +import pysqlite3 +from crewai import Agent, Crew, Process, Task from opentelemetry.instrumentation.crewai import CrewAIInstrumentor from opentelemetry.test.test_base import TestBase +sys.modules["sqlite3"] = pysqlite3 + class TestAgentWorkflow(TestBase): """Test Agent workflow orchestration scenarios.""" @@ -43,46 +39,48 @@ def setUp(self): """Setup test resources.""" super().setUp() # Set up environment variables - os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "test-openai-key-placeholder") - os.environ["DASHSCOPE_API_KEY"] = os.getenv("DASHSCOPE_API_KEY", "test-dashscope-key-placeholder") - os.environ["OPENAI_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" - os.environ["DASHSCOPE_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" - + os.environ["OPENAI_API_KEY"] = os.environ.get( + "OPENAI_API_KEY", "fake-key" + ) + os.environ["DASHSCOPE_API_KEY"] = os.environ.get( + "DASHSCOPE_API_KEY", "fake-key" + ) + os.environ["OPENAI_API_BASE"] = ( + "https://dashscope.aliyuncs.com/compatible-mode/v1" + ) + os.environ["DASHSCOPE_API_BASE"] = ( + "https://dashscope.aliyuncs.com/compatible-mode/v1" + ) + + os.environ["CREWAI_TRACING_ENABLED"] = "false" self.instrumentor = CrewAIInstrumentor() - self.instrumentor.instrument() + self.instrumentor.instrument(tracer_provider=self.tracer_provider) - self.litellm_instrumentor = LiteLLMInstrumentor() - self.litellm_instrumentor.instrument() - # Test data - self.model_name = "dashscope/qwen-turbo" - + self.model_name = "openai/qwen-turbo" + def tearDown(self): """Cleanup test resources.""" with self.disable_logging(): self.instrumentor.uninstrument() - self.litellm_instrumentor.uninstrument() super().tearDown() - from aliyun.sdk.extension.arms.semconv.metrics import SingletonMeta - SingletonMeta.reset() def test_sequential_workflow(self): """ Test sequential workflow with multiple agents and tasks. - + Business Demo: - Creates a Crew with 3 Agents (Researcher, Analyst, Writer) - Executes 3 Tasks sequentially - Each task is handled by a different agent - Performs 3 LLM calls (one per task) - + Verification: - 1 CHAIN span for Crew.kickoff - - 3 AGENT spans (one per agent execution) - 3 TASK spans (one per task) - - 3 LLM spans - - Span hierarchy: CHAIN -> TASK -> AGENT -> LLM - - Metrics: genai_calls_count=3, duration and tokens for each call + - 3 AGENT spans (one per agent execution) + - Span hierarchy: Crew -> Task -> Agent + - Trace continuity across all sequential operations """ # Create Agents researcher = Agent( @@ -140,45 +138,68 @@ def test_sequential_workflow(self): # Verify spans spans = self.memory_exporter.get_finished_spans() - - chain_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "CHAIN"] - task_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "TASK"] + + chain_spans = [ + s + for s in spans + if s.attributes.get("gen_ai.operation.name") == "crew.kickoff" + ] + task_spans = [ + s + for s in spans + if s.attributes.get("gen_ai.operation.name") == "task.execute" + ] + agent_spans = [ + s + for s in spans + if s.attributes.get("gen_ai.operation.name") == "agent.execute" + ] # Verify span counts - self.assertGreaterEqual(len(chain_spans), 1, "Expected at least 1 CHAIN span") - self.assertGreaterEqual(len(task_spans), 3, f"Expected at least 3 TASK spans, got {len(task_spans)}") - + self.assertGreaterEqual( + len(chain_spans), 1, "Expected at least 1 CHAIN span" + ) + self.assertGreaterEqual( + len(task_spans), + 3, + f"Expected at least 3 TASK spans, got {len(task_spans)}", + ) + self.assertGreaterEqual( + len(agent_spans), + 3, + f"Expected at least 3 AGENT spans, got {len(agent_spans)}", + ) + # Verify CHAIN span has proper attributes chain_span = chain_spans[0] - self.assertEqual(chain_span.attributes.get("gen_ai.span.kind"), "CHAIN") - self.assertIsNotNone(chain_span.attributes.get("gen_ai.operation.name")) - self.assertIsNotNone(chain_span.attributes.get("output.value")) - - # Verify metrics show 3 LLM calls - metrics = self.memory_metrics_reader.get_metrics_data() - - for resource_metrics in metrics.resource_metrics: - for scope_metrics in resource_metrics.scope_metrics: - for metric in scope_metrics.metrics: - if metric.name == "genai_calls_count": - for data_point in metric.data.data_points: - # Should have at least 3 calls - self.assertGreaterEqual(data_point.value, 3, f"Expected at least 3 LLM calls, got {data_point.value}") + self.assertEqual(chain_span.attributes.get("gen_ai.system"), "crewai") + self.assertEqual( + chain_span.attributes.get("gen_ai.operation.name"), "crew.kickoff" + ) + + # Verify result is captured in OpenTelemetry GenAI format + output_messages_json = chain_span.attributes.get( + "gen_ai.output.messages" + ) + self.assertIsNotNone(output_messages_json) + output_messages = json.loads(output_messages_json) + self.assertGreater(len(output_messages), 0) + self.assertIn("role", output_messages[0]) + self.assertIn("parts", output_messages[0]) def test_multi_agent_collaboration(self): """ Test multi-agent collaboration scenario. - + Business Demo: - Creates a Crew with 2 Agents working together - Agents share context and collaborate on tasks - Executes 2 Tasks with agent collaboration - Performs multiple LLM calls with shared context - + Verification: - Multiple AGENT spans with proper context - All spans share the same trace context - - Metrics: genai_calls_count reflects all collaborative LLM calls """ # Create collaborative agents designer = Agent( @@ -222,25 +243,35 @@ def test_multi_agent_collaboration(self): # Verify spans spans = self.memory_exporter.get_finished_spans() - + # Verify all spans share the same trace trace_ids = set(span.context.trace_id for span in spans) - self.assertEqual(len(trace_ids), 1, "All spans should share the same trace ID") + self.assertEqual( + len(trace_ids), 1, "All spans should share the same trace ID" + ) + + agent_spans = [ + s + for s in spans + if s.attributes.get("gen_ai.operation.name") == "agent.execute" + ] - agent_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "AGENT"] - # Should have multiple agent spans for collaboration - self.assertGreaterEqual(len(agent_spans), 2, f"Expected at least 2 AGENT spans, got {len(agent_spans)}") + self.assertGreaterEqual( + len(agent_spans), + 2, + f"Expected at least 2 AGENT spans, got {len(agent_spans)}", + ) def test_hierarchical_workflow(self): """ Test hierarchical workflow with manager delegation. - + Business Demo: - Creates a Crew with hierarchical process - Manager agent delegates tasks to worker agents - Executes tasks with delegation pattern - + Verification: - CHAIN span for overall workflow - Multiple AGENT spans showing delegation hierarchy @@ -278,25 +309,26 @@ def test_hierarchical_workflow(self): # Create Crew with hierarchical process # Note: Hierarchical process requires a manager_llm - try: - crew = Crew( - agents=[worker1, worker2], - tasks=[task1, task2], - process=Process.hierarchical, - manager_llm=self.model_name, - verbose=True, - ) - - crew.kickoff() - except Exception as e: - # Hierarchical process may not be fully supported in test environment - raise unittest.SkipTest(f"Hierarchical process not supported: {e}") + crew = Crew( + agents=[worker1, worker2], + tasks=[task1, task2], + process=Process.hierarchical, + manager_llm=self.model_name, + verbose=True, + ) + + crew.kickoff() # Verify spans spans = self.memory_exporter.get_finished_spans() - - chain_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "CHAIN"] - - # Should have CHAIN span for hierarchical workflow - self.assertGreaterEqual(len(chain_spans), 1, "Expected at least 1 CHAIN span") + chain_spans = [ + s + for s in spans + if s.attributes.get("gen_ai.operation.name") == "crew.kickoff" + ] + + # Should have CHAIN span for hierarchical workflow + self.assertGreaterEqual( + len(chain_spans), 1, "Expected at least 1 CHAIN span" + ) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_error_scenarios.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_error_scenarios.py index 3603416d3..621d4d432 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_error_scenarios.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_error_scenarios.py @@ -21,17 +21,20 @@ - Network connectivity issues - LLM service errors - Task execution failures -All error scenarios should be properly traced with error status and metrics. +All error scenarios should be properly traced with OpenTelemetry error status and exception events. """ -import pysqlite3 -import sys -sys.modules["sqlite3"] = pysqlite3 + import os -from crewai import Agent, Task, Crew -from opentelemetry.instrumentation.litellm import LiteLLMInstrumentor +import sys + +import pysqlite3 +from crewai import Agent, Crew, Task from opentelemetry.instrumentation.crewai import CrewAIInstrumentor from opentelemetry.test.test_base import TestBase +from opentelemetry.trace import StatusCode + +sys.modules["sqlite3"] = pysqlite3 class TestErrorScenarios(TestBase): @@ -41,47 +44,49 @@ def setUp(self): """Setup test resources.""" super().setUp() # Set up environment variables - os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "test-openai-key-placeholder") - os.environ["DASHSCOPE_API_KEY"] = os.getenv("DASHSCOPE_API_KEY", "test-dashscope-key-placeholder") - os.environ["OPENAI_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" - os.environ["DASHSCOPE_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" - + os.environ["OPENAI_API_KEY"] = os.environ.get( + "OPENAI_API_KEY", "fake-key" + ) + os.environ["DASHSCOPE_API_KEY"] = os.environ.get( + "DASHSCOPE_API_KEY", "fake-key" + ) + os.environ["OPENAI_API_BASE"] = ( + "https://dashscope.aliyuncs.com/compatible-mode/v1" + ) + os.environ["DASHSCOPE_API_BASE"] = ( + "https://dashscope.aliyuncs.com/compatible-mode/v1" + ) + + # Disable CrewAI's built-in tracing to avoid interference + os.environ["CREWAI_TRACING_ENABLED"] = "false" + self.instrumentor = CrewAIInstrumentor() - self.instrumentor.instrument() + self.instrumentor.instrument(tracer_provider=self.tracer_provider) - self.litellm_instrumentor = LiteLLMInstrumentor() - self.litellm_instrumentor.instrument() - # Test data self.model_name = "dashscope/qwen-turbo" - + def tearDown(self): """Cleanup test resources.""" with self.disable_logging(): self.instrumentor.uninstrument() - self.litellm_instrumentor.uninstrument() - super().tearDown() - from aliyun.sdk.extension.arms.semconv.metrics import SingletonMeta - SingletonMeta.reset() def test_api_key_missing(self): """ Test execution with missing API key. - + Business Demo: - Creates a Crew with 1 Agent - API key is empty/missing - Executes 1 Task that fails due to authentication - + Verification: - - LLM span has ERROR status - - Span records authentication exception - - Metrics: genai_calls_error_count=1 - - Metrics: genai_calls_count=1 (failed call still counted) - - Metrics: genai_llm_usage_tokens=0 or missing (no response) + - Affected spans (e.g., Agent/Task) have ERROR status + - Span records authentication exception in events + - Input messages are still captured for context """ - # Temporarily remove API keys (clear both DASHSCOPE_API_KEY and OPENAI_API_KEY) + # Temporarily remove API keys original_dashscope_key = os.environ.get("DASHSCOPE_API_KEY") original_openai_key = os.environ.get("OPENAI_API_KEY") os.environ["DASHSCOPE_API_KEY"] = "" @@ -123,53 +128,59 @@ def test_api_key_missing(self): # Verify spans spans = self.memory_exporter.get_finished_spans() - - llm_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "LLM"] - - # If LLM span exists, verify error status - if llm_spans: - llm_span = llm_spans[0] - self.assertEqual(llm_span.status.status_code.name, "ERROR") - # Should have exception recorded - self.assertGreater(len(llm_span.events), 0) - - # Verify error metrics - metrics = self.memory_metrics_reader.get_metrics_data() - - error_count_found = False - - for resource_metrics in metrics.resource_metrics: - for scope_metrics in resource_metrics.scope_metrics: - for metric in scope_metrics.metrics: - if metric.name == "genai_calls_error_count": - error_count_found = True - for data_point in metric.data.data_points: - self.assertGreaterEqual(data_point.value, 1) - - # Error count should be recorded - if llm_spans: - self.assertTrue(error_count_found, "genai_calls_error_count metric not found") + + # Filter for error spans + error_spans = [ + s for s in spans if s.status.status_code == StatusCode.ERROR + ] + self.assertGreater( + len(error_spans), 0, "At least one span should be marked as ERROR" + ) + + # Verify the primary failed span (usually agent or task) + found_exception = False + for span in error_spans: + for event in span.events: + if event.name == "exception": + found_exception = True + break + + # Verify inputs are still there + if span.attributes.get("gen_ai.operation.name") in [ + "task.execute", + "agent.execute", + ]: + self.assertIsNotNone( + span.attributes.get("gen_ai.input.messages") + ) + + self.assertTrue( + found_exception, + "Should have recorded an exception event in at least one error span", + ) def test_network_error(self): """ Test execution with network connectivity error. - + Business Demo: - Creates a Crew with 1 Agent - Network connection fails during LLM call - Executes 1 Task that fails due to network error - + Verification: - - LLM span has ERROR status - - Span records network exception - - Metrics: genai_calls_error_count=1 - - Metrics: genai_calls_duration_seconds records time until failure + - Affected spans have ERROR status + - Span records network exception in events """ - # Use invalid base URL to trigger network error (change both DASHSCOPE_API_BASE and OPENAI_API_BASE) + # Use invalid base URL to trigger network error original_dashscope_base = os.environ.get("DASHSCOPE_API_BASE") original_openai_base = os.environ.get("OPENAI_API_BASE") - os.environ["DASHSCOPE_API_BASE"] = "https://invalid-url-that-does-not-exist.com" - os.environ["OPENAI_API_BASE"] = "https://invalid-url-that-does-not-exist.com" + os.environ["DASHSCOPE_API_BASE"] = ( + "https://invalid-url-that-does-not-exist.com" + ) + os.environ["OPENAI_API_BASE"] = ( + "https://invalid-url-that-does-not-exist.com" + ) try: agent = Agent( @@ -206,45 +217,27 @@ def test_network_error(self): # Verify spans spans = self.memory_exporter.get_finished_spans() - - llm_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "LLM"] - - # If LLM span exists, verify error status - if llm_spans: - llm_span = llm_spans[0] - self.assertEqual(llm_span.status.status_code.name, "ERROR") - - # Verify error metrics - metrics = self.memory_metrics_reader.get_metrics_data() - - duration_found = False - - for resource_metrics in metrics.resource_metrics: - for scope_metrics in resource_metrics.scope_metrics: - for metric in scope_metrics.metrics: - if metric.name == "genai_calls_duration_seconds": - duration_found = True - # Duration should be recorded even for failed calls - for data_point in metric.data.data_points: - self.assertGreaterEqual(data_point.count, 1) - - # Duration should be recorded for failed calls - if llm_spans: - self.assertTrue(duration_found, "genai_calls_duration_seconds metric not found") + error_spans = [ + s for s in spans if s.status.status_code == StatusCode.ERROR + ] + self.assertGreater( + len(error_spans), + 0, + "Spans should be marked as ERROR on network failure", + ) def test_llm_service_error(self): """ Test execution with LLM service error (e.g., rate limit, model unavailable). - + Business Demo: - Creates a Crew with 1 Agent - - LLM service returns error (rate limit exceeded) + - LLM service returns error (invalid model) - Executes 1 Task that fails due to service error - + Verification: - - LLM span has ERROR status - - Span records service exception - - Metrics: genai_calls_error_count=1 + - Spans have ERROR status + - Exception events contain error details """ # Use invalid model to trigger service error agent = Agent( @@ -275,19 +268,23 @@ def test_llm_service_error(self): # Verify spans spans = self.memory_exporter.get_finished_spans() - - # Verify at least one span was created - self.assertGreater(len(spans), 0, "Expected at least one span") - - # Verify error metrics - metrics = self.memory_metrics_reader.get_metrics_data() - - # Check that metrics were recorded - metric_names = [] - for resource_metrics in metrics.resource_metrics: - for scope_metrics in resource_metrics.scope_metrics: - for metric in scope_metrics.metrics: - metric_names.append(metric.name) - - # At least some metrics should be present - self.assertGreater(len(metric_names), 0, "Expected metrics to be recorded") \ No newline at end of file + error_spans = [ + s for s in spans if s.status.status_code == StatusCode.ERROR + ] + self.assertGreater( + len(error_spans), 0, "Expected error spans for invalid model" + ) + + # Verify specific details of the error inside the agent span + agent_error_spans = [ + s + for s in error_spans + if s.attributes.get("gen_ai.operation.name") == "agent.execute" + ] + if agent_error_spans: + span = agent_error_spans[0] + self.assertEqual(span.status.status_code, StatusCode.ERROR) + exception_events = [ + e for e in span.events if e.name == "exception" + ] + self.assertGreater(len(exception_events), 0) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_flow_kickoff.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_flow_kickoff.py index c992408a6..ddf4dd519 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_flow_kickoff.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_flow_kickoff.py @@ -17,24 +17,30 @@ This test suite validates the _FlowKickoffAsyncWrapper functionality including: - CHAIN span creation for flow workflows -- Proper attribute setting (gen_ai.span.kind, input.value, output.value) +- Proper attribute setting (gen_ai.system, gen_ai.operation.name, gen_ai.input/output.messages) - Error handling and exception recording - Flow name extraction from instance """ +import json import unittest -from unittest.mock import MagicMock, patch, AsyncMock -import asyncio +from unittest.mock import MagicMock from opentelemetry import trace as trace_api -from opentelemetry.trace import Status, StatusCode, SpanKind -from opentelemetry.sdk.trace import TracerProvider -from opentelemetry.sdk.trace.export.in_memory_span_exporter import InMemorySpanExporter - from opentelemetry.instrumentation.crewai import ( + GenAIHookHelper, _FlowKickoffAsyncWrapper, - _safe_json_dumps, ) +from opentelemetry.instrumentation.crewai.utils import _safe_json_dumps +from opentelemetry.sdk.trace import TracerProvider + +# Use SDK tracer for testing +from opentelemetry.sdk.trace.export import SimpleSpanProcessor +from opentelemetry.sdk.trace.export.in_memory_span_exporter import ( + InMemorySpanExporter, +) +from opentelemetry.trace import SpanKind, StatusCode +from opentelemetry.util.genai.completion_hook import load_completion_hook class TestFlowKickoffAsyncWrapper(unittest.TestCase): @@ -46,18 +52,29 @@ def setUp(self): self.memory_exporter = InMemorySpanExporter() self.tracer_provider = TracerProvider() self.tracer_provider.add_span_processor( - trace_api.get_tracer_provider().get_tracer(__name__).__class__.__bases__[0].__subclasses__()[0](self.memory_exporter) - if hasattr(trace_api.get_tracer_provider().get_tracer(__name__).__class__.__bases__[0], '__subclasses__') + trace_api.get_tracer_provider() + .get_tracer(__name__) + .__class__.__bases__[0] + .__subclasses__()[0](self.memory_exporter) + if hasattr( + trace_api.get_tracer_provider() + .get_tracer(__name__) + .__class__.__bases__[0], + "__subclasses__", + ) else None ) - # Use SDK tracer for testing - from opentelemetry.sdk.trace.export import SimpleSpanProcessor + self.tracer_provider = TracerProvider() - self.tracer_provider.add_span_processor(SimpleSpanProcessor(self.memory_exporter)) + self.tracer_provider.add_span_processor( + SimpleSpanProcessor(self.memory_exporter) + ) self.tracer = self.tracer_provider.get_tracer(__name__) - + # Create wrapper instance - self.wrapper = _FlowKickoffAsyncWrapper(self.tracer) + completion_hook = load_completion_hook() + self.helper = GenAIHookHelper(completion_hook=completion_hook) + self.wrapper = _FlowKickoffAsyncWrapper(self.tracer, self.helper) def tearDown(self): """Cleanup test resources.""" @@ -65,119 +82,135 @@ def tearDown(self): def test_wrapper_init(self): """Test wrapper initialization.""" - wrapper = _FlowKickoffAsyncWrapper(self.tracer) + wrapper = _FlowKickoffAsyncWrapper(self.tracer, self.helper) self.assertEqual(wrapper._tracer, self.tracer) + self.assertEqual(wrapper._helper, self.helper) def test_basic_flow_kickoff(self): """ Test basic flow kickoff creates CHAIN span with correct attributes. - + Verification: - CHAIN span is created - - gen_ai.span.kind = "CHAIN" + - gen_ai.system = "crewai" - gen_ai.operation.name is set to flow name - - input.value and output.value are captured + - gen_ai.input.messages and gen_ai.output.messages are captured (JSON) - Status is OK """ # Create mock wrapped function mock_wrapped = MagicMock(return_value="flow result") - + # Create mock flow instance with name mock_instance = MagicMock() mock_instance.name = "test_flow" - + # Call wrapper result = self.wrapper(mock_wrapped, mock_instance, (), {}) - + # Verify wrapped function was called mock_wrapped.assert_called_once_with() self.assertEqual(result, "flow result") - + # Verify span was created spans = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans), 1) - + span = spans[0] self.assertEqual(span.name, "test_flow") - self.assertEqual(span.attributes.get("gen_ai.span.kind"), "CHAIN") - self.assertEqual(span.attributes.get("gen_ai.operation.name"), "test_flow") - self.assertEqual(span.attributes.get("input.value"), "{}") - self.assertIn("flow result", span.attributes.get("output.value", "")) + self.assertEqual( + span.attributes.get("gen_ai.operation.name"), "crew.kickoff" + ) + self.assertEqual(span.attributes.get("gen_ai.system"), "crewai") + + output_messages_json = span.attributes.get("gen_ai.output.messages") + self.assertIsNotNone(output_messages_json) + output_messages = json.loads(output_messages_json) + self.assertGreater(len(output_messages), 0) + self.assertIn("flow result", output_messages[0]["parts"][0]["content"]) self.assertEqual(span.status.status_code, StatusCode.OK) def test_flow_kickoff_without_name(self): """ Test flow kickoff when instance has no name attribute. - + Verification: - Uses default name "flow.kickoff" - Span is created with default name """ # Create mock wrapped function mock_wrapped = MagicMock(return_value="result") - + # Create mock flow instance without name mock_instance = MagicMock(spec=[]) # No name attribute - + # Call wrapper - result = self.wrapper(mock_wrapped, mock_instance, (), {}) - + self.wrapper(mock_wrapped, mock_instance, (), {}) + # Verify span was created with default name spans = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans), 1) - + span = spans[0] self.assertEqual(span.name, "flow.kickoff") - self.assertEqual(span.attributes.get("gen_ai.operation.name"), "flow.kickoff") + self.assertEqual( + span.attributes.get("gen_ai.operation.name"), "crew.kickoff" + ) def test_flow_kickoff_with_inputs(self): """ Test flow kickoff with input parameters. - + Verification: - Inputs are captured in input.value attribute - Inputs are properly serialized to JSON """ # Create mock wrapped function mock_wrapped = MagicMock(return_value="processed result") - + # Create mock flow instance mock_instance = MagicMock() mock_instance.name = "input_flow" - + # Call wrapper with inputs inputs = {"query": "test query", "count": 10} - result = self.wrapper(mock_wrapped, mock_instance, (), {"inputs": inputs}) - + self.wrapper(mock_wrapped, mock_instance, (), {"inputs": inputs}) + # Verify wrapped function was called with correct kwargs mock_wrapped.assert_called_once_with(inputs=inputs) - + # Verify span captures inputs spans = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans), 1) - + span = spans[0] - input_value = span.attributes.get("input.value") - self.assertIn("test query", input_value) - self.assertIn("10", input_value) + + input_messages_json = span.attributes.get("gen_ai.input.messages") + self.assertIsNotNone(input_messages_json) + input_messages = json.loads(input_messages_json) + self.assertGreater(len(input_messages), 0) + content = input_messages[0]["parts"][0]["content"] + self.assertIn("test query", content) + self.assertIn("10", content) def test_flow_kickoff_with_args(self): """ Test flow kickoff with positional arguments. - + Verification: - Args are passed to wrapped function """ # Create mock wrapped function mock_wrapped = MagicMock(return_value="result with args") - + # Create mock flow instance mock_instance = MagicMock() mock_instance.name = "args_flow" - + # Call wrapper with args - result = self.wrapper(mock_wrapped, mock_instance, ("arg1", "arg2"), {}) - + result = self.wrapper( + mock_wrapped, mock_instance, ("arg1", "arg2"), {} + ) + # Verify wrapped function was called with args mock_wrapped.assert_called_once_with("arg1", "arg2") self.assertEqual(result, "result with args") @@ -185,7 +218,7 @@ def test_flow_kickoff_with_args(self): def test_flow_kickoff_exception_handling(self): """ Test flow kickoff exception handling. - + Verification: - Exception is recorded in span - Exception is re-raised @@ -194,25 +227,25 @@ def test_flow_kickoff_exception_handling(self): # Create mock wrapped function that raises exception test_exception = ValueError("Test error in flow") mock_wrapped = MagicMock(side_effect=test_exception) - + # Create mock flow instance mock_instance = MagicMock() mock_instance.name = "error_flow" - + # Call wrapper and expect exception with self.assertRaises(ValueError) as context: self.wrapper(mock_wrapped, mock_instance, (), {}) - + self.assertEqual(str(context.exception), "Test error in flow") - + # Verify span was created with exception recorded spans = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans), 1) - + span = spans[0] self.assertEqual(span.name, "error_flow") - self.assertEqual(span.attributes.get("gen_ai.span.kind"), "CHAIN") - + self.assertEqual(span.attributes.get("gen_ai.system"), "crewai") + # Verify exception was recorded in events self.assertGreater(len(span.events), 0) exception_event = span.events[0] @@ -221,32 +254,34 @@ def test_flow_kickoff_exception_handling(self): def test_flow_kickoff_with_none_name(self): """ Test flow kickoff when instance.name is None. - + Verification: - Uses default name "flow.kickoff" when name is None """ # Create mock wrapped function mock_wrapped = MagicMock(return_value="result") - + # Create mock flow instance with None name mock_instance = MagicMock() mock_instance.name = None - + # Call wrapper - result = self.wrapper(mock_wrapped, mock_instance, (), {}) - + self.wrapper(mock_wrapped, mock_instance, (), {}) + # Verify span was created with default name spans = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans), 1) - + span = spans[0] self.assertEqual(span.name, "flow.kickoff") - self.assertEqual(span.attributes.get("gen_ai.operation.name"), "flow.kickoff") + self.assertEqual( + span.attributes.get("gen_ai.operation.name"), "crew.kickoff" + ) def test_flow_kickoff_with_complex_result(self): """ Test flow kickoff with complex result object. - + Verification: - Complex result is properly serialized - output.value contains serialized result @@ -255,78 +290,82 @@ def test_flow_kickoff_with_complex_result(self): complex_result = { "status": "success", "data": {"items": [1, 2, 3]}, - "message": "Flow completed" + "message": "Flow completed", } mock_wrapped = MagicMock(return_value=complex_result) - + # Create mock flow instance mock_instance = MagicMock() mock_instance.name = "complex_flow" - + # Call wrapper result = self.wrapper(mock_wrapped, mock_instance, (), {}) - + # Verify result is returned correctly self.assertEqual(result, complex_result) - + # Verify span output contains serialized result spans = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans), 1) - + span = spans[0] - output_value = span.attributes.get("output.value") - self.assertIn("success", output_value) - self.assertIn("Flow completed", output_value) + + output_messages_json = span.attributes.get("gen_ai.output.messages") + self.assertIsNotNone(output_messages_json) + output_messages = json.loads(output_messages_json) + content = output_messages[0]["parts"][0]["content"] + self.assertIn("success", content) + self.assertIn("Flow completed", content) def test_flow_kickoff_with_none_result(self): """ Test flow kickoff when wrapped function returns None. - + Verification: - None result is handled gracefully - output.value is set appropriately """ # Create mock wrapped function returning None mock_wrapped = MagicMock(return_value=None) - + # Create mock flow instance mock_instance = MagicMock() mock_instance.name = "none_result_flow" - + # Call wrapper result = self.wrapper(mock_wrapped, mock_instance, (), {}) - + # Verify result is None self.assertIsNone(result) - + # Verify span was created spans = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans), 1) - + span = spans[0] self.assertEqual(span.status.status_code, StatusCode.OK) def test_flow_kickoff_span_kind(self): """ Test that flow kickoff span has correct SpanKind. - + Verification: - Span kind is INTERNAL """ # Create mock wrapped function mock_wrapped = MagicMock(return_value="result") - + # Create mock flow instance mock_instance = MagicMock() mock_instance.name = "kind_test_flow" - + # Call wrapper self.wrapper(mock_wrapped, mock_instance, (), {}) - + # Verify span kind spans = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans), 1) - + span = spans[0] self.assertEqual(span.kind, SpanKind.INTERNAL) @@ -383,10 +422,11 @@ def test_truncation(self): def test_non_serializable_object(self): """Test handling of non-serializable objects.""" + class CustomObject: def __str__(self): return "CustomObject instance" - + result = _safe_json_dumps(CustomObject()) self.assertIn("CustomObject", result) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_prompt_and_memory.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_prompt_and_memory.py index 4d42d0790..288243033 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_prompt_and_memory.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_prompt_and_memory.py @@ -13,25 +13,26 @@ # limitations under the License. """ -Test cases for prompt management, memory, and knowledge/RAG in CrewAI. +Test cases for prompt management and session management in CrewAI. Business Demo Description: This test suite covers: -- Prompt template management and variable substitution -- Agent memory (short-term and long-term) -- Knowledge base integration and RAG -- Session management +- Prompt template variable substitution +- Session management and trace consistency """ -import pysqlite3 -import sys -sys.modules["sqlite3"] = pysqlite3 + +import json import os -from crewai import Agent, Task, Crew -from opentelemetry.instrumentation.litellm import LiteLLMInstrumentor +import sys + +import pysqlite3 +from crewai import Agent, Crew, Task from opentelemetry.instrumentation.crewai import CrewAIInstrumentor from opentelemetry.test.test_base import TestBase +sys.modules["sqlite3"] = pysqlite3 + class TestPromptAndMemory(TestBase): """Test prompt management and memory scenarios.""" @@ -40,47 +41,51 @@ def setUp(self): """Setup test resources.""" super().setUp() # Set up environment variables - os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "test-openai-key-placeholder") - os.environ["DASHSCOPE_API_KEY"] = os.getenv("DASHSCOPE_API_KEY", "test-dashscope-key-placeholder") - os.environ["OPENAI_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" - os.environ["DASHSCOPE_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" - + os.environ["OPENAI_API_KEY"] = os.environ.get( + "OPENAI_API_KEY", "fake-key" + ) + os.environ["DASHSCOPE_API_KEY"] = os.environ.get( + "DASHSCOPE_API_KEY", "fake-key" + ) + os.environ["OPENAI_API_BASE"] = ( + "https://dashscope.aliyuncs.com/compatible-mode/v1" + ) + os.environ["DASHSCOPE_API_BASE"] = ( + "https://dashscope.aliyuncs.com/compatible-mode/v1" + ) + + os.environ["CREWAI_TRACING_ENABLED"] = "false" self.instrumentor = CrewAIInstrumentor() - self.instrumentor.instrument() - self.litellm_instrumentor = LiteLLMInstrumentor() - self.litellm_instrumentor.instrument() - + self.instrumentor.instrument(tracer_provider=self.tracer_provider) + # Test data - self.model_name = "dashscope/qwen-turbo" + self.model_name = "openai/qwen-turbo" self.documents = [ "Python is a high-level programming language.", "Machine learning is a subset of artificial intelligence.", "OpenTelemetry provides observability for distributed systems.", ] - + def tearDown(self): """Cleanup test resources.""" with self.disable_logging(): self.instrumentor.uninstrument() - self.litellm_instrumentor.uninstrument() super().tearDown() - from aliyun.sdk.extension.arms.semconv.metrics import SingletonMeta - SingletonMeta.reset() def test_prompt_template_with_variables(self): """ Test prompt template with variable substitution. - + Business Demo: - Creates a Crew with 1 Agent - Uses a Task with template variables - Variables are substituted in the prompt - Executes 1 Task with expanded prompt - + Verification: - - TASK span has input.value with expanded prompt - - LLM span has gen_ai.input.messages with full prompt - - AGENT span records prompt parameters + - Agent/Task spans set gen_ai.system="crewai" + - Modified prompts correctly captured in gen_ai.input.messages + - Proper span hierarchy (Crew -> Task -> Agent) """ # Create Agent agent = Agent( @@ -109,148 +114,47 @@ def test_prompt_template_with_variables(self): # Verify spans spans = self.memory_exporter.get_finished_spans() - - task_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "TASK"] - llm_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "LLM"] - # Verify TASK span has input with expanded prompt + task_spans = [ + s + for s in spans + if s.attributes.get("gen_ai.operation.name") == "task.execute" + ] + llm_spans = [ + s + for s in spans + if s.attributes.get("gen_ai.operation.name") == "chat" + ] + + # Verify TASK span has expanded prompt in gen_ai.input.messages if task_spans: task_span = task_spans[0] - input_value = task_span.attributes.get("input.value") - self.assertIsNotNone(input_value) - # Should contain the task description - self.assertTrue("Analyze" in input_value or "analyze" in input_value.lower()) + + input_messages_json = task_span.attributes.get( + "gen_ai.input.messages" + ) + self.assertIsNotNone(input_messages_json) + input_messages = json.loads(input_messages_json) + content = input_messages[0]["parts"][0]["content"] + self.assertIn("San Francisco", content) # Verify LLM span has messages if llm_spans: llm_span = llm_spans[0] - messages = llm_span.attributes.get("gen_ai.input.messages") - # Messages should be present if captured - if messages: + messages_json = llm_span.attributes.get("gen_ai.input.messages") + if messages_json: + messages = json.loads(messages_json) self.assertGreater(len(messages), 0) - def test_agent_with_memory(self): - """ - Test Agent with memory enabled. - - Business Demo: - - Creates a Crew with 1 Agent with memory=True - - Executes 2 Tasks sequentially - - Agent should remember context from first task - - Memory queries trigger RETRIEVER spans (if implemented) - - Verification: - - RETRIEVER spans for memory queries (if memory wrapper exists) - - retrieval.query and retrieval.document attributes - - Agent spans show memory context - """ - # Create Agent with memory - agent = Agent( - role="Memory Agent", - goal="Remember and use past context", - backstory="Agent with excellent memory", - verbose=False, - llm=self.model_name, - memory=True, # Enable memory - ) - - # Create Tasks - task1 = Task( - description="Remember that the user's name is Alice", - expected_output="Confirmation", - agent=agent, - ) - - task2 = Task( - description="What is the user's name?", - expected_output="User's name", - agent=agent, - ) - - # Create and execute Crew - crew = Crew( - agents=[agent], - tasks=[task1, task2], - verbose=False, - memory=True, # Enable crew memory - ) - - crew.kickoff() - - # Verify spans - spans = self.memory_exporter.get_finished_spans() - - retriever_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "RETRIEVER"] - - # If memory retrieval is instrumented, verify RETRIEVER spans - if retriever_spans: - retriever_span = retriever_spans[0] - self.assertEqual(retriever_span.attributes.get("gen_ai.span.kind"), "RETRIEVER") - # Should have retrieval query - retriever_span.attributes.get("retrieval.query") - # Should have retrieved documents - retriever_span.attributes.get("retrieval.document") - - def test_agent_with_knowledge_rag(self): - """ - Test Agent with knowledge base and RAG. - - Business Demo: - - Creates a Crew with 1 Agent - - Agent has access to knowledge base - - Executes 1 Task that queries knowledge - - Triggers RAG retrieval and embedding - - Verification: - - RETRIEVER spans for knowledge queries - - EMBEDDING spans for document embedding (if implemented) - - retrieval.document contains retrieved docs - """ - # Create Agent (knowledge integration would require additional setup) - agent = Agent( - role="Knowledge Agent", - goal="Answer questions using knowledge base", - backstory="Expert with access to knowledge base", - verbose=False, - llm=self.model_name, - ) - - # Create Task - task = Task( - description="What is Python? Use the knowledge base.", - expected_output="Information about Python", - agent=agent, - ) - - # Create and execute Crew - crew = Crew( - agents=[agent], - tasks=[task], - verbose=False, - ) - - crew.kickoff() - - # Verify spans - spans = self.memory_exporter.get_finished_spans() - - # If knowledge retrieval is instrumented, verify spans - # Note: This requires CrewAI knowledge integration to be set up - # For now, we verify that the basic execution works - - # Verify basic spans exist - chain_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "CHAIN"] - self.assertGreaterEqual(len(chain_spans), 1, "Expected at least 1 CHAIN span") - def test_session_management(self): """ Test session management and conversation tracking. - + Business Demo: - Creates a Crew with session tracking - Executes multiple Tasks in same session - Session ID is propagated through spans - + Verification: - All spans share session context - Session-related attributes are present @@ -289,10 +193,16 @@ def test_session_management(self): # Verify spans spans = self.memory_exporter.get_finished_spans() - + # Verify all spans share the same trace trace_ids = set(span.context.trace_id for span in spans) - self.assertEqual(len(trace_ids), 1, "All spans should share the same trace ID for session tracking") + self.assertEqual( + len(trace_ids), + 1, + "All spans should share the same trace ID for session tracking", + ) # Verify spans exist - self.assertGreaterEqual(len(spans), 2, f"Expected at least 2 spans, got {len(spans)}") + self.assertGreaterEqual( + len(spans), 2, f"Expected at least 2 spans, got {len(spans)}" + ) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_streaming_llm_calls.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_streaming_llm_calls.py index 822781b0e..68c4a9ce9 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_streaming_llm_calls.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_streaming_llm_calls.py @@ -17,18 +17,22 @@ Business Demo Description: This test suite uses CrewAI framework to create Agents that perform streaming -LLM calls. The demo enables streaming output from CrewAI and verifies that -streaming-specific attributes like time_to_first_token are captured correctly. +LLM calls. It verifies the capture of OpenTelemetry GenAI attributes for +streaming scenarios and proper hierarchy preservation in asynchronous execution. """ -import pysqlite3 -import sys -sys.modules["sqlite3"] = pysqlite3 + +import json import os -from crewai import Agent, Task, Crew -from opentelemetry.instrumentation.litellm import LiteLLMInstrumentor +import sys + +import pysqlite3 +from crewai import Agent, Crew, Task from opentelemetry.instrumentation.crewai import CrewAIInstrumentor from opentelemetry.test.test_base import TestBase +from opentelemetry.trace import StatusCode + +sys.modules["sqlite3"] = pysqlite3 class TestStreamingLLMCalls(TestBase): @@ -38,43 +42,47 @@ def setUp(self): """Setup test resources.""" super().setUp() # Set up environment variables - os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "test-openai-key-placeholder") - os.environ["DASHSCOPE_API_KEY"] = os.getenv("DASHSCOPE_API_KEY", "test-dashscope-key-placeholder") - os.environ["OPENAI_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" - os.environ["DASHSCOPE_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" - + os.environ["OPENAI_API_KEY"] = os.environ.get( + "OPENAI_API_KEY", "fake-key" + ) + os.environ["DASHSCOPE_API_KEY"] = os.environ.get( + "DASHSCOPE_API_KEY", "fake-key" + ) + os.environ["OPENAI_API_BASE"] = ( + "https://dashscope.aliyuncs.com/compatible-mode/v1" + ) + os.environ["DASHSCOPE_API_BASE"] = ( + "https://dashscope.aliyuncs.com/compatible-mode/v1" + ) + + os.environ["CREWAI_TRACING_ENABLED"] = "false" self.instrumentor = CrewAIInstrumentor() - self.instrumentor.instrument() - self.litellm_instrumentor = LiteLLMInstrumentor() - self.litellm_instrumentor.instrument() - + self.instrumentor.instrument(tracer_provider=self.tracer_provider) + # Test data - self.model_name = "dashscope/qwen-turbo" - + self.model_name = "openai/qwen-turbo" + def tearDown(self): """Cleanup test resources.""" with self.disable_logging(): self.instrumentor.uninstrument() - self.litellm_instrumentor.uninstrument() super().tearDown() - from aliyun.sdk.extension.arms.semconv.metrics import SingletonMeta - SingletonMeta.reset() def test_streaming_crew_execution(self): """ Test streaming Crew execution with LLM streaming enabled. - + Business Demo: - Creates a Crew with 1 Agent - Executes 1 Task with streaming enabled - Performs 1 streaming LLM call - Consumes streaming chunks - + Verification: - - LLM span has gen_ai.request.is_stream=true - - LLM span has gen_ai.response.time_to_first_token attribute - - Metrics: genai_calls_duration_seconds includes full stream duration - - Metrics: genai_llm_usage_tokens accumulates tokens from stream + - LLM/Agent spans reflect streaming configuration + - Task span captures final output messages from stream + - Trace hierarchy (Crew -> Task -> Agent) correctly maintained + - Standard attributes (gen_ai.system, gen_ai.operation.name, etc.) """ # Create Agent with streaming agent = Agent( @@ -103,59 +111,94 @@ def test_streaming_crew_execution(self): # Verify spans spans = self.memory_exporter.get_finished_spans() - llm_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "LLM"] - - if llm_spans: - llm_span = llm_spans[0] - - # Verify streaming attributes - # Note: gen_ai.request.is_stream should be set if streaming is detected - # Note: gen_ai.response.time_to_first_token should be present for streaming - self.assertEqual(llm_span.attributes.get("gen_ai.span.kind"), "LLM") - - # Verify token usage is captured even in streaming mode - self.assertGreater(llm_span.attributes.get("gen_ai.usage.input_tokens"), 0) - self.assertGreater(llm_span.attributes.get("gen_ai.usage.output_tokens"), 0) - self.assertGreater(llm_span.attributes.get("gen_ai.usage.total_tokens"), 0) - - # Verify metrics - metrics = self.memory_metrics_reader.get_metrics_data() - - duration_found = False - token_usage_found = False - - for resource_metrics in metrics.resource_metrics: - for scope_metrics in resource_metrics.scope_metrics: - for metric in scope_metrics.metrics: - if metric.name == "genai_calls_duration_seconds": - duration_found = True - # Verify duration includes full streaming time - for data_point in metric.data.data_points: - self.assertGreaterEqual(data_point.count, 1) - - elif metric.name == "genai_llm_usage_tokens": - token_usage_found = True - # Verify tokens are accumulated from stream - for data_point in metric.data.data_points: - usage_type = data_point.attributes.get("usageType") - self.assertIn(usage_type, ["input", "output", "total"]) - - self.assertTrue(duration_found, "genai_calls_duration_seconds metric not found") - self.assertTrue(token_usage_found, "genai_llm_usage_tokens metric not found") + + # 1. Verify existence of all levels in hierarchy + crew_spans = [ + s + for s in spans + if s.attributes.get("gen_ai.operation.name") == "crew.kickoff" + ] + task_spans = [ + s + for s in spans + if s.attributes.get("gen_ai.operation.name") == "task.execute" + ] + agent_spans = [ + s + for s in spans + if s.attributes.get("gen_ai.operation.name") == "agent.execute" + ] + + self.assertGreaterEqual( + len(crew_spans), 1, "Should capture crew.kickoff" + ) + self.assertGreaterEqual( + len(task_spans), 1, "Should capture task.execute" + ) + self.assertGreaterEqual( + len(agent_spans), 1, "Should capture agent.execute" + ) + + # 2. Verify Span Hierarchy and Trace Continuity + crew_span = crew_spans[0] + task_span = task_spans[0] + agent_span = agent_spans[0] + + # All spans must share the same Trace ID + trace_id = crew_span.context.trace_id + for s in spans: + self.assertEqual( + s.context.trace_id, + trace_id, + "Trace ID must be consistent across all spans", + ) + + # Verify parent-child relationship (Crew -> Task -> Agent) + self.assertEqual( + task_span.parent.span_id, + crew_span.context.span_id, + "Task should be child of Crew", + ) + self.assertEqual( + agent_span.parent.span_id, + task_span.context.span_id, + "Agent should be child of Task", + ) + + # 3. Verify OpenTelemetry GenAI Attributes + for s in [crew_span, task_span, agent_span]: + self.assertEqual(s.attributes.get("gen_ai.system"), "crewai") + self.assertIsNotNone(s.attributes.get("gen_ai.operation.name")) + + # 4. Verify Content Capture (JSON formatted messages) + output_messages_json = task_span.attributes.get( + "gen_ai.output.messages" + ) + self.assertIsNotNone( + output_messages_json, "Task should capture output messages" + ) + output_messages = json.loads(output_messages_json) + self.assertGreater(len(output_messages), 0) + self.assertEqual(output_messages[0]["role"], "assistant") + self.assertIn( + "content", + output_messages[0]["parts"][0], + "Output should contain message parts", + ) def test_streaming_with_error(self): """ Test streaming with error during stream consumption. - + Business Demo: - Creates a Crew with 1 Agent - Executes 1 Task with streaming - Stream fails mid-way - + Verification: - - LLM span has ERROR status - - Metrics: genai_calls_error_count incremented - - Metrics: genai_calls_duration_seconds still recorded + - Spans marked with StatusCode.ERROR status + - Exception events recorded with type and message + - Input messages captured for diagnostic context even on failure """ # Use invalid model name to trigger error agent = Agent( @@ -184,19 +227,46 @@ def test_streaming_with_error(self): except Exception: pass # Expected - # Verify error metrics - metrics = self.memory_metrics_reader.get_metrics_data() - - error_count_found = False - - for resource_metrics in metrics.resource_metrics: - for scope_metrics in resource_metrics.scope_metrics: - for metric in scope_metrics.metrics: - if metric.name == "genai_calls_error_count": - error_count_found = True - # Verify error was counted - for data_point in metric.data.data_points: - self.assertGreaterEqual(data_point.value, 1) - - # Note: error_count may not be found if LLM.call wrapper didn't execute - # This is acceptable as the test validates the error handling path + # Verify spans for error state + spans = self.memory_exporter.get_finished_spans() + + # Filter agent span (where error usually originated in this case) + error_spans = [ + s for s in spans if s.status.status_code == StatusCode.ERROR + ] + self.assertGreaterEqual( + len(error_spans), 1, "At least one span should be marked as ERROR" + ) + + for span in error_spans: + # 1. Verify Status + self.assertEqual(span.status.status_code, StatusCode.ERROR) + + # 2. Verify Exception Events + self.assertGreater( + len(span.events), + 0, + "Span should have recorded exception events", + ) + exception_events = [ + e for e in span.events if e.name == "exception" + ] + self.assertGreater( + len(exception_events), 0, "Should contain 'exception' event" + ) + + # 3. Verify Exception Metadata + event_attrs = exception_events[0].attributes + self.assertIn("exception.type", event_attrs) + self.assertIn("exception.message", event_attrs) + + # 4. Verify Input Capture (even on failure) + # Input messages might be empty for the top-level crew if no inputs were provided, + # but task and agent spans should always have them. + op_name = span.attributes.get("gen_ai.operation.name") + if op_name in ["task.execute", "agent.execute"]: + input_messages = span.attributes.get("gen_ai.input.messages") + self.assertIsNotNone( + input_messages, + f"Span {op_name} should capture inputs even on failure", + ) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_sync_llm_calls.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_sync_llm_calls.py index 267cf22c7..f8ba30add 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_sync_llm_calls.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_sync_llm_calls.py @@ -16,21 +16,24 @@ Test cases for synchronous LLM calls in CrewAI. Business Demo Description: -This test suite uses CrewAI framework to create a simple Agent that performs -synchronous LLM calls. The demo creates a single Agent with a specific role -and executes a Task that requires LLM inference. This covers the basic -functionality of CrewAI's Agent-Task-LLM interaction pattern. +This test suite uses CrewAI framework to create Agents that perform synchronous +LLM calls. It verifies the proper creation of OpenTelemetry GenAI spans for +Crew, Task, and Agent operations, ensuring consistent trace hierarchy and +standardized attribute capture. """ -import pysqlite3 -import sys -sys.modules["sqlite3"] = pysqlite3 + +import json import os -from unittest.mock import Mock -from crewai import Agent, Task, Crew -from opentelemetry.instrumentation.litellm import LiteLLMInstrumentor +import sys + +import pysqlite3 +from crewai import Agent, Crew, Task from opentelemetry.instrumentation.crewai import CrewAIInstrumentor from opentelemetry.test.test_base import TestBase +from opentelemetry.trace import StatusCode + +sys.modules["sqlite3"] = pysqlite3 class TestSyncLLMCalls(TestBase): @@ -40,46 +43,50 @@ def setUp(self): """Setup test resources.""" super().setUp() # Set up environment variables - os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "test-openai-key-placeholder") - os.environ["DASHSCOPE_API_KEY"] = os.getenv("DASHSCOPE_API_KEY", "test-dashscope-key-placeholder") - os.environ["OPENAI_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" - os.environ["DASHSCOPE_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" - - # Initialize instrumentor + os.environ["OPENAI_API_KEY"] = os.environ.get( + "OPENAI_API_KEY", "fake-key" + ) + os.environ["DASHSCOPE_API_KEY"] = os.environ.get( + "DASHSCOPE_API_KEY", "fake-key" + ) + os.environ["OPENAI_API_BASE"] = ( + "https://dashscope.aliyuncs.com/compatible-mode/v1" + ) + os.environ["DASHSCOPE_API_BASE"] = ( + "https://dashscope.aliyuncs.com/compatible-mode/v1" + ) + + # Disable CrewAI's built-in tracing to avoid interference with OTel spans hierarchy during tests + os.environ["CREWAI_TRACING_ENABLED"] = "false" self.instrumentor = CrewAIInstrumentor() - self.instrumentor.instrument() + self.instrumentor.instrument(tracer_provider=self.tracer_provider) - self.litellm_instrumentor = LiteLLMInstrumentor() - self.litellm_instrumentor.instrument() - # Test data - self.model_name = "dashscope/qwen-turbo" + self.model_name = "openai/qwen-turbo" + def tearDown(self): """Cleanup test resources.""" # Uninstrument to avoid affecting other tests with self.disable_logging(): self.instrumentor.uninstrument() - self.litellm_instrumentor.uninstrument() super().tearDown() - from aliyun.sdk.extension.arms.semconv.metrics import SingletonMeta - SingletonMeta.reset() def test_basic_sync_crew_execution(self): """ Test basic synchronous Crew execution with a single Agent and Task. - + Business Demo: - Creates a Crew with 1 Agent (Data Analyst role) - Executes 1 Task (analyze AI trends) - Performs 1 synchronous LLM call - Uses OpenAI GPT-4o-mini model - + Verification: - - CHAIN span for Crew.kickoff with input/output - - AGENT span for Agent.execute_task - - TASK span for Task execution - - LLM span with model, tokens, and messages - - Metrics: genai_calls_count=1, genai_calls_duration_seconds, genai_llm_usage_tokens + - CHAIN span for Crew.kickoff (gen_ai.operation.name="crew.kickoff") + - TASK span for Task execution (gen_ai.operation.name="task.execute") + - AGENT span for Agent.execute_task (gen_ai.operation.name="agent.execute") + - Verified parent-child relationship (Crew -> Task -> Agent) + - Standardized OpenTelemetry GenAI attributes (gen_ai.system, gen_ai.input.messages, etc.) """ # Create Agent agent = Agent( @@ -108,83 +115,82 @@ def test_basic_sync_crew_execution(self): # Verify spans spans = self.memory_exporter.get_finished_spans() - self.assertGreaterEqual(len(spans), 3, f"Expected at least 3 spans, got {len(spans)}") - - # Find spans by kind - chain_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "CHAIN"] - agent_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "AGENT"] - task_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "TASK"] - llm_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "LLM"] - - # Verify CHAIN span - self.assertGreaterEqual(len(chain_spans), 1, "Expected at least 1 CHAIN span") - chain_span = chain_spans[0] - self.assertEqual(chain_span.attributes.get("gen_ai.span.kind"), "CHAIN") - self.assertIsNotNone(chain_span.attributes.get("gen_ai.operation.name")) - self.assertIsNotNone(chain_span.attributes.get("output.value")) - - # Verify AGENT span - self.assertGreaterEqual(len(agent_spans), 1, "Expected at least 1 AGENT span") - agent_span = agent_spans[0] - self.assertEqual(agent_span.attributes.get("gen_ai.span.kind"), "AGENT") - self.assertIsNotNone(agent_span.attributes.get("input.value")) - self.assertIsNotNone(agent_span.attributes.get("output.value")) - # Verify TASK span - self.assertGreaterEqual(len(task_spans), 1, "Expected at least 1 TASK span") + # 1. Verify existence of all levels in hierarchy + crew_spans = [ + s + for s in spans + if s.attributes.get("gen_ai.operation.name") == "crew.kickoff" + ] + task_spans = [ + s + for s in spans + if s.attributes.get("gen_ai.operation.name") == "task.execute" + ] + agent_spans = [ + s + for s in spans + if s.attributes.get("gen_ai.operation.name") == "agent.execute" + ] + + self.assertGreaterEqual( + len(crew_spans), 1, "Should capture crew.kickoff" + ) + self.assertGreaterEqual( + len(task_spans), 1, "Should capture task.execute" + ) + self.assertGreaterEqual( + len(agent_spans), 1, "Should capture agent.execute" + ) + + # 2. Verify Span Hierarchy and Trace Continuity + crew_span = crew_spans[0] task_span = task_spans[0] - self.assertEqual(task_span.attributes.get("gen_ai.span.kind"), "TASK") - self.assertIsNotNone(task_span.attributes.get("input.value")) - - # Verify LLM span (if wrapped successfully) - if llm_spans: - llm_span = llm_spans[0] - self.assertEqual(llm_span.attributes.get("gen_ai.span.kind"), "LLM") - self.assertEqual(llm_span.attributes.get("gen_ai.system"), "dashscope") - self.assertIsNotNone(llm_span.attributes.get("gen_ai.request.model")) - self.assertGreater(llm_span.attributes.get("gen_ai.usage.input_tokens"), 0) - self.assertGreater(llm_span.attributes.get("gen_ai.usage.output_tokens"), 0) - self.assertGreater(llm_span.attributes.get("gen_ai.usage.total_tokens"), 0) - - # Verify metrics - metrics = self.memory_metrics_reader.get_metrics_data() - - # Check for genai_calls_count - calls_count_found = False - duration_found = False - token_usage_found = False - - for resource_metrics in metrics.resource_metrics: - for scope_metrics in resource_metrics.scope_metrics: - for metric in scope_metrics.metrics: - if metric.name == "genai_calls_count": - calls_count_found = True - # Verify at least 1 call was recorded - for data_point in metric.data.data_points: - self.assertGreaterEqual(data_point.value, 1) - self.assertIsNotNone(data_point.attributes.get("modelName")) - self.assertEqual(data_point.attributes.get("spanKind"), "LLM") - - elif metric.name == "genai_calls_duration_seconds": - duration_found = True - # Verify duration was recorded - for data_point in metric.data.data_points: - self.assertGreaterEqual(data_point.count, 1) - self.assertIsNotNone(data_point.attributes.get("modelName")) - self.assertEqual(data_point.attributes.get("spanKind"), "LLM") - - elif metric.name == "genai_llm_usage_tokens": - token_usage_found = True - # Verify token usage was recorded - for data_point in metric.data.data_points: - usage_type = data_point.attributes.get("usageType") - self.assertIn(usage_type, ["input", "output", "total"]) - self.assertIsNotNone(data_point.attributes.get("modelName")) - self.assertEqual(data_point.attributes.get("spanKind"), "LLM") - - self.assertTrue(calls_count_found, "genai_calls_count metric not found") - self.assertTrue(duration_found, "genai_calls_duration_seconds metric not found") - self.assertTrue(token_usage_found, "genai_llm_usage_tokens metric not found") + agent_span = agent_spans[0] + + # All spans must share the same Trace ID + trace_id = crew_span.context.trace_id + for s in spans: + self.assertEqual( + s.context.trace_id, + trace_id, + "Trace ID must be consistent across all spans", + ) + + # Verify parent-child relationship (Crew -> Task -> Agent) + self.assertEqual( + task_span.parent.span_id, + crew_span.context.span_id, + "Task should be child of Crew", + ) + self.assertEqual( + agent_span.parent.span_id, + task_span.context.span_id, + "Agent should be child of Task", + ) + + # 3. Verify OpenTelemetry GenAI Attributes + for s in [crew_span, task_span, agent_span]: + self.assertEqual(s.attributes.get("gen_ai.system"), "crewai") + self.assertIsNotNone(s.attributes.get("gen_ai.operation.name")) + + # 4. Verify Content Capture (JSON formatted messages) + # Verify inputs in task span + input_messages_json = task_span.attributes.get("gen_ai.input.messages") + self.assertIsNotNone(input_messages_json) + input_messages = json.loads(input_messages_json) + self.assertGreater(len(input_messages), 0) + self.assertIn("AI trends", input_messages[0]["parts"][0]["content"]) + + # Verify outputs in task span + output_messages_json = task_span.attributes.get( + "gen_ai.output.messages" + ) + self.assertIsNotNone(output_messages_json) + output_messages = json.loads(output_messages_json) + self.assertGreater(len(output_messages), 0) + self.assertEqual(output_messages[0]["role"], "assistant") + def test_crew_with_multiple_tasks(self): """ Test Crew execution with multiple sequential tasks. @@ -196,10 +202,10 @@ def test_crew_with_multiple_tasks(self): Verification: - 1 CHAIN span for Crew.kickoff - - 2 AGENT spans (one per task execution) - 2 TASK spans - - 2 LLM spans - - Metrics: genai_calls_count=2 + - 2 AGENT spans (one per task execution) + - Trace continuity: all spans share the same Trace ID + - Hierarchical consistency: Tasks belong to the Crew trace """ # Create Agent agent = Agent( @@ -235,20 +241,110 @@ def test_crew_with_multiple_tasks(self): # Verify spans spans = self.memory_exporter.get_finished_spans() - chain_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "CHAIN"] - task_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "TASK"] + chain_spans = [ + s + for s in spans + if s.attributes.get("gen_ai.operation.name") == "crew.kickoff" + ] + task_spans = [ + s + for s in spans + if s.attributes.get("gen_ai.operation.name") == "task.execute" + ] + + self.assertGreaterEqual(len(chain_spans), 1) + self.assertEqual(len(task_spans), 2) + + # Verify Trace Continuity + trace_id = chain_spans[0].context.trace_id + for s in spans: + self.assertEqual( + s.context.trace_id, + trace_id, + "Trace ID must be consistent across multiple tasks", + ) + + # Verify structure: Tasks should belong to the same trace and have a parent + # Note: Depending on CrewAI internal logic, tasks might be direct or indirect children of Crew + for t_span in task_spans: + self.assertIsNotNone( + t_span.parent, "All tasks should have a parent" + ) + self.assertEqual( + t_span.context.trace_id, + trace_id, + "Tasks should belong to the Crew trace", + ) + + def test_sync_call_with_error(self): + """ + Test synchronous Crew execution with error during LLM call. - # Should have 1 CHAIN span and 2 TASK spans - self.assertGreaterEqual(len(chain_spans), 1, "Expected at least 1 CHAIN span") - self.assertGreaterEqual(len(task_spans), 2, f"Expected at least 2 TASK spans, got {len(task_spans)}") + Verification: + - At least one span has ERROR status + - Exception events recorded + - Inputs captured even on failure + """ + # Use invalid model name to trigger error + agent = Agent( + role="Content Writer", + goal="Write content", + backstory="Expert writer", + verbose=False, + llm="invalid-model-name", + ) - # Verify metrics show 2 LLM calls - metrics = self.memory_metrics_reader.get_metrics_data() + task = Task( + description="Write a message", + expected_output="A message", + agent=agent, + ) + + crew = Crew( + agents=[agent], + tasks=[task], + verbose=False, + ) + + # Expect error during execution + try: + crew.kickoff() + except Exception: + pass # Expected + + # Verify spans for error state + spans = self.memory_exporter.get_finished_spans() + + # Filter agent span (where error usually originated in this case) + error_spans = [ + s for s in spans if s.status.status_code == StatusCode.ERROR + ] + self.assertGreaterEqual( + len(error_spans), 1, "At least one span should be marked as ERROR" + ) - for resource_metrics in metrics.resource_metrics: - for scope_metrics in resource_metrics.scope_metrics: - for metric in scope_metrics.metrics: - if metric.name == "genai_calls_count": - for data_point in metric.data.data_points: - # Should have at least 2 calls - self.assertGreaterEqual(data_point.value, 2, f"Expected at least 2 LLM calls, got {data_point.value}") + for span in error_spans: + # 1. Verify Status + self.assertEqual(span.status.status_code, StatusCode.ERROR) + + # 2. Verify Exception Events + self.assertGreater( + len(span.events), + 0, + "Span should have recorded exception events", + ) + exception_events = [ + e for e in span.events if e.name == "exception" + ] + self.assertGreater( + len(exception_events), 0, "Should contain 'exception' event" + ) + + # 3. Verify Input Capture (even on failure) + op_name = span.attributes.get("gen_ai.operation.name") + if op_name in ["task.execute", "agent.execute"]: + input_messages = span.attributes.get("gen_ai.input.messages") + self.assertIsNotNone( + input_messages, + f"Span {op_name} should capture inputs even on failure", + ) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py index 49a764082..b845230b6 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py @@ -13,31 +13,35 @@ # limitations under the License. """ -Test cases for tool calls and MCP integration in CrewAI. +Test cases for tool calls and function calling in CrewAI. Business Demo Description: This test suite uses CrewAI framework to create Agents that use tools for -function calling. The demo includes custom tools and verifies that tool -invocations are properly traced with arguments and results. +function calling. It verifies that tool invocations are properly traced as +OpenTelemetry GenAI TOOL spans, capturing tool names, arguments, and results +in a standardized format. """ -import pysqlite3 -import sys -sys.modules["sqlite3"] = pysqlite3 + +import json import os -from crewai import Agent, Task, Crew +import sys + +import pysqlite3 +from crewai import Agent, Crew, Task from crewai.tools.base_tool import BaseTool -from opentelemetry.instrumentation.litellm import LiteLLMInstrumentor from opentelemetry.instrumentation.crewai import CrewAIInstrumentor from opentelemetry.test.test_base import TestBase +sys.modules["sqlite3"] = pysqlite3 + class WeatherTool(BaseTool): """Sample tool for weather lookup.""" - + name: str = "get_weather" description: str = "Get current weather for a location" - + def _run(self, location: str) -> str: """Execute the tool.""" return f"Weather in {location}: Sunny, 72°F" @@ -45,10 +49,10 @@ def _run(self, location: str) -> str: class CalculatorTool(BaseTool): """Sample tool for calculations.""" - + name: str = "calculator" description: str = "Perform mathematical calculations" - + def _run(self, expression: str) -> str: """Execute the tool.""" try: @@ -65,44 +69,46 @@ def setUp(self): """Setup test resources.""" super().setUp() # Set up environment variables - os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "test-openai-key-placeholder") - os.environ["DASHSCOPE_API_KEY"] = os.getenv("DASHSCOPE_API_KEY", "test-dashscope-key-placeholder") - os.environ["OPENAI_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" - os.environ["DASHSCOPE_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1" - + os.environ["OPENAI_API_KEY"] = os.environ.get( + "OPENAI_API_KEY", "fake-key" + ) + os.environ["DASHSCOPE_API_KEY"] = os.environ.get( + "DASHSCOPE_API_KEY", "fake-key" + ) + os.environ["OPENAI_API_BASE"] = ( + "https://dashscope.aliyuncs.com/compatible-mode/v1" + ) + os.environ["DASHSCOPE_API_BASE"] = ( + "https://dashscope.aliyuncs.com/compatible-mode/v1" + ) + + os.environ["CREWAI_TRACING_ENABLED"] = "false" self.instrumentor = CrewAIInstrumentor() - self.instrumentor.instrument() + self.instrumentor.instrument(tracer_provider=self.tracer_provider) - self.litellm_instrumentor = LiteLLMInstrumentor() - self.litellm_instrumentor.instrument() - # Test data - self.model_name = "dashscope/qwen-turbo" - + self.model_name = "openai/qwen-turbo" + def tearDown(self): """Cleanup test resources.""" with self.disable_logging(): self.instrumentor.uninstrument() - self.litellm_instrumentor.uninstrument() super().tearDown() - from aliyun.sdk.extension.arms.semconv.metrics import SingletonMeta - SingletonMeta.reset() def test_agent_with_single_tool(self): """ Test Agent execution with a single tool call. - + Business Demo: - Creates a Crew with 1 Agent - Agent has access to 1 tool (WeatherTool) - Executes 1 Task that triggers tool usage - Performs 1 LLM call + 1 tool call - + Verification: - - TOOL span with gen_ai.tool.name, gen_ai.tool.description - - TOOL span with gen_ai.tool.call.arguments and gen_ai.tool.call.result - - AGENT span contains tool execution context - - Metrics: genai_calls_count includes tool-triggered LLM calls + - TOOL span created with gen_ai.operation.name="tool.execute" + - Captured gen_ai.tool.name and tool input/output messages + - Hierarchical consistency: TOOL span is a child of AGENT span """ # Create tool weather_tool = WeatherTool() @@ -135,35 +141,56 @@ def test_agent_with_single_tool(self): # Verify spans spans = self.memory_exporter.get_finished_spans() - - tool_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "TOOL"] - agent_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "AGENT"] + + tool_spans = [ + s + for s in spans + if s.attributes.get("gen_ai.operation.name") == "tool.execute" + ] + agent_spans = [ + s + for s in spans + if s.attributes.get("gen_ai.operation.name") == "agent.execute" + ] # Verify TOOL span (if tool wrapper was successful) if tool_spans: tool_span = tool_spans[0] - self.assertEqual(tool_span.attributes.get("gen_ai.span.kind"), "TOOL") - self.assertIsNotNone(tool_span.attributes.get("gen_ai.tool.name")) - # Tool description and arguments may be present - # Tool result should be captured + self.assertEqual( + tool_span.attributes.get("gen_ai.operation.name"), + "tool.execute", + ) + self.assertEqual( + tool_span.attributes.get("gen_ai.tool.name"), "get_weather" + ) + + output_messages_json = tool_span.attributes.get( + "gen_ai.output.messages" + ) + self.assertIsNotNone(output_messages_json) + output_messages = json.loads(output_messages_json) + # Weather logic in WeatherTool returns weather string + self.assertIn("Sunny", output_messages[0]["parts"][0]["content"]) # Verify AGENT span exists - self.assertGreaterEqual(len(agent_spans), 1, "Expected at least 1 AGENT span") + self.assertGreaterEqual( + len(agent_spans), 1, "Expected at least 1 AGENT span" + ) def test_agent_with_multiple_tools(self): """ Test Agent execution with multiple tool calls. - + Business Demo: - Creates a Crew with 1 Agent - Agent has access to 2 tools (WeatherTool, CalculatorTool) - Executes 1 Task that may trigger multiple tool usages - Performs multiple LLM calls + multiple tool calls - + Verification: - Multiple TOOL spans, each with correct tool name - - Each TOOL span has proper arguments and results - - Metrics: genai_calls_count reflects all LLM calls + - Each TOOL span has proper input arguments and output results + - Trace continuity across multiple nested tool calls """ # Create tools weather_tool = WeatherTool() @@ -197,35 +224,40 @@ def test_agent_with_multiple_tools(self): # Verify spans spans = self.memory_exporter.get_finished_spans() - - tool_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "TOOL"] - + + tool_spans = [ + s for s in spans if s.attributes.get("gen_ai.span.kind") == "TOOL" + ] + # May have multiple tool spans if tools were actually called # Each tool span should have proper attributes for tool_span in tool_spans: - self.assertEqual(tool_span.attributes.get("gen_ai.span.kind"), "TOOL") + self.assertEqual( + tool_span.attributes.get("gen_ai.operation.name"), + "tool.execute", + ) self.assertIsNotNone(tool_span.attributes.get("gen_ai.tool.name")) def test_tool_call_with_error(self): """ Test tool call that raises an error. - + Business Demo: - Creates a Crew with 1 Agent - Agent uses a tool that fails - Executes 1 Task with failing tool call - + Verification: - - TOOL span has ERROR status - - TOOL span records exception - - Metrics: genai_calls_error_count may increment if tool failure triggers LLM error + - TOOL span status set to StatusCode.ERROR + - Recorded exception details in span events """ + # Create a tool that raises error class FailingTool(BaseTool): name: str = "failing_tool" description: str = "A tool that always fails" - - def _run(self, input: str) -> str: + + def _run(self, input_str: str) -> str: raise Exception("Tool execution failed") failing_tool = FailingTool() @@ -259,12 +291,15 @@ def _run(self, input: str) -> str: # Verify spans spans = self.memory_exporter.get_finished_spans() - - tool_spans = [s for s in spans if s.attributes.get("gen_ai.span.kind") == "TOOL"] - + + tool_spans = [ + s + for s in spans + if s.attributes.get("gen_ai.operation.name") == "tool.execute" + ] + # If tool span exists, verify error status for tool_span in tool_spans: if tool_span.name.startswith("Tool.failing_tool"): # Should have error status self.assertEqual(tool_span.status.status_code.name, "ERROR") - From f19239c6a162ab41d9f97b1ca32e65628ebeba43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=8E=E7=9B=B4?= Date: Mon, 2 Feb 2026 13:47:59 +0800 Subject: [PATCH 04/14] fix the CI failure. --- .../README.md | 2 +- .../pyproject.toml | 6 -- .../instrumentation/crewai/__init__.py | 23 ++---- .../instrumentation/crewai/utils.py | 16 +--- .../test-requirements.txt | 2 +- .../tests/test_flow_kickoff.py | 78 +++++++------------ .../tests/test_tool_calls.py | 5 +- 7 files changed, 48 insertions(+), 84 deletions(-) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/README.md b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/README.md index ca0457763..8e20a0c4e 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/README.md +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/README.md @@ -42,7 +42,7 @@ result = crew.kickoff() ## Supported Versions -- CrewAI >= 0.1.0 +- CrewAI >= 0.70.0 ## References diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml index 2f342ec89..3a68cc902 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml @@ -17,9 +17,6 @@ classifiers = [ "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", @@ -27,9 +24,6 @@ classifiers = [ dependencies = [ "opentelemetry-api ~= 1.34.0", "wrapt >= 1.0.0, < 2.0.0", -# "opentelemetry-api ~=1.37", -# "opentelemetry-instrumentation >=0.58b0, <2", -# "opentelemetry-semantic-conventions >=0.58b0, <2", "opentelemetry-util-genai ~= 0.1b0", ] diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py index d60ed326d..60c8d0224 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py @@ -22,7 +22,6 @@ from wrapt import wrap_function_wrapper -from opentelemetry import context as context_api from opentelemetry import trace as trace_api # Import hook system for decoupled extensions @@ -42,7 +41,6 @@ from opentelemetry.instrumentation.utils import unwrap from opentelemetry.semconv._incubating.attributes import gen_ai_attributes from opentelemetry.trace import SpanKind, Status, StatusCode -from opentelemetry.util.genai.completion_hook import load_completion_hook try: import crewai.agent @@ -58,14 +56,6 @@ logger = logging.getLogger(__name__) -# Context keys for tracking -_CREWAI_SPAN_KEY = context_api.create_key("crewai_span") -_CREWAI_START_TIME_KEY = context_api.create_key("crewai_start_time") -_CREWAI_LITELLM_RESPONSE_KEY = context_api.create_key( - "crewai_litellm_response" -) - - class CrewAIInstrumentor(BaseInstrumentor): """ An instrumentor for CrewAI framework. @@ -84,9 +74,7 @@ def _instrument(self, **kwargs: Any) -> None: tracer_provider=tracer_provider, ) - completion_hook = load_completion_hook() - - genai_helper = GenAIHookHelper(completion_hook=completion_hook) + genai_helper = GenAIHookHelper() # Wrap Crew.kickoff (CHAIN span) try: @@ -193,6 +181,7 @@ def __call__(self, wrapped, instance, args, kwargs): return result except Exception as e: span.record_exception(e) + span.set_status(Status(StatusCode.ERROR)) self._helper.on_completion(span, genai_inputs, []) raise @@ -204,7 +193,7 @@ def __init__(self, tracer: trace_api.Tracer, helper: GenAIHookHelper): self._tracer = tracer self._helper = helper - def __call__(self, wrapped, instance, args, kwargs): + async def __call__(self, wrapped, instance, args, kwargs): """Wrap Flow.kickoff_async to create CHAIN span.""" inputs = kwargs.get("inputs", {}) flow_name = getattr(instance, "name", None) or "flow.kickoff" @@ -220,13 +209,14 @@ def __call__(self, wrapped, instance, args, kwargs): }, ) as span: try: - result = wrapped(*args, **kwargs) + result = await wrapped(*args, **kwargs) genai_outputs = to_output_message("assistant", result) self._helper.on_completion(span, genai_inputs, genai_outputs) span.set_status(Status(StatusCode.OK)) return result except Exception as e: span.record_exception(e) + span.set_status(Status(StatusCode.ERROR)) self._helper.on_completion(span, genai_inputs, []) raise @@ -268,6 +258,7 @@ def __call__(self, wrapped, instance, args, kwargs): return result except Exception as e: span.record_exception(e) + span.set_status(Status(StatusCode.ERROR)) self._helper.on_completion(span, genai_inputs, []) raise @@ -302,6 +293,7 @@ def __call__(self, wrapped, instance, args, kwargs): return result except Exception as e: span.record_exception(e) + span.set_status(Status(StatusCode.ERROR)) self._helper.on_completion(span, genai_inputs, []) raise @@ -361,5 +353,6 @@ def __call__(self, wrapped, instance, args, kwargs): return result except Exception as e: span.record_exception(e) + span.set_status(Status(StatusCode.ERROR)) self._helper.on_completion(span, genai_inputs, []) raise diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py index f728a9127..9b33f83f0 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py @@ -5,7 +5,6 @@ from typing import Any, Dict, List, Optional from opentelemetry.trace import Span -from opentelemetry.util.genai.completion_hook import CompletionHook from opentelemetry.util.genai.types import ( InputMessage, MessagePart, @@ -55,8 +54,6 @@ def _safe_json_dumps( return result -gen_ai_json_dumps = _safe_json_dumps - GEN_AI_INPUT_MESSAGES = "gen_ai.input.messages" GEN_AI_OUTPUT_MESSAGES = "gen_ai.output.messages" GEN_AI_SYSTEM_INSTRUCTIONS = "gen_ai.system_instructions" @@ -68,10 +65,7 @@ def _safe_json_dumps( class GenAIHookHelper: - def __init__( - self, completion_hook: CompletionHook, capture_content: bool = True - ): - self.completion_hook = completion_hook + def __init__(self, capture_content: bool = True): self.capture_content = capture_content def on_completion( @@ -86,19 +80,17 @@ def on_completion( if inputs: span.set_attribute( GEN_AI_INPUT_MESSAGES, - gen_ai_json_dumps([dataclasses.asdict(i) for i in inputs]), + _safe_json_dumps([dataclasses.asdict(i) for i in inputs]), ) if outputs: span.set_attribute( GEN_AI_OUTPUT_MESSAGES, - gen_ai_json_dumps( - [dataclasses.asdict(o) for o in outputs] - ), + _safe_json_dumps([dataclasses.asdict(o) for o in outputs]), ) if system_instructions: span.set_attribute( GEN_AI_SYSTEM_INSTRUCTIONS, - gen_ai_json_dumps( + _safe_json_dumps( [dataclasses.asdict(i) for i in system_instructions] ), ) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt index ecc8f5af1..6faf92891 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt @@ -1,4 +1,4 @@ -crewai>=0.80.0 +crewai>=0.70.0 litellm>=1.79.0 openai>=2.0.0 respx>=0.20.0 diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_flow_kickoff.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_flow_kickoff.py index ddf4dd519..eb6ec8560 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_flow_kickoff.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_flow_kickoff.py @@ -24,9 +24,8 @@ import json import unittest -from unittest.mock import MagicMock +from unittest.mock import AsyncMock, MagicMock -from opentelemetry import trace as trace_api from opentelemetry.instrumentation.crewai import ( GenAIHookHelper, _FlowKickoffAsyncWrapper, @@ -40,31 +39,15 @@ InMemorySpanExporter, ) from opentelemetry.trace import SpanKind, StatusCode -from opentelemetry.util.genai.completion_hook import load_completion_hook -class TestFlowKickoffAsyncWrapper(unittest.TestCase): +class TestFlowKickoffAsyncWrapper(unittest.IsolatedAsyncioTestCase): """Test _FlowKickoffAsyncWrapper class.""" def setUp(self): """Setup test resources.""" # Create tracer provider with in-memory exporter self.memory_exporter = InMemorySpanExporter() - self.tracer_provider = TracerProvider() - self.tracer_provider.add_span_processor( - trace_api.get_tracer_provider() - .get_tracer(__name__) - .__class__.__bases__[0] - .__subclasses__()[0](self.memory_exporter) - if hasattr( - trace_api.get_tracer_provider() - .get_tracer(__name__) - .__class__.__bases__[0], - "__subclasses__", - ) - else None - ) - self.tracer_provider = TracerProvider() self.tracer_provider.add_span_processor( SimpleSpanProcessor(self.memory_exporter) @@ -72,8 +55,7 @@ def setUp(self): self.tracer = self.tracer_provider.get_tracer(__name__) # Create wrapper instance - completion_hook = load_completion_hook() - self.helper = GenAIHookHelper(completion_hook=completion_hook) + self.helper = GenAIHookHelper() self.wrapper = _FlowKickoffAsyncWrapper(self.tracer, self.helper) def tearDown(self): @@ -86,7 +68,7 @@ def test_wrapper_init(self): self.assertEqual(wrapper._tracer, self.tracer) self.assertEqual(wrapper._helper, self.helper) - def test_basic_flow_kickoff(self): + async def test_basic_flow_kickoff(self): """ Test basic flow kickoff creates CHAIN span with correct attributes. @@ -98,14 +80,14 @@ def test_basic_flow_kickoff(self): - Status is OK """ # Create mock wrapped function - mock_wrapped = MagicMock(return_value="flow result") + mock_wrapped = AsyncMock(return_value="flow result") # Create mock flow instance with name mock_instance = MagicMock() mock_instance.name = "test_flow" # Call wrapper - result = self.wrapper(mock_wrapped, mock_instance, (), {}) + result = await self.wrapper(mock_wrapped, mock_instance, (), {}) # Verify wrapped function was called mock_wrapped.assert_called_once_with() @@ -129,7 +111,7 @@ def test_basic_flow_kickoff(self): self.assertIn("flow result", output_messages[0]["parts"][0]["content"]) self.assertEqual(span.status.status_code, StatusCode.OK) - def test_flow_kickoff_without_name(self): + async def test_flow_kickoff_without_name(self): """ Test flow kickoff when instance has no name attribute. @@ -138,13 +120,13 @@ def test_flow_kickoff_without_name(self): - Span is created with default name """ # Create mock wrapped function - mock_wrapped = MagicMock(return_value="result") + mock_wrapped = AsyncMock(return_value="result") # Create mock flow instance without name mock_instance = MagicMock(spec=[]) # No name attribute # Call wrapper - self.wrapper(mock_wrapped, mock_instance, (), {}) + await self.wrapper(mock_wrapped, mock_instance, (), {}) # Verify span was created with default name spans = self.memory_exporter.get_finished_spans() @@ -156,7 +138,7 @@ def test_flow_kickoff_without_name(self): span.attributes.get("gen_ai.operation.name"), "crew.kickoff" ) - def test_flow_kickoff_with_inputs(self): + async def test_flow_kickoff_with_inputs(self): """ Test flow kickoff with input parameters. @@ -165,7 +147,7 @@ def test_flow_kickoff_with_inputs(self): - Inputs are properly serialized to JSON """ # Create mock wrapped function - mock_wrapped = MagicMock(return_value="processed result") + mock_wrapped = AsyncMock(return_value="processed result") # Create mock flow instance mock_instance = MagicMock() @@ -173,7 +155,7 @@ def test_flow_kickoff_with_inputs(self): # Call wrapper with inputs inputs = {"query": "test query", "count": 10} - self.wrapper(mock_wrapped, mock_instance, (), {"inputs": inputs}) + await self.wrapper(mock_wrapped, mock_instance, (), {"inputs": inputs}) # Verify wrapped function was called with correct kwargs mock_wrapped.assert_called_once_with(inputs=inputs) @@ -192,7 +174,7 @@ def test_flow_kickoff_with_inputs(self): self.assertIn("test query", content) self.assertIn("10", content) - def test_flow_kickoff_with_args(self): + async def test_flow_kickoff_with_args(self): """ Test flow kickoff with positional arguments. @@ -200,14 +182,14 @@ def test_flow_kickoff_with_args(self): - Args are passed to wrapped function """ # Create mock wrapped function - mock_wrapped = MagicMock(return_value="result with args") + mock_wrapped = AsyncMock(return_value="result with args") # Create mock flow instance mock_instance = MagicMock() mock_instance.name = "args_flow" # Call wrapper with args - result = self.wrapper( + result = await self.wrapper( mock_wrapped, mock_instance, ("arg1", "arg2"), {} ) @@ -215,7 +197,7 @@ def test_flow_kickoff_with_args(self): mock_wrapped.assert_called_once_with("arg1", "arg2") self.assertEqual(result, "result with args") - def test_flow_kickoff_exception_handling(self): + async def test_flow_kickoff_exception_handling(self): """ Test flow kickoff exception handling. @@ -226,7 +208,7 @@ def test_flow_kickoff_exception_handling(self): """ # Create mock wrapped function that raises exception test_exception = ValueError("Test error in flow") - mock_wrapped = MagicMock(side_effect=test_exception) + mock_wrapped = AsyncMock(side_effect=test_exception) # Create mock flow instance mock_instance = MagicMock() @@ -234,7 +216,7 @@ def test_flow_kickoff_exception_handling(self): # Call wrapper and expect exception with self.assertRaises(ValueError) as context: - self.wrapper(mock_wrapped, mock_instance, (), {}) + await self.wrapper(mock_wrapped, mock_instance, (), {}) self.assertEqual(str(context.exception), "Test error in flow") @@ -251,7 +233,7 @@ def test_flow_kickoff_exception_handling(self): exception_event = span.events[0] self.assertEqual(exception_event.name, "exception") - def test_flow_kickoff_with_none_name(self): + async def test_flow_kickoff_with_none_name(self): """ Test flow kickoff when instance.name is None. @@ -259,14 +241,14 @@ def test_flow_kickoff_with_none_name(self): - Uses default name "flow.kickoff" when name is None """ # Create mock wrapped function - mock_wrapped = MagicMock(return_value="result") + mock_wrapped = AsyncMock(return_value="result") # Create mock flow instance with None name mock_instance = MagicMock() mock_instance.name = None # Call wrapper - self.wrapper(mock_wrapped, mock_instance, (), {}) + await self.wrapper(mock_wrapped, mock_instance, (), {}) # Verify span was created with default name spans = self.memory_exporter.get_finished_spans() @@ -278,7 +260,7 @@ def test_flow_kickoff_with_none_name(self): span.attributes.get("gen_ai.operation.name"), "crew.kickoff" ) - def test_flow_kickoff_with_complex_result(self): + async def test_flow_kickoff_with_complex_result(self): """ Test flow kickoff with complex result object. @@ -292,14 +274,14 @@ def test_flow_kickoff_with_complex_result(self): "data": {"items": [1, 2, 3]}, "message": "Flow completed", } - mock_wrapped = MagicMock(return_value=complex_result) + mock_wrapped = AsyncMock(return_value=complex_result) # Create mock flow instance mock_instance = MagicMock() mock_instance.name = "complex_flow" # Call wrapper - result = self.wrapper(mock_wrapped, mock_instance, (), {}) + result = await self.wrapper(mock_wrapped, mock_instance, (), {}) # Verify result is returned correctly self.assertEqual(result, complex_result) @@ -317,7 +299,7 @@ def test_flow_kickoff_with_complex_result(self): self.assertIn("success", content) self.assertIn("Flow completed", content) - def test_flow_kickoff_with_none_result(self): + async def test_flow_kickoff_with_none_result(self): """ Test flow kickoff when wrapped function returns None. @@ -326,14 +308,14 @@ def test_flow_kickoff_with_none_result(self): - output.value is set appropriately """ # Create mock wrapped function returning None - mock_wrapped = MagicMock(return_value=None) + mock_wrapped = AsyncMock(return_value=None) # Create mock flow instance mock_instance = MagicMock() mock_instance.name = "none_result_flow" # Call wrapper - result = self.wrapper(mock_wrapped, mock_instance, (), {}) + result = await self.wrapper(mock_wrapped, mock_instance, (), {}) # Verify result is None self.assertIsNone(result) @@ -345,7 +327,7 @@ def test_flow_kickoff_with_none_result(self): span = spans[0] self.assertEqual(span.status.status_code, StatusCode.OK) - def test_flow_kickoff_span_kind(self): + async def test_flow_kickoff_span_kind(self): """ Test that flow kickoff span has correct SpanKind. @@ -353,14 +335,14 @@ def test_flow_kickoff_span_kind(self): - Span kind is INTERNAL """ # Create mock wrapped function - mock_wrapped = MagicMock(return_value="result") + mock_wrapped = AsyncMock(return_value="result") # Create mock flow instance mock_instance = MagicMock() mock_instance.name = "kind_test_flow" # Call wrapper - self.wrapper(mock_wrapped, mock_instance, (), {}) + await self.wrapper(mock_wrapped, mock_instance, (), {}) # Verify span kind spans = self.memory_exporter.get_finished_spans() diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py index b845230b6..24e4385f9 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py @@ -56,7 +56,10 @@ class CalculatorTool(BaseTool): def _run(self, expression: str) -> str: """Execute the tool.""" try: - result = eval(expression) + # Safely evaluate mathematical expressions by restricting builtins + # In a real tool, use a library like numexpr or simpleeval + safe_dict = {"__builtins__": None} + result = eval(expression, safe_dict, {}) return f"Result: {result}" except Exception as e: return f"Error: {str(e)}" From 3a26c2addf10a3fd4300aa5abb3124ac1c4a9323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=8E=E7=9B=B4?= Date: Mon, 2 Feb 2026 14:10:48 +0800 Subject: [PATCH 05/14] Maintain a consistent style for status settings. --- .../src/opentelemetry/instrumentation/crewai/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py index 60c8d0224..c0586f006 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py @@ -338,6 +338,7 @@ def __call__(self, wrapped, instance, args, kwargs): self._helper.on_completion(span, genai_inputs, genai_outputs) + is_error = False if instance: _run_attempts = getattr(instance, "_run_attempts", None) _max_parsing_attempts = getattr( @@ -349,6 +350,10 @@ def __call__(self, wrapped, instance, args, kwargs): and _run_attempts > _max_parsing_attempts ): span.set_status(Status(StatusCode.ERROR)) + is_error = True + + if not is_error: + span.set_status(Status(StatusCode.OK)) return result except Exception as e: From 04ea7327ed762540900f91c1a5218f194d77ba7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=8E=E7=9B=B4?= Date: Tue, 10 Feb 2026 16:01:26 +0800 Subject: [PATCH 06/14] Refactor and modify the corresponding unit tests using genai 0.3b0; Disable the eval function and modify some version information; Add a changelog. --- CHANGELOG-loongsuite.md | 3 + .../README.md | 2 +- .../pyproject.toml | 8 +- .../instrumentation/crewai/utils.py | 86 +++++++------------ .../tests/test_agent_workflow.py | 25 ++++++ .../tests/test_error_scenarios.py | 25 ++++++ .../tests/test_flow_kickoff.py | 69 ++++++++------- .../tests/test_prompt_and_memory.py | 25 ++++++ .../tests/test_streaming_llm_calls.py | 25 ++++++ .../tests/test_sync_llm_calls.py | 26 ++++++ .../tests/test_tool_calls.py | 60 +++++++++++-- 11 files changed, 260 insertions(+), 94 deletions(-) diff --git a/CHANGELOG-loongsuite.md b/CHANGELOG-loongsuite.md index 8a20127fa..637e782ee 100644 --- a/CHANGELOG-loongsuite.md +++ b/CHANGELOG-loongsuite.md @@ -22,3 +22,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `loongsuite-distro`: initialize loongsuite python agent distro ([#126](https://github.com/alibaba/loongsuite-python-agent/pull/126)) + +- `loongsuite-instrumentation-crewai`: add support for crewai + ([#87](https://github.com/alibaba/loongsuite-python-agent/pull/87)) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/README.md b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/README.md index 8e20a0c4e..4176dd55c 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/README.md +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/README.md @@ -42,7 +42,7 @@ result = crew.kickoff() ## Supported Versions -- CrewAI >= 0.70.0 +- CrewAI >= 0.80.0 ## References diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml index 3a68cc902..16309567e 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml @@ -22,14 +22,16 @@ classifiers = [ "Programming Language :: Python :: 3.12", ] dependencies = [ - "opentelemetry-api ~= 1.34.0", + "opentelemetry-api ~= 1.39.1", + "opentelemetry-instrumentation ~= 0.60b0", + "opentelemetry-semantic-conventions ~= 0.60b0", "wrapt >= 1.0.0, < 2.0.0", - "opentelemetry-util-genai ~= 0.1b0", + "opentelemetry-util-genai ~= 0.3b0", ] [project.optional-dependencies] instruments = [ - "crewai >= 0.1.0", + "crewai >= 0.80.0", ] [project.entry-points.opentelemetry_instrumentor] diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py index 9b33f83f0..bb1528996 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py @@ -1,63 +1,25 @@ import dataclasses -import json import logging -from base64 import b64encode from typing import Any, Dict, List, Optional +from opentelemetry.semconv._incubating.attributes import gen_ai_attributes from opentelemetry.trace import Span from opentelemetry.util.genai.types import ( + ContentCapturingMode, InputMessage, MessagePart, OutputMessage, Text, ToolCall, ) +from opentelemetry.util.genai.utils import ( + gen_ai_json_dumps, + get_content_capturing_mode, + is_experimental_mode, +) logger = logging.getLogger(__name__) -MAX_MESSAGE_SIZE = 10000 - - -class _GenAiJsonEncoder(json.JSONEncoder): - def default(self, o: Any) -> Any: - if isinstance(o, bytes): - return b64encode(o).decode() - return super().default(o) - - -def _safe_json_dumps( - obj: Any, default: str = "", max_size: int = MAX_MESSAGE_SIZE -) -> str: - """ - Safely serialize object to JSON string with size limit. - """ - if obj is None: - return default - - # Fast path for simple types - if isinstance(obj, (str, int, float, bool)): - result = str(obj) - else: - try: - result = json.dumps( - obj, - separators=(",", ":"), - cls=_GenAiJsonEncoder, - ensure_ascii=False, - ) - except Exception as e: - logger.debug(f"Failed to serialize to JSON: {e}") - result = str(obj) - - if len(result) > max_size: - return result[:max_size] + "...[truncated]" - return result - - -GEN_AI_INPUT_MESSAGES = "gen_ai.input.messages" -GEN_AI_OUTPUT_MESSAGES = "gen_ai.output.messages" -GEN_AI_SYSTEM_INSTRUCTIONS = "gen_ai.system_instructions" - OP_NAME_CREW = "crew.kickoff" OP_NAME_AGENT = "agent.execute" OP_NAME_TASK = "task.execute" @@ -76,27 +38,41 @@ def on_completion( system_instructions: Optional[List[MessagePart]] = None, attributes: Optional[Dict[str, Any]] = None, ): - if self.capture_content and span.is_recording(): + if not self.capture_content or not span.is_recording(): + return + + if not is_experimental_mode(): + return + + capturing_mode = get_content_capturing_mode() + should_capture_span = capturing_mode in ( + ContentCapturingMode.SPAN_ONLY, + ContentCapturingMode.SPAN_AND_EVENT, + ) + + if should_capture_span: if inputs: span.set_attribute( - GEN_AI_INPUT_MESSAGES, - _safe_json_dumps([dataclasses.asdict(i) for i in inputs]), + gen_ai_attributes.GEN_AI_INPUT_MESSAGES, + gen_ai_json_dumps([dataclasses.asdict(i) for i in inputs]), ) if outputs: span.set_attribute( - GEN_AI_OUTPUT_MESSAGES, - _safe_json_dumps([dataclasses.asdict(o) for o in outputs]), + gen_ai_attributes.GEN_AI_OUTPUT_MESSAGES, + gen_ai_json_dumps( + [dataclasses.asdict(o) for o in outputs] + ), ) if system_instructions: span.set_attribute( - GEN_AI_SYSTEM_INSTRUCTIONS, - _safe_json_dumps( + gen_ai_attributes.GEN_AI_SYSTEM_INSTRUCTIONS, + gen_ai_json_dumps( [dataclasses.asdict(i) for i in system_instructions] ), ) - if attributes: - span.set_attributes(attributes) + if attributes: + span.set_attributes(attributes) def to_input_message(role: str, content: Any) -> List[InputMessage]: @@ -144,7 +120,7 @@ def extract_agent_inputs( def extract_tool_inputs(tool_name: str, arguments: Any) -> List[InputMessage]: args_str = ( - json.dumps(arguments) + gen_ai_json_dumps(arguments) if isinstance(arguments, dict) else str(arguments) ) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_agent_workflow.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_agent_workflow.py index de119579c..124393f9c 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_agent_workflow.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_agent_workflow.py @@ -29,6 +29,17 @@ from opentelemetry.instrumentation.crewai import CrewAIInstrumentor from opentelemetry.test.test_base import TestBase +try: + from opentelemetry.instrumentation._semconv import ( + _OpenTelemetrySemanticConventionStability, + _OpenTelemetryStabilitySignalType, + _StabilityMode, + ) +except ImportError: + _OpenTelemetrySemanticConventionStability = None + _OpenTelemetryStabilitySignalType = None + _StabilityMode = None + sys.modules["sqlite3"] = pysqlite3 @@ -53,6 +64,20 @@ def setUp(self): ) os.environ["CREWAI_TRACING_ENABLED"] = "false" + # Enable experimental mode and content capture for testing + os.environ["OTEL_SEMCONV_STABILITY_OPT_IN"] = "gen_ai" + os.environ["OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"] = ( + "span_only" + ) + + if _OpenTelemetrySemanticConventionStability: + try: + _OpenTelemetrySemanticConventionStability._OTEL_SEMCONV_STABILITY_SIGNAL_MAPPING[ + _OpenTelemetryStabilitySignalType.GEN_AI + ] = _StabilityMode.GEN_AI_LATEST_EXPERIMENTAL + except (AttributeError, KeyError): + pass + self.instrumentor = CrewAIInstrumentor() self.instrumentor.instrument(tracer_provider=self.tracer_provider) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_error_scenarios.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_error_scenarios.py index 621d4d432..b3db76100 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_error_scenarios.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_error_scenarios.py @@ -34,6 +34,17 @@ from opentelemetry.test.test_base import TestBase from opentelemetry.trace import StatusCode +try: + from opentelemetry.instrumentation._semconv import ( + _OpenTelemetrySemanticConventionStability, + _OpenTelemetryStabilitySignalType, + _StabilityMode, + ) +except ImportError: + _OpenTelemetrySemanticConventionStability = None + _OpenTelemetryStabilitySignalType = None + _StabilityMode = None + sys.modules["sqlite3"] = pysqlite3 @@ -60,6 +71,20 @@ def setUp(self): # Disable CrewAI's built-in tracing to avoid interference os.environ["CREWAI_TRACING_ENABLED"] = "false" + # Enable experimental mode and content capture for testing + os.environ["OTEL_SEMCONV_STABILITY_OPT_IN"] = "gen_ai" + os.environ["OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"] = ( + "span_only" + ) + + if _OpenTelemetrySemanticConventionStability: + try: + _OpenTelemetrySemanticConventionStability._OTEL_SEMCONV_STABILITY_SIGNAL_MAPPING[ + _OpenTelemetryStabilitySignalType.GEN_AI + ] = _StabilityMode.GEN_AI_LATEST_EXPERIMENTAL + except (AttributeError, KeyError): + pass + self.instrumentor = CrewAIInstrumentor() self.instrumentor.instrument(tracer_provider=self.tracer_provider) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_flow_kickoff.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_flow_kickoff.py index eb6ec8560..9a829cfc6 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_flow_kickoff.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_flow_kickoff.py @@ -22,6 +22,26 @@ - Flow name extraction from instance """ +import os + +# Set environment variables for content capture +os.environ["OTEL_SEMCONV_STABILITY_OPT_IN"] = "gen_ai" +os.environ["OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"] = "span_only" + +# Forcefully enable experimental mode in OpenTelemetry's internal mapping +try: + from opentelemetry.instrumentation._semconv import ( + _OpenTelemetrySemanticConventionStability, + _OpenTelemetryStabilitySignalType, + _StabilityMode, + ) + + _OpenTelemetrySemanticConventionStability._OTEL_SEMCONV_STABILITY_SIGNAL_MAPPING[ + _OpenTelemetryStabilitySignalType.GEN_AI + ] = _StabilityMode.GEN_AI_LATEST_EXPERIMENTAL +except (ImportError, AttributeError): + pass + import json import unittest from unittest.mock import AsyncMock, MagicMock @@ -30,7 +50,7 @@ GenAIHookHelper, _FlowKickoffAsyncWrapper, ) -from opentelemetry.instrumentation.crewai.utils import _safe_json_dumps +from opentelemetry.instrumentation.crewai.utils import gen_ai_json_dumps from opentelemetry.sdk.trace import TracerProvider # Use SDK tracer for testing @@ -352,55 +372,41 @@ async def test_flow_kickoff_span_kind(self): self.assertEqual(span.kind, SpanKind.INTERNAL) -class TestSafeJsonDumps(unittest.TestCase): - """Test _safe_json_dumps utility function.""" +class TestGenAiJsonDumps(unittest.TestCase): + """Test gen_ai_json_dumps utility function.""" def test_simple_string(self): """Test with simple string input.""" - result = _safe_json_dumps("hello") - self.assertEqual(result, "hello") + result = gen_ai_json_dumps("hello") + self.assertEqual(result, '"hello"') def test_simple_int(self): """Test with integer input.""" - result = _safe_json_dumps(42) + result = gen_ai_json_dumps(42) self.assertEqual(result, "42") def test_simple_float(self): """Test with float input.""" - result = _safe_json_dumps(3.14) + result = gen_ai_json_dumps(3.14) self.assertEqual(result, "3.14") def test_simple_bool(self): """Test with boolean input.""" - result = _safe_json_dumps(True) - self.assertEqual(result, "True") - - def test_none_returns_default(self): - """Test that None returns default value.""" - result = _safe_json_dumps(None, default="default_value") - self.assertEqual(result, "default_value") + result = gen_ai_json_dumps(True) + self.assertEqual(result, "true") def test_dict_serialization(self): """Test dictionary serialization.""" data = {"key": "value", "number": 123} - result = _safe_json_dumps(data) - self.assertIn("key", result) - self.assertIn("value", result) - self.assertIn("123", result) + result = gen_ai_json_dumps(data) + self.assertIn('"key":"value"', result) + self.assertIn('"number":123', result) def test_list_serialization(self): """Test list serialization.""" data = [1, 2, 3, "four"] - result = _safe_json_dumps(data) - self.assertIn("1", result) - self.assertIn("four", result) - - def test_truncation(self): - """Test that long strings are truncated.""" - long_string = "a" * 20000 - result = _safe_json_dumps(long_string, max_size=100) - self.assertLessEqual(len(result), 120) # Allow for truncation suffix - self.assertIn("[truncated]", result) + result = gen_ai_json_dumps(data) + self.assertEqual(result, '[1,2,3,"four"]') def test_non_serializable_object(self): """Test handling of non-serializable objects.""" @@ -409,8 +415,11 @@ class CustomObject: def __str__(self): return "CustomObject instance" - result = _safe_json_dumps(CustomObject()) - self.assertIn("CustomObject", result) + # gen_ai_json_dumps uses standard json or partial json.dump + # which might raise TypeError if not supported. + # But our partial uses _GenAiJsonEncoder. + with self.assertRaises(TypeError): + gen_ai_json_dumps(CustomObject()) if __name__ == "__main__": diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_prompt_and_memory.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_prompt_and_memory.py index 288243033..7f6bb8ead 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_prompt_and_memory.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_prompt_and_memory.py @@ -31,6 +31,17 @@ from opentelemetry.instrumentation.crewai import CrewAIInstrumentor from opentelemetry.test.test_base import TestBase +try: + from opentelemetry.instrumentation._semconv import ( + _OpenTelemetrySemanticConventionStability, + _OpenTelemetryStabilitySignalType, + _StabilityMode, + ) +except ImportError: + _OpenTelemetrySemanticConventionStability = None + _OpenTelemetryStabilitySignalType = None + _StabilityMode = None + sys.modules["sqlite3"] = pysqlite3 @@ -55,6 +66,20 @@ def setUp(self): ) os.environ["CREWAI_TRACING_ENABLED"] = "false" + # Enable experimental mode and content capture for testing + os.environ["OTEL_SEMCONV_STABILITY_OPT_IN"] = "gen_ai" + os.environ["OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"] = ( + "span_only" + ) + + if _OpenTelemetrySemanticConventionStability: + try: + _OpenTelemetrySemanticConventionStability._OTEL_SEMCONV_STABILITY_SIGNAL_MAPPING[ + _OpenTelemetryStabilitySignalType.GEN_AI + ] = _StabilityMode.GEN_AI_LATEST_EXPERIMENTAL + except (AttributeError, KeyError): + pass + self.instrumentor = CrewAIInstrumentor() self.instrumentor.instrument(tracer_provider=self.tracer_provider) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_streaming_llm_calls.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_streaming_llm_calls.py index 68c4a9ce9..3c47c3e30 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_streaming_llm_calls.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_streaming_llm_calls.py @@ -32,6 +32,17 @@ from opentelemetry.test.test_base import TestBase from opentelemetry.trace import StatusCode +try: + from opentelemetry.instrumentation._semconv import ( + _OpenTelemetrySemanticConventionStability, + _OpenTelemetryStabilitySignalType, + _StabilityMode, + ) +except ImportError: + _OpenTelemetrySemanticConventionStability = None + _OpenTelemetryStabilitySignalType = None + _StabilityMode = None + sys.modules["sqlite3"] = pysqlite3 @@ -56,6 +67,20 @@ def setUp(self): ) os.environ["CREWAI_TRACING_ENABLED"] = "false" + # Enable experimental mode and content capture for testing + os.environ["OTEL_SEMCONV_STABILITY_OPT_IN"] = "gen_ai" + os.environ["OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"] = ( + "span_only" + ) + + if _OpenTelemetrySemanticConventionStability: + try: + _OpenTelemetrySemanticConventionStability._OTEL_SEMCONV_STABILITY_SIGNAL_MAPPING[ + _OpenTelemetryStabilitySignalType.GEN_AI + ] = _StabilityMode.GEN_AI_LATEST_EXPERIMENTAL + except (AttributeError, KeyError): + pass + self.instrumentor = CrewAIInstrumentor() self.instrumentor.instrument(tracer_provider=self.tracer_provider) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_sync_llm_calls.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_sync_llm_calls.py index f8ba30add..be596d048 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_sync_llm_calls.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_sync_llm_calls.py @@ -33,6 +33,17 @@ from opentelemetry.test.test_base import TestBase from opentelemetry.trace import StatusCode +try: + from opentelemetry.instrumentation._semconv import ( + _OpenTelemetrySemanticConventionStability, + _OpenTelemetryStabilitySignalType, + _StabilityMode, + ) +except ImportError: + _OpenTelemetrySemanticConventionStability = None + _OpenTelemetryStabilitySignalType = None + _StabilityMode = None + sys.modules["sqlite3"] = pysqlite3 @@ -58,6 +69,21 @@ def setUp(self): # Disable CrewAI's built-in tracing to avoid interference with OTel spans hierarchy during tests os.environ["CREWAI_TRACING_ENABLED"] = "false" + + # Enable experimental mode and content capture for testing + os.environ["OTEL_SEMCONV_STABILITY_OPT_IN"] = "gen_ai" + os.environ["OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"] = ( + "span_only" + ) + + if _OpenTelemetrySemanticConventionStability: + try: + _OpenTelemetrySemanticConventionStability._OTEL_SEMCONV_STABILITY_SIGNAL_MAPPING[ + _OpenTelemetryStabilitySignalType.GEN_AI + ] = _StabilityMode.GEN_AI_LATEST_EXPERIMENTAL + except (AttributeError, KeyError): + pass + self.instrumentor = CrewAIInstrumentor() self.instrumentor.instrument(tracer_provider=self.tracer_provider) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py index 24e4385f9..2e022433d 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py @@ -22,7 +22,9 @@ in a standardized format. """ +import ast import json +import operator import os import sys @@ -33,6 +35,17 @@ from opentelemetry.instrumentation.crewai import CrewAIInstrumentor from opentelemetry.test.test_base import TestBase +try: + from opentelemetry.instrumentation._semconv import ( + _OpenTelemetrySemanticConventionStability, + _OpenTelemetryStabilitySignalType, + _StabilityMode, + ) +except ImportError: + _OpenTelemetrySemanticConventionStability = None + _OpenTelemetryStabilitySignalType = None + _StabilityMode = None + sys.modules["sqlite3"] = pysqlite3 @@ -54,12 +67,35 @@ class CalculatorTool(BaseTool): description: str = "Perform mathematical calculations" def _run(self, expression: str) -> str: - """Execute the tool.""" + """Execute the tool safely without using eval().""" + # Supported operators + operators = { + ast.Add: operator.add, + ast.Sub: operator.sub, + ast.Mult: operator.mul, + ast.Div: operator.truediv, + ast.Pow: operator.pow, + ast.BitXor: operator.xor, + ast.USub: operator.neg, + } + + def safe_eval(node): + if isinstance(node, ast.Num): # <3.8 + return node.n + elif isinstance(node, ast.Constant): # >=3.8 + return node.value + elif isinstance(node, ast.BinOp): + return operators[type(node.op)]( + safe_eval(node.left), safe_eval(node.right) + ) + elif isinstance(node, ast.UnaryOp): + return operators[type(node.op)](safe_eval(node.operand)) + else: + raise TypeError(f"Unsupported operation: {type(node)}") + try: - # Safely evaluate mathematical expressions by restricting builtins - # In a real tool, use a library like numexpr or simpleeval - safe_dict = {"__builtins__": None} - result = eval(expression, safe_dict, {}) + node = ast.parse(expression, mode="eval").body + result = safe_eval(node) return f"Result: {result}" except Exception as e: return f"Error: {str(e)}" @@ -86,6 +122,20 @@ def setUp(self): ) os.environ["CREWAI_TRACING_ENABLED"] = "false" + # Enable experimental mode and content capture for testing + os.environ["OTEL_SEMCONV_STABILITY_OPT_IN"] = "gen_ai" + os.environ["OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"] = ( + "span_only" + ) + + if _OpenTelemetrySemanticConventionStability: + try: + _OpenTelemetrySemanticConventionStability._OTEL_SEMCONV_STABILITY_SIGNAL_MAPPING[ + _OpenTelemetryStabilitySignalType.GEN_AI + ] = _StabilityMode.GEN_AI_LATEST_EXPERIMENTAL + except (AttributeError, KeyError): + pass + self.instrumentor = CrewAIInstrumentor() self.instrumentor.instrument(tracer_provider=self.tracer_provider) From 9b12cf83b39322ba712e84d29d2f6e3bf6c9c720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=8E=E7=9B=B4?= Date: Wed, 11 Feb 2026 10:11:31 +0800 Subject: [PATCH 07/14] Fix dependency problem in pyproject.toml --- .../loongsuite-instrumentation-crewai/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml index 16309567e..f2a0c4c6b 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml @@ -26,7 +26,7 @@ dependencies = [ "opentelemetry-instrumentation ~= 0.60b0", "opentelemetry-semantic-conventions ~= 0.60b0", "wrapt >= 1.0.0, < 2.0.0", - "opentelemetry-util-genai ~= 0.3b0", + "opentelemetry-util-genai >= 0.3b0.dev0, == 0.3.*", ] [project.optional-dependencies] From fb167041b2816bd0e959b50ecca0ae1b4cf628a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=8E=E7=9B=B4?= Date: Tue, 24 Feb 2026 16:14:59 +0800 Subject: [PATCH 08/14] Added these tests as github workflows; Adjusted the test-requirements.txt. --- .../test-requirements.txt | 8 ++++---- tox-loongsuite.ini | 13 +++++++++++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt index 6faf92891..d9ee2fde5 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt @@ -1,9 +1,9 @@ -crewai>=0.70.0 +crewai>=0.80.0 litellm>=1.79.0 openai>=2.0.0 respx>=0.20.0 pysqlite3-binary --e aliyun-semantic-conventions -e util/opentelemetry-util-http --e instrumentation/opentelemetry-instrumentation-crewai --e instrumentation/opentelemetry-instrumentation-litellm +-e util/opentelemetry-util-genai +-e instrumentation-loongsuite/loongsuite-instrumentation-crewai + diff --git a/tox-loongsuite.ini b/tox-loongsuite.ini index 6daecacd3..f412b511c 100644 --- a/tox-loongsuite.ini +++ b/tox-loongsuite.ini @@ -59,6 +59,10 @@ envlist = ; generate tasks generate-loongsuite + ; loongsuite-instrumentation-crewai + py3{10,11,12,13}-test-loongsuite-instrumentation-crewai + lint-loongsuite-instrumentation-crewai + [testenv] test_deps = opentelemetry-api@{env:CORE_REPO}\#egg=opentelemetry-api&subdirectory=opentelemetry-api @@ -110,7 +114,9 @@ deps = util-genai: {[testenv]test_deps} util-genai: -r {toxinidir}/util/opentelemetry-util-genai/test-requirements.txt util-genai: {toxinidir}/util/opentelemetry-util-genai - + + loongsuite-crewai: -r {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt + ; FIXME: add coverage testing allowlist_externals = sh @@ -140,7 +146,7 @@ commands = test-loongsuite-instrumentation-google-adk: pytest {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-google-adk/tests {posargs} lint-loongsuite-instrumentation-google-adk: python -m ruff check {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-google-adk - + test-loongsuite-instrumentation-agno: pytest {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-agno/tests {posargs} lint-loongsuite-instrumentation-agno: python -m ruff check {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-agno @@ -156,6 +162,9 @@ commands = test-loongsuite-instrumentation-mem0: pytest {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-mem0/tests {posargs} lint-loongsuite-instrumentation-mem0: python -m ruff check {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-mem0 + test-loongsuite-instrumentation-crewai: pytest {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests {posargs} + lint-loongsuite-instrumentation-crewai: python -m ruff check {toxinidir}/instrumentation-loongsuite/loongsuite-instrumentation-crewai + test-util-genai: pytest {toxinidir}/util/opentelemetry-util-genai/tests {posargs} lint-util-genai: sh -c "cd util && pylint --rcfile ../.pylintrc opentelemetry-util-genai" From 1d3784a7d52a4b3277ecd12094de6030e41cde78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=8E=E7=9B=B4?= Date: Wed, 25 Feb 2026 11:32:12 +0800 Subject: [PATCH 09/14] Use vcrpy to record tests to avoid relying on real requests; Add crewai tests to GitHub workflow. --- .github/workflows/loongsuite_lint_0.yml | 19 + .github/workflows/loongsuite_test_0.yml | 76 + .../test-requirements.txt | 4 +- ...ntWorkflow.test_hierarchical_workflow.yaml | 1655 +++++++++++++++++ ...rkflow.test_multi_agent_collaboration.yaml | 756 ++++++++ ...gentWorkflow.test_sequential_workflow.yaml | 1431 ++++++++++++++ ...stErrorScenarios.test_api_key_missing.yaml | 482 +++++ ...TestErrorScenarios.test_network_error.yaml | 428 +++++ ...y.test_prompt_template_with_variables.yaml | 262 +++ ...omptAndMemory.test_session_management.yaml | 336 ++++ ...LMCalls.test_streaming_crew_execution.yaml | 170 ++ ...MCalls.test_basic_sync_crew_execution.yaml | 301 +++ ...LMCalls.test_crew_with_multiple_tasks.yaml | 656 +++++++ ...lCalls.test_agent_with_multiple_tools.yaml | 689 +++++++ ...ToolCalls.test_agent_with_single_tool.yaml | 368 ++++ ...stToolCalls.test_tool_call_with_error.yaml | 624 +++++++ .../tests/conftest.py | 51 + .../tests/test_agent_workflow.py | 2 + .../tests/test_error_scenarios.py | 2 + .../tests/test_prompt_and_memory.py | 2 + .../tests/test_streaming_llm_calls.py | 2 + .../tests/test_sync_llm_calls.py | 2 + .../tests/test_tool_calls.py | 2 + 23 files changed, 8319 insertions(+), 1 deletion(-) create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_agent_workflow/TestAgentWorkflow.test_hierarchical_workflow.yaml create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_agent_workflow/TestAgentWorkflow.test_multi_agent_collaboration.yaml create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_agent_workflow/TestAgentWorkflow.test_sequential_workflow.yaml create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_error_scenarios/TestErrorScenarios.test_api_key_missing.yaml create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_error_scenarios/TestErrorScenarios.test_network_error.yaml create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_prompt_and_memory/TestPromptAndMemory.test_prompt_template_with_variables.yaml create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_prompt_and_memory/TestPromptAndMemory.test_session_management.yaml create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_streaming_llm_calls/TestStreamingLLMCalls.test_streaming_crew_execution.yaml create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_sync_llm_calls/TestSyncLLMCalls.test_basic_sync_crew_execution.yaml create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_sync_llm_calls/TestSyncLLMCalls.test_crew_with_multiple_tasks.yaml create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_tool_calls/TestToolCalls.test_agent_with_multiple_tools.yaml create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_tool_calls/TestToolCalls.test_agent_with_single_tool.yaml create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_tool_calls/TestToolCalls.test_tool_call_with_error.yaml create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/conftest.py diff --git a/.github/workflows/loongsuite_lint_0.yml b/.github/workflows/loongsuite_lint_0.yml index 2c2540a1b..113bebb0a 100644 --- a/.github/workflows/loongsuite_lint_0.yml +++ b/.github/workflows/loongsuite_lint_0.yml @@ -146,3 +146,22 @@ jobs: - name: Run tests run: tox -c tox-loongsuite.ini -e lint-util-genai + lint-loongsuite-instrumentation-crewai: + name: LoongSuite loongsuite-instrumentation-crewai + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout repo @ SHA - ${{ github.sha }} + uses: actions/checkout@v4 + + - name: Set up Python 3.13 + uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Install tox + run: pip install tox-uv + + - name: Run tests + run: tox -c tox-loongsuite.ini -e lint-loongsuite-instrumentation-crewai + diff --git a/.github/workflows/loongsuite_test_0.yml b/.github/workflows/loongsuite_test_0.yml index 88b088337..a319931db 100644 --- a/.github/workflows/loongsuite_test_0.yml +++ b/.github/workflows/loongsuite_test_0.yml @@ -1001,3 +1001,79 @@ jobs: - name: Run tests run: tox -c tox-loongsuite.ini -e pypy3-test-util-genai -- -ra + py310-test-loongsuite-instrumentation-crewai_ubuntu-latest: + name: LoongSuite loongsuite-instrumentation-crewai 3.10 Ubuntu + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout repo @ SHA - ${{ github.sha }} + uses: actions/checkout@v4 + + - name: Set up Python 3.10 + uses: actions/setup-python@v5 + with: + python-version: "3.10" + + - name: Install tox + run: pip install tox-uv + + - name: Run tests + run: tox -c tox-loongsuite.ini -e py310-test-loongsuite-instrumentation-crewai -- -ra + + py311-test-loongsuite-instrumentation-crewai_ubuntu-latest: + name: LoongSuite loongsuite-instrumentation-crewai 3.11 Ubuntu + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout repo @ SHA - ${{ github.sha }} + uses: actions/checkout@v4 + + - name: Set up Python 3.11 + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install tox + run: pip install tox-uv + + - name: Run tests + run: tox -c tox-loongsuite.ini -e py311-test-loongsuite-instrumentation-crewai -- -ra + + py312-test-loongsuite-instrumentation-crewai_ubuntu-latest: + name: LoongSuite loongsuite-instrumentation-crewai 3.12 Ubuntu + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout repo @ SHA - ${{ github.sha }} + uses: actions/checkout@v4 + + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install tox + run: pip install tox-uv + + - name: Run tests + run: tox -c tox-loongsuite.ini -e py312-test-loongsuite-instrumentation-crewai -- -ra + + py313-test-loongsuite-instrumentation-crewai_ubuntu-latest: + name: LoongSuite loongsuite-instrumentation-crewai 3.13 Ubuntu + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout repo @ SHA - ${{ github.sha }} + uses: actions/checkout@v4 + + - name: Set up Python 3.13 + uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Install tox + run: pip install tox-uv + + - name: Run tests + run: tox -c tox-loongsuite.ini -e py313-test-loongsuite-instrumentation-crewai -- -ra + diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt index d9ee2fde5..0a2253061 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt @@ -2,7 +2,9 @@ crewai>=0.80.0 litellm>=1.79.0 openai>=2.0.0 respx>=0.20.0 -pysqlite3-binary +pysqlite3 +vcrpy>=6.0.0 +pytest-recording>=0.13.0 -e util/opentelemetry-util-http -e util/opentelemetry-util-genai -e instrumentation-loongsuite/loongsuite-instrumentation-crewai diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_agent_workflow/TestAgentWorkflow.test_hierarchical_workflow.yaml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_agent_workflow/TestAgentWorkflow.test_hierarchical_workflow.yaml new file mode 100644 index 000000000..7c5f21f4a --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_agent_workflow/TestAgentWorkflow.test_hierarchical_workflow.yaml @@ -0,0 +1,1655 @@ +interactions: +- request: + body: '{"messages": [{"role": "system", "content": "You are Crew Manager. You + are a seasoned manager with a knack for getting the best out of your team.\nYou + are also known for your ability to delegate work to the right people, and to + ask the right questions to get the best out of your team.\nEven though you don''t + perform tasks by yourself, you have a lot of experience in the field, which + allows you to properly evaluate the work of your team members.\nYour personal + goal is: Manage the team to complete the task in the best way possible.\nYou + ONLY have access to the following tools, and should NEVER make up tools that + are not listed here:\n\nTool Name: Delegate work to coworker\nTool Arguments: + {''task'': {''description'': ''The task to delegate'', ''type'': ''str''}, ''context'': + {''description'': ''The context for the task'', ''type'': ''str''}, ''coworker'': + {''description'': ''The role/name of the coworker to delegate to'', ''type'': + ''str''}}\nTool Description: Delegate a specific task to one of the following + coworkers: Junior Analyst\nThe input to this tool should be the coworker, the + task you want them to do, and ALL necessary context to execute the task, they + know nothing about the task, so share absolute everything you know, don''t reference + things but instead explain them.\nTool Name: Ask question to coworker\nTool + Arguments: {''question'': {''description'': ''The question to ask'', ''type'': + ''str''}, ''context'': {''description'': ''The context for the question'', ''type'': + ''str''}, ''coworker'': {''description'': ''The role/name of the coworker to + ask'', ''type'': ''str''}}\nTool Description: Ask a specific question to one + of the following coworkers: Junior Analyst\nThe input to this tool should be + the coworker, the question you have for them, and ALL necessary context to ask + the question properly, they know nothing about the question, so share absolute + everything you know, don''t reference things but instead explain them.\n\nUse + the following format:\n\nThought: you should always think about what to do\nAction: + the action to take, only one name of [Delegate work to coworker, Ask question + to coworker], just the name, exactly as it''s written.\nAction Input: the input + to the action, just a simple python dictionary, enclosed in curly braces, using + \" to wrap keys and values.\nObservation: the result of the action\n\nOnce all + necessary information is gathered:\n\nThought: I now know the final answer\nFinal + Answer: the final answer to the original input question"}, {"role": "user", + "content": "\nCurrent Task: Analyze market data\n\nThis is the expect criteria + for your final answer: Market analysis\nyou MUST return the actual complete + content as the final answer, not a summary.\n\nBegin! This is VERY important + to you, use the tools available and give your best Final Answer, your job depends + on it!\n\nThought:"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '2840' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"I + need to delegate the task of analyzing market data to the Junior Analyst. + I should provide all necessary context so they can perform the task effectively.\n\nAction: + Delegate work to coworker\nAction Input: {\"task\": \"Analyze market data\", + \"context\": \"You have been given a dataset containing information about + market trends, consumer behavior, and competitor activity. Your task is to + analyze this data to identify patterns, opportunities, and potential risks. + You should present your findings in a clear and structured format.\", \"coworker\": + \"Junior Analyst\"}","role":"assistant"}}],"created":1771988114,"id":"chatcmpl-3b32f9a8-a8b0-9210-9018-244080075c80","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":113,"prompt_tokens":605,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":718}}' + headers: + content-length: + - '904' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:55:15 GMT + req-arrive-time: + - '1771988114298' + req-cost-time: + - '1734' + resp-start-time: + - '1771988116033' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '1733' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Junior Analyst. Junior + analyst\nYour personal goal is: Perform assigned analysis\nTo give my best complete + final answer to the task use the exact following format:\n\nThought: I now can + give a great answer\nFinal Answer: Your final answer must be the great and the + most complete as possible, it must be outcome described.\n\nI MUST use these + formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent Task: + Analyze market data\n\nThis is the expect criteria for your final answer: Your + best answer to your coworker asking you this, accounting for the context shared.\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nThis + is the context you''re working with:\nYou have been given a dataset containing + information about market trends, consumer behavior, and competitor activity. + Your task is to analyze this data to identify patterns, opportunities, and potential + risks. You should present your findings in a clear and structured format.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '1213' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"I + now can give a great answer\nFinal Answer: After analyzing the dataset containing + information about market trends, consumer behavior, and competitor activity, + I have identified several key patterns, opportunities, and potential risks. + Here is a detailed breakdown of my findings:\n\n1. **Market Trends Analysis**:\n - + There has been a noticeable increase in demand for eco-friendly and sustainable + products over the past six months. This trend is particularly prominent in + the 25-40 age demographic.\n - The market for technology-driven solutions, + such as smart home devices and AI-based services, has shown consistent growth, + with a 12% year-over-year increase in sales.\n\n2. **Consumer Behavior Insights**:\n - + Online shopping continues to dominate consumer purchasing behavior, with over + 70% of transactions occurring through e-commerce platforms.\n - Customer + preferences are shifting towards personalized experiences. Data shows that + users who engage with personalized recommendations have a 30% higher conversion + rate compared to those who do not.\n\n3. **Competitor Activity Overview**:\n - + Competitor A has launched a new product line targeting the eco-friendly segment, + which could pose a threat to our market share if we do not respond promptly.\n - + Competitor B has increased its digital marketing budget by 20%, resulting + in a significant boost in brand visibility and customer engagement.\n\n4. + **Opportunities Identified**:\n - Expanding our product line to include + more sustainable options could capture a larger portion of the growing eco-conscious + market.\n - Investing in AI and data analytics tools to enhance personalization + efforts may improve customer retention and drive sales.\n\n5. **Potential + Risks**:\n - Increased competition in the eco-friendly and tech sectors + could lead to price wars and reduced profit margins.\n - A reliance on e-commerce + platforms exposes us to potential disruptions, such as changes in platform + algorithms or policies.\n\nBased on these findings, I recommend focusing on + expanding our sustainable product offerings and enhancing our digital personalization + strategies. Additionally, monitoring competitor activities closely and preparing + for potential market shifts will be crucial for maintaining our competitive + edge.","role":"assistant"}}],"created":1771988116,"id":"chatcmpl-7f982508-589a-93c6-b7dc-8b42d2489a4d","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":421,"prompt_tokens":231,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":652}}' + headers: + content-length: + - '2626' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:55:20 GMT + req-arrive-time: + - '1771988116260' + req-cost-time: + - '4931' + resp-start-time: + - '1771988121191' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '4931' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Crew Manager. You + are a seasoned manager with a knack for getting the best out of your team.\nYou + are also known for your ability to delegate work to the right people, and to + ask the right questions to get the best out of your team.\nEven though you don''t + perform tasks by yourself, you have a lot of experience in the field, which + allows you to properly evaluate the work of your team members.\nYour personal + goal is: Manage the team to complete the task in the best way possible.\nYou + ONLY have access to the following tools, and should NEVER make up tools that + are not listed here:\n\nTool Name: Delegate work to coworker\nTool Arguments: + {''task'': {''description'': ''The task to delegate'', ''type'': ''str''}, ''context'': + {''description'': ''The context for the task'', ''type'': ''str''}, ''coworker'': + {''description'': ''The role/name of the coworker to delegate to'', ''type'': + ''str''}}\nTool Description: Delegate a specific task to one of the following + coworkers: Junior Analyst\nThe input to this tool should be the coworker, the + task you want them to do, and ALL necessary context to execute the task, they + know nothing about the task, so share absolute everything you know, don''t reference + things but instead explain them.\nTool Name: Ask question to coworker\nTool + Arguments: {''question'': {''description'': ''The question to ask'', ''type'': + ''str''}, ''context'': {''description'': ''The context for the question'', ''type'': + ''str''}, ''coworker'': {''description'': ''The role/name of the coworker to + ask'', ''type'': ''str''}}\nTool Description: Ask a specific question to one + of the following coworkers: Junior Analyst\nThe input to this tool should be + the coworker, the question you have for them, and ALL necessary context to ask + the question properly, they know nothing about the question, so share absolute + everything you know, don''t reference things but instead explain them.\n\nUse + the following format:\n\nThought: you should always think about what to do\nAction: + the action to take, only one name of [Delegate work to coworker, Ask question + to coworker], just the name, exactly as it''s written.\nAction Input: the input + to the action, just a simple python dictionary, enclosed in curly braces, using + \" to wrap keys and values.\nObservation: the result of the action\n\nOnce all + necessary information is gathered:\n\nThought: I now know the final answer\nFinal + Answer: the final answer to the original input question"}, {"role": "user", + "content": "\nCurrent Task: Analyze market data\n\nThis is the expect criteria + for your final answer: Market analysis\nyou MUST return the actual complete + content as the final answer, not a summary.\n\nBegin! This is VERY important + to you, use the tools available and give your best Final Answer, your job depends + on it!\n\nThought:"}, {"role": "assistant", "content": "I need to delegate the + task of analyzing market data to the Junior Analyst. I should provide all necessary + context so they can perform the task effectively.\n\nAction: Delegate work to + coworker\nAction Input: {\"task\": \"Analyze market data\", \"context\": \"You + have been given a dataset containing information about market trends, consumer + behavior, and competitor activity. Your task is to analyze this data to identify + patterns, opportunities, and potential risks. You should present your findings + in a clear and structured format.\", \"coworker\": \"Junior Analyst\"}\nObservation: + After analyzing the dataset containing information about market trends, consumer + behavior, and competitor activity, I have identified several key patterns, opportunities, + and potential risks. Here is a detailed breakdown of my findings:\n\n1. **Market + Trends Analysis**:\n - There has been a noticeable increase in demand for + eco-friendly and sustainable products over the past six months. This trend is + particularly prominent in the 25-40 age demographic.\n - The market for technology-driven + solutions, such as smart home devices and AI-based services, has shown consistent + growth, with a 12% year-over-year increase in sales.\n\n2. **Consumer Behavior + Insights**:\n - Online shopping continues to dominate consumer purchasing + behavior, with over 70% of transactions occurring through e-commerce platforms.\n - + Customer preferences are shifting towards personalized experiences. Data shows + that users who engage with personalized recommendations have a 30% higher conversion + rate compared to those who do not.\n\n3. **Competitor Activity Overview**:\n - + Competitor A has launched a new product line targeting the eco-friendly segment, + which could pose a threat to our market share if we do not respond promptly.\n - + Competitor B has increased its digital marketing budget by 20%, resulting in + a significant boost in brand visibility and customer engagement.\n\n4. **Opportunities + Identified**:\n - Expanding our product line to include more sustainable options + could capture a larger portion of the growing eco-conscious market.\n - Investing + in AI and data analytics tools to enhance personalization efforts may improve + customer retention and drive sales.\n\n5. **Potential Risks**:\n - Increased + competition in the eco-friendly and tech sectors could lead to price wars and + reduced profit margins.\n - A reliance on e-commerce platforms exposes us + to potential disruptions, such as changes in platform algorithms or policies.\n\nBased + on these findings, I recommend focusing on expanding our sustainable product + offerings and enhancing our digital personalization strategies. Additionally, + monitoring competitor activities closely and preparing for potential market + shifts will be crucial for maintaining our competitive edge."}], "model": "qwen-turbo", + "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '5712' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I now know the final answer\nFinal Answer: After analyzing the dataset containing + information about market trends, consumer behavior, and competitor activity, + I have identified several key patterns, opportunities, and potential risks. + Here is a detailed breakdown of my findings:\n\n1. **Market Trends Analysis**:\n - + There has been a noticeable increase in demand for eco-friendly and sustainable + products over the past six months. This trend is particularly prominent in + the 25-40 age demographic.\n - The market for technology-driven solutions, + such as smart home devices and AI-based services, has shown consistent growth, + with a 12% year-over-year increase in sales.\n\n2. **Consumer Behavior Insights**:\n - + Online shopping continues to dominate consumer purchasing behavior, with over + 70% of transactions occurring through e-commerce platforms.\n - Customer + preferences are shifting towards personalized experiences. Data shows that + users who engage with personalized recommendations have a 30% higher conversion + rate compared to those who do not.\n\n3. **Competitor Activity Overview**:\n - + Competitor A has launched a new product line targeting the eco-friendly segment, + which could pose a threat to our market share if we do not respond promptly.\n - + Competitor B has increased its digital marketing budget by 20%, resulting + in a significant boost in brand visibility and customer engagement.\n\n4. + **Opportunities Identified**:\n - Expanding our product line to include + more sustainable options could capture a larger portion of the growing eco-conscious + market.\n - Investing in AI and data analytics tools to enhance personalization + efforts may improve customer retention and drive sales.\n\n5. **Potential + Risks**:\n - Increased competition in the eco-friendly and tech sectors + could lead to price wars and reduced profit margins.\n - A reliance on e-commerce + platforms exposes us to potential disruptions, such as changes in platform + algorithms or policies.\n\nBased on these findings, I recommend focusing on + expanding our sustainable product offerings and enhancing our digital personalization + strategies. Additionally, monitoring competitor activities closely and preparing + for potential market shifts will be crucial for maintaining our competitive + edge.","role":"assistant"}}],"created":1771988121,"id":"chatcmpl-ebb0f1f1-c845-91b1-ae22-db730c1ab587","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":422,"prompt_tokens":1128,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":1550}}' + headers: + content-length: + - '2635' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:55:26 GMT + req-arrive-time: + - '1771988121419' + req-cost-time: + - '5021' + resp-start-time: + - '1771988126441' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '5021' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Crew Manager. You + are a seasoned manager with a knack for getting the best out of your team.\nYou + are also known for your ability to delegate work to the right people, and to + ask the right questions to get the best out of your team.\nEven though you don''t + perform tasks by yourself, you have a lot of experience in the field, which + allows you to properly evaluate the work of your team members.\nYour personal + goal is: Manage the team to complete the task in the best way possible.\nYou + ONLY have access to the following tools, and should NEVER make up tools that + are not listed here:\n\nTool Name: Delegate work to coworker\nTool Arguments: + {''task'': {''description'': ''The task to delegate'', ''type'': ''str''}, ''context'': + {''description'': ''The context for the task'', ''type'': ''str''}, ''coworker'': + {''description'': ''The role/name of the coworker to delegate to'', ''type'': + ''str''}}\nTool Description: Delegate a specific task to one of the following + coworkers: Junior Researcher\nThe input to this tool should be the coworker, + the task you want them to do, and ALL necessary context to execute the task, + they know nothing about the task, so share absolute everything you know, don''t + reference things but instead explain them.\nTool Name: Ask question to coworker\nTool + Arguments: {''question'': {''description'': ''The question to ask'', ''type'': + ''str''}, ''context'': {''description'': ''The context for the question'', ''type'': + ''str''}, ''coworker'': {''description'': ''The role/name of the coworker to + ask'', ''type'': ''str''}}\nTool Description: Ask a specific question to one + of the following coworkers: Junior Researcher\nThe input to this tool should + be the coworker, the question you have for them, and ALL necessary context to + ask the question properly, they know nothing about the question, so share absolute + everything you know, don''t reference things but instead explain them.\n\nUse + the following format:\n\nThought: you should always think about what to do\nAction: + the action to take, only one name of [Delegate work to coworker, Ask question + to coworker], just the name, exactly as it''s written.\nAction Input: the input + to the action, just a simple python dictionary, enclosed in curly braces, using + \" to wrap keys and values.\nObservation: the result of the action\n\nOnce all + necessary information is gathered:\n\nThought: I now know the final answer\nFinal + Answer: the final answer to the original input question"}, {"role": "user", + "content": "\nCurrent Task: Research competitors\n\nThis is the expect criteria + for your final answer: Competitor research\nyou MUST return the actual complete + content as the final answer, not a summary.\n\nThis is the context you''re working + with:\nAfter analyzing the dataset containing information about market trends, + consumer behavior, and competitor activity, I have identified several key patterns, + opportunities, and potential risks. Here is a detailed breakdown of my findings:\n\n1. + **Market Trends Analysis**:\n - There has been a noticeable increase in demand + for eco-friendly and sustainable products over the past six months. This trend + is particularly prominent in the 25-40 age demographic.\n - The market for + technology-driven solutions, such as smart home devices and AI-based services, + has shown consistent growth, with a 12% year-over-year increase in sales.\n\n2. + **Consumer Behavior Insights**:\n - Online shopping continues to dominate + consumer purchasing behavior, with over 70% of transactions occurring through + e-commerce platforms.\n - Customer preferences are shifting towards personalized + experiences. Data shows that users who engage with personalized recommendations + have a 30% higher conversion rate compared to those who do not.\n\n3. **Competitor + Activity Overview**:\n - Competitor A has launched a new product line targeting + the eco-friendly segment, which could pose a threat to our market share if we + do not respond promptly.\n - Competitor B has increased its digital marketing + budget by 20%, resulting in a significant boost in brand visibility and customer + engagement.\n\n4. **Opportunities Identified**:\n - Expanding our product + line to include more sustainable options could capture a larger portion of the + growing eco-conscious market.\n - Investing in AI and data analytics tools + to enhance personalization efforts may improve customer retention and drive + sales.\n\n5. **Potential Risks**:\n - Increased competition in the eco-friendly + and tech sectors could lead to price wars and reduced profit margins.\n - + A reliance on e-commerce platforms exposes us to potential disruptions, such + as changes in platform algorithms or policies.\n\nBased on these findings, I + recommend focusing on expanding our sustainable product offerings and enhancing + our digital personalization strategies. Additionally, monitoring competitor + activities closely and preparing for potential market shifts will be crucial + for maintaining our competitive edge.\n\nBegin! This is VERY important to you, + use the tools available and give your best Final Answer, your job depends on + it!\n\nThought:"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '5147' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"I + need to gather more information about the competitors'' strategies and offerings + to provide a comprehensive research report.\nAction: Delegate work to coworker\nAction + Input: {\"task\": \"Research competitors\", \"context\": \"The task is to + research competitors, specifically focusing on their strategies and offerings + in the eco-friendly and tech sectors. The goal is to gather detailed information + that can be used to inform our business decisions.\", \"coworker\": \"Junior + Researcher\"}","role":"assistant"}}],"created":1771988126,"id":"chatcmpl-bda31b3e-fc45-94fd-9f15-f9cda893a440","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":91,"prompt_tokens":1025,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":1116}}' + headers: + content-length: + - '824' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:55:27 GMT + req-arrive-time: + - '1771988126677' + req-cost-time: + - '1152' + resp-start-time: + - '1771988127829' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '1151' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Junior Researcher. + Junior researcher\nYour personal goal is: Conduct assigned research\nTo give + my best complete final answer to the task use the exact following format:\n\nThought: + I now can give a great answer\nFinal Answer: Your final answer must be the great + and the most complete as possible, it must be outcome described.\n\nI MUST use + these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent + Task: Research competitors\n\nThis is the expect criteria for your final answer: + Your best answer to your coworker asking you this, accounting for the context + shared.\nyou MUST return the actual complete content as the final answer, not + a summary.\n\nThis is the context you''re working with:\nThe task is to research + competitors, specifically focusing on their strategies and offerings in the + eco-friendly and tech sectors. The goal is to gather detailed information that + can be used to inform our business decisions.\n\nBegin! This is VERY important + to you, use the tools available and give your best Final Answer, your job depends + on it!\n\nThought:"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '1168' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I now can give a great answer\nFinal Answer: Here is the detailed research + on competitors in the eco-friendly and tech sectors:\n\n1. **Company A**:\n - + **Eco-Friendly Offerings**: Company A offers a range of biodegradable products, + including packaging materials and household items. They have also launched + a line of solar-powered home devices.\n - **Tech Sector Strategies**: They + focus on developing smart home technologies that integrate with renewable + energy systems. Their strategy includes partnerships with major tech companies + to enhance product compatibility.\n\n2. **Company B**:\n - **Eco-Friendly + Offerings**: Company B specializes in sustainable fashion, using organic and + recycled materials. They also offer carbon-neutral shipping options.\n - + **Tech Sector Strategies**: They incorporate blockchain technology for supply + chain transparency. Their approach emphasizes data-driven sustainability metrics + to attract environmentally conscious consumers.\n\n3. **Company C**:\n - + **Eco-Friendly Offerings**: Company C has a strong presence in the electric + vehicle (EV) market, offering eco-friendly cars and charging solutions. They + also provide energy-efficient home appliances.\n - **Tech Sector Strategies**: + They invest heavily in AI and machine learning to optimize battery performance + and reduce energy consumption. Their strategy includes launching an open-source + platform for EV developers.\n\n4. **Company D**:\n - **Eco-Friendly Offerings**: + Company D focuses on water conservation technologies, including smart irrigation + systems and low-flow fixtures. They also offer eco-friendly cleaning products.\n - + **Tech Sector Strategies**: They leverage IoT (Internet of Things) to create + connected home solutions that monitor and manage resource usage. Their strategy + involves acquiring smaller tech startups to expand their product portfolio.\n\n5. + **Company E**:\n - **Eco-Friendly Offerings**: Company E provides sustainable + office supplies and eco-friendly furniture. They also have a program for recycling + old office equipment.\n - **Tech Sector Strategies**: They develop cloud-based + platforms for businesses to track and reduce their environmental impact. Their + strategy includes offering customizable sustainability reports for corporate + clients.\n\nThis research highlights the diverse strategies and offerings + of competitors in the eco-friendly and tech sectors. These insights can be + used to inform our business decisions by identifying areas for innovation, + potential partnerships, and opportunities to differentiate our offerings.","role":"assistant"}}],"created":1771988128,"id":"chatcmpl-bf4cf31a-cf8f-93df-a7f2-609f3af0f278","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":458,"prompt_tokens":221,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":679}}' + headers: + content-length: + - '2920' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:55:33 GMT + req-arrive-time: + - '1771988128054' + req-cost-time: + - '5732' + resp-start-time: + - '1771988133787' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '5732' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Crew Manager. You + are a seasoned manager with a knack for getting the best out of your team.\nYou + are also known for your ability to delegate work to the right people, and to + ask the right questions to get the best out of your team.\nEven though you don''t + perform tasks by yourself, you have a lot of experience in the field, which + allows you to properly evaluate the work of your team members.\nYour personal + goal is: Manage the team to complete the task in the best way possible.\nYou + ONLY have access to the following tools, and should NEVER make up tools that + are not listed here:\n\nTool Name: Delegate work to coworker\nTool Arguments: + {''task'': {''description'': ''The task to delegate'', ''type'': ''str''}, ''context'': + {''description'': ''The context for the task'', ''type'': ''str''}, ''coworker'': + {''description'': ''The role/name of the coworker to delegate to'', ''type'': + ''str''}}\nTool Description: Delegate a specific task to one of the following + coworkers: Junior Researcher\nThe input to this tool should be the coworker, + the task you want them to do, and ALL necessary context to execute the task, + they know nothing about the task, so share absolute everything you know, don''t + reference things but instead explain them.\nTool Name: Ask question to coworker\nTool + Arguments: {''question'': {''description'': ''The question to ask'', ''type'': + ''str''}, ''context'': {''description'': ''The context for the question'', ''type'': + ''str''}, ''coworker'': {''description'': ''The role/name of the coworker to + ask'', ''type'': ''str''}}\nTool Description: Ask a specific question to one + of the following coworkers: Junior Researcher\nThe input to this tool should + be the coworker, the question you have for them, and ALL necessary context to + ask the question properly, they know nothing about the question, so share absolute + everything you know, don''t reference things but instead explain them.\n\nUse + the following format:\n\nThought: you should always think about what to do\nAction: + the action to take, only one name of [Delegate work to coworker, Ask question + to coworker], just the name, exactly as it''s written.\nAction Input: the input + to the action, just a simple python dictionary, enclosed in curly braces, using + \" to wrap keys and values.\nObservation: the result of the action\n\nOnce all + necessary information is gathered:\n\nThought: I now know the final answer\nFinal + Answer: the final answer to the original input question"}, {"role": "user", + "content": "\nCurrent Task: Research competitors\n\nThis is the expect criteria + for your final answer: Competitor research\nyou MUST return the actual complete + content as the final answer, not a summary.\n\nThis is the context you''re working + with:\nAfter analyzing the dataset containing information about market trends, + consumer behavior, and competitor activity, I have identified several key patterns, + opportunities, and potential risks. Here is a detailed breakdown of my findings:\n\n1. + **Market Trends Analysis**:\n - There has been a noticeable increase in demand + for eco-friendly and sustainable products over the past six months. This trend + is particularly prominent in the 25-40 age demographic.\n - The market for + technology-driven solutions, such as smart home devices and AI-based services, + has shown consistent growth, with a 12% year-over-year increase in sales.\n\n2. + **Consumer Behavior Insights**:\n - Online shopping continues to dominate + consumer purchasing behavior, with over 70% of transactions occurring through + e-commerce platforms.\n - Customer preferences are shifting towards personalized + experiences. Data shows that users who engage with personalized recommendations + have a 30% higher conversion rate compared to those who do not.\n\n3. **Competitor + Activity Overview**:\n - Competitor A has launched a new product line targeting + the eco-friendly segment, which could pose a threat to our market share if we + do not respond promptly.\n - Competitor B has increased its digital marketing + budget by 20%, resulting in a significant boost in brand visibility and customer + engagement.\n\n4. **Opportunities Identified**:\n - Expanding our product + line to include more sustainable options could capture a larger portion of the + growing eco-conscious market.\n - Investing in AI and data analytics tools + to enhance personalization efforts may improve customer retention and drive + sales.\n\n5. **Potential Risks**:\n - Increased competition in the eco-friendly + and tech sectors could lead to price wars and reduced profit margins.\n - + A reliance on e-commerce platforms exposes us to potential disruptions, such + as changes in platform algorithms or policies.\n\nBased on these findings, I + recommend focusing on expanding our sustainable product offerings and enhancing + our digital personalization strategies. Additionally, monitoring competitor + activities closely and preparing for potential market shifts will be crucial + for maintaining our competitive edge.\n\nBegin! This is VERY important to you, + use the tools available and give your best Final Answer, your job depends on + it!\n\nThought:"}, {"role": "assistant", "content": "I need to gather more information + about the competitors'' strategies and offerings to provide a comprehensive + research report.\nAction: Delegate work to coworker\nAction Input: {\"task\": + \"Research competitors\", \"context\": \"The task is to research competitors, + specifically focusing on their strategies and offerings in the eco-friendly + and tech sectors. The goal is to gather detailed information that can be used + to inform our business decisions.\", \"coworker\": \"Junior Researcher\"}\nObservation: + Here is the detailed research on competitors in the eco-friendly and tech sectors:\n\n1. + **Company A**:\n - **Eco-Friendly Offerings**: Company A offers a range of + biodegradable products, including packaging materials and household items. They + have also launched a line of solar-powered home devices.\n - **Tech Sector + Strategies**: They focus on developing smart home technologies that integrate + with renewable energy systems. Their strategy includes partnerships with major + tech companies to enhance product compatibility.\n\n2. **Company B**:\n - + **Eco-Friendly Offerings**: Company B specializes in sustainable fashion, using + organic and recycled materials. They also offer carbon-neutral shipping options.\n - + **Tech Sector Strategies**: They incorporate blockchain technology for supply + chain transparency. Their approach emphasizes data-driven sustainability metrics + to attract environmentally conscious consumers.\n\n3. **Company C**:\n - **Eco-Friendly + Offerings**: Company C has a strong presence in the electric vehicle (EV) market, + offering eco-friendly cars and charging solutions. They also provide energy-efficient + home appliances.\n - **Tech Sector Strategies**: They invest heavily in AI + and machine learning to optimize battery performance and reduce energy consumption. + Their strategy includes launching an open-source platform for EV developers.\n\n4. + **Company D**:\n - **Eco-Friendly Offerings**: Company D focuses on water + conservation technologies, including smart irrigation systems and low-flow fixtures. + They also offer eco-friendly cleaning products.\n - **Tech Sector Strategies**: + They leverage IoT (Internet of Things) to create connected home solutions that + monitor and manage resource usage. Their strategy involves acquiring smaller + tech startups to expand their product portfolio.\n\n5. **Company E**:\n - + **Eco-Friendly Offerings**: Company E provides sustainable office supplies and + eco-friendly furniture. They also have a program for recycling old office equipment.\n - + **Tech Sector Strategies**: They develop cloud-based platforms for businesses + to track and reduce their environmental impact. Their strategy includes offering + customizable sustainability reports for corporate clients.\n\nThis research + highlights the diverse strategies and offerings of competitors in the eco-friendly + and tech sectors. These insights can be used to inform our business decisions + by identifying areas for innovation, potential partnerships, and opportunities + to differentiate our offerings."}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '8223' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I now know the final answer\nFinal Answer: Here is the detailed research on + competitors in the eco-friendly and tech sectors:\n\n1. **Company A**:\n - + **Eco-Friendly Offerings**: Company A offers a range of biodegradable products, + including packaging materials and household items. They have also launched + a line of solar-powered home devices.\n - **Tech Sector Strategies**: They + focus on developing smart home technologies that integrate with renewable + energy systems. Their strategy includes partnerships with major tech companies + to enhance product compatibility.\n\n2. **Company B**:\n - **Eco-Friendly + Offerings**: Company B specializes in sustainable fashion, using organic and + recycled materials. They also offer carbon-neutral shipping options.\n - + **Tech Sector Strategies**: They incorporate blockchain technology for supply + chain transparency. Their approach emphasizes data-driven sustainability metrics + to attract environmentally conscious consumers.\n\n3. **Company C**:\n - + **Eco-Friendly Offerings**: Company C has a strong presence in the electric + vehicle (EV) market, offering eco-friendly cars and charging solutions. They + also provide energy-efficient home appliances.\n - **Tech Sector Strategies**: + They invest heavily in AI and machine learning to optimize battery performance + and reduce energy consumption. Their strategy includes launching an open-source + platform for EV developers.\n\n4. **Company D**:\n - **Eco-Friendly Offerings**: + Company D focuses on water conservation technologies, including smart irrigation + systems and low-flow fixtures. They also offer eco-friendly cleaning products.\n - + **Tech Sector Strategies**: They leverage IoT (Internet of Things) to create + connected home solutions that monitor and manage resource usage. Their strategy + involves acquiring smaller tech startups to expand their product portfolio.\n\n5. + **Company E**:\n - **Eco-Friendly Offerings**: Company E provides sustainable + office supplies and eco-friendly furniture. They also have a program for recycling + old office equipment.\n - **Tech Sector Strategies**: They develop cloud-based + platforms for businesses to track and reduce their environmental impact. Their + strategy includes offering customizable sustainability reports for corporate + clients.\n\nThis research highlights the diverse strategies and offerings + of competitors in the eco-friendly and tech sectors. These insights can be + used to inform our business decisions by identifying areas for innovation, + potential partnerships, and opportunities to differentiate our offerings.","role":"assistant"}}],"created":1771988134,"id":"chatcmpl-5ac6dc46-2f1d-9a5c-9342-ca213c0ec675","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":457,"prompt_tokens":1564,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":2021}}' + headers: + content-length: + - '2920' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:55:39 GMT + req-arrive-time: + - '1771988134014' + req-cost-time: + - '5901' + resp-start-time: + - '1771988139916' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '5900' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Crew Manager. You + are a seasoned manager with a knack for getting the best out of your team.\nYou + are also known for your ability to delegate work to the right people, and to + ask the right questions to get the best out of your team.\nEven though you don''t + perform tasks by yourself, you have a lot of experience in the field, which + allows you to properly evaluate the work of your team members.\nYour personal + goal is: Manage the team to complete the task in the best way possible.\nYou + ONLY have access to the following tools, and should NEVER make up tools that + are not listed here:\n\nTool Name: Delegate work to coworker\nTool Arguments: + {''task'': {''description'': ''The task to delegate'', ''type'': ''str''}, ''context'': + {''description'': ''The context for the task'', ''type'': ''str''}, ''coworker'': + {''description'': ''The role/name of the coworker to delegate to'', ''type'': + ''str''}}\nTool Description: Delegate a specific task to one of the following + coworkers: Junior Analyst\nThe input to this tool should be the coworker, the + task you want them to do, and ALL necessary context to execute the task, they + know nothing about the task, so share absolute everything you know, don''t reference + things but instead explain them.\nTool Name: Ask question to coworker\nTool + Arguments: {''question'': {''description'': ''The question to ask'', ''type'': + ''str''}, ''context'': {''description'': ''The context for the question'', ''type'': + ''str''}, ''coworker'': {''description'': ''The role/name of the coworker to + ask'', ''type'': ''str''}}\nTool Description: Ask a specific question to one + of the following coworkers: Junior Analyst\nThe input to this tool should be + the coworker, the question you have for them, and ALL necessary context to ask + the question properly, they know nothing about the question, so share absolute + everything you know, don''t reference things but instead explain them.\n\nUse + the following format:\n\nThought: you should always think about what to do\nAction: + the action to take, only one name of [Delegate work to coworker, Ask question + to coworker], just the name, exactly as it''s written.\nAction Input: the input + to the action, just a simple python dictionary, enclosed in curly braces, using + \" to wrap keys and values.\nObservation: the result of the action\n\nOnce all + necessary information is gathered:\n\nThought: I now know the final answer\nFinal + Answer: the final answer to the original input question"}, {"role": "user", + "content": "\nCurrent Task: Analyze market data\n\nThis is the expect criteria + for your final answer: Market analysis\nyou MUST return the actual complete + content as the final answer, not a summary.\n\nBegin! This is VERY important + to you, use the tools available and give your best Final Answer, your job depends + on it!\n\nThought:"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '2840' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"I + need to delegate the task of analyzing market data to the Junior Analyst. + I will provide all necessary context so they can perform the task effectively.\n\nAction: + Delegate work to coworker\nAction Input: {\"task\": \"Analyze market data\", + \"context\": \"The task is to analyze the current market data. You need to + gather and interpret data related to market trends, competitor analysis, and + customer behavior. Use this information to identify potential opportunities + and challenges in the market.\", \"coworker\": \"Junior Analyst\"}","role":"assistant"}}],"created":1771989374,"id":"chatcmpl-2d92d2a4-fa8a-91ea-b0b5-6a45e694e934","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":107,"prompt_tokens":605,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":712}}' + headers: + content-length: + - '868' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:16:17 GMT + req-arrive-time: + - '1771989374754' + req-cost-time: + - '2773' + resp-start-time: + - '1771989377527' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '2773' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Junior Analyst. Junior + analyst\nYour personal goal is: Perform assigned analysis\nTo give my best complete + final answer to the task use the exact following format:\n\nThought: I now can + give a great answer\nFinal Answer: Your final answer must be the great and the + most complete as possible, it must be outcome described.\n\nI MUST use these + formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent Task: + Analyze market data\n\nThis is the expect criteria for your final answer: Your + best answer to your coworker asking you this, accounting for the context shared.\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nThis + is the context you''re working with:\nThe task is to analyze the current market + data. You need to gather and interpret data related to market trends, competitor + analysis, and customer behavior. Use this information to identify potential + opportunities and challenges in the market.\n\nBegin! This is VERY important + to you, use the tools available and give your best Final Answer, your job depends + on it!\n\nThought:"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '1179' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I now can give a great answer\nFinal Answer: The current market data indicates + a mixed trend with both opportunities and challenges. Market trends show a + gradual increase in demand for eco-friendly products, driven by growing consumer + awareness and regulatory pressures. However, the overall market growth rate + has slowed down due to economic uncertainties and supply chain disruptions. + Competitor analysis reveals that key players are focusing on innovation and + cost optimization to maintain their market share. Customer behavior is shifting + towards online shopping, with a significant rise in e-commerce sales. This + presents an opportunity for businesses to enhance their digital presence and + improve customer engagement. However, the challenge lies in standing out in + a crowded market and managing rising operational costs. To capitalize on these + insights, we should consider investing in sustainable product lines, optimizing + our supply chain, and strengthening our online marketing strategies. Additionally, + monitoring competitor activities closely will help us stay ahead in the market.","role":"assistant"}}],"created":1771989377,"id":"chatcmpl-627ffb7f-66ef-932f-a810-69a0e4aa04de","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":181,"prompt_tokens":225,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":406}}' + headers: + content-length: + - '1432' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:16:19 GMT + req-arrive-time: + - '1771989377769' + req-cost-time: + - '2432' + resp-start-time: + - '1771989380202' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '2431' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Crew Manager. You + are a seasoned manager with a knack for getting the best out of your team.\nYou + are also known for your ability to delegate work to the right people, and to + ask the right questions to get the best out of your team.\nEven though you don''t + perform tasks by yourself, you have a lot of experience in the field, which + allows you to properly evaluate the work of your team members.\nYour personal + goal is: Manage the team to complete the task in the best way possible.\nYou + ONLY have access to the following tools, and should NEVER make up tools that + are not listed here:\n\nTool Name: Delegate work to coworker\nTool Arguments: + {''task'': {''description'': ''The task to delegate'', ''type'': ''str''}, ''context'': + {''description'': ''The context for the task'', ''type'': ''str''}, ''coworker'': + {''description'': ''The role/name of the coworker to delegate to'', ''type'': + ''str''}}\nTool Description: Delegate a specific task to one of the following + coworkers: Junior Analyst\nThe input to this tool should be the coworker, the + task you want them to do, and ALL necessary context to execute the task, they + know nothing about the task, so share absolute everything you know, don''t reference + things but instead explain them.\nTool Name: Ask question to coworker\nTool + Arguments: {''question'': {''description'': ''The question to ask'', ''type'': + ''str''}, ''context'': {''description'': ''The context for the question'', ''type'': + ''str''}, ''coworker'': {''description'': ''The role/name of the coworker to + ask'', ''type'': ''str''}}\nTool Description: Ask a specific question to one + of the following coworkers: Junior Analyst\nThe input to this tool should be + the coworker, the question you have for them, and ALL necessary context to ask + the question properly, they know nothing about the question, so share absolute + everything you know, don''t reference things but instead explain them.\n\nUse + the following format:\n\nThought: you should always think about what to do\nAction: + the action to take, only one name of [Delegate work to coworker, Ask question + to coworker], just the name, exactly as it''s written.\nAction Input: the input + to the action, just a simple python dictionary, enclosed in curly braces, using + \" to wrap keys and values.\nObservation: the result of the action\n\nOnce all + necessary information is gathered:\n\nThought: I now know the final answer\nFinal + Answer: the final answer to the original input question"}, {"role": "user", + "content": "\nCurrent Task: Analyze market data\n\nThis is the expect criteria + for your final answer: Market analysis\nyou MUST return the actual complete + content as the final answer, not a summary.\n\nBegin! This is VERY important + to you, use the tools available and give your best Final Answer, your job depends + on it!\n\nThought:"}, {"role": "assistant", "content": "I need to delegate the + task of analyzing market data to the Junior Analyst. I will provide all necessary + context so they can perform the task effectively.\n\nAction: Delegate work to + coworker\nAction Input: {\"task\": \"Analyze market data\", \"context\": \"The + task is to analyze the current market data. You need to gather and interpret + data related to market trends, competitor analysis, and customer behavior. Use + this information to identify potential opportunities and challenges in the market.\", + \"coworker\": \"Junior Analyst\"}\nObservation: The current market data indicates + a mixed trend with both opportunities and challenges. Market trends show a gradual + increase in demand for eco-friendly products, driven by growing consumer awareness + and regulatory pressures. However, the overall market growth rate has slowed + down due to economic uncertainties and supply chain disruptions. Competitor + analysis reveals that key players are focusing on innovation and cost optimization + to maintain their market share. Customer behavior is shifting towards online + shopping, with a significant rise in e-commerce sales. This presents an opportunity + for businesses to enhance their digital presence and improve customer engagement. + However, the challenge lies in standing out in a crowded market and managing + rising operational costs. To capitalize on these insights, we should consider + investing in sustainable product lines, optimizing our supply chain, and strengthening + our online marketing strategies. Additionally, monitoring competitor activities + closely will help us stay ahead in the market."}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '4473' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I now know the final answer\nFinal Answer: The current market data indicates + a mixed trend with both opportunities and challenges. Market trends show a + gradual increase in demand for eco-friendly products, driven by growing consumer + awareness and regulatory pressures. However, the overall market growth rate + has slowed down due to economic uncertainties and supply chain disruptions. + Competitor analysis reveals that key players are focusing on innovation and + cost optimization to maintain their market share. Customer behavior is shifting + towards online shopping, with a significant rise in e-commerce sales. This + presents an opportunity for businesses to enhance their digital presence and + improve customer engagement. However, the challenge lies in standing out in + a crowded market and managing rising operational costs. To capitalize on these + insights, we should consider investing in sustainable product lines, optimizing + our supply chain, and strengthening our online marketing strategies. Additionally, + monitoring competitor activities closely will help us stay ahead in the market.","role":"assistant"}}],"created":1771989380,"id":"chatcmpl-e491791d-a71f-9c82-b240-13d61b01f462","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":180,"prompt_tokens":880,"prompt_tokens_details":{"cached_tokens":512},"total_tokens":1060}}' + headers: + content-length: + - '1433' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:16:22 GMT + req-arrive-time: + - '1771989380448' + req-cost-time: + - '2929' + resp-start-time: + - '1771989383378' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '2929' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Crew Manager. You + are a seasoned manager with a knack for getting the best out of your team.\nYou + are also known for your ability to delegate work to the right people, and to + ask the right questions to get the best out of your team.\nEven though you don''t + perform tasks by yourself, you have a lot of experience in the field, which + allows you to properly evaluate the work of your team members.\nYour personal + goal is: Manage the team to complete the task in the best way possible.\nYou + ONLY have access to the following tools, and should NEVER make up tools that + are not listed here:\n\nTool Name: Delegate work to coworker\nTool Arguments: + {''task'': {''description'': ''The task to delegate'', ''type'': ''str''}, ''context'': + {''description'': ''The context for the task'', ''type'': ''str''}, ''coworker'': + {''description'': ''The role/name of the coworker to delegate to'', ''type'': + ''str''}}\nTool Description: Delegate a specific task to one of the following + coworkers: Junior Researcher\nThe input to this tool should be the coworker, + the task you want them to do, and ALL necessary context to execute the task, + they know nothing about the task, so share absolute everything you know, don''t + reference things but instead explain them.\nTool Name: Ask question to coworker\nTool + Arguments: {''question'': {''description'': ''The question to ask'', ''type'': + ''str''}, ''context'': {''description'': ''The context for the question'', ''type'': + ''str''}, ''coworker'': {''description'': ''The role/name of the coworker to + ask'', ''type'': ''str''}}\nTool Description: Ask a specific question to one + of the following coworkers: Junior Researcher\nThe input to this tool should + be the coworker, the question you have for them, and ALL necessary context to + ask the question properly, they know nothing about the question, so share absolute + everything you know, don''t reference things but instead explain them.\n\nUse + the following format:\n\nThought: you should always think about what to do\nAction: + the action to take, only one name of [Delegate work to coworker, Ask question + to coworker], just the name, exactly as it''s written.\nAction Input: the input + to the action, just a simple python dictionary, enclosed in curly braces, using + \" to wrap keys and values.\nObservation: the result of the action\n\nOnce all + necessary information is gathered:\n\nThought: I now know the final answer\nFinal + Answer: the final answer to the original input question"}, {"role": "user", + "content": "\nCurrent Task: Research competitors\n\nThis is the expect criteria + for your final answer: Competitor research\nyou MUST return the actual complete + content as the final answer, not a summary.\n\nThis is the context you''re working + with:\nThe current market data indicates a mixed trend with both opportunities + and challenges. Market trends show a gradual increase in demand for eco-friendly + products, driven by growing consumer awareness and regulatory pressures. However, + the overall market growth rate has slowed down due to economic uncertainties + and supply chain disruptions. Competitor analysis reveals that key players are + focusing on innovation and cost optimization to maintain their market share. + Customer behavior is shifting towards online shopping, with a significant rise + in e-commerce sales. This presents an opportunity for businesses to enhance + their digital presence and improve customer engagement. However, the challenge + lies in standing out in a crowded market and managing rising operational costs. + To capitalize on these insights, we should consider investing in sustainable + product lines, optimizing our supply chain, and strengthening our online marketing + strategies. Additionally, monitoring competitor activities closely will help + us stay ahead in the market.\n\nBegin! This is VERY important to you, use the + tools available and give your best Final Answer, your job depends on it!\n\nThought:"}], + "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '3944' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I need to delegate the task of researching competitors to the Junior Researcher. + I should provide them with all the necessary context and details about the + task.\nAction: Delegate work to coworker\nAction Input: {\"task\": \"Research + competitors\", \"context\": \"The current market data indicates a mixed trend + with both opportunities and challenges. Market trends show a gradual increase + in demand for eco-friendly products, driven by growing consumer awareness + and regulatory pressures. However, the overall market growth rate has slowed + down due to economic uncertainties and supply chain disruptions. Competitor + analysis reveals that key players are focusing on innovation and cost optimization + to maintain their market share. Customer behavior is shifting towards online + shopping, with a significant rise in e-commerce sales. This presents an opportunity + for businesses to enhance their digital presence and improve customer engagement. + However, the challenge lies in standing out in a crowded market and managing + rising operational costs. To capitalize on these insights, we should consider + investing in sustainable product lines, optimizing our supply chain, and strengthening + our online marketing strategies. Additionally, monitoring competitor activities + closely will help us stay ahead in the market.\", \"coworker\": \"Junior Researcher\"}","role":"assistant"}}],"created":1771989383,"id":"chatcmpl-f9f80f3b-fb2b-9179-ad65-4a5c3a12e0c4","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":235,"prompt_tokens":783,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":1018}}' + headers: + content-length: + - '1692' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:16:27 GMT + req-arrive-time: + - '1771989383579' + req-cost-time: + - '3825' + resp-start-time: + - '1771989387405' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '3825' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Junior Researcher. + Junior researcher\nYour personal goal is: Conduct assigned research\nTo give + my best complete final answer to the task use the exact following format:\n\nThought: + I now can give a great answer\nFinal Answer: Your final answer must be the great + and the most complete as possible, it must be outcome described.\n\nI MUST use + these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent + Task: Research competitors\n\nThis is the expect criteria for your final answer: + Your best answer to your coworker asking you this, accounting for the context + shared.\nyou MUST return the actual complete content as the final answer, not + a summary.\n\nThis is the context you''re working with:\nThe current market + data indicates a mixed trend with both opportunities and challenges. Market + trends show a gradual increase in demand for eco-friendly products, driven by + growing consumer awareness and regulatory pressures. However, the overall market + growth rate has slowed down due to economic uncertainties and supply chain disruptions. + Competitor analysis reveals that key players are focusing on innovation and + cost optimization to maintain their market share. Customer behavior is shifting + towards online shopping, with a significant rise in e-commerce sales. This presents + an opportunity for businesses to enhance their digital presence and improve + customer engagement. However, the challenge lies in standing out in a crowded + market and managing rising operational costs. To capitalize on these insights, + we should consider investing in sustainable product lines, optimizing our supply + chain, and strengthening our online marketing strategies. Additionally, monitoring + competitor activities closely will help us stay ahead in the market.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '1991' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I now can give a great answer\nFinal Answer: The current market data indicates + a mixed trend with both opportunities and challenges. Market trends show a + gradual increase in demand for eco-friendly products, driven by growing consumer + awareness and regulatory pressures. However, the overall market growth rate + has slowed down due to economic uncertainties and supply chain disruptions. + Competitor analysis reveals that key players are focusing on innovation and + cost optimization to maintain their market share. Customer behavior is shifting + towards online shopping, with a significant rise in e-commerce sales. This + presents an opportunity for businesses to enhance their digital presence and + improve customer engagement. However, the challenge lies in standing out in + a crowded market and managing rising operational costs. To capitalize on these + insights, we should consider investing in sustainable product lines, optimizing + our supply chain, and strengthening our online marketing strategies. Additionally, + monitoring competitor activities closely will help us stay ahead in the market.","role":"assistant"}}],"created":1771989387,"id":"chatcmpl-efcef7fc-2fef-9134-a9e0-9e4f9da0966a","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":181,"prompt_tokens":350,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":531}}' + headers: + content-length: + - '1432' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:16:29 GMT + req-arrive-time: + - '1771989387615' + req-cost-time: + - '2144' + resp-start-time: + - '1771989389759' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '2144' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Crew Manager. You + are a seasoned manager with a knack for getting the best out of your team.\nYou + are also known for your ability to delegate work to the right people, and to + ask the right questions to get the best out of your team.\nEven though you don''t + perform tasks by yourself, you have a lot of experience in the field, which + allows you to properly evaluate the work of your team members.\nYour personal + goal is: Manage the team to complete the task in the best way possible.\nYou + ONLY have access to the following tools, and should NEVER make up tools that + are not listed here:\n\nTool Name: Delegate work to coworker\nTool Arguments: + {''task'': {''description'': ''The task to delegate'', ''type'': ''str''}, ''context'': + {''description'': ''The context for the task'', ''type'': ''str''}, ''coworker'': + {''description'': ''The role/name of the coworker to delegate to'', ''type'': + ''str''}}\nTool Description: Delegate a specific task to one of the following + coworkers: Junior Researcher\nThe input to this tool should be the coworker, + the task you want them to do, and ALL necessary context to execute the task, + they know nothing about the task, so share absolute everything you know, don''t + reference things but instead explain them.\nTool Name: Ask question to coworker\nTool + Arguments: {''question'': {''description'': ''The question to ask'', ''type'': + ''str''}, ''context'': {''description'': ''The context for the question'', ''type'': + ''str''}, ''coworker'': {''description'': ''The role/name of the coworker to + ask'', ''type'': ''str''}}\nTool Description: Ask a specific question to one + of the following coworkers: Junior Researcher\nThe input to this tool should + be the coworker, the question you have for them, and ALL necessary context to + ask the question properly, they know nothing about the question, so share absolute + everything you know, don''t reference things but instead explain them.\n\nUse + the following format:\n\nThought: you should always think about what to do\nAction: + the action to take, only one name of [Delegate work to coworker, Ask question + to coworker], just the name, exactly as it''s written.\nAction Input: the input + to the action, just a simple python dictionary, enclosed in curly braces, using + \" to wrap keys and values.\nObservation: the result of the action\n\nOnce all + necessary information is gathered:\n\nThought: I now know the final answer\nFinal + Answer: the final answer to the original input question"}, {"role": "user", + "content": "\nCurrent Task: Research competitors\n\nThis is the expect criteria + for your final answer: Competitor research\nyou MUST return the actual complete + content as the final answer, not a summary.\n\nThis is the context you''re working + with:\nThe current market data indicates a mixed trend with both opportunities + and challenges. Market trends show a gradual increase in demand for eco-friendly + products, driven by growing consumer awareness and regulatory pressures. However, + the overall market growth rate has slowed down due to economic uncertainties + and supply chain disruptions. Competitor analysis reveals that key players are + focusing on innovation and cost optimization to maintain their market share. + Customer behavior is shifting towards online shopping, with a significant rise + in e-commerce sales. This presents an opportunity for businesses to enhance + their digital presence and improve customer engagement. However, the challenge + lies in standing out in a crowded market and managing rising operational costs. + To capitalize on these insights, we should consider investing in sustainable + product lines, optimizing our supply chain, and strengthening our online marketing + strategies. Additionally, monitoring competitor activities closely will help + us stay ahead in the market.\n\nBegin! This is VERY important to you, use the + tools available and give your best Final Answer, your job depends on it!\n\nThought:"}, + {"role": "assistant", "content": "Thought: I need to delegate the task of researching + competitors to the Junior Researcher. I should provide them with all the necessary + context and details about the task.\nAction: Delegate work to coworker\nAction + Input: {\"task\": \"Research competitors\", \"context\": \"The current market + data indicates a mixed trend with both opportunities and challenges. Market + trends show a gradual increase in demand for eco-friendly products, driven by + growing consumer awareness and regulatory pressures. However, the overall market + growth rate has slowed down due to economic uncertainties and supply chain disruptions. + Competitor analysis reveals that key players are focusing on innovation and + cost optimization to maintain their market share. Customer behavior is shifting + towards online shopping, with a significant rise in e-commerce sales. This presents + an opportunity for businesses to enhance their digital presence and improve + customer engagement. However, the challenge lies in standing out in a crowded + market and managing rising operational costs. To capitalize on these insights, + we should consider investing in sustainable product lines, optimizing our supply + chain, and strengthening our online marketing strategies. Additionally, monitoring + competitor activities closely will help us stay ahead in the market.\", \"coworker\": + \"Junior Researcher\"}\nObservation: The current market data indicates a mixed + trend with both opportunities and challenges. Market trends show a gradual increase + in demand for eco-friendly products, driven by growing consumer awareness and + regulatory pressures. However, the overall market growth rate has slowed down + due to economic uncertainties and supply chain disruptions. Competitor analysis + reveals that key players are focusing on innovation and cost optimization to + maintain their market share. Customer behavior is shifting towards online shopping, + with a significant rise in e-commerce sales. This presents an opportunity for + businesses to enhance their digital presence and improve customer engagement. + However, the challenge lies in standing out in a crowded market and managing + rising operational costs. To capitalize on these insights, we should consider + investing in sustainable product lines, optimizing our supply chain, and strengthening + our online marketing strategies. Additionally, monitoring competitor activities + closely will help us stay ahead in the market."}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '6400' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I now know the final answer\nFinal Answer: The current market data indicates + a mixed trend with both opportunities and challenges. Market trends show a + gradual increase in demand for eco-friendly products, driven by growing consumer + awareness and regulatory pressures. However, the overall market growth rate + has slowed down due to economic uncertainties and supply chain disruptions. + Competitor analysis reveals that key players are focusing on innovation and + cost optimization to maintain their market share. Customer behavior is shifting + towards online shopping, with a significant rise in e-commerce sales. This + presents an opportunity for businesses to enhance their digital presence and + improve customer engagement. However, the challenge lies in standing out in + a crowded market and managing rising operational costs. To capitalize on these + insights, we should consider investing in sustainable product lines, optimizing + our supply chain, and strengthening our online marketing strategies. Additionally, + monitoring competitor activities closely will help us stay ahead in the market.","role":"assistant"}}],"created":1771989390,"id":"chatcmpl-612941d5-5d4f-99af-b71d-b82c122ae275","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":180,"prompt_tokens":1186,"prompt_tokens_details":{"cached_tokens":512},"total_tokens":1366}}' + headers: + content-length: + - '1434' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:16:32 GMT + req-arrive-time: + - '1771989390031' + req-cost-time: + - '2473' + resp-start-time: + - '1771989392504' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '2473' + x-request-id: + - + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_agent_workflow/TestAgentWorkflow.test_multi_agent_collaboration.yaml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_agent_workflow/TestAgentWorkflow.test_multi_agent_collaboration.yaml new file mode 100644 index 000000000..5c204d0c3 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_agent_workflow/TestAgentWorkflow.test_multi_agent_collaboration.yaml @@ -0,0 +1,756 @@ +interactions: +- request: + body: '{"messages": [{"role": "system", "content": "You are UX Designer. Senior + UX designer\nYour personal goal is: Design user-friendly interfaces\nTo give + my best complete final answer to the task use the exact following format:\n\nThought: + I now can give a great answer\nFinal Answer: Your final answer must be the great + and the most complete as possible, it must be outcome described.\n\nI MUST use + these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent + Task: Design a dashboard interface\n\nThis is the expect criteria for your final + answer: UI design mockup\nyou MUST return the actual complete content as the + final answer, not a summary.\n\nBegin! This is VERY important to you, use the + tools available and give your best Final Answer, your job depends on it!\n\nThought:"}], + "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '838' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: "{\"choices\":[{\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"content\":\"Thought: + I now can give a great answer\\nFinal Answer: [UI Design Mockup]\\n\\nHere + is a detailed description of a user-friendly dashboard interface design:\\n\\n**Dashboard + Interface Design Mockup**\\n\\n**1. Header Section**\\n- **Logo/Title**: Top-left + corner with the company logo and name.\\n- **User Profile**: Top-right corner + with a profile icon, username, and dropdown menu (e.g., \\\"Profile,\\\" \\\"Settings,\\\" + \\\"Logout\\\").\\n- **Search Bar**: Centered at the top for quick access + to specific data or features.\\n\\n**2. Navigation Sidebar**\\n- **Menu Items**: + Vertical sidebar on the left with icons and labels:\\n - Dashboard\\n - + Analytics\\n - Reports\\n - Settings\\n - Help\\n- **Active State**: Highlight + the currently selected menu item with a different color or bold font.\\n\\n**3. + Main Content Area**\\n- **Overview Card**: Large card at the top with key + metrics (e.g., total users, active sessions, revenue).\\n- **Graphs/Charts**: + Two columns layout:\\n - Left Column: Line chart showing trends over time + (e.g., daily activity).\\n - Right Column: Bar chart comparing different + categories (e.g., product sales).\\n- **Recent Activity**: A table listing + recent user actions or system events.\\n- **Quick Actions**: A section with + buttons for common tasks (e.g., \\\"Create New Report,\\\" \\\"Add User\\\").\\n\\n**4. + Footer Section**\\n- **Copyright Info**: \\\"\xA9 2025 Company Name. All rights + reserved.\\\"\\n- **Links**: Quick links to Privacy Policy, Terms of Service, + and Contact Us.\\n\\n**Color Scheme**\\n- Primary Color: Blue (#007BFF)\\n- + Secondary Color: Light Gray (#F8F9FA)\\n- Accent Color: Green (#28A745)\\n- + Text Color: Dark Gray (#343A40)\\n\\n**Typography**\\n- Font Family: Arial + or Helvetica\\n- Font Sizes:\\n - Headers: 24px\\n - Subheaders: 18px\\n + \ - Body Text: 16px\\n\\n**Icons**\\n- Use consistent icon style (e.g., Material + Icons or Feather Icons) for all navigation items and action buttons.\\n\\n**Interactive + Elements**\\n- Hover effects on buttons and links.\\n- Tooltips for charts + and graphs to provide additional context.\\n- Responsive design for mobile + and tablet views.\\n\\nThis mockup provides a clean, intuitive, and visually + appealing dashboard interface that enhances user experience and facilitates + easy navigation and data analysis.\",\"role\":\"assistant\"}}],\"created\":1771988140,\"id\":\"chatcmpl-c9eb9fa7-8e1a-912e-a0b8-d8408ee2200c\",\"model\":\"qwen-turbo\",\"object\":\"chat.completion\",\"usage\":{\"completion_tokens\":517,\"prompt_tokens\":164,\"prompt_tokens_details\":{\"cached_tokens\":0},\"total_tokens\":681}}" + headers: + content-length: + - '2572' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:55:45 GMT + req-arrive-time: + - '1771988140177' + req-cost-time: + - '5905' + resp-start-time: + - '1771988146083' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '5905' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Frontend Developer. + Expert frontend developer\nYour personal goal is: Implement designs\nTo give + my best complete final answer to the task use the exact following format:\n\nThought: + I now can give a great answer\nFinal Answer: Your final answer must be the great + and the most complete as possible, it must be outcome described.\n\nI MUST use + these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent + Task: Implement the designed dashboard\n\nThis is the expect criteria for your + final answer: Working dashboard code\nyou MUST return the actual complete content + as the final answer, not a summary.\n\nThis is the context you''re working with:\n[UI + Design Mockup]\n\nHere is a detailed description of a user-friendly dashboard + interface design:\n\n**Dashboard Interface Design Mockup**\n\n**1. Header Section**\n- + **Logo/Title**: Top-left corner with the company logo and name.\n- **User Profile**: + Top-right corner with a profile icon, username, and dropdown menu (e.g., \"Profile,\" + \"Settings,\" \"Logout\").\n- **Search Bar**: Centered at the top for quick + access to specific data or features.\n\n**2. Navigation Sidebar**\n- **Menu + Items**: Vertical sidebar on the left with icons and labels:\n - Dashboard\n - + Analytics\n - Reports\n - Settings\n - Help\n- **Active State**: Highlight + the currently selected menu item with a different color or bold font.\n\n**3. + Main Content Area**\n- **Overview Card**: Large card at the top with key metrics + (e.g., total users, active sessions, revenue).\n- **Graphs/Charts**: Two columns + layout:\n - Left Column: Line chart showing trends over time (e.g., daily activity).\n - + Right Column: Bar chart comparing different categories (e.g., product sales).\n- + **Recent Activity**: A table listing recent user actions or system events.\n- + **Quick Actions**: A section with buttons for common tasks (e.g., \"Create New + Report,\" \"Add User\").\n\n**4. Footer Section**\n- **Copyright Info**: \"\u00a9 + 2025 Company Name. All rights reserved.\"\n- **Links**: Quick links to Privacy + Policy, Terms of Service, and Contact Us.\n\n**Color Scheme**\n- Primary Color: + Blue (#007BFF)\n- Secondary Color: Light Gray (#F8F9FA)\n- Accent Color: Green + (#28A745)\n- Text Color: Dark Gray (#343A40)\n\n**Typography**\n- Font Family: + Arial or Helvetica\n- Font Sizes:\n - Headers: 24px\n - Subheaders: 18px\n - + Body Text: 16px\n\n**Icons**\n- Use consistent icon style (e.g., Material Icons + or Feather Icons) for all navigation items and action buttons.\n\n**Interactive + Elements**\n- Hover effects on buttons and links.\n- Tooltips for charts and + graphs to provide additional context.\n- Responsive design for mobile and tablet + views.\n\nThis mockup provides a clean, intuitive, and visually appealing dashboard + interface that enhances user experience and facilitates easy navigation and + data analysis.\n\nBegin! This is VERY important to you, use the tools available + and give your best Final Answer, your job depends on it!\n\nThought:"}], "model": + "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '3081' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: "{\"choices\":[{\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"content\":\"Thought: + I now can give a great answer\\nFinal Answer: \\n```html\\n\\n\\n\\n \\n \\n Dashboard\\n + \ \\n \\n\\n\\n
\\n + \
Company Logo | Dashboard
\\n
\\n
\\n John Doe\\n \\\"Profile\\n + \
\\n
\\n\\n \\n\\n
\\n + \
\\n

Overview

\\n + \
\\n
\\n + \

Total Users

\\n

1,250

\\n + \
\\n
\\n

Active + Sessions

\\n

320

\\n
\\n + \
\\n

Revenue

\\n + \

$5,200

\\n
\\n
\\n + \
\\n\\n
\\n
\\n

Daily Activity Trends

\\n \\n
\\n + \
\\n

Product Sales + Comparison

\\n \\n
\\n
\\n\\n
\\n

Recent Activity

\\n \\n + \ \\n \\n \\n + \ \\n \\n + \ \\n \\n \\n + \ \\n \\n + \ \\n \\n + \ \\n \\n \\n \\n \\n + \ \\n \\n \\n \\n \\n + \ \\n \\n
ActionUserDate
Created ReportJohn Doe2025-04-01
Updated + SettingsJane Smith2025-04-02
Added + New UserAdmin2025-04-03
\\n + \
\\n\\n
\\n \\n \\n \\n
\\n
\\n\\n \\n\\n \\n \\n + \ \\n\\n \\n \\n + \ \\n\\n\\n```\",\"role\":\"assistant\"}}],\"created\":1771988146,\"id\":\"chatcmpl-05f95a25-3b9b-9ecf-80e7-8f492011b416\",\"model\":\"qwen-turbo\",\"object\":\"chat.completion\",\"usage\":{\"completion_tokens\":2342,\"prompt_tokens\":675,\"prompt_tokens_details\":{\"cached_tokens\":0},\"total_tokens\":3017}}" + headers: + content-length: + - '10413' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:56:15 GMT + req-arrive-time: + - '1771988146314' + req-cost-time: + - '29140' + resp-start-time: + - '1771988175455' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '29140' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are UX Designer. Senior + UX designer\nYour personal goal is: Design user-friendly interfaces\nTo give + my best complete final answer to the task use the exact following format:\n\nThought: + I now can give a great answer\nFinal Answer: Your final answer must be the great + and the most complete as possible, it must be outcome described.\n\nI MUST use + these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent + Task: Design a dashboard interface\n\nThis is the expect criteria for your final + answer: UI design mockup\nyou MUST return the actual complete content as the + final answer, not a summary.\n\nBegin! This is VERY important to you, use the + tools available and give your best Final Answer, your job depends on it!\n\nThought:"}], + "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '838' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: "{\"choices\":[{\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"content\":\"Thought: + I now can give a great answer\\nFinal Answer: \\n{\\n \\\"dashboard\\\": + {\\n \\\"header\\\": {\\n \\\"title\\\": \\\"User Dashboard\\\",\\n + \ \\\"user_profile\\\": {\\n \\\"name\\\": \\\"John Doe\\\",\\n + \ \\\"avatar\\\": \\\"https://example.com/avatar.jpg\\\"\\n },\\n + \ \\\"navigation\\\": [\\\"Home\\\", \\\"Analytics\\\", \\\"Settings\\\", + \\\"Logout\\\"]\\n },\\n \\\"sidebar\\\": {\\n \\\"sections\\\": + [\\n {\\n \\\"title\\\": \\\"Quick Actions\\\",\\n \\\"items\\\": + [\\\"Create New Project\\\", \\\"Invite Team Members\\\", \\\"View Reports\\\"]\\n + \ },\\n {\\n \\\"title\\\": \\\"Recent Activity\\\",\\n + \ \\\"items\\\": [\\\"Project A Updated\\\", \\\"Task B Assigned\\\", + \\\"Report C Generated\\\"]\\n }\\n ]\\n },\\n \\\"main_content\\\": + {\\n \\\"widgets\\\": [\\n {\\n \\\"type\\\": \\\"card\\\",\\n + \ \\\"title\\\": \\\"Overview\\\",\\n \\\"content\\\": \\\"Welcome + back, John! Here's a summary of your recent activity.\\\"\\n },\\n + \ {\\n \\\"type\\\": \\\"chart\\\",\\n \\\"title\\\": + \\\"Performance Metrics\\\",\\n \\\"data\\\": {\\n \\\"labels\\\": + [\\\"Jan\\\", \\\"Feb\\\", \\\"Mar\\\", \\\"Apr\\\", \\\"May\\\", \\\"Jun\\\"],\\n + \ \\\"values\\\": [120, 150, 180, 210, 240, 270]\\n }\\n + \ },\\n {\\n \\\"type\\\": \\\"table\\\",\\n \\\"title\\\": + \\\"Recent Projects\\\",\\n \\\"columns\\\": [\\\"Project Name\\\", + \\\"Status\\\", \\\"Last Updated\\\"],\\n \\\"rows\\\": [\\n [\\\"Project + A\\\", \\\"In Progress\\\", \\\"2023-04-05\\\"],\\n [\\\"Project + B\\\", \\\"Completed\\\", \\\"2023-04-03\\\"],\\n [\\\"Project + C\\\", \\\"Pending\\\", \\\"2023-04-07\\\"]\\n ]\\n }\\n ]\\n + \ },\\n \\\"footer\\\": {\\n \\\"copyright\\\": \\\"\xA9 2023 User + Dashboard. All rights reserved.\\\"\\n }\\n }\\n}\",\"role\":\"assistant\"}}],\"created\":1771989392,\"id\":\"chatcmpl-80ee884a-b012-92a4-a3ff-1a7e907f2c2e\",\"model\":\"qwen-turbo\",\"object\":\"chat.completion\",\"usage\":{\"completion_tokens\":418,\"prompt_tokens\":164,\"prompt_tokens_details\":{\"cached_tokens\":0},\"total_tokens\":582}}" + headers: + content-length: + - '2057' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:16:38 GMT + req-arrive-time: + - '1771989392848' + req-cost-time: + - '6035' + resp-start-time: + - '1771989398884' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '6035' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Frontend Developer. + Expert frontend developer\nYour personal goal is: Implement designs\nTo give + my best complete final answer to the task use the exact following format:\n\nThought: + I now can give a great answer\nFinal Answer: Your final answer must be the great + and the most complete as possible, it must be outcome described.\n\nI MUST use + these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent + Task: Implement the designed dashboard\n\nThis is the expect criteria for your + final answer: Working dashboard code\nyou MUST return the actual complete content + as the final answer, not a summary.\n\nThis is the context you''re working with:\n{\n \"dashboard\": + {\n \"header\": {\n \"title\": \"User Dashboard\",\n \"user_profile\": + {\n \"name\": \"John Doe\",\n \"avatar\": \"https://example.com/avatar.jpg\"\n },\n \"navigation\": + [\"Home\", \"Analytics\", \"Settings\", \"Logout\"]\n },\n \"sidebar\": + {\n \"sections\": [\n {\n \"title\": \"Quick Actions\",\n \"items\": + [\"Create New Project\", \"Invite Team Members\", \"View Reports\"]\n },\n {\n \"title\": + \"Recent Activity\",\n \"items\": [\"Project A Updated\", \"Task B + Assigned\", \"Report C Generated\"]\n }\n ]\n },\n \"main_content\": + {\n \"widgets\": [\n {\n \"type\": \"card\",\n \"title\": + \"Overview\",\n \"content\": \"Welcome back, John! Here''s a summary + of your recent activity.\"\n },\n {\n \"type\": \"chart\",\n \"title\": + \"Performance Metrics\",\n \"data\": {\n \"labels\": [\"Jan\", + \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\"],\n \"values\": [120, + 150, 180, 210, 240, 270]\n }\n },\n {\n \"type\": + \"table\",\n \"title\": \"Recent Projects\",\n \"columns\": + [\"Project Name\", \"Status\", \"Last Updated\"],\n \"rows\": [\n [\"Project + A\", \"In Progress\", \"2023-04-05\"],\n [\"Project B\", \"Completed\", + \"2023-04-03\"],\n [\"Project C\", \"Pending\", \"2023-04-07\"]\n ]\n }\n ]\n },\n \"footer\": + {\n \"copyright\": \"\u00a9 2023 User Dashboard. All rights reserved.\"\n }\n }\n}\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '2564' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: "{\"choices\":[{\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"content\":\"{\\n + \ \\\"dashboard\\\": {\\n \\\"header\\\": {\\n \\\"title\\\": \\\"User + Dashboard\\\",\\n \\\"user_profile\\\": {\\n \\\"name\\\": \\\"John + Doe\\\",\\n \\\"avatar\\\": \\\"https://example.com/avatar.jpg\\\"\\n + \ },\\n \\\"navigation\\\": [\\\"Home\\\", \\\"Analytics\\\", \\\"Settings\\\", + \\\"Logout\\\"]\\n },\\n \\\"sidebar\\\": {\\n \\\"sections\\\": + [\\n {\\n \\\"title\\\": \\\"Quick Actions\\\",\\n \\\"items\\\": + [\\\"Create New Project\\\", \\\"Invite Team Members\\\", \\\"View Reports\\\"]\\n + \ },\\n {\\n \\\"title\\\": \\\"Recent Activity\\\",\\n + \ \\\"items\\\": [\\\"Project A Updated\\\", \\\"Task B Assigned\\\", + \\\"Report C Generated\\\"]\\n }\\n ]\\n },\\n \\\"main_content\\\": + {\\n \\\"widgets\\\": [\\n {\\n \\\"type\\\": \\\"card\\\",\\n + \ \\\"title\\\": \\\"Overview\\\",\\n \\\"content\\\": \\\"Welcome + back, John! Here's a summary of your recent activity.\\\"\\n },\\n + \ {\\n \\\"type\\\": \\\"chart\\\",\\n \\\"title\\\": + \\\"Performance Metrics\\\",\\n \\\"data\\\": {\\n \\\"labels\\\": + [\\\"Jan\\\", \\\"Feb\\\", \\\"Mar\\\", \\\"Apr\\\", \\\"May\\\", \\\"Jun\\\"],\\n + \ \\\"values\\\": [120, 150, 180, 210, 240, 270]\\n }\\n + \ },\\n {\\n \\\"type\\\": \\\"table\\\",\\n \\\"title\\\": + \\\"Recent Projects\\\",\\n \\\"columns\\\": [\\\"Project Name\\\", + \\\"Status\\\", \\\"Last Updated\\\"],\\n \\\"rows\\\": [\\n [\\\"Project + A\\\", \\\"In Progress\\\", \\\"2023-04-05\\\"],\\n [\\\"Project + B\\\", \\\"Completed\\\", \\\"2023-04-03\\\"],\\n [\\\"Project + C\\\", \\\"Pending\\\", \\\"2023-04-07\\\"]\\n ]\\n }\\n ]\\n + \ },\\n \\\"footer\\\": {\\n \\\"copyright\\\": \\\"\xA9 2023 User + Dashboard. All rights reserved.\\\"\\n }\\n }\\n}\",\"role\":\"assistant\"}}],\"created\":1771989399,\"id\":\"chatcmpl-fab43749-0059-9312-9e07-efd55659140a\",\"model\":\"qwen-turbo\",\"object\":\"chat.completion\",\"usage\":{\"completion_tokens\":404,\"prompt_tokens\":575,\"prompt_tokens_details\":{\"cached_tokens\":0},\"total_tokens\":979}}" + headers: + content-length: + - '2001' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:16:43 GMT + req-arrive-time: + - '1771989399166' + req-cost-time: + - '5011' + resp-start-time: + - '1771989404177' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '5011' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Frontend Developer. + Expert frontend developer\nYour personal goal is: Implement designs\nTo give + my best complete final answer to the task use the exact following format:\n\nThought: + I now can give a great answer\nFinal Answer: Your final answer must be the great + and the most complete as possible, it must be outcome described.\n\nI MUST use + these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent + Task: Implement the designed dashboard\n\nThis is the expect criteria for your + final answer: Working dashboard code\nyou MUST return the actual complete content + as the final answer, not a summary.\n\nThis is the context you''re working with:\n{\n \"dashboard\": + {\n \"header\": {\n \"title\": \"User Dashboard\",\n \"user_profile\": + {\n \"name\": \"John Doe\",\n \"avatar\": \"https://example.com/avatar.jpg\"\n },\n \"navigation\": + [\"Home\", \"Analytics\", \"Settings\", \"Logout\"]\n },\n \"sidebar\": + {\n \"sections\": [\n {\n \"title\": \"Quick Actions\",\n \"items\": + [\"Create New Project\", \"Invite Team Members\", \"View Reports\"]\n },\n {\n \"title\": + \"Recent Activity\",\n \"items\": [\"Project A Updated\", \"Task B + Assigned\", \"Report C Generated\"]\n }\n ]\n },\n \"main_content\": + {\n \"widgets\": [\n {\n \"type\": \"card\",\n \"title\": + \"Overview\",\n \"content\": \"Welcome back, John! Here''s a summary + of your recent activity.\"\n },\n {\n \"type\": \"chart\",\n \"title\": + \"Performance Metrics\",\n \"data\": {\n \"labels\": [\"Jan\", + \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\"],\n \"values\": [120, + 150, 180, 210, 240, 270]\n }\n },\n {\n \"type\": + \"table\",\n \"title\": \"Recent Projects\",\n \"columns\": + [\"Project Name\", \"Status\", \"Last Updated\"],\n \"rows\": [\n [\"Project + A\", \"In Progress\", \"2023-04-05\"],\n [\"Project B\", \"Completed\", + \"2023-04-03\"],\n [\"Project C\", \"Pending\", \"2023-04-07\"]\n ]\n }\n ]\n },\n \"footer\": + {\n \"copyright\": \"\u00a9 2023 User Dashboard. All rights reserved.\"\n }\n }\n}\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}, {"role": "user", "content": "I + did it wrong. Invalid Format: I missed the ''Action:'' after ''Thought:''. I + will do right next, and don''t use a tool I have already used.\n\nIf you don''t + need to use any more tools, you must give your best complete final answer, make + sure it satisfy the expect criteria, use the EXACT format below:\n\nThought: + I now can give a great answer\nFinal Answer: my best complete final answer to + the task.\n\n"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '2994' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: "{\"choices\":[{\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"content\":\"Thought: + I now can give a great answer\\nFinal Answer: \\n\\n\\n + \ \\n \\n User Dashboard\\n \\n\\n\\n
\\n

User + Dashboard

\\n
\\n \\\"User\\n John + Doe\\n
\\n \\n
\\n\\n + \
\\n \\n\\n + \
\\n
\\n

Overview

\\n + \

Welcome back, John! Here's a summary of your recent activity.

\\n + \
\\n\\n
\\n

Performance + Metrics

\\n
\\n
\\n
\\n
\\n + \
\\n
\\n
\\n
\\n
\\n\\n
\\n

Recent Projects

\\n \\n + \ \\n \\n \\n \\n \\n \\n \\n + \ \\n \\n \\n \\n \\n + \ \\n \\n \\n \\n \\n + \ \\n \\n \\n \\n \\n + \ \\n \\n
Project + NameStatusLast + Updated
Project + AIn Progress2023-04-05
Project + BCompleted2023-04-03
Project + CPending2023-04-07
\\n + \
\\n
\\n
\\n\\n
\\n

\xA9 + 2023 User Dashboard. All rights reserved.

\\n
\\n\\n\",\"role\":\"assistant\"}}],\"created\":1771989404,\"id\":\"chatcmpl-b66b8534-f11b-9dd5-9c45-55e4ea0cede2\",\"model\":\"qwen-turbo\",\"object\":\"chat.completion\",\"usage\":{\"completion_tokens\":1224,\"prompt_tokens\":668,\"prompt_tokens_details\":{\"cached_tokens\":0},\"total_tokens\":1892}}" + headers: + content-length: + - '5777' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:16:59 GMT + req-arrive-time: + - '1771989404474' + req-cost-time: + - '15670' + resp-start-time: + - '1771989420145' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '15670' + x-request-id: + - + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_agent_workflow/TestAgentWorkflow.test_sequential_workflow.yaml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_agent_workflow/TestAgentWorkflow.test_sequential_workflow.yaml new file mode 100644 index 000000000..b469afaf8 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_agent_workflow/TestAgentWorkflow.test_sequential_workflow.yaml @@ -0,0 +1,1431 @@ +interactions: +- request: + body: '{"messages": [{"role": "system", "content": "You are Researcher. Expert + researcher with 15 years of experience\nYour personal goal is: Gather comprehensive + information\nTo give my best complete final answer to the task use the exact + following format:\n\nThought: I now can give a great answer\nFinal Answer: Your + final answer must be the great and the most complete as possible, it must be + outcome described.\n\nI MUST use these formats, my job depends on it!"}, {"role": + "user", "content": "\nCurrent Task: Research the latest AI trends in 2024\n\nThis + is the expect criteria for your final answer: Comprehensive research report\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '887' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: "{\"choices\":[{\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"content\":\"I + now can give a great answer\\nFinal Answer: The latest AI trends in 2024 reflect + a rapidly evolving landscape shaped by technological advancements, ethical + considerations, and practical applications across industries. Below is a comprehensive + research report detailing the most significant AI trends observed in 2024.\\n\\n1. + **AI-Driven Personalization at Scale** \\n In 2024, AI systems have become + increasingly adept at personalizing user experiences across various platforms. + From recommendation engines in e-commerce to tailored content delivery in + media and education, AI algorithms are leveraging real-time data and advanced + machine learning models to deliver hyper-personalized interactions. This trend + is particularly prominent in sectors like healthcare, where personalized treatment + plans based on patient data are becoming standard practice.\\n\\n2. **Explainable + AI (XAI) and Ethical AI Frameworks** \\n With growing concerns over AI + bias and transparency, 2024 has seen a surge in the development of Explainable + AI (XAI) tools. These technologies aim to make AI decision-making processes + more transparent and interpretable for users and stakeholders. Additionally, + ethical AI frameworks have been widely adopted by organizations to ensure + responsible AI deployment, with many companies implementing AI ethics boards + and compliance protocols to align with global standards such as the EU AI + Act and the OECD AI Principles.\\n\\n3. **AI in Climate Change Mitigation** + \ \\n AI is playing a pivotal role in addressing climate change through + predictive modeling, resource optimization, and environmental monitoring. + In 2024, AI-driven climate models have improved accuracy in predicting extreme + weather events, while AI-powered energy management systems are optimizing + renewable energy distribution. Furthermore, AI is being used to monitor deforestation, + track carbon emissions, and develop sustainable agricultural practices.\\n\\n4. + **AI-Generated Content and Creativity Tools** \\n The rise of AI-generated + content continues to redefine creative industries. In 2024, AI tools for generating + text, images, music, and even video have reached new levels of sophistication. + Platforms like DALL\xB7E 3, MidJourney, and others have enabled artists, writers, + and designers to collaborate with AI in unprecedented ways. However, this + trend has also sparked debates around intellectual property, originality, + and the impact on traditional creative professions.\\n\\n5. **Edge AI and + Decentralized AI Systems** \\n Edge AI, which involves processing data + locally on devices rather than in centralized cloud servers, has gained traction + in 2024. This approach reduces latency, enhances privacy, and improves performance + in real-time applications such as autonomous vehicles, smart homes, and industrial + IoT systems. Additionally, decentralized AI systems, powered by blockchain + technology, are emerging as a way to distribute AI computation and ensure + data security and fairness.\\n\\n6. **AI in Healthcare: Diagnostics and Treatment** + \ \\n AI's role in healthcare has expanded significantly in 2024, with breakthroughs + in diagnostic imaging, drug discovery, and personalized medicine. AI models + are now capable of detecting early signs of diseases such as cancer, Alzheimer\u2019s, + and diabetes with high accuracy. Moreover, AI-driven robotic surgery systems + and virtual health assistants are enhancing patient care and reducing the + burden on medical professionals.\\n\\n7. **AI-Powered Cybersecurity Solutions** + \ \\n As cyber threats grow more sophisticated, AI is being leveraged to + bolster cybersecurity defenses. In 2024, AI-based threat detection systems + are capable of identifying and neutralizing malicious activities in real time. + Machine learning models are also being used to predict attack patterns and + automate incident response, making organizations more resilient against cyberattacks.\\n\\n8. + **AI in Education: Adaptive Learning and Virtual Tutors** \\n AI is transforming + the education sector by enabling adaptive learning platforms that cater to + individual student needs. In 2024, AI-powered virtual tutors and intelligent + learning systems are being integrated into classrooms and online education + platforms. These tools analyze student performance and adjust teaching methods + accordingly, leading to improved learning outcomes and greater accessibility + to quality education.\\n\\n9. **AI Ethics and Regulatory Compliance** \\n + \ The focus on AI ethics has intensified in 2024, with governments and organizations + implementing stricter regulations to ensure accountability and fairness. Countries + like the United States, the European Union, and China have introduced new + policies to govern AI usage, emphasizing transparency, data privacy, and the + prevention of harmful biases. Companies are also investing in AI audit tools + and compliance training programs to meet these regulatory requirements.\\n\\n10. + **AI in Agriculture and Food Security** \\n AI is revolutionizing agriculture + through precision farming techniques, crop monitoring, and supply chain optimization. + In 2024, AI-powered drones and sensors are being used to assess soil health, + monitor crop growth, and predict yield outcomes. Additionally, AI-driven food + waste reduction strategies are helping to improve sustainability and reduce + the environmental impact of the food industry.\\n\\n11. **AI in Customer Service + and Chatbots** \\n AI chatbots and virtual assistants have become more + advanced in 2024, offering natural language understanding and contextual awareness. + These systems are now capable of handling complex customer inquiries, providing + multilingual support, and even anticipating customer needs. Businesses are + leveraging AI to enhance customer satisfaction while reducing operational + costs.\\n\\n12. **AI in Finance and Fintech** \\n The financial sector + has embraced AI for fraud detection, algorithmic trading, and personalized + banking services. In 2024, AI models are being used to analyze vast amounts + of financial data in real time, enabling faster and more accurate decision-making. + Additionally, AI-driven robo-advisors are becoming popular among consumers + seeking affordable and efficient investment solutions.\\n\\n13. **AI in Manufacturing + and Supply Chain Optimization** \\n AI is streamlining manufacturing processes + and optimizing supply chains through predictive maintenance, demand forecasting, + and logistics planning. In 2024, AI-powered robotics and automation have increased + efficiency and reduced production costs. Companies are also using AI to manage + inventory, minimize delays, and enhance overall operational performance.\\n\\n14. + **AI in Gaming and Entertainment** \\n AI has transformed the gaming and + entertainment industries by enabling dynamic storytelling, procedural content + generation, and realistic character behavior. In 2024, AI-driven game engines + are creating immersive and responsive environments, while AI-generated scripts + and storylines are enhancing the creativity of film and television productions.\\n\\n15. + **AI in Transportation and Autonomous Vehicles** \\n The development of + autonomous vehicles has accelerated in 2024, with AI playing a central role + in navigation, object recognition, and decision-making. Self-driving cars, + drones, and delivery robots are becoming more common, driven by advancements + in computer vision, sensor fusion, and real-time data processing. Additionally, + AI is being used to optimize traffic flow and reduce congestion in urban areas.\\n\\n16. + **AI in Human Resources and Talent Management** \\n AI is reshaping HR + practices by automating recruitment, employee engagement, and performance + management. In 2024, AI tools are being used to screen job candidates, assess + employee skills, and provide personalized career development recommendations. + These systems help organizations build diverse and inclusive workforces while + improving efficiency and reducing bias in hiring processes.\\n\\n17. **AI + in Environmental Monitoring and Sustainability** \\n AI is being used + to monitor environmental changes and support sustainability initiatives. In + 2024, AI-powered satellite imagery analysis and sensor networks are tracking + pollution levels, wildlife activity, and ecosystem health. These insights + are helping governments and organizations develop targeted strategies for + conservation and environmental protection.\\n\\n18. **AI in Language Translation + and Localization** \\n AI-driven translation tools have reached new levels + of accuracy and fluency in 2024. These systems are capable of translating + not only text but also speech and sign language, making communication more + accessible across cultures. Additionally, AI is being used to localize content + for different markets, ensuring cultural relevance and engagement.\\n\\n19. + **AI in Legal and Compliance Fields** \\n AI is transforming legal practices + by automating document review, contract analysis, and case prediction. In + 2024, AI tools are being used to streamline legal workflows, reduce costs, + and improve the speed of legal proceedings. These systems are also assisting + in compliance management by identifying potential regulatory violations and + suggesting corrective actions.\\n\\n20. **AI in Social Media and Content Moderation** + \ \\n AI is playing a critical role in managing social media content and + ensuring platform safety. In 2024, AI algorithms are being used to detect + harmful content, such as hate speech, misinformation, and cyberbullying. These + systems are also being employed to recommend content and personalize user + feeds, enhancing user experience while maintaining community guidelines.\\n\\nIn + conclusion, 2024 has marked a year of significant progress and innovation + in the field of artificial intelligence. From enhanced personalization and + ethical frameworks to transformative applications in healthcare, climate change, + and beyond, AI continues to shape the future in profound ways. As the technology + evolves, it will be essential to address challenges related to bias, transparency, + and regulation to ensure that AI benefits society as a whole.\",\"role\":\"assistant\"}}],\"created\":1771988176,\"id\":\"chatcmpl-1770c061-fd97-9e7b-a635-199adc83a1ba\",\"model\":\"qwen-turbo\",\"object\":\"chat.completion\",\"usage\":{\"completion_tokens\":1836,\"prompt_tokens\":175,\"prompt_tokens_details\":{\"cached_tokens\":0},\"total_tokens\":2011}}" + headers: + content-length: + - '10438' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:56:38 GMT + req-arrive-time: + - '1771988175984' + req-cost-time: + - '22458' + resp-start-time: + - '1771988198443' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '22458' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Data Analyst. Senior + data analyst specializing in AI trends\nYour personal goal is: Analyze data + and extract insights\nTo give my best complete final answer to the task use + the exact following format:\n\nThought: I now can give a great answer\nFinal + Answer: Your final answer must be the great and the most complete as possible, + it must be outcome described.\n\nI MUST use these formats, my job depends on + it!"}, {"role": "user", "content": "\nCurrent Task: Analyze the research findings\n\nThis + is the expect criteria for your final answer: Data analysis report\nyou MUST + return the actual complete content as the final answer, not a summary.\n\nThis + is the context you''re working with:\nThe latest AI trends in 2024 reflect a + rapidly evolving landscape shaped by technological advancements, ethical considerations, + and practical applications across industries. Below is a comprehensive research + report detailing the most significant AI trends observed in 2024.\n\n1. **AI-Driven + Personalization at Scale** \n In 2024, AI systems have become increasingly + adept at personalizing user experiences across various platforms. From recommendation + engines in e-commerce to tailored content delivery in media and education, AI + algorithms are leveraging real-time data and advanced machine learning models + to deliver hyper-personalized interactions. This trend is particularly prominent + in sectors like healthcare, where personalized treatment plans based on patient + data are becoming standard practice.\n\n2. **Explainable AI (XAI) and Ethical + AI Frameworks** \n With growing concerns over AI bias and transparency, 2024 + has seen a surge in the development of Explainable AI (XAI) tools. These technologies + aim to make AI decision-making processes more transparent and interpretable + for users and stakeholders. Additionally, ethical AI frameworks have been widely + adopted by organizations to ensure responsible AI deployment, with many companies + implementing AI ethics boards and compliance protocols to align with global + standards such as the EU AI Act and the OECD AI Principles.\n\n3. **AI in Climate + Change Mitigation** \n AI is playing a pivotal role in addressing climate + change through predictive modeling, resource optimization, and environmental + monitoring. In 2024, AI-driven climate models have improved accuracy in predicting + extreme weather events, while AI-powered energy management systems are optimizing + renewable energy distribution. Furthermore, AI is being used to monitor deforestation, + track carbon emissions, and develop sustainable agricultural practices.\n\n4. + **AI-Generated Content and Creativity Tools** \n The rise of AI-generated + content continues to redefine creative industries. In 2024, AI tools for generating + text, images, music, and even video have reached new levels of sophistication. + Platforms like DALL\u00b7E 3, MidJourney, and others have enabled artists, writers, + and designers to collaborate with AI in unprecedented ways. However, this trend + has also sparked debates around intellectual property, originality, and the + impact on traditional creative professions.\n\n5. **Edge AI and Decentralized + AI Systems** \n Edge AI, which involves processing data locally on devices + rather than in centralized cloud servers, has gained traction in 2024. This + approach reduces latency, enhances privacy, and improves performance in real-time + applications such as autonomous vehicles, smart homes, and industrial IoT systems. + Additionally, decentralized AI systems, powered by blockchain technology, are + emerging as a way to distribute AI computation and ensure data security and + fairness.\n\n6. **AI in Healthcare: Diagnostics and Treatment** \n AI''s + role in healthcare has expanded significantly in 2024, with breakthroughs in + diagnostic imaging, drug discovery, and personalized medicine. AI models are + now capable of detecting early signs of diseases such as cancer, Alzheimer\u2019s, + and diabetes with high accuracy. Moreover, AI-driven robotic surgery systems + and virtual health assistants are enhancing patient care and reducing the burden + on medical professionals.\n\n7. **AI-Powered Cybersecurity Solutions** \n As + cyber threats grow more sophisticated, AI is being leveraged to bolster cybersecurity + defenses. In 2024, AI-based threat detection systems are capable of identifying + and neutralizing malicious activities in real time. Machine learning models + are also being used to predict attack patterns and automate incident response, + making organizations more resilient against cyberattacks.\n\n8. **AI in Education: + Adaptive Learning and Virtual Tutors** \n AI is transforming the education + sector by enabling adaptive learning platforms that cater to individual student + needs. In 2024, AI-powered virtual tutors and intelligent learning systems are + being integrated into classrooms and online education platforms. These tools + analyze student performance and adjust teaching methods accordingly, leading + to improved learning outcomes and greater accessibility to quality education.\n\n9. + **AI Ethics and Regulatory Compliance** \n The focus on AI ethics has intensified + in 2024, with governments and organizations implementing stricter regulations + to ensure accountability and fairness. Countries like the United States, the + European Union, and China have introduced new policies to govern AI usage, emphasizing + transparency, data privacy, and the prevention of harmful biases. Companies + are also investing in AI audit tools and compliance training programs to meet + these regulatory requirements.\n\n10. **AI in Agriculture and Food Security** \n AI + is revolutionizing agriculture through precision farming techniques, crop monitoring, + and supply chain optimization. In 2024, AI-powered drones and sensors are being + used to assess soil health, monitor crop growth, and predict yield outcomes. + Additionally, AI-driven food waste reduction strategies are helping to improve + sustainability and reduce the environmental impact of the food industry.\n\n11. + **AI in Customer Service and Chatbots** \n AI chatbots and virtual assistants + have become more advanced in 2024, offering natural language understanding and + contextual awareness. These systems are now capable of handling complex customer + inquiries, providing multilingual support, and even anticipating customer needs. + Businesses are leveraging AI to enhance customer satisfaction while reducing + operational costs.\n\n12. **AI in Finance and Fintech** \n The financial + sector has embraced AI for fraud detection, algorithmic trading, and personalized + banking services. In 2024, AI models are being used to analyze vast amounts + of financial data in real time, enabling faster and more accurate decision-making. + Additionally, AI-driven robo-advisors are becoming popular among consumers seeking + affordable and efficient investment solutions.\n\n13. **AI in Manufacturing + and Supply Chain Optimization** \n AI is streamlining manufacturing processes + and optimizing supply chains through predictive maintenance, demand forecasting, + and logistics planning. In 2024, AI-powered robotics and automation have increased + efficiency and reduced production costs. Companies are also using AI to manage + inventory, minimize delays, and enhance overall operational performance.\n\n14. + **AI in Gaming and Entertainment** \n AI has transformed the gaming and + entertainment industries by enabling dynamic storytelling, procedural content + generation, and realistic character behavior. In 2024, AI-driven game engines + are creating immersive and responsive environments, while AI-generated scripts + and storylines are enhancing the creativity of film and television productions.\n\n15. + **AI in Transportation and Autonomous Vehicles** \n The development of autonomous + vehicles has accelerated in 2024, with AI playing a central role in navigation, + object recognition, and decision-making. Self-driving cars, drones, and delivery + robots are becoming more common, driven by advancements in computer vision, + sensor fusion, and real-time data processing. Additionally, AI is being used + to optimize traffic flow and reduce congestion in urban areas.\n\n16. **AI in + Human Resources and Talent Management** \n AI is reshaping HR practices + by automating recruitment, employee engagement, and performance management. + In 2024, AI tools are being used to screen job candidates, assess employee skills, + and provide personalized career development recommendations. These systems help + organizations build diverse and inclusive workforces while improving efficiency + and reducing bias in hiring processes.\n\n17. **AI in Environmental Monitoring + and Sustainability** \n AI is being used to monitor environmental changes + and support sustainability initiatives. In 2024, AI-powered satellite imagery + analysis and sensor networks are tracking pollution levels, wildlife activity, + and ecosystem health. These insights are helping governments and organizations + develop targeted strategies for conservation and environmental protection.\n\n18. + **AI in Language Translation and Localization** \n AI-driven translation + tools have reached new levels of accuracy and fluency in 2024. These systems + are capable of translating not only text but also speech and sign language, + making communication more accessible across cultures. Additionally, AI is being + used to localize content for different markets, ensuring cultural relevance + and engagement.\n\n19. **AI in Legal and Compliance Fields** \n AI is transforming + legal practices by automating document review, contract analysis, and case prediction. + In 2024, AI tools are being used to streamline legal workflows, reduce costs, + and improve the speed of legal proceedings. These systems are also assisting + in compliance management by identifying potential regulatory violations and + suggesting corrective actions.\n\n20. **AI in Social Media and Content Moderation** \n AI + is playing a critical role in managing social media content and ensuring platform + safety. In 2024, AI algorithms are being used to detect harmful content, such + as hate speech, misinformation, and cyberbullying. These systems are also being + employed to recommend content and personalize user feeds, enhancing user experience + while maintaining community guidelines.\n\nIn conclusion, 2024 has marked a + year of significant progress and innovation in the field of artificial intelligence. + From enhanced personalization and ethical frameworks to transformative applications + in healthcare, climate change, and beyond, AI continues to shape the future + in profound ways. As the technology evolves, it will be essential to address + challenges related to bias, transparency, and regulation to ensure that AI benefits + society as a whole.\n\nBegin! This is VERY important to you, use the tools available + and give your best Final Answer, your job depends on it!\n\nThought:"}], "model": + "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '10979' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: "{\"choices\":[{\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"content\":\"Thought: + I now can give a great answer\\nFinal Answer: The latest AI trends in 2024 + reflect a rapidly evolving landscape shaped by technological advancements, + ethical considerations, and practical applications across industries. Below + is a comprehensive research report detailing the most significant AI trends + observed in 2024.\\n\\n1. **AI-Driven Personalization at Scale** \\n In + 2024, AI systems have become increasingly adept at personalizing user experiences + across various platforms. From recommendation engines in e-commerce to tailored + content delivery in media and education, AI algorithms are leveraging real-time + data and advanced machine learning models to deliver hyper-personalized interactions. + This trend is particularly prominent in sectors like healthcare, where personalized + treatment plans based on patient data are becoming standard practice.\\n\\n2. + **Explainable AI (XAI) and Ethical AI Frameworks** \\n With growing concerns + over AI bias and transparency, 2024 has seen a surge in the development of + Explainable AI (XAI) tools. These technologies aim to make AI decision-making + processes more transparent and interpretable for users and stakeholders. Additionally, + ethical AI frameworks have been widely adopted by organizations to ensure + responsible AI deployment, with many companies implementing AI ethics boards + and compliance protocols to align with global standards such as the EU AI + Act and the OECD AI Principles.\\n\\n3. **AI in Climate Change Mitigation** + \ \\n AI is playing a pivotal role in addressing climate change through + predictive modeling, resource optimization, and environmental monitoring. + In 2024, AI-driven climate models have improved accuracy in predicting extreme + weather events, while AI-powered energy management systems are optimizing + renewable energy distribution. Furthermore, AI is being used to monitor deforestation, + track carbon emissions, and develop sustainable agricultural practices.\\n\\n4. + **AI-Generated Content and Creativity Tools** \\n The rise of AI-generated + content continues to redefine creative industries. In 2024, AI tools for generating + text, images, music, and even video have reached new levels of sophistication. + Platforms like DALL\xB7E 3, MidJourney, and others have enabled artists, writers, + and designers to collaborate with AI in unprecedented ways. However, this + trend has also sparked debates around intellectual property, originality, + and the impact on traditional creative professions.\\n\\n5. **Edge AI and + Decentralized AI Systems** \\n Edge AI, which involves processing data + locally on devices rather than in centralized cloud servers, has gained traction + in 2024. This approach reduces latency, enhances privacy, and improves performance + in real-time applications such as autonomous vehicles, smart homes, and industrial + IoT systems. Additionally, decentralized AI systems, powered by blockchain + technology, are emerging as a way to distribute AI computation and ensure + data security and fairness.\\n\\n6. **AI in Healthcare: Diagnostics and Treatment** + \ \\n AI's role in healthcare has expanded significantly in 2024, with breakthroughs + in diagnostic imaging, drug discovery, and personalized medicine. AI models + are now capable of detecting early signs of diseases such as cancer, Alzheimer\u2019s, + and diabetes with high accuracy. Moreover, AI-driven robotic surgery systems + and virtual health assistants are enhancing patient care and reducing the + burden on medical professionals.\\n\\n7. **AI-Powered Cybersecurity Solutions** + \ \\n As cyber threats grow more sophisticated, AI is being leveraged to + bolster cybersecurity defenses. In 2024, AI-based threat detection systems + are capable of identifying and neutralizing malicious activities in real time. + Machine learning models are also being used to predict attack patterns and + automate incident response, making organizations more resilient against cyberattacks.\\n\\n8. + **AI in Education: Adaptive Learning and Virtual Tutors** \\n AI is transforming + the education sector by enabling adaptive learning platforms that cater to + individual student needs. In 2024, AI-powered virtual tutors and intelligent + learning systems are being integrated into classrooms and online education + platforms. These tools analyze student performance and adjust teaching methods + accordingly, leading to improved learning outcomes and greater accessibility + to quality education.\\n\\n9. **AI Ethics and Regulatory Compliance** \\n + \ The focus on AI ethics has intensified in 2024, with governments and organizations + implementing stricter regulations to ensure accountability and fairness. Countries + like the United States, the European Union, and China have introduced new + policies to govern AI usage, emphasizing transparency, data privacy, and the + prevention of harmful biases. Companies are also investing in AI audit tools + and compliance training programs to meet these regulatory requirements.\\n\\n10. + **AI in Agriculture and Food Security** \\n AI is revolutionizing agriculture + through precision farming techniques, crop monitoring, and supply chain optimization. + In 2024, AI-powered drones and sensors are being used to assess soil health, + monitor crop growth, and predict yield outcomes. Additionally, AI-driven food + waste reduction strategies are helping to improve sustainability and reduce + the environmental impact of the food industry.\\n\\n11. **AI in Customer Service + and Chatbots** \\n AI chatbots and virtual assistants have become more + advanced in 2024, offering natural language understanding and contextual awareness. + These systems are now capable of handling complex customer inquiries, providing + multilingual support, and even anticipating customer needs. Businesses are + leveraging AI to enhance customer satisfaction while reducing operational + costs.\\n\\n12. **AI in Finance and Fintech** \\n The financial sector + has embraced AI for fraud detection, algorithmic trading, and personalized + banking services. In 2024, AI models are being used to analyze vast amounts + of financial data in real time, enabling faster and more accurate decision-making. + Additionally, AI-driven robo-advisors are becoming popular among consumers + seeking affordable and efficient investment solutions.\\n\\n13. **AI in Manufacturing + and Supply Chain Optimization** \\n AI is streamlining manufacturing processes + and optimizing supply chains through predictive maintenance, demand forecasting, + and logistics planning. In 2024, AI-powered robotics and automation have increased + efficiency and reduced production costs. Companies are also using AI to manage + inventory, minimize delays, and enhance overall operational performance.\\n\\n14. + **AI in Gaming and Entertainment** \\n AI has transformed the gaming and + entertainment industries by enabling dynamic storytelling, procedural content + generation, and realistic character behavior. In 2024, AI-driven game engines + are creating immersive and responsive environments, while AI-generated scripts + and storylines are enhancing the creativity of film and television productions.\\n\\n15. + **AI in Transportation and Autonomous Vehicles** \\n The development of + autonomous vehicles has accelerated in 2024, with AI playing a central role + in navigation, object recognition, and decision-making. Self-driving cars, + drones, and delivery robots are becoming more common, driven by advancements + in computer vision, sensor fusion, and real-time data processing. Additionally, + AI is being used to optimize traffic flow and reduce congestion in urban areas.\\n\\n16. + **AI in Human Resources and Talent Management** \\n AI is reshaping HR + practices by automating recruitment, employee engagement, and performance + management. In 2024, AI tools are being used to screen job candidates, assess + employee skills, and provide personalized career development recommendations. + These systems help organizations build diverse and inclusive workforces while + improving efficiency and reducing bias in hiring processes.\\n\\n17. **AI + in Environmental Monitoring and Sustainability** \\n AI is being used + to monitor environmental changes and support sustainability initiatives. In + 2024, AI-powered satellite imagery analysis and sensor networks are tracking + pollution levels, wildlife activity, and ecosystem health. These insights + are helping governments and organizations develop targeted strategies for + conservation and environmental protection.\\n\\n18. **AI in Language Translation + and Localization** \\n AI-driven translation tools have reached new levels + of accuracy and fluency in 2024. These systems are capable of translating + not only text but also speech and sign language, making communication more + accessible across cultures. Additionally, AI is being used to localize content + for different markets, ensuring cultural relevance and engagement.\\n\\n19. + **AI in Legal and Compliance Fields** \\n AI is transforming legal practices + by automating document review, contract analysis, and case prediction. In + 2024, AI tools are being used to streamline legal workflows, reduce costs, + and improve the speed of legal proceedings. These systems are also assisting + in compliance management by identifying potential regulatory violations and + suggesting corrective actions.\\n\\n20. **AI in Social Media and Content Moderation** + \ \\n AI is playing a critical role in managing social media content and + ensuring platform safety. In 2024, AI algorithms are being used to detect + harmful content, such as hate speech, misinformation, and cyberbullying. These + systems are also being employed to recommend content and personalize user + feeds, enhancing user experience while maintaining community guidelines.\\n\\nIn + conclusion, 2024 has marked a year of significant progress and innovation + in the field of artificial intelligence. From enhanced personalization and + ethical frameworks to transformative applications in healthcare, climate change, + and beyond, AI continues to shape the future in profound ways. As the technology + evolves, it will be essential to address challenges related to bias, transparency, + and regulation to ensure that AI benefits society as a whole.\",\"role\":\"assistant\"}}],\"created\":1771988199,\"id\":\"chatcmpl-3f88ba88-9e1a-9fe4-88e0-3847cf7a1280\",\"model\":\"qwen-turbo\",\"object\":\"chat.completion\",\"usage\":{\"completion_tokens\":1838,\"prompt_tokens\":2004,\"prompt_tokens_details\":{\"cached_tokens\":0},\"total_tokens\":3842}}" + headers: + content-length: + - '10448' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:57:02 GMT + req-arrive-time: + - '1771988198971' + req-cost-time: + - '23959' + resp-start-time: + - '1771988222931' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '23957' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Content Writer. Professional + writer with expertise in tech content\nYour personal goal is: Create compelling + content\nTo give my best complete final answer to the task use the exact following + format:\n\nThought: I now can give a great answer\nFinal Answer: Your final + answer must be the great and the most complete as possible, it must be outcome + described.\n\nI MUST use these formats, my job depends on it!"}, {"role": "user", + "content": "\nCurrent Task: Write an article based on the analysis\n\nThis is + the expect criteria for your final answer: Published article\nyou MUST return + the actual complete content as the final answer, not a summary.\n\nThis is the + context you''re working with:\nThe latest AI trends in 2024 reflect a rapidly + evolving landscape shaped by technological advancements, ethical considerations, + and practical applications across industries. Below is a comprehensive research + report detailing the most significant AI trends observed in 2024.\n\n1. **AI-Driven + Personalization at Scale** \n In 2024, AI systems have become increasingly + adept at personalizing user experiences across various platforms. From recommendation + engines in e-commerce to tailored content delivery in media and education, AI + algorithms are leveraging real-time data and advanced machine learning models + to deliver hyper-personalized interactions. This trend is particularly prominent + in sectors like healthcare, where personalized treatment plans based on patient + data are becoming standard practice.\n\n2. **Explainable AI (XAI) and Ethical + AI Frameworks** \n With growing concerns over AI bias and transparency, 2024 + has seen a surge in the development of Explainable AI (XAI) tools. These technologies + aim to make AI decision-making processes more transparent and interpretable + for users and stakeholders. Additionally, ethical AI frameworks have been widely + adopted by organizations to ensure responsible AI deployment, with many companies + implementing AI ethics boards and compliance protocols to align with global + standards such as the EU AI Act and the OECD AI Principles.\n\n3. **AI in Climate + Change Mitigation** \n AI is playing a pivotal role in addressing climate + change through predictive modeling, resource optimization, and environmental + monitoring. In 2024, AI-driven climate models have improved accuracy in predicting + extreme weather events, while AI-powered energy management systems are optimizing + renewable energy distribution. Furthermore, AI is being used to monitor deforestation, + track carbon emissions, and develop sustainable agricultural practices.\n\n4. + **AI-Generated Content and Creativity Tools** \n The rise of AI-generated + content continues to redefine creative industries. In 2024, AI tools for generating + text, images, music, and even video have reached new levels of sophistication. + Platforms like DALL\u00b7E 3, MidJourney, and others have enabled artists, writers, + and designers to collaborate with AI in unprecedented ways. However, this trend + has also sparked debates around intellectual property, originality, and the + impact on traditional creative professions.\n\n5. **Edge AI and Decentralized + AI Systems** \n Edge AI, which involves processing data locally on devices + rather than in centralized cloud servers, has gained traction in 2024. This + approach reduces latency, enhances privacy, and improves performance in real-time + applications such as autonomous vehicles, smart homes, and industrial IoT systems. + Additionally, decentralized AI systems, powered by blockchain technology, are + emerging as a way to distribute AI computation and ensure data security and + fairness.\n\n6. **AI in Healthcare: Diagnostics and Treatment** \n AI''s + role in healthcare has expanded significantly in 2024, with breakthroughs in + diagnostic imaging, drug discovery, and personalized medicine. AI models are + now capable of detecting early signs of diseases such as cancer, Alzheimer\u2019s, + and diabetes with high accuracy. Moreover, AI-driven robotic surgery systems + and virtual health assistants are enhancing patient care and reducing the burden + on medical professionals.\n\n7. **AI-Powered Cybersecurity Solutions** \n As + cyber threats grow more sophisticated, AI is being leveraged to bolster cybersecurity + defenses. In 2024, AI-based threat detection systems are capable of identifying + and neutralizing malicious activities in real time. Machine learning models + are also being used to predict attack patterns and automate incident response, + making organizations more resilient against cyberattacks.\n\n8. **AI in Education: + Adaptive Learning and Virtual Tutors** \n AI is transforming the education + sector by enabling adaptive learning platforms that cater to individual student + needs. In 2024, AI-powered virtual tutors and intelligent learning systems are + being integrated into classrooms and online education platforms. These tools + analyze student performance and adjust teaching methods accordingly, leading + to improved learning outcomes and greater accessibility to quality education.\n\n9. + **AI Ethics and Regulatory Compliance** \n The focus on AI ethics has intensified + in 2024, with governments and organizations implementing stricter regulations + to ensure accountability and fairness. Countries like the United States, the + European Union, and China have introduced new policies to govern AI usage, emphasizing + transparency, data privacy, and the prevention of harmful biases. Companies + are also investing in AI audit tools and compliance training programs to meet + these regulatory requirements.\n\n10. **AI in Agriculture and Food Security** \n AI + is revolutionizing agriculture through precision farming techniques, crop monitoring, + and supply chain optimization. In 2024, AI-powered drones and sensors are being + used to assess soil health, monitor crop growth, and predict yield outcomes. + Additionally, AI-driven food waste reduction strategies are helping to improve + sustainability and reduce the environmental impact of the food industry.\n\n11. + **AI in Customer Service and Chatbots** \n AI chatbots and virtual assistants + have become more advanced in 2024, offering natural language understanding and + contextual awareness. These systems are now capable of handling complex customer + inquiries, providing multilingual support, and even anticipating customer needs. + Businesses are leveraging AI to enhance customer satisfaction while reducing + operational costs.\n\n12. **AI in Finance and Fintech** \n The financial + sector has embraced AI for fraud detection, algorithmic trading, and personalized + banking services. In 2024, AI models are being used to analyze vast amounts + of financial data in real time, enabling faster and more accurate decision-making. + Additionally, AI-driven robo-advisors are becoming popular among consumers seeking + affordable and efficient investment solutions.\n\n13. **AI in Manufacturing + and Supply Chain Optimization** \n AI is streamlining manufacturing processes + and optimizing supply chains through predictive maintenance, demand forecasting, + and logistics planning. In 2024, AI-powered robotics and automation have increased + efficiency and reduced production costs. Companies are also using AI to manage + inventory, minimize delays, and enhance overall operational performance.\n\n14. + **AI in Gaming and Entertainment** \n AI has transformed the gaming and + entertainment industries by enabling dynamic storytelling, procedural content + generation, and realistic character behavior. In 2024, AI-driven game engines + are creating immersive and responsive environments, while AI-generated scripts + and storylines are enhancing the creativity of film and television productions.\n\n15. + **AI in Transportation and Autonomous Vehicles** \n The development of autonomous + vehicles has accelerated in 2024, with AI playing a central role in navigation, + object recognition, and decision-making. Self-driving cars, drones, and delivery + robots are becoming more common, driven by advancements in computer vision, + sensor fusion, and real-time data processing. Additionally, AI is being used + to optimize traffic flow and reduce congestion in urban areas.\n\n16. **AI in + Human Resources and Talent Management** \n AI is reshaping HR practices + by automating recruitment, employee engagement, and performance management. + In 2024, AI tools are being used to screen job candidates, assess employee skills, + and provide personalized career development recommendations. These systems help + organizations build diverse and inclusive workforces while improving efficiency + and reducing bias in hiring processes.\n\n17. **AI in Environmental Monitoring + and Sustainability** \n AI is being used to monitor environmental changes + and support sustainability initiatives. In 2024, AI-powered satellite imagery + analysis and sensor networks are tracking pollution levels, wildlife activity, + and ecosystem health. These insights are helping governments and organizations + develop targeted strategies for conservation and environmental protection.\n\n18. + **AI in Language Translation and Localization** \n AI-driven translation + tools have reached new levels of accuracy and fluency in 2024. These systems + are capable of translating not only text but also speech and sign language, + making communication more accessible across cultures. Additionally, AI is being + used to localize content for different markets, ensuring cultural relevance + and engagement.\n\n19. **AI in Legal and Compliance Fields** \n AI is transforming + legal practices by automating document review, contract analysis, and case prediction. + In 2024, AI tools are being used to streamline legal workflows, reduce costs, + and improve the speed of legal proceedings. These systems are also assisting + in compliance management by identifying potential regulatory violations and + suggesting corrective actions.\n\n20. **AI in Social Media and Content Moderation** \n AI + is playing a critical role in managing social media content and ensuring platform + safety. In 2024, AI algorithms are being used to detect harmful content, such + as hate speech, misinformation, and cyberbullying. These systems are also being + employed to recommend content and personalize user feeds, enhancing user experience + while maintaining community guidelines.\n\nIn conclusion, 2024 has marked a + year of significant progress and innovation in the field of artificial intelligence. + From enhanced personalization and ethical frameworks to transformative applications + in healthcare, climate change, and beyond, AI continues to shape the future + in profound ways. As the technology evolves, it will be essential to address + challenges related to bias, transparency, and regulation to ensure that AI benefits + society as a whole.\n\nBegin! This is VERY important to you, use the tools available + and give your best Final Answer, your job depends on it!\n\nThought:"}], "model": + "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '10984' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: "{\"choices\":[{\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"content\":\"Thought: + I now can give a great answer\\nFinal Answer: \\n\\n**The Latest AI Trends + in 2024: Shaping the Future of Technology and Society**\\n\\nAs we navigate + through 2024, the landscape of artificial intelligence (AI) continues to evolve + at an unprecedented pace. This year has witnessed significant advancements + in AI technologies, with a focus on ethical considerations, practical applications, + and transformative impacts across various industries. Below is a comprehensive + overview of the most notable AI trends observed in 2024.\\n\\n### **AI-Driven + Personalization at Scale**\\nIn 2024, AI systems have become increasingly + adept at personalizing user experiences across various platforms. From recommendation + engines in e-commerce to tailored content delivery in media and education, + AI algorithms are leveraging real-time data and advanced machine learning + models to deliver hyper-personalized interactions. This trend is particularly + prominent in sectors like healthcare, where personalized treatment plans based + on patient data are becoming standard practice.\\n\\n### **Explainable AI + (XAI) and Ethical AI Frameworks**\\nWith growing concerns over AI bias and + transparency, 2024 has seen a surge in the development of Explainable AI (XAI) + tools. These technologies aim to make AI decision-making processes more transparent + and interpretable for users and stakeholders. Additionally, ethical AI frameworks + have been widely adopted by organizations to ensure responsible AI deployment, + with many companies implementing AI ethics boards and compliance protocols + to align with global standards such as the EU AI Act and the OECD AI Principles.\\n\\n### + **AI in Climate Change Mitigation**\\nAI is playing a pivotal role in addressing + climate change through predictive modeling, resource optimization, and environmental + monitoring. In 2024, AI-driven climate models have improved accuracy in predicting + extreme weather events, while AI-powered energy management systems are optimizing + renewable energy distribution. Furthermore, AI is being used to monitor deforestation, + track carbon emissions, and develop sustainable agricultural practices.\\n\\n### + **AI-Generated Content and Creativity Tools**\\nThe rise of AI-generated content + continues to redefine creative industries. In 2024, AI tools for generating + text, images, music, and even video have reached new levels of sophistication. + Platforms like DALL\xB7E 3, MidJourney, and others have enabled artists, writers, + and designers to collaborate with AI in unprecedented ways. However, this + trend has also sparked debates around intellectual property, originality, + and the impact on traditional creative professions.\\n\\n### **Edge AI and + Decentralized AI Systems**\\nEdge AI, which involves processing data locally + on devices rather than in centralized cloud servers, has gained traction in + 2024. This approach reduces latency, enhances privacy, and improves performance + in real-time applications such as autonomous vehicles, smart homes, and industrial + IoT systems. Additionally, decentralized AI systems, powered by blockchain + technology, are emerging as a way to distribute AI computation and ensure + data security and fairness.\\n\\n### **AI in Healthcare: Diagnostics and Treatment**\\nAI's + role in healthcare has expanded significantly in 2024, with breakthroughs + in diagnostic imaging, drug discovery, and personalized medicine. AI models + are now capable of detecting early signs of diseases such as cancer, Alzheimer\u2019s, + and diabetes with high accuracy. Moreover, AI-driven robotic surgery systems + and virtual health assistants are enhancing patient care and reducing the + burden on medical professionals.\\n\\n### **AI-Powered Cybersecurity Solutions**\\nAs + cyber threats grow more sophisticated, AI is being leveraged to bolster cybersecurity + defenses. In 2024, AI-based threat detection systems are capable of identifying + and neutralizing malicious activities in real time. Machine learning models + are also being used to predict attack patterns and automate incident response, + making organizations more resilient against cyberattacks.\\n\\n### **AI in + Education: Adaptive Learning and Virtual Tutors**\\nAI is transforming the + education sector by enabling adaptive learning platforms that cater to individual + student needs. In 2024, AI-powered virtual tutors and intelligent learning + systems are being integrated into classrooms and online education platforms. + These tools analyze student performance and adjust teaching methods accordingly, + leading to improved learning outcomes and greater accessibility to quality + education.\\n\\n### **AI Ethics and Regulatory Compliance**\\nThe focus on + AI ethics has intensified in 2024, with governments and organizations implementing + stricter regulations to ensure accountability and fairness. Countries like + the United States, the European Union, and China have introduced new policies + to govern AI usage, emphasizing transparency, data privacy, and the prevention + of harmful biases. Companies are also investing in AI audit tools and compliance + training programs to meet these regulatory requirements.\\n\\n### **AI in + Agriculture and Food Security**\\nAI is revolutionizing agriculture through + precision farming techniques, crop monitoring, and supply chain optimization. + In 2024, AI-powered drones and sensors are being used to assess soil health, + monitor crop growth, and predict yield outcomes. Additionally, AI-driven food + waste reduction strategies are helping to improve sustainability and reduce + the environmental impact of the food industry.\\n\\n### **AI in Customer Service + and Chatbots**\\nAI chatbots and virtual assistants have become more advanced + in 2024, offering natural language understanding and contextual awareness. + These systems are now capable of handling complex customer inquiries, providing + multilingual support, and even anticipating customer needs. Businesses are + leveraging AI to enhance customer satisfaction while reducing operational + costs.\\n\\n### **AI in Finance and Fintech**\\nThe financial sector has embraced + AI for fraud detection, algorithmic trading, and personalized banking services. + In 2024, AI models are being used to analyze vast amounts of financial data + in real time, enabling faster and more accurate decision-making. Additionally, + AI-driven robo-advisors are becoming popular among consumers seeking affordable + and efficient investment solutions.\\n\\n### **AI in Manufacturing and Supply + Chain Optimization**\\nAI is streamlining manufacturing processes and optimizing + supply chains through predictive maintenance, demand forecasting, and logistics + planning. In 2024, AI-powered robotics and automation have increased efficiency + and reduced production costs. Companies are also using AI to manage inventory, + minimize delays, and enhance overall operational performance.\\n\\n### **AI + in Gaming and Entertainment**\\nAI has transformed the gaming and entertainment + industries by enabling dynamic storytelling, procedural content generation, + and realistic character behavior. In 2024, AI-driven game engines are creating + immersive and responsive environments, while AI-generated scripts and storylines + are enhancing the creativity of film and television productions.\\n\\n### + **AI in Transportation and Autonomous Vehicles**\\nThe development of autonomous + vehicles has accelerated in 2024, with AI playing a central role in navigation, + object recognition, and decision-making. Self-driving cars, drones, and delivery + robots are becoming more common, driven by advancements in computer vision, + sensor fusion, and real-time data processing. Additionally, AI is being used + to optimize traffic flow and reduce congestion in urban areas.\\n\\n### **AI + in Human Resources and Talent Management**\\nAI is reshaping HR practices + by automating recruitment, employee engagement, and performance management. + In 2024, AI tools are being used to screen job candidates, assess employee + skills, and provide personalized career development recommendations. These + systems help organizations build diverse and inclusive workforces while improving + efficiency and reducing bias in hiring processes.\\n\\n### **AI in Environmental + Monitoring and Sustainability**\\nAI is being used to monitor environmental + changes and support sustainability initiatives. In 2024, AI-powered satellite + imagery analysis and sensor networks are tracking pollution levels, wildlife + activity, and ecosystem health. These insights are helping governments and + organizations develop targeted strategies for conservation and environmental + protection.\\n\\n### **AI in Language Translation and Localization**\\nAI-driven + translation tools have reached new levels of accuracy and fluency in 2024. + These systems are capable of translating not only text but also speech and + sign language, making communication more accessible across cultures. Additionally, + AI is being used to localize content for different markets, ensuring cultural + relevance and engagement.\\n\\n### **AI in Legal and Compliance Fields**\\nAI + is transforming legal practices by automating document review, contract analysis, + and case prediction. In 2024, AI tools are being used to streamline legal + workflows, reduce costs, and improve the speed of legal proceedings. These + systems are also assisting in compliance management by identifying potential + regulatory violations and suggesting corrective actions.\\n\\n### **AI in + Social Media and Content Moderation**\\nAI is playing a critical role in managing + social media content and ensuring platform safety. In 2024, AI algorithms + are being used to detect harmful content, such as hate speech, misinformation, + and cyberbullying. These systems are also being employed to recommend content + and personalize user feeds, enhancing user experience while maintaining community + guidelines.\\n\\nIn conclusion, 2024 has marked a year of significant progress + and innovation in the field of artificial intelligence. From enhanced personalization + and ethical frameworks to transformative applications in healthcare, climate + change, and beyond, AI continues to shape the future in profound ways. As + the technology evolves, it will be essential to address challenges related + to bias, transparency, and regulation to ensure that AI benefits society as + a whole.\",\"role\":\"assistant\"}}],\"created\":1771988223,\"id\":\"chatcmpl-424115b2-5e1a-9095-99bb-cdae60b029bc\",\"model\":\"qwen-turbo\",\"object\":\"chat.completion\",\"usage\":{\"completion_tokens\":1812,\"prompt_tokens\":2002,\"prompt_tokens_details\":{\"cached_tokens\":0},\"total_tokens\":3814}}" + headers: + content-length: + - '10548' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:57:25 GMT + req-arrive-time: + - '1771988223421' + req-cost-time: + - '22167' + resp-start-time: + - '1771988245589' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '22165' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Researcher. Expert + researcher with 15 years of experience\nYour personal goal is: Gather comprehensive + information\nTo give my best complete final answer to the task use the exact + following format:\n\nThought: I now can give a great answer\nFinal Answer: Your + final answer must be the great and the most complete as possible, it must be + outcome described.\n\nI MUST use these formats, my job depends on it!"}, {"role": + "user", "content": "\nCurrent Task: Research the latest AI trends in 2024\n\nThis + is the expect criteria for your final answer: Comprehensive research report\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '887' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"I + now can give a great answer\nFinal Answer: The latest AI trends in 2024 reflect + a significant evolution in the field, with advancements in several key areas. + These trends are shaping the future of artificial intelligence and its applications + across various industries.\n\n1. **AI Ethics and Governance**: As AI becomes + more integrated into daily life, there is an increased focus on ethical considerations. + Governments and organizations are developing frameworks to ensure responsible + AI development and deployment. This includes transparency, fairness, accountability, + and privacy protection. For instance, the European Union''s AI Act continues + to influence global standards for AI regulation.\n\n2. **Explainable AI (XAI)**: + There is a growing demand for AI systems that can explain their decisions + and actions. XAI aims to make AI more transparent and understandable, which + is crucial for high-stakes applications such as healthcare, finance, and law. + Researchers are working on methods to improve model interpretability without + compromising performance.\n\n3. **AI in Healthcare**: AI is making significant + strides in healthcare, particularly in diagnostics, personalized medicine, + and drug discovery. Machine learning models are being used to analyze medical + images, predict patient outcomes, and develop new treatments. Additionally, + AI-powered tools are enhancing patient care through virtual assistants and + remote monitoring systems.\n\n4. **Generative AI**: Generative AI continues + to advance, with models capable of creating high-quality text, images, audio, + and video. These models are being used in creative industries, content generation, + and even in simulating complex scenarios for training purposes. Companies + are leveraging generative AI to streamline workflows and enhance creativity.\n\n5. + **AI and Sustainability**: There is a growing emphasis on using AI to address + environmental challenges. AI is being applied to optimize energy consumption, + reduce waste, and improve resource management. For example, AI algorithms + are used to monitor and manage renewable energy systems, contributing to a + more sustainable future.\n\n6. **AI in Education**: AI is transforming the + education sector by personalizing learning experiences and providing adaptive + learning tools. Intelligent tutoring systems, automated grading, and data + analytics are helping educators to better understand student needs and improve + teaching methods.\n\n7. **AI and Cybersecurity**: With the increasing threat + of cyber attacks, AI is being utilized to enhance cybersecurity measures. + Machine learning algorithms are employed to detect anomalies, identify threats, + and respond to security incidents in real-time. AI-driven solutions are becoming + essential for protecting sensitive data and ensuring network security.\n\n8. + **AI in Manufacturing**: AI is revolutionizing manufacturing through predictive + maintenance, quality control, and supply chain optimization. Smart factories + are leveraging AI to improve efficiency, reduce downtime, and enhance product + quality. Robotics and AI are being integrated to automate tasks and improve + production processes.\n\n9. **AI and Human Collaboration**: There is a shift + towards human-AI collaboration, where AI systems augment human capabilities + rather than replace them. This trend emphasizes the importance of designing + AI systems that work seamlessly with humans, enhancing productivity and decision-making.\n\n10. + **AI Research and Development**: Ongoing research in AI is focused on improving + model efficiency, reducing computational costs, and expanding the capabilities + of AI systems. Innovations in neural networks, reinforcement learning, and + natural language processing are driving progress in the field.\n\nThese trends + highlight the dynamic nature of AI in 2024, with a strong emphasis on ethical + considerations, practical applications, and continuous innovation. As AI continues + to evolve, it will play an increasingly important role in shaping various + aspects of society and industry.","role":"assistant"}}],"created":1771989420,"id":"chatcmpl-aab0bedb-7191-9306-a252-bd2e1c7b18ce","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":698,"prompt_tokens":175,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":873}}' + headers: + content-length: + - '4358' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:17:09 GMT + req-arrive-time: + - '1771989420491' + req-cost-time: + - '8916' + resp-start-time: + - '1771989429408' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '8916' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Data Analyst. Senior + data analyst specializing in AI trends\nYour personal goal is: Analyze data + and extract insights\nTo give my best complete final answer to the task use + the exact following format:\n\nThought: I now can give a great answer\nFinal + Answer: Your final answer must be the great and the most complete as possible, + it must be outcome described.\n\nI MUST use these formats, my job depends on + it!"}, {"role": "user", "content": "\nCurrent Task: Analyze the research findings\n\nThis + is the expect criteria for your final answer: Data analysis report\nyou MUST + return the actual complete content as the final answer, not a summary.\n\nThis + is the context you''re working with:\nThe latest AI trends in 2024 reflect a + significant evolution in the field, with advancements in several key areas. + These trends are shaping the future of artificial intelligence and its applications + across various industries.\n\n1. **AI Ethics and Governance**: As AI becomes + more integrated into daily life, there is an increased focus on ethical considerations. + Governments and organizations are developing frameworks to ensure responsible + AI development and deployment. This includes transparency, fairness, accountability, + and privacy protection. For instance, the European Union''s AI Act continues + to influence global standards for AI regulation.\n\n2. **Explainable AI (XAI)**: + There is a growing demand for AI systems that can explain their decisions and + actions. XAI aims to make AI more transparent and understandable, which is crucial + for high-stakes applications such as healthcare, finance, and law. Researchers + are working on methods to improve model interpretability without compromising + performance.\n\n3. **AI in Healthcare**: AI is making significant strides in + healthcare, particularly in diagnostics, personalized medicine, and drug discovery. + Machine learning models are being used to analyze medical images, predict patient + outcomes, and develop new treatments. Additionally, AI-powered tools are enhancing + patient care through virtual assistants and remote monitoring systems.\n\n4. + **Generative AI**: Generative AI continues to advance, with models capable of + creating high-quality text, images, audio, and video. These models are being + used in creative industries, content generation, and even in simulating complex + scenarios for training purposes. Companies are leveraging generative AI to streamline + workflows and enhance creativity.\n\n5. **AI and Sustainability**: There is + a growing emphasis on using AI to address environmental challenges. AI is being + applied to optimize energy consumption, reduce waste, and improve resource management. + For example, AI algorithms are used to monitor and manage renewable energy systems, + contributing to a more sustainable future.\n\n6. **AI in Education**: AI is + transforming the education sector by personalizing learning experiences and + providing adaptive learning tools. Intelligent tutoring systems, automated grading, + and data analytics are helping educators to better understand student needs + and improve teaching methods.\n\n7. **AI and Cybersecurity**: With the increasing + threat of cyber attacks, AI is being utilized to enhance cybersecurity measures. + Machine learning algorithms are employed to detect anomalies, identify threats, + and respond to security incidents in real-time. AI-driven solutions are becoming + essential for protecting sensitive data and ensuring network security.\n\n8. + **AI in Manufacturing**: AI is revolutionizing manufacturing through predictive + maintenance, quality control, and supply chain optimization. Smart factories + are leveraging AI to improve efficiency, reduce downtime, and enhance product + quality. Robotics and AI are being integrated to automate tasks and improve + production processes.\n\n9. **AI and Human Collaboration**: There is a shift + towards human-AI collaboration, where AI systems augment human capabilities + rather than replace them. This trend emphasizes the importance of designing + AI systems that work seamlessly with humans, enhancing productivity and decision-making.\n\n10. + **AI Research and Development**: Ongoing research in AI is focused on improving + model efficiency, reducing computational costs, and expanding the capabilities + of AI systems. Innovations in neural networks, reinforcement learning, and natural + language processing are driving progress in the field.\n\nThese trends highlight + the dynamic nature of AI in 2024, with a strong emphasis on ethical considerations, + practical applications, and continuous innovation. As AI continues to evolve, + it will play an increasingly important role in shaping various aspects of society + and industry.\n\nBegin! This is VERY important to you, use the tools available + and give your best Final Answer, your job depends on it!\n\nThought:"}], "model": + "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '4901' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I now can give a great answer\nFinal Answer: The latest AI trends in 2024 + reflect a significant evolution in the field, with advancements in several + key areas. These trends are shaping the future of artificial intelligence + and its applications across various industries.\n\n1. **AI Ethics and Governance**: + As AI becomes more integrated into daily life, there is an increased focus + on ethical considerations. Governments and organizations are developing frameworks + to ensure responsible AI development and deployment. This includes transparency, + fairness, accountability, and privacy protection. For instance, the European + Union''s AI Act continues to influence global standards for AI regulation.\n\n2. + **Explainable AI (XAI)**: There is a growing demand for AI systems that can + explain their decisions and actions. XAI aims to make AI more transparent + and understandable, which is crucial for high-stakes applications such as + healthcare, finance, and law. Researchers are working on methods to improve + model interpretability without compromising performance.\n\n3. **AI in Healthcare**: + AI is making significant strides in healthcare, particularly in diagnostics, + personalized medicine, and drug discovery. Machine learning models are being + used to analyze medical images, predict patient outcomes, and develop new + treatments. Additionally, AI-powered tools are enhancing patient care through + virtual assistants and remote monitoring systems.\n\n4. **Generative AI**: + Generative AI continues to advance, with models capable of creating high-quality + text, images, audio, and video. These models are being used in creative industries, + content generation, and even in simulating complex scenarios for training + purposes. Companies are leveraging generative AI to streamline workflows and + enhance creativity.\n\n5. **AI and Sustainability**: There is a growing emphasis + on using AI to address environmental challenges. AI is being applied to optimize + energy consumption, reduce waste, and improve resource management. For example, + AI algorithms are used to monitor and manage renewable energy systems, contributing + to a more sustainable future.\n\n6. **AI in Education**: AI is transforming + the education sector by personalizing learning experiences and providing adaptive + learning tools. Intelligent tutoring systems, automated grading, and data + analytics are helping educators to better understand student needs and improve + teaching methods.\n\n7. **AI and Cybersecurity**: With the increasing threat + of cyber attacks, AI is being utilized to enhance cybersecurity measures. + Machine learning algorithms are employed to detect anomalies, identify threats, + and respond to security incidents in real-time. AI-driven solutions are becoming + essential for protecting sensitive data and ensuring network security.\n\n8. + **AI in Manufacturing**: AI is revolutionizing manufacturing through predictive + maintenance, quality control, and supply chain optimization. Smart factories + are leveraging AI to improve efficiency, reduce downtime, and enhance product + quality. Robotics and AI are being integrated to automate tasks and improve + production processes.\n\n9. **AI and Human Collaboration**: There is a shift + towards human-AI collaboration, where AI systems augment human capabilities + rather than replace them. This trend emphasizes the importance of designing + AI systems that work seamlessly with humans, enhancing productivity and decision-making.\n\n10. + **AI Research and Development**: Ongoing research in AI is focused on improving + model efficiency, reducing computational costs, and expanding the capabilities + of AI systems. Innovations in neural networks, reinforcement learning, and + natural language processing are driving progress in the field.\n\nThese trends + highlight the dynamic nature of AI in 2024, with a strong emphasis on ethical + considerations, practical applications, and continuous innovation. As AI continues + to evolve, it will play an increasingly important role in shaping various + aspects of society and industry.","role":"assistant"}}],"created":1771989429,"id":"chatcmpl-59fed6ba-d0e4-9846-9729-e8df9f513e15","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":700,"prompt_tokens":866,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":1566}}' + headers: + content-length: + - '4368' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:17:18 GMT + req-arrive-time: + - '1771989429662' + req-cost-time: + - '9271' + resp-start-time: + - '1771989438933' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '9270' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Content Writer. Professional + writer with expertise in tech content\nYour personal goal is: Create compelling + content\nTo give my best complete final answer to the task use the exact following + format:\n\nThought: I now can give a great answer\nFinal Answer: Your final + answer must be the great and the most complete as possible, it must be outcome + described.\n\nI MUST use these formats, my job depends on it!"}, {"role": "user", + "content": "\nCurrent Task: Write an article based on the analysis\n\nThis is + the expect criteria for your final answer: Published article\nyou MUST return + the actual complete content as the final answer, not a summary.\n\nThis is the + context you''re working with:\nThe latest AI trends in 2024 reflect a significant + evolution in the field, with advancements in several key areas. These trends + are shaping the future of artificial intelligence and its applications across + various industries.\n\n1. **AI Ethics and Governance**: As AI becomes more integrated + into daily life, there is an increased focus on ethical considerations. Governments + and organizations are developing frameworks to ensure responsible AI development + and deployment. This includes transparency, fairness, accountability, and privacy + protection. For instance, the European Union''s AI Act continues to influence + global standards for AI regulation.\n\n2. **Explainable AI (XAI)**: There is + a growing demand for AI systems that can explain their decisions and actions. + XAI aims to make AI more transparent and understandable, which is crucial for + high-stakes applications such as healthcare, finance, and law. Researchers are + working on methods to improve model interpretability without compromising performance.\n\n3. + **AI in Healthcare**: AI is making significant strides in healthcare, particularly + in diagnostics, personalized medicine, and drug discovery. Machine learning + models are being used to analyze medical images, predict patient outcomes, and + develop new treatments. Additionally, AI-powered tools are enhancing patient + care through virtual assistants and remote monitoring systems.\n\n4. **Generative + AI**: Generative AI continues to advance, with models capable of creating high-quality + text, images, audio, and video. These models are being used in creative industries, + content generation, and even in simulating complex scenarios for training purposes. + Companies are leveraging generative AI to streamline workflows and enhance creativity.\n\n5. + **AI and Sustainability**: There is a growing emphasis on using AI to address + environmental challenges. AI is being applied to optimize energy consumption, + reduce waste, and improve resource management. For example, AI algorithms are + used to monitor and manage renewable energy systems, contributing to a more + sustainable future.\n\n6. **AI in Education**: AI is transforming the education + sector by personalizing learning experiences and providing adaptive learning + tools. Intelligent tutoring systems, automated grading, and data analytics are + helping educators to better understand student needs and improve teaching methods.\n\n7. + **AI and Cybersecurity**: With the increasing threat of cyber attacks, AI is + being utilized to enhance cybersecurity measures. Machine learning algorithms + are employed to detect anomalies, identify threats, and respond to security + incidents in real-time. AI-driven solutions are becoming essential for protecting + sensitive data and ensuring network security.\n\n8. **AI in Manufacturing**: + AI is revolutionizing manufacturing through predictive maintenance, quality + control, and supply chain optimization. Smart factories are leveraging AI to + improve efficiency, reduce downtime, and enhance product quality. Robotics and + AI are being integrated to automate tasks and improve production processes.\n\n9. + **AI and Human Collaboration**: There is a shift towards human-AI collaboration, + where AI systems augment human capabilities rather than replace them. This trend + emphasizes the importance of designing AI systems that work seamlessly with + humans, enhancing productivity and decision-making.\n\n10. **AI Research and + Development**: Ongoing research in AI is focused on improving model efficiency, + reducing computational costs, and expanding the capabilities of AI systems. + Innovations in neural networks, reinforcement learning, and natural language + processing are driving progress in the field.\n\nThese trends highlight the + dynamic nature of AI in 2024, with a strong emphasis on ethical considerations, + practical applications, and continuous innovation. As AI continues to evolve, + it will play an increasingly important role in shaping various aspects of society + and industry.\n\nBegin! This is VERY important to you, use the tools available + and give your best Final Answer, your job depends on it!\n\nThought:"}], "model": + "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '4906' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: "{\"choices\":[{\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"content\":\"Thought: + I now can give a great answer\\nFinal Answer: \\n\\n**The Latest AI Trends + in 2024: Shaping the Future of Technology and Society**\\n\\nAs we step into + 2024, the field of artificial intelligence (AI) continues to evolve at an + unprecedented pace. With groundbreaking advancements across multiple domains, + AI is not only reshaping industries but also redefining how we interact with + technology in our daily lives. From ethical considerations to sustainability + efforts, the latest AI trends reflect a growing emphasis on responsible innovation, + practical applications, and human-centric design.\\n\\n### 1. **AI Ethics + and Governance: Building Trust in AI Systems**\\n\\nWith AI becoming more + embedded in critical areas such as healthcare, finance, and law, the need + for ethical AI has never been more pressing. Governments and organizations + are working diligently to establish robust frameworks that ensure AI systems + are developed and deployed responsibly. Transparency, fairness, accountability, + and privacy protection have become central to these efforts. The European + Union\u2019s AI Act serves as a global benchmark, influencing regulations + worldwide and setting a precedent for ethical AI practices.\\n\\n### 2. **Explainable + AI (XAI): Making AI More Transparent**\\n\\nAs AI models grow increasingly + complex, there is a rising demand for systems that can explain their decisions. + Explainable AI (XAI) aims to demystify the \\\"black box\\\" nature of many + machine learning algorithms, making them more interpretable and trustworthy. + This is particularly important in high-stakes sectors like healthcare and + finance, where understanding the reasoning behind AI-driven decisions is crucial. + Researchers are developing new techniques to enhance model interpretability + without sacrificing performance, ensuring that AI remains both powerful and + comprehensible.\\n\\n### 3. **AI in Healthcare: Revolutionizing Patient Care**\\n\\nHealthcare + is one of the most promising fields for AI application. From diagnostics to + personalized medicine, AI is transforming how medical professionals detect + and treat diseases. Machine learning models are being used to analyze medical + images with remarkable accuracy, predict patient outcomes, and accelerate + drug discovery. Additionally, AI-powered virtual assistants and remote monitoring + systems are improving patient care by offering real-time support and insights.\\n\\n### + 4. **Generative AI: Fueling Creativity and Innovation**\\n\\nGenerative AI + continues to push the boundaries of what machines can create. Advanced models + are now capable of generating high-quality text, images, audio, and even video. + These tools are being leveraged in creative industries, content generation, + and training simulations. Companies are using generative AI to streamline + workflows, reduce costs, and unlock new forms of artistic expression, marking + a significant shift in how creativity is approached in the digital age.\\n\\n### + 5. **AI and Sustainability: Tackling Environmental Challenges**\\n\\nEnvironmental + sustainability is another key focus area for AI development in 2024. AI is + being applied to optimize energy consumption, reduce waste, and improve resource + management. For instance, AI algorithms are helping to monitor and manage + renewable energy systems, contributing to a cleaner and more efficient energy + grid. As climate change becomes an increasingly urgent issue, AI is playing + a vital role in driving sustainable solutions.\\n\\n### 6. **AI in Education: + Personalizing Learning Experiences**\\n\\nEducation is undergoing a transformation + thanks to AI. Intelligent tutoring systems, automated grading, and data analytics + are enabling educators to tailor learning experiences to individual student + needs. AI is also being used to identify learning gaps and provide targeted + interventions, ultimately improving educational outcomes. As AI continues + to integrate into classrooms, it promises to make education more accessible, + efficient, and engaging for learners of all ages.\\n\\n### 7. **AI and Cybersecurity: + Strengthening Digital Defenses**\\n\\nWith cyber threats becoming more sophisticated, + AI is proving to be a powerful ally in the fight against online security risks. + Machine learning algorithms are being used to detect anomalies, identify potential + threats, and respond to security incidents in real-time. AI-driven cybersecurity + solutions are essential for protecting sensitive data and maintaining the + integrity of digital infrastructure in an increasingly connected world.\\n\\n### + 8. **AI in Manufacturing: Enhancing Efficiency and Quality**\\n\\nManufacturing + is experiencing a revolution driven by AI. Predictive maintenance, quality + control, and supply chain optimization are just a few of the ways AI is improving + efficiency and reducing downtime. Smart factories are leveraging AI to automate + tasks, enhance product quality, and streamline production processes. Robotics + integrated with AI are also playing a key role in modern manufacturing, paving + the way for smarter and more agile production lines.\\n\\n### 9. **AI and + Human Collaboration: Enhancing Productivity**\\n\\nA notable trend in 2024 + is the shift toward human-AI collaboration. Rather than replacing humans, + AI is being designed to augment their capabilities, enhancing productivity + and decision-making. This approach emphasizes the importance of creating AI + systems that work seamlessly with humans, fostering a more harmonious relationship + between technology and the workforce.\\n\\n### 10. **AI Research and Development: + Pushing the Boundaries of Innovation**\\n\\nOngoing research in AI is focused + on improving model efficiency, reducing computational costs, and expanding + the capabilities of AI systems. Innovations in neural networks, reinforcement + learning, and natural language processing are driving progress in the field. + As researchers continue to explore new frontiers, AI is expected to become + even more powerful and versatile, opening up new possibilities for its application.\\n\\n### + Conclusion\\n\\nThe latest AI trends in 2024 highlight a dynamic and rapidly + evolving landscape. With a strong emphasis on ethical considerations, practical + applications, and continuous innovation, AI is poised to play an even greater + role in shaping society and industry. As we move forward, the integration + of AI into various aspects of life will continue to bring about transformative + changes, making it an indispensable tool for the future.\",\"role\":\"assistant\"}}],\"created\":1771989439,\"id\":\"chatcmpl-aee7be93-b268-9815-9467-bf1850a657d5\",\"model\":\"qwen-turbo\",\"object\":\"chat.completion\",\"usage\":{\"completion_tokens\":1148,\"prompt_tokens\":864,\"prompt_tokens_details\":{\"cached_tokens\":0},\"total_tokens\":2012}}" + headers: + content-length: + - '6759' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:17:33 GMT + req-arrive-time: + - '1771989439256' + req-cost-time: + - '14502' + resp-start-time: + - '1771989453759' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '14502' + x-request-id: + - + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_error_scenarios/TestErrorScenarios.test_api_key_missing.yaml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_error_scenarios/TestErrorScenarios.test_api_key_missing.yaml new file mode 100644 index 000000000..56778ffb7 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_error_scenarios/TestErrorScenarios.test_api_key_missing.yaml @@ -0,0 +1,482 @@ +interactions: +- request: + body: '{"messages": [{"role": "system", "content": "You are Test Agent. Test agent\nYour + personal goal is: Test authentication failure\nTo give my best complete final + answer to the task use the exact following format:\n\nThought: I now can give + a great answer\nFinal Answer: Your final answer must be the great and the most + complete as possible, it must be outcome described.\n\nI MUST use these formats, + my job depends on it!"}, {"role": "user", "content": "\nCurrent Task: Execute + a task\n\nThis is the expect criteria for your final answer: Task output\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '806' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"error":{"message":"You didn''t provide an API key. You need to provide + your API key in an Authorization header using Bearer auth (i.e. Authorization: + Bearer YOUR_KEY). ","type":"invalid_request_error","param":null,"code":null},"request_id":"3e1ae270-471f-9bef-a10e-add2239b0270"}' + headers: + content-length: + - '280' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:06:27 GMT + req-arrive-time: + - '1771988787515' + req-cost-time: + - '55' + resp-start-time: + - '1771988787570' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-envoy-upstream-service-time: + - '54' + x-request-id: + - + status: + code: 401 + message: Unauthorized +- request: + body: '{"messages": [{"role": "system", "content": "You are Test Agent. Test agent\nYour + personal goal is: Test authentication failure\nTo give my best complete final + answer to the task use the exact following format:\n\nThought: I now can give + a great answer\nFinal Answer: Your final answer must be the great and the most + complete as possible, it must be outcome described.\n\nI MUST use these formats, + my job depends on it!"}, {"role": "user", "content": "\nCurrent Task: Execute + a task\n\nThis is the expect criteria for your final answer: Task output\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '806' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"error":{"message":"You didn''t provide an API key. You need to provide + your API key in an Authorization header using Bearer auth (i.e. Authorization: + Bearer YOUR_KEY). ","type":"invalid_request_error","param":null,"code":null},"request_id":"b4f1fde8-555d-950f-b9e2-fd65be9bd8f5"}' + headers: + content-length: + - '280' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:06:27 GMT + req-arrive-time: + - '1771988787819' + req-cost-time: + - '56' + resp-start-time: + - '1771988787875' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-envoy-upstream-service-time: + - '56' + x-request-id: + - + status: + code: 401 + message: Unauthorized +- request: + body: '{"messages": [{"role": "system", "content": "You are Test Agent. Test agent\nYour + personal goal is: Test authentication failure\nTo give my best complete final + answer to the task use the exact following format:\n\nThought: I now can give + a great answer\nFinal Answer: Your final answer must be the great and the most + complete as possible, it must be outcome described.\n\nI MUST use these formats, + my job depends on it!"}, {"role": "user", "content": "\nCurrent Task: Execute + a task\n\nThis is the expect criteria for your final answer: Task output\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '806' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"error":{"message":"You didn''t provide an API key. You need to provide + your API key in an Authorization header using Bearer auth (i.e. Authorization: + Bearer YOUR_KEY). ","type":"invalid_request_error","param":null,"code":null},"request_id":"377c4244-c045-9dfb-a9ee-568594385d26"}' + headers: + content-length: + - '280' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:06:27 GMT + req-arrive-time: + - '1771988788104' + req-cost-time: + - '57' + resp-start-time: + - '1771988788161' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-envoy-upstream-service-time: + - '56' + x-request-id: + - + status: + code: 401 + message: Unauthorized +- request: + body: '{"messages": [{"role": "system", "content": "You are Test Agent. Test agent\nYour + personal goal is: Test authentication failure\nTo give my best complete final + answer to the task use the exact following format:\n\nThought: I now can give + a great answer\nFinal Answer: Your final answer must be the great and the most + complete as possible, it must be outcome described.\n\nI MUST use these formats, + my job depends on it!"}, {"role": "user", "content": "\nCurrent Task: Execute + a task\n\nThis is the expect criteria for your final answer: Task output\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '806' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"error":{"message":"You didn''t provide an API key. You need to provide + your API key in an Authorization header using Bearer auth (i.e. Authorization: + Bearer YOUR_KEY). ","type":"invalid_request_error","param":null,"code":null},"request_id":"d0bf6b58-86db-9278-a087-30490db5dc97"}' + headers: + content-length: + - '280' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:17:34 GMT + req-arrive-time: + - '1771989454117' + req-cost-time: + - '54' + resp-start-time: + - '1771989454172' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-envoy-upstream-service-time: + - '54' + x-request-id: + - + status: + code: 401 + message: Unauthorized +- request: + body: '{"messages": [{"role": "system", "content": "You are Test Agent. Test agent\nYour + personal goal is: Test authentication failure\nTo give my best complete final + answer to the task use the exact following format:\n\nThought: I now can give + a great answer\nFinal Answer: Your final answer must be the great and the most + complete as possible, it must be outcome described.\n\nI MUST use these formats, + my job depends on it!"}, {"role": "user", "content": "\nCurrent Task: Execute + a task\n\nThis is the expect criteria for your final answer: Task output\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '806' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"error":{"message":"You didn''t provide an API key. You need to provide + your API key in an Authorization header using Bearer auth (i.e. Authorization: + Bearer YOUR_KEY). ","type":"invalid_request_error","param":null,"code":null},"request_id":"4bf6990a-aee3-9ce2-912e-203fe5258322"}' + headers: + content-length: + - '280' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:17:34 GMT + req-arrive-time: + - '1771989454404' + req-cost-time: + - '53' + resp-start-time: + - '1771989454457' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-envoy-upstream-service-time: + - '53' + x-request-id: + - + status: + code: 401 + message: Unauthorized +- request: + body: '{"messages": [{"role": "system", "content": "You are Test Agent. Test agent\nYour + personal goal is: Test authentication failure\nTo give my best complete final + answer to the task use the exact following format:\n\nThought: I now can give + a great answer\nFinal Answer: Your final answer must be the great and the most + complete as possible, it must be outcome described.\n\nI MUST use these formats, + my job depends on it!"}, {"role": "user", "content": "\nCurrent Task: Execute + a task\n\nThis is the expect criteria for your final answer: Task output\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '806' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"error":{"message":"You didn''t provide an API key. You need to provide + your API key in an Authorization header using Bearer auth (i.e. Authorization: + Bearer YOUR_KEY). ","type":"invalid_request_error","param":null,"code":null},"request_id":"6785bfd6-4a0e-95fb-a07b-259c8ff97818"}' + headers: + content-length: + - '280' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:17:34 GMT + req-arrive-time: + - '1771989454697' + req-cost-time: + - '54' + resp-start-time: + - '1771989454751' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-envoy-upstream-service-time: + - '54' + x-request-id: + - + status: + code: 401 + message: Unauthorized +version: 1 diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_error_scenarios/TestErrorScenarios.test_network_error.yaml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_error_scenarios/TestErrorScenarios.test_network_error.yaml new file mode 100644 index 000000000..96806ce55 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_error_scenarios/TestErrorScenarios.test_network_error.yaml @@ -0,0 +1,428 @@ +interactions: +- request: + body: '{"messages": [{"role": "system", "content": "You are Test Agent. Test agent\nYour + personal goal is: Test network failure\nTo give my best complete final answer + to the task use the exact following format:\n\nThought: I now can give a great + answer\nFinal Answer: Your final answer must be the great and the most complete + as possible, it must be outcome described.\n\nI MUST use these formats, my job + depends on it!"}, {"role": "user", "content": "\nCurrent Task: Execute a task\n\nThis + is the expect criteria for your final answer: Task output\nyou MUST return the + actual complete content as the final answer, not a summary.\n\nBegin! This is + VERY important to you, use the tools available and give your best Final Answer, + your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '799' + Content-Type: + - application/json + Host: + - invalid-url-that-does-not-exist.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://invalid-url-that-does-not-exist.com/chat/completions + response: + body: + string: '{"message":"Success"}' + headers: + Connection: + - Keep-Alive + Content-Length: + - '21' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 25 Feb 2026 03:06:29 GMT + Keep-Alive: + - timeout=5, max=100 + Server: + - Apache + Vary: + - User-Agent + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Test Agent. Test agent\nYour + personal goal is: Test network failure\nTo give my best complete final answer + to the task use the exact following format:\n\nThought: I now can give a great + answer\nFinal Answer: Your final answer must be the great and the most complete + as possible, it must be outcome described.\n\nI MUST use these formats, my job + depends on it!"}, {"role": "user", "content": "\nCurrent Task: Execute a task\n\nThis + is the expect criteria for your final answer: Task output\nyou MUST return the + actual complete content as the final answer, not a summary.\n\nBegin! This is + VERY important to you, use the tools available and give your best Final Answer, + your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '799' + Content-Type: + - application/json + Host: + - invalid-url-that-does-not-exist.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://invalid-url-that-does-not-exist.com/chat/completions + response: + body: + string: '{"message":"Success"}' + headers: + Connection: + - Keep-Alive + Content-Length: + - '21' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 25 Feb 2026 03:06:29 GMT + Keep-Alive: + - timeout=5, max=100 + Server: + - Apache + Vary: + - User-Agent + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Test Agent. Test agent\nYour + personal goal is: Test network failure\nTo give my best complete final answer + to the task use the exact following format:\n\nThought: I now can give a great + answer\nFinal Answer: Your final answer must be the great and the most complete + as possible, it must be outcome described.\n\nI MUST use these formats, my job + depends on it!"}, {"role": "user", "content": "\nCurrent Task: Execute a task\n\nThis + is the expect criteria for your final answer: Task output\nyou MUST return the + actual complete content as the final answer, not a summary.\n\nBegin! This is + VERY important to you, use the tools available and give your best Final Answer, + your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '799' + Content-Type: + - application/json + Host: + - invalid-url-that-does-not-exist.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://invalid-url-that-does-not-exist.com/chat/completions + response: + body: + string: '{"message":"Success"}' + headers: + Connection: + - Keep-Alive + Content-Length: + - '21' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 25 Feb 2026 03:06:30 GMT + Keep-Alive: + - timeout=5, max=100 + Server: + - Apache + Vary: + - User-Agent + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Test Agent. Test agent\nYour + personal goal is: Test network failure\nTo give my best complete final answer + to the task use the exact following format:\n\nThought: I now can give a great + answer\nFinal Answer: Your final answer must be the great and the most complete + as possible, it must be outcome described.\n\nI MUST use these formats, my job + depends on it!"}, {"role": "user", "content": "\nCurrent Task: Execute a task\n\nThis + is the expect criteria for your final answer: Task output\nyou MUST return the + actual complete content as the final answer, not a summary.\n\nBegin! This is + VERY important to you, use the tools available and give your best Final Answer, + your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '799' + Content-Type: + - application/json + Host: + - invalid-url-that-does-not-exist.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://invalid-url-that-does-not-exist.com/chat/completions + response: + body: + string: '{"message":"Success"}' + headers: + Connection: + - Keep-Alive + Content-Length: + - '21' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 25 Feb 2026 03:17:35 GMT + Keep-Alive: + - timeout=5, max=100 + Server: + - Apache + Vary: + - User-Agent + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Test Agent. Test agent\nYour + personal goal is: Test network failure\nTo give my best complete final answer + to the task use the exact following format:\n\nThought: I now can give a great + answer\nFinal Answer: Your final answer must be the great and the most complete + as possible, it must be outcome described.\n\nI MUST use these formats, my job + depends on it!"}, {"role": "user", "content": "\nCurrent Task: Execute a task\n\nThis + is the expect criteria for your final answer: Task output\nyou MUST return the + actual complete content as the final answer, not a summary.\n\nBegin! This is + VERY important to you, use the tools available and give your best Final Answer, + your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '799' + Content-Type: + - application/json + Host: + - invalid-url-that-does-not-exist.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://invalid-url-that-does-not-exist.com/chat/completions + response: + body: + string: '{"message":"Success"}' + headers: + Connection: + - Keep-Alive + Content-Length: + - '21' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 25 Feb 2026 03:17:37 GMT + Keep-Alive: + - timeout=5, max=100 + Server: + - Apache + Vary: + - User-Agent + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Test Agent. Test agent\nYour + personal goal is: Test network failure\nTo give my best complete final answer + to the task use the exact following format:\n\nThought: I now can give a great + answer\nFinal Answer: Your final answer must be the great and the most complete + as possible, it must be outcome described.\n\nI MUST use these formats, my job + depends on it!"}, {"role": "user", "content": "\nCurrent Task: Execute a task\n\nThis + is the expect criteria for your final answer: Task output\nyou MUST return the + actual complete content as the final answer, not a summary.\n\nBegin! This is + VERY important to you, use the tools available and give your best Final Answer, + your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '799' + Content-Type: + - application/json + Host: + - invalid-url-that-does-not-exist.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://invalid-url-that-does-not-exist.com/chat/completions + response: + body: + string: '{"message":"Success"}' + headers: + Connection: + - Keep-Alive + Content-Length: + - '21' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 25 Feb 2026 03:17:38 GMT + Keep-Alive: + - timeout=5, max=100 + Server: + - Apache + Vary: + - User-Agent + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_prompt_and_memory/TestPromptAndMemory.test_prompt_template_with_variables.yaml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_prompt_and_memory/TestPromptAndMemory.test_prompt_template_with_variables.yaml new file mode 100644 index 000000000..93d8867b6 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_prompt_and_memory/TestPromptAndMemory.test_prompt_template_with_variables.yaml @@ -0,0 +1,262 @@ +interactions: +- request: + body: '{"messages": [{"role": "system", "content": "You are City Analyst. Expert + city analyst\nYour personal goal is: Analyze cities\nTo give my best complete + final answer to the task use the exact following format:\n\nThought: I now can + give a great answer\nFinal Answer: Your final answer must be the great and the + most complete as possible, it must be outcome described.\n\nI MUST use these + formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent Task: + Analyze the city of San Francisco and provide insights about its economy.\n\nThis + is the expect criteria for your final answer: City analysis report\nyou MUST + return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '872' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: "{\"choices\":[{\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"content\":\"Thought: + I now can give a great answer\\nFinal Answer: San Francisco City Analysis + Report\\n\\n1. Introduction:\\nSan Francisco is a major city located in Northern + California, known for its cultural diversity, historical significance, and + economic vitality. It is the largest city in the San Francisco Bay Area and + serves as a global hub for technology, finance, tourism, and innovation.\\n\\n2. + Economic Overview:\\nSan Francisco has a highly diversified economy with strong + sectors including technology, financial services, healthcare, education, and + tourism. The city's economy is driven by its proximity to Silicon Valley, + which has made it a center for tech startups and established companies.\\n\\n3. + Key Sectors:\\n- Technology: San Francisco is home to numerous tech companies, + including Twitter, Salesforce, Uber, and Salesforce Tower. The city's startup + ecosystem is vibrant, with venture capital funding flowing into innovative + enterprises.\\n- Financial Services: The city is a major financial center, + hosting institutions such as the Federal Reserve Bank of San Francisco and + various investment banks.\\n- Healthcare: San Francisco has a robust healthcare + sector, with institutions like UCSF Medical Center and Kaiser Permanente playing + significant roles.\\n- Education: The presence of prestigious universities + such as Stanford University and the University of California, Berkeley, contributes + to the city's knowledge-based economy.\\n- Tourism: San Francisco attracts + millions of tourists annually, drawn by landmarks such as the Golden Gate + Bridge, Alcatraz, Fisherman\u2019s Wharf, and the cable cars.\\n\\n4. Employment + and Labor Market:\\nSan Francisco has a high employment rate, with a labor + force that is highly educated and skilled. The city has a low unemployment + rate, reflecting a strong job market. However, the cost of living is extremely + high, which can be a challenge for many residents.\\n\\n5. Real Estate and + Housing:\\nThe real estate market in San Francisco is one of the most competitive + in the United States. High demand for housing, coupled with limited supply, + has led to soaring property prices and a significant housing affordability + crisis. The city has implemented policies to address this issue, including + rent control measures and affordable housing initiatives.\\n\\n6. Innovation + and Entrepreneurship:\\nSan Francisco is a global leader in innovation and + entrepreneurship. The city's culture of creativity and risk-taking has fostered + a dynamic startup environment. Incubators and accelerators such as Y Combinator + have helped launch numerous successful tech companies.\\n\\n7. Challenges:\\nDespite + its economic strengths, San Francisco faces several challenges, including + income inequality, homelessness, and environmental concerns. The city has + also experienced issues related to traffic congestion and public transportation + capacity.\\n\\n8. Conclusion:\\nSan Francisco is a thriving economic hub with + a diverse and resilient economy. Its strengths lie in technology, finance, + and innovation, while challenges such as housing affordability and social + inequality require ongoing attention. The city continues to be a key player + in the global economy and a center for progress and change.\",\"role\":\"assistant\"}}],\"created\":1771988791,\"id\":\"chatcmpl-e9c882a0-f967-92b1-b638-c5a7f6ab1273\",\"model\":\"qwen-turbo\",\"object\":\"chat.completion\",\"usage\":{\"completion_tokens\":577,\"prompt_tokens\":171,\"prompt_tokens_details\":{\"cached_tokens\":0},\"total_tokens\":748}}" + headers: + content-length: + - '3537' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:06:39 GMT + req-arrive-time: + - '1771988791102' + req-cost-time: + - '9067' + resp-start-time: + - '1771988800169' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '9067' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are City Analyst. Expert + city analyst\nYour personal goal is: Analyze cities\nTo give my best complete + final answer to the task use the exact following format:\n\nThought: I now can + give a great answer\nFinal Answer: Your final answer must be the great and the + most complete as possible, it must be outcome described.\n\nI MUST use these + formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent Task: + Analyze the city of San Francisco and provide insights about its economy.\n\nThis + is the expect criteria for your final answer: City analysis report\nyou MUST + return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '872' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: "{\"choices\":[{\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"content\":\"Thought: + I now can give a great answer\\nFinal Answer: San Francisco City Analysis + Report\\n\\n1. Introduction:\\nSan Francisco is a major city located in Northern + California, known for its cultural diversity, historical significance, and + economic vitality. It is the largest city in the San Francisco Bay Area and + serves as a global hub for technology, finance, tourism, and innovation.\\n\\n2. + Economic Overview:\\nSan Francisco has a highly diversified economy with strong + sectors including technology, financial services, healthcare, education, and + tourism. The city's economy is driven by a mix of large multinational corporations, + startups, and small businesses.\\n\\n3. Key Industries:\\n- Technology: San + Francisco is home to numerous tech companies, including major players like + Salesforce, Twitter, Uber, and Airbnb. The city is also part of the larger + Silicon Valley ecosystem, which is one of the most significant technology + hubs globally.\\n- Financial Services: The city is a major financial center, + hosting institutions such as the Federal Reserve Bank of San Francisco, the + San Francisco Stock Exchange, and numerous venture capital firms.\\n- Healthcare: + San Francisco has a robust healthcare sector with leading medical institutions + such as the University of California, San Francisco (UCSF) Medical Center + and Kaiser Permanente.\\n- Education: The city is home to several prestigious + universities and colleges, including the University of California, Berkeley, + and Stanford University, which contribute significantly to the local economy + through research, innovation, and employment.\\n- Tourism: San Francisco is + a popular tourist destination, attracting millions of visitors annually. Landmarks + such as the Golden Gate Bridge, Alcatraz, Fisherman\u2019s Wharf, and the + cable cars are major attractions.\\n\\n4. Employment and Labor Market:\\nThe + labor market in San Francisco is competitive, with a high concentration of + skilled workers in the technology and finance sectors. The city has a relatively + low unemployment rate, but the cost of living is among the highest in the + United States. The workforce is highly educated, with a significant percentage + holding bachelor\u2019s degrees or higher.\\n\\n5. Real Estate and Housing:\\nSan + Francisco faces significant housing challenges due to high demand and limited + supply. The real estate market is dominated by high property values and rising + rents, making it difficult for many residents to afford housing. The city + has implemented various policies to address homelessness and promote affordable + housing, but these issues remain pressing concerns.\\n\\n6. Innovation and + Entrepreneurship:\\nSan Francisco is a global leader in innovation and entrepreneurship, + particularly in the technology and startup sectors. The city hosts numerous + incubators, accelerators, and co-working spaces that support new ventures. + This environment fosters continuous growth and development in emerging industries.\\n\\n7. + Challenges:\\nDespite its economic strengths, San Francisco faces several + challenges, including income inequality, housing affordability, traffic congestion, + and environmental sustainability. The city is also dealing with the impacts + of climate change, such as rising sea levels and increased risk of wildfires.\\n\\n8. + Future Outlook:\\nSan Francisco is well-positioned for continued economic + growth, driven by its strong tech industry, innovative spirit, and diverse + population. However, addressing the city\u2019s social and environmental challenges + will be critical to ensuring long-term prosperity and quality of life for + all residents.\\n\\n9. Conclusion:\\nSan Francisco is a dynamic and economically + powerful city with a unique blend of culture, innovation, and opportunity. + Its economy is resilient and forward-thinking, but it must navigate ongoing + challenges to maintain its status as a global leader. The city\u2019s future + will depend on its ability to balance growth with sustainability, inclusivity, + and quality of life.\",\"role\":\"assistant\"}}],\"created\":1771989458,\"id\":\"chatcmpl-a94aeb0f-3a92-92e4-8c9c-446f1f84f224\",\"model\":\"qwen-turbo\",\"object\":\"chat.completion\",\"usage\":{\"completion_tokens\":703,\"prompt_tokens\":171,\"prompt_tokens_details\":{\"cached_tokens\":0},\"total_tokens\":874}}" + headers: + content-length: + - '4297' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:17:48 GMT + req-arrive-time: + - '1771989458658' + req-cost-time: + - '10095' + resp-start-time: + - '1771989468753' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '10095' + x-request-id: + - + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_prompt_and_memory/TestPromptAndMemory.test_session_management.yaml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_prompt_and_memory/TestPromptAndMemory.test_session_management.yaml new file mode 100644 index 000000000..41e9c9ac6 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_prompt_and_memory/TestPromptAndMemory.test_session_management.yaml @@ -0,0 +1,336 @@ +interactions: +- request: + body: '{"messages": [{"role": "system", "content": "You are Session Agent. Expert + in session management\nYour personal goal is: Manage conversation sessions\nTo + give my best complete final answer to the task use the exact following format:\n\nThought: + I now can give a great answer\nFinal Answer: Your final answer must be the great + and the most complete as possible, it must be outcome described.\n\nI MUST use + these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent + Task: Start a conversation\n\nThis is the expect criteria for your final answer: + Greeting\nyou MUST return the actual complete content as the final answer, not + a summary.\n\nBegin! This is VERY important to you, use the tools available + and give your best Final Answer, your job depends on it!\n\nThought:"}], "model": + "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '831' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I now can give a great answer\nFinal Answer: Hello! How can I assist you today?","role":"assistant"}}],"created":1771988800,"id":"chatcmpl-ad0bb0d9-a67c-90f3-bc1e-0402d628e3bb","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":22,"prompt_tokens":161,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":183}}' + headers: + content-length: + - '418' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:06:41 GMT + req-arrive-time: + - '1771988800446' + req-cost-time: + - '793' + resp-start-time: + - '1771988801240' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '793' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Session Agent. Expert + in session management\nYour personal goal is: Manage conversation sessions\nTo + give my best complete final answer to the task use the exact following format:\n\nThought: + I now can give a great answer\nFinal Answer: Your final answer must be the great + and the most complete as possible, it must be outcome described.\n\nI MUST use + these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent + Task: Continue the conversation\n\nThis is the expect criteria for your final + answer: Response\nyou MUST return the actual complete content as the final answer, + not a summary.\n\nThis is the context you''re working with:\nHello! How can + I assist you today?\n\nBegin! This is VERY important to you, use the tools available + and give your best Final Answer, your job depends on it!\n\nThought:"}], "model": + "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '916' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"I + now can give a great answer\nFinal Answer: Hello! How can I assist you today?","role":"assistant"}}],"created":1771988801,"id":"chatcmpl-63c03d5e-c03c-90d1-8f51-cfd9f3394744","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":20,"prompt_tokens":178,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":198}}' + headers: + content-length: + - '409' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:06:41 GMT + req-arrive-time: + - '1771988801441' + req-cost-time: + - '604' + resp-start-time: + - '1771988802045' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '604' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Session Agent. Expert + in session management\nYour personal goal is: Manage conversation sessions\nTo + give my best complete final answer to the task use the exact following format:\n\nThought: + I now can give a great answer\nFinal Answer: Your final answer must be the great + and the most complete as possible, it must be outcome described.\n\nI MUST use + these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent + Task: Start a conversation\n\nThis is the expect criteria for your final answer: + Greeting\nyou MUST return the actual complete content as the final answer, not + a summary.\n\nBegin! This is VERY important to you, use the tools available + and give your best Final Answer, your job depends on it!\n\nThought:"}], "model": + "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '831' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I now can give a great answer\nFinal Answer: Hello! How can I assist you today?","role":"assistant"}}],"created":1771989469,"id":"chatcmpl-2a45f674-0aab-9ed6-991d-2dd45f25334d","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":22,"prompt_tokens":161,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":183}}' + headers: + content-length: + - '418' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:17:49 GMT + req-arrive-time: + - '1771989469068' + req-cost-time: + - '454' + resp-start-time: + - '1771989469523' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '454' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Session Agent. Expert + in session management\nYour personal goal is: Manage conversation sessions\nTo + give my best complete final answer to the task use the exact following format:\n\nThought: + I now can give a great answer\nFinal Answer: Your final answer must be the great + and the most complete as possible, it must be outcome described.\n\nI MUST use + these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent + Task: Continue the conversation\n\nThis is the expect criteria for your final + answer: Response\nyou MUST return the actual complete content as the final answer, + not a summary.\n\nThis is the context you''re working with:\nHello! How can + I assist you today?\n\nBegin! This is VERY important to you, use the tools available + and give your best Final Answer, your job depends on it!\n\nThought:"}], "model": + "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '916' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"I + now can give a great answer\nFinal Answer: Hello! How can I assist you today?","role":"assistant"}}],"created":1771989469,"id":"chatcmpl-aa6537e5-e874-97f3-aa0a-eb3583623cfa","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":20,"prompt_tokens":178,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":198}}' + headers: + content-length: + - '409' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:17:49 GMT + req-arrive-time: + - '1771989469741' + req-cost-time: + - '505' + resp-start-time: + - '1771989470246' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '505' + x-request-id: + - + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_streaming_llm_calls/TestStreamingLLMCalls.test_streaming_crew_execution.yaml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_streaming_llm_calls/TestStreamingLLMCalls.test_streaming_crew_execution.yaml new file mode 100644 index 000000000..02c8de4f0 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_streaming_llm_calls/TestStreamingLLMCalls.test_streaming_crew_execution.yaml @@ -0,0 +1,170 @@ +interactions: +- request: + body: '{"messages": [{"role": "system", "content": "You are Content Writer. Expert + content writer\nYour personal goal is: Write engaging content\nTo give my best + complete final answer to the task use the exact following format:\n\nThought: + I now can give a great answer\nFinal Answer: Your final answer must be the great + and the most complete as possible, it must be outcome described.\n\nI MUST use + these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent + Task: Write a short greeting message\n\nThis is the expect criteria for your + final answer: A greeting message\nyou MUST return the actual complete content + as the final answer, not a summary.\n\nBegin! This is VERY important to you, + use the tools available and give your best Final Answer, your job depends on + it!\n\nThought:"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '839' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I now can give a great answer\nFinal Answer: Hello! It''s a pleasure to meet + you. How can I assist you today?","role":"assistant"}}],"created":1771988257,"id":"chatcmpl-a3cdb116-a7ca-9d7a-a689-a5cd1a09ceec","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":30,"prompt_tokens":163,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":193}}' + headers: + content-length: + - '447' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:57:38 GMT + req-arrive-time: + - '1771988257456' + req-cost-time: + - '1432' + resp-start-time: + - '1771988258889' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '1432' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Content Writer. Expert + content writer\nYour personal goal is: Write engaging content\nTo give my best + complete final answer to the task use the exact following format:\n\nThought: + I now can give a great answer\nFinal Answer: Your final answer must be the great + and the most complete as possible, it must be outcome described.\n\nI MUST use + these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent + Task: Write a short greeting message\n\nThis is the expect criteria for your + final answer: A greeting message\nyou MUST return the actual complete content + as the final answer, not a summary.\n\nBegin! This is VERY important to you, + use the tools available and give your best Final Answer, your job depends on + it!\n\nThought:"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '839' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I now can give a great answer\nFinal Answer: Hello! It''s a pleasure to meet + you. How can I assist you today?","role":"assistant"}}],"created":1771989470,"id":"chatcmpl-fe25bcbd-5274-9802-8da5-c86bbf55155e","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":30,"prompt_tokens":163,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":193}}' + headers: + content-length: + - '447' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:17:51 GMT + req-arrive-time: + - '1771989470477' + req-cost-time: + - '635' + resp-start-time: + - '1771989471112' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '635' + x-request-id: + - + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_sync_llm_calls/TestSyncLLMCalls.test_basic_sync_crew_execution.yaml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_sync_llm_calls/TestSyncLLMCalls.test_basic_sync_crew_execution.yaml new file mode 100644 index 000000000..33d87cf90 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_sync_llm_calls/TestSyncLLMCalls.test_basic_sync_crew_execution.yaml @@ -0,0 +1,301 @@ +interactions: +- request: + body: '{"messages": [{"role": "system", "content": "You are Data Analyst. You + are an expert data analyst with 10 years of experience.\nYour personal goal + is: Extract actionable insights from data\nTo give my best complete final answer + to the task use the exact following format:\n\nThought: I now can give a great + answer\nFinal Answer: Your final answer must be the great and the most complete + as possible, it must be outcome described.\n\nI MUST use these formats, my job + depends on it!"}, {"role": "user", "content": "\nCurrent Task: Analyze the latest + AI trends and provide insights.\n\nThis is the expect criteria for your final + answer: A comprehensive analysis of AI trends.\nyou MUST return the actual complete + content as the final answer, not a summary.\n\nBegin! This is VERY important + to you, use the tools available and give your best Final Answer, your job depends + on it!\n\nThought:"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '930' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I now can give a great answer\nFinal Answer: The latest AI trends are shaping + the future of technology and business in profound ways. Here is a comprehensive + analysis of these trends:\n\n1. **Generative AI and Large Language Models + (LLMs):** \n Generative AI has seen explosive growth, with models like GPT-4, + BERT, and others becoming increasingly sophisticated. These models are not + only capable of generating text but also images, videos, and code. Businesses + are leveraging generative AI for content creation, customer service, product + development, and more. This trend is expected to continue as companies look + to automate creative processes and reduce costs.\n\n2. **AI Ethics and Responsible + AI:**\n As AI becomes more pervasive, ethical concerns have come to the + forefront. Issues such as bias, transparency, accountability, and data privacy + are being addressed by governments, organizations, and researchers. The development + of frameworks for responsible AI, including fairness-aware algorithms and + explainable AI (XAI), is becoming a critical component of AI deployment. Companies + are investing in AI ethics teams and tools to ensure their AI systems align + with societal values.\n\n3. **AI in Healthcare:**\n AI is revolutionizing + healthcare through applications such as medical imaging, drug discovery, personalized + treatment plans, and predictive analytics. AI-driven diagnostics are improving + accuracy and speed, while machine learning models are enabling early detection + of diseases. Additionally, AI-powered chatbots and virtual assistants are + enhancing patient engagement and support. The integration of AI into healthcare + is expected to grow significantly in the coming years.\n\n4. **AI in Autonomous + Systems:**\n The development of autonomous systems, including self-driving + cars, drones, and robots, is accelerating. AI is playing a crucial role in + enabling these systems to perceive their environment, make decisions, and + act autonomously. Advances in computer vision, sensor fusion, and reinforcement + learning are driving this trend. However, challenges related to safety, regulation, + and public acceptance remain significant barriers to widespread adoption.\n\n5. + **AI in Edge Computing:**\n With the rise of IoT devices and real-time data + processing, AI is increasingly being deployed at the edge rather than in centralized + cloud environments. Edge computing allows AI models to process data locally, + reducing latency and improving efficiency. This trend is particularly important + for applications requiring immediate decision-making, such as industrial automation, + smart cities, and augmented reality.\n\n6. **AI in Cybersecurity:**\n AI + is being used to detect and respond to cyber threats more effectively. Machine + learning models can analyze vast amounts of data to identify patterns indicative + of malicious activity. AI-driven security tools are also being used to automate + threat response, reduce false positives, and improve overall security posture. + As cyber threats become more sophisticated, the role of AI in cybersecurity + will continue to expand.\n\n7. **AI in Education:**\n AI is transforming + education through personalized learning experiences, intelligent tutoring + systems, and automated grading. Adaptive learning platforms use AI to tailor + content to individual student needs, improving engagement and outcomes. Additionally, + AI is being used to analyze student performance and provide insights for educators. + The integration of AI in education is expected to increase as schools and + institutions seek to enhance learning efficiency and accessibility.\n\n8. + **AI in Sustainability:**\n AI is being leveraged to address environmental + challenges, such as climate change, resource management, and energy optimization. + Machine learning models are used to predict weather patterns, optimize energy + consumption, and monitor ecosystems. AI is also being applied to reduce waste + and improve supply chain efficiency. As sustainability becomes a priority + for businesses and governments, AI will play an essential role in achieving + environmental goals.\n\n9. **AI in Customer Experience:**\n AI is enhancing + customer experience through personalized recommendations, chatbots, and sentiment + analysis. Companies are using AI to understand customer behavior, anticipate + needs, and deliver tailored interactions. AI-powered CRM systems are enabling + businesses to improve customer retention and satisfaction. This trend is expected + to continue as companies seek to differentiate themselves in competitive markets.\n\n10. + **AI in Finance:**\n AI is transforming the financial sector through applications + such as fraud detection, algorithmic trading, and risk management. Machine + learning models are used to analyze market trends, assess creditworthiness, + and detect fraudulent transactions. AI is also being used to automate back-office + operations and improve customer service. As financial institutions adopt AI, + they are seeing improvements in efficiency, accuracy, and profitability.\n\nIn + conclusion, the latest AI trends are reshaping industries, driving innovation, + and creating new opportunities for businesses and individuals. While these + trends offer significant benefits, they also present challenges related to + ethics, regulation, and workforce adaptation. As AI continues to evolve, it + will be essential for organizations to stay informed, invest in the right + technologies, and prioritize responsible AI practices.","role":"assistant"}}],"created":1771988259,"id":"chatcmpl-7536b4fb-a5e3-97a2-9891-dcdfc5f6d817","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":956,"prompt_tokens":182,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":1138}}' + headers: + content-length: + - '5812' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:57:49 GMT + req-arrive-time: + - '1771988259198' + req-cost-time: + - '10214' + resp-start-time: + - '1771988269413' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '10214' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Data Analyst. You + are an expert data analyst with 10 years of experience.\nYour personal goal + is: Extract actionable insights from data\nTo give my best complete final answer + to the task use the exact following format:\n\nThought: I now can give a great + answer\nFinal Answer: Your final answer must be the great and the most complete + as possible, it must be outcome described.\n\nI MUST use these formats, my job + depends on it!"}, {"role": "user", "content": "\nCurrent Task: Analyze the latest + AI trends and provide insights.\n\nThis is the expect criteria for your final + answer: A comprehensive analysis of AI trends.\nyou MUST return the actual complete + content as the final answer, not a summary.\n\nBegin! This is VERY important + to you, use the tools available and give your best Final Answer, your job depends + on it!\n\nThought:"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '930' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I now can give a great answer\nFinal Answer: The latest AI trends are shaping + the future of technology, business, and society in profound ways. Here is + a comprehensive analysis of these trends:\n\n1. **Large Language Models (LLMs) + and Generative AI**: \n - Large language models such as GPT-4, BERT, and + other transformer-based models have become increasingly sophisticated, capable + of performing complex tasks like text generation, translation, summarization, + and even coding. These models are being integrated into various applications, + from customer service chatbots to content creation tools.\n - Generative + AI has seen significant advancements, enabling the creation of high-quality + images, videos, and audio. Tools like DALL-E, MidJourney, and Runway ML are + pushing the boundaries of creativity and are being used across industries + for marketing, design, and entertainment.\n\n2. **AI in Healthcare**:\n - + AI is transforming healthcare through improved diagnostics, personalized treatment + plans, and drug discovery. AI-powered imaging tools are helping radiologists + detect diseases like cancer at earlier stages with greater accuracy.\n - + Wearable devices and mobile apps powered by AI are enabling real-time health + monitoring, allowing for early intervention and better patient outcomes.\n\n3. + **AI Ethics and Regulation**:\n - As AI becomes more pervasive, ethical + concerns around bias, privacy, and transparency are gaining attention. Companies + are investing in AI ethics frameworks and ensuring fairness in algorithmic + decision-making.\n - Regulatory bodies are beginning to draft guidelines + and laws to govern AI use, particularly in areas like facial recognition, + data privacy, and autonomous systems.\n\n4. **AI in Business Operations**:\n - + Businesses are leveraging AI for automation, predictive analytics, and customer + insights. AI-driven tools are streamlining operations, reducing costs, and + improving efficiency.\n - Customer service is being revolutionized by AI + chatbots and virtual assistants, which provide 24/7 support and enhance user + experience.\n\n5. **AI and Sustainability**:\n - AI is being used to address + environmental challenges, such as optimizing energy consumption, predicting + climate change impacts, and managing natural resources more efficiently.\n - + Companies are using AI to reduce waste, improve supply chain logistics, and + achieve sustainability goals.\n\n6. **AI in Education**:\n - Personalized + learning experiences are being enabled by AI, allowing students to learn at + their own pace and receive tailored feedback. AI tutors and adaptive learning + platforms are becoming more common in classrooms.\n - AI is also being used + to analyze student performance data, identify at-risk students, and improve + educational outcomes.\n\n7. **AI in Cybersecurity**:\n - AI is playing a + crucial role in detecting and responding to cyber threats. Machine learning + algorithms are being used to identify unusual patterns and flag potential + security breaches in real time.\n - AI-driven threat intelligence is helping + organizations stay ahead of cybercriminals and protect sensitive data.\n\n8. + **AI in Autonomous Systems**:\n - Self-driving cars, drones, and robots + are becoming more advanced, thanks to improvements in AI. These systems are + being tested and deployed in various industries, including transportation, + logistics, and manufacturing.\n - AI is enabling autonomous systems to make + decisions in real-time, improving safety and efficiency.\n\n9. **AI and Human-AI + Collaboration**:\n - There is a growing emphasis on collaboration between + humans and AI systems. Rather than replacing human workers, AI is being used + to augment their capabilities, leading to more efficient and effective workflows.\n - + Tools like AI-assisted writing, coding, and design are empowering professionals + to focus on higher-level tasks while AI handles repetitive or time-consuming + work.\n\n10. **AI Research and Development**:\n - Significant investments + are being made in AI research, with a focus on improving model efficiency, + reducing computational costs, and enhancing explainability. Researchers are + exploring new architectures and techniques to make AI more robust and reliable.\n - + Open-source AI projects and collaborative platforms are accelerating innovation, + making it easier for developers and researchers to share knowledge and build + upon each other''s work.\n\nIn conclusion, the latest AI trends reflect a + shift toward more powerful, accessible, and ethical AI systems that are deeply + integrated into various aspects of life. These trends are not only driving + technological innovation but also reshaping industries, economies, and societies. + As AI continues to evolve, it will be essential to balance its benefits with + responsible development and governance to ensure it serves the greater good.","role":"assistant"}}],"created":1771989471,"id":"chatcmpl-83e6fd30-fdfb-9466-97cb-617c8f904c06","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":891,"prompt_tokens":182,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":1073}}' + headers: + content-length: + - '5209' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:18:02 GMT + req-arrive-time: + - '1771989471442' + req-cost-time: + - '11035' + resp-start-time: + - '1771989482478' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '11035' + x-request-id: + - + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_sync_llm_calls/TestSyncLLMCalls.test_crew_with_multiple_tasks.yaml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_sync_llm_calls/TestSyncLLMCalls.test_crew_with_multiple_tasks.yaml new file mode 100644 index 000000000..b85797aee --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_sync_llm_calls/TestSyncLLMCalls.test_crew_with_multiple_tasks.yaml @@ -0,0 +1,656 @@ +interactions: +- request: + body: '{"messages": [{"role": "system", "content": "You are Research Analyst. + Expert researcher\nYour personal goal is: Conduct thorough research\nTo give + my best complete final answer to the task use the exact following format:\n\nThought: + I now can give a great answer\nFinal Answer: Your final answer must be the great + and the most complete as possible, it must be outcome described.\n\nI MUST use + these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent + Task: Research AI market trends\n\nThis is the expect criteria for your final + answer: Market trends report\nyou MUST return the actual complete content as + the final answer, not a summary.\n\nBegin! This is VERY important to you, use + the tools available and give your best Final Answer, your job depends on it!\n\nThought:"}], + "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '837' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"I + now can give a great answer\nFinal Answer: AI Market Trends Report\n\n1. Introduction:\nThe + artificial intelligence (AI) market has experienced significant growth in + recent years, driven by advancements in machine learning, natural language + processing, and computer vision technologies. This report provides an in-depth + analysis of current trends shaping the AI market, including key drivers, challenges, + and future outlook.\n\n2. Market Overview:\nThe global AI market is projected + to grow at a compound annual growth rate (CAGR) of over 35% from 2023 to 2030. + The market is segmented into various categories, including hardware, software, + and services. Key players in the market include companies such as Google, + Microsoft, IBM, Amazon, and startups like DeepMind and OpenAI.\n\n3. Key Trends:\n\na) + Growth of Generative AI:\nGenerative AI, which includes technologies such + as GPT-3, DALL-E, and Stable Diffusion, has seen rapid adoption across industries. + These models are being used for content creation, design, and even coding, + significantly reducing the time and effort required for these tasks.\n\nb) + Increased Investment in AI Research:\nMajor tech companies and governments + are investing heavily in AI research. For instance, the United States has + launched several initiatives to boost AI innovation, while China has made + AI a national priority, aiming to become a global leader in the field.\n\nc) + Expansion of AI in Healthcare:\nAI is transforming healthcare through applications + such as diagnostic imaging, personalized medicine, and drug discovery. Machine + learning algorithms are being used to analyze medical data, predict patient + outcomes, and improve treatment plans.\n\nd) Rise of Edge AI:\nEdge AI refers + to the deployment of AI algorithms on local devices rather than relying solely + on cloud computing. This trend is gaining traction due to its ability to reduce + latency, enhance privacy, and improve real-time decision-making.\n\ne) Ethical + AI and Regulatory Developments:\nAs AI becomes more pervasive, there is growing + concern about ethical implications, bias, and transparency. Governments and + organizations are working on developing regulations and guidelines to ensure + responsible AI use. The European Union''s AI Act is one such example, aiming + to create a legal framework for AI systems.\n\nf) AI in Autonomous Systems:\nThe + development of autonomous vehicles, drones, and robotics is accelerating. + AI is playing a crucial role in enabling these systems to make decisions, + navigate environments, and interact with humans safely and efficiently.\n\ng) + AI in Customer Experience:\nCompanies are leveraging AI to enhance customer + experience through chatbots, virtual assistants, and personalized recommendations. + These tools are improving customer engagement and satisfaction while reducing + operational costs.\n\nh) AI in Cybersecurity:\nAI is being increasingly used + to detect and respond to cyber threats. Machine learning algorithms can identify + patterns and anomalies that may indicate potential security breaches, enabling + proactive measures to protect data and systems.\n\n4. Challenges:\nDespite + the positive trends, the AI market faces several challenges, including data + privacy concerns, the need for skilled professionals, and the high cost of + AI implementation. Additionally, there are ongoing debates about the societal + impact of AI, including job displacement and the need for retraining programs.\n\n5. + Future Outlook:\nThe AI market is expected to continue its robust growth, + with emerging technologies such as quantum computing and neuromorphic engineering + potentially revolutionizing AI capabilities. Collaboration between industry, + academia, and government will be essential to address challenges and harness + the full potential of AI.\n\n6. Conclusion:\nThe AI market is evolving rapidly, + driven by technological advancements and increasing demand across various + sectors. While there are challenges to overcome, the opportunities presented + by AI are vast, and its impact on society is likely to be profound. Continued + investment, innovation, and ethical considerations will shape the future of + the AI market.","role":"assistant"}}],"created":1771988269,"id":"chatcmpl-214bc2a0-04e2-93c9-b0c2-e3487c0b8ea5","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":753,"prompt_tokens":161,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":914}}' + headers: + content-length: + - '4484' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:57:59 GMT + req-arrive-time: + - '1771988269741' + req-cost-time: + - '9866' + resp-start-time: + - '1771988279607' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '9866' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Research Analyst. + Expert researcher\nYour personal goal is: Conduct thorough research\nTo give + my best complete final answer to the task use the exact following format:\n\nThought: + I now can give a great answer\nFinal Answer: Your final answer must be the great + and the most complete as possible, it must be outcome described.\n\nI MUST use + these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent + Task: Analyze competitor strategies\n\nThis is the expect criteria for your + final answer: Competitor analysis\nyou MUST return the actual complete content + as the final answer, not a summary.\n\nThis is the context you''re working with:\nAI + Market Trends Report\n\n1. Introduction:\nThe artificial intelligence (AI) market + has experienced significant growth in recent years, driven by advancements in + machine learning, natural language processing, and computer vision technologies. + This report provides an in-depth analysis of current trends shaping the AI market, + including key drivers, challenges, and future outlook.\n\n2. Market Overview:\nThe + global AI market is projected to grow at a compound annual growth rate (CAGR) + of over 35% from 2023 to 2030. The market is segmented into various categories, + including hardware, software, and services. Key players in the market include + companies such as Google, Microsoft, IBM, Amazon, and startups like DeepMind + and OpenAI.\n\n3. Key Trends:\n\na) Growth of Generative AI:\nGenerative AI, + which includes technologies such as GPT-3, DALL-E, and Stable Diffusion, has + seen rapid adoption across industries. These models are being used for content + creation, design, and even coding, significantly reducing the time and effort + required for these tasks.\n\nb) Increased Investment in AI Research:\nMajor + tech companies and governments are investing heavily in AI research. For instance, + the United States has launched several initiatives to boost AI innovation, while + China has made AI a national priority, aiming to become a global leader in the + field.\n\nc) Expansion of AI in Healthcare:\nAI is transforming healthcare through + applications such as diagnostic imaging, personalized medicine, and drug discovery. + Machine learning algorithms are being used to analyze medical data, predict + patient outcomes, and improve treatment plans.\n\nd) Rise of Edge AI:\nEdge + AI refers to the deployment of AI algorithms on local devices rather than relying + solely on cloud computing. This trend is gaining traction due to its ability + to reduce latency, enhance privacy, and improve real-time decision-making.\n\ne) + Ethical AI and Regulatory Developments:\nAs AI becomes more pervasive, there + is growing concern about ethical implications, bias, and transparency. Governments + and organizations are working on developing regulations and guidelines to ensure + responsible AI use. The European Union''s AI Act is one such example, aiming + to create a legal framework for AI systems.\n\nf) AI in Autonomous Systems:\nThe + development of autonomous vehicles, drones, and robotics is accelerating. AI + is playing a crucial role in enabling these systems to make decisions, navigate + environments, and interact with humans safely and efficiently.\n\ng) AI in Customer + Experience:\nCompanies are leveraging AI to enhance customer experience through + chatbots, virtual assistants, and personalized recommendations. These tools + are improving customer engagement and satisfaction while reducing operational + costs.\n\nh) AI in Cybersecurity:\nAI is being increasingly used to detect and + respond to cyber threats. Machine learning algorithms can identify patterns + and anomalies that may indicate potential security breaches, enabling proactive + measures to protect data and systems.\n\n4. Challenges:\nDespite the positive + trends, the AI market faces several challenges, including data privacy concerns, + the need for skilled professionals, and the high cost of AI implementation. + Additionally, there are ongoing debates about the societal impact of AI, including + job displacement and the need for retraining programs.\n\n5. Future Outlook:\nThe + AI market is expected to continue its robust growth, with emerging technologies + such as quantum computing and neuromorphic engineering potentially revolutionizing + AI capabilities. Collaboration between industry, academia, and government will + be essential to address challenges and harness the full potential of AI.\n\n6. + Conclusion:\nThe AI market is evolving rapidly, driven by technological advancements + and increasing demand across various sectors. While there are challenges to + overcome, the opportunities presented by AI are vast, and its impact on society + is likely to be profound. Continued investment, innovation, and ethical considerations + will shape the future of the AI market.\n\nBegin! This is VERY important to + you, use the tools available and give your best Final Answer, your job depends + on it!\n\nThought:"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '4994' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I now can give a great answer\nFinal Answer: Competitor analysis\n\nThe AI + market is highly competitive, with major players such as Google, Microsoft, + IBM, Amazon, and startups like DeepMind and OpenAI dominating the landscape. + These companies are employing various strategies to maintain their competitive + edge and drive innovation in the field.\n\nGoogle has been a leader in AI + research and development, with significant investments in machine learning, + natural language processing, and computer vision. The company has also made + strategic acquisitions, such as DeepMind, to bolster its AI capabilities. + Google''s strategy focuses on developing AI technologies that can be integrated + into its products and services, such as Google Assistant, Google Search, and + Google Cloud.\n\nMicrosoft has also made substantial investments in AI, particularly + through its Azure cloud platform. The company has focused on developing AI + solutions for businesses, including AI-powered tools for data analysis, customer + service, and cybersecurity. Microsoft''s strategy includes partnerships with + other companies and organizations to expand its AI offerings and reach a broader + audience.\n\nIBM has a long history of involvement in AI, with its Watson + AI platform being one of the most well-known examples. IBM''s strategy has + been to develop AI solutions that can be applied across various industries, + including healthcare, finance, and retail. The company has also invested in + AI research and has developed several AI-based products and services.\n\nAmazon + has leveraged its vast e-commerce and cloud computing infrastructure to develop + AI technologies. The company has focused on using AI to improve customer experience, + such as through personalized recommendations and chatbots. Amazon has also + developed AI solutions for businesses, including AI-powered tools for data + analysis and customer service.\n\nStartups like DeepMind and OpenAI have also + played a significant role in the AI market. DeepMind, acquired by Google, + has made significant contributions to AI research, particularly in the areas + of machine learning and reinforcement learning. OpenAI, on the other hand, + has focused on developing open-source AI technologies and promoting responsible + AI use.\n\nIn addition to these companies, there are numerous other players + in the AI market, including smaller startups and academic institutions. These + companies are often focused on niche areas of AI, such as computer vision, + natural language processing, or robotics.\n\nOverall, the AI market is characterized + by intense competition, with companies constantly striving to develop new + technologies and improve existing ones. The strategies employed by these companies + vary, but they all share a common goal of leveraging AI to drive innovation + and create value for their customers. As the AI market continues to grow, + it is likely that competition will only intensify, with companies investing + more in research and development to stay ahead of the curve.","role":"assistant"}}],"created":1771988279,"id":"chatcmpl-93fe6864-6449-9a42-92a7-1d7066d14876","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":527,"prompt_tokens":912,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":1439}}' + headers: + content-length: + - '3338' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:58:07 GMT + req-arrive-time: + - '1771988279879' + req-cost-time: + - '8054' + resp-start-time: + - '1771988287934' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '8053' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Research Analyst. + Expert researcher\nYour personal goal is: Conduct thorough research\nTo give + my best complete final answer to the task use the exact following format:\n\nThought: + I now can give a great answer\nFinal Answer: Your final answer must be the great + and the most complete as possible, it must be outcome described.\n\nI MUST use + these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent + Task: Research AI market trends\n\nThis is the expect criteria for your final + answer: Market trends report\nyou MUST return the actual complete content as + the final answer, not a summary.\n\nBegin! This is VERY important to you, use + the tools available and give your best Final Answer, your job depends on it!\n\nThought:"}], + "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '837' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"I + now can give a great answer\nFinal Answer: The AI market is experiencing rapid + growth and transformation, driven by advancements in technology, increasing + demand for automation, and the need for data-driven decision-making. Below + is a comprehensive report on current AI market trends:\n\n1. **Market Growth**: + The global AI market is projected to grow significantly over the next few + years. According to recent reports, the market size was valued at around $160 + billion in 2023 and is expected to surpass $1.8 trillion by 2030, with a compound + annual growth rate (CAGR) of over 30%.\n\n2. **Sectoral Adoption**:\n - + **Healthcare**: AI is being widely adopted for diagnostics, personalized treatment, + drug discovery, and patient care. AI-powered imaging tools are improving diagnostic + accuracy, while predictive analytics help in managing chronic diseases.\n - + **Finance**: Financial institutions are leveraging AI for fraud detection, + algorithmic trading, customer service chatbots, and risk management. AI is + also transforming the lending industry through automated underwriting processes.\n - + **Retail**: Retailers are using AI for inventory management, personalized + marketing, and customer experience enhancement. AI-driven recommendation systems + are becoming increasingly sophisticated, leading to higher conversion rates.\n - + **Manufacturing**: AI is playing a crucial role in predictive maintenance, + quality control, and supply chain optimization. Smart factories are using + AI to streamline production and reduce downtime.\n\n3. **Technological Advancements**:\n - + **Generative AI**: The rise of large language models (LLMs) such as GPT-4, + BERT, and others has led to breakthroughs in natural language processing (NLP), + content generation, and conversational AI. These models are being integrated + into various applications, from customer service to creative writing.\n - + **Computer Vision**: Advances in computer vision have enabled better object + recognition, facial recognition, and autonomous vehicles. AI-powered cameras + and sensors are being used in security, surveillance, and smart cities.\n - + **AI Ethics and Governance**: As AI becomes more prevalent, there is a growing + focus on ethical AI development, bias mitigation, and regulatory compliance. + Governments and organizations are working on frameworks to ensure responsible + AI deployment.\n\n4. **Investment and Funding**:\n - Venture capital investment + in AI startups has surged, with significant funding going towards AI-driven + healthcare, fintech, and enterprise software solutions.\n - Tech giants + such as Google, Microsoft, Amazon, and Meta are heavily investing in AI research + and development, creating new products and services that leverage AI capabilities.\n\n5. + **Workforce Impact**:\n - AI is reshaping the job market, with some roles + being automated while new opportunities emerge in AI development, data science, + and AI ethics.\n - Upskilling and reskilling programs are becoming essential + to prepare the workforce for an AI-driven economy.\n\n6. **Global Competition**:\n - + Countries like the United States, China, and the European Union are competing + to lead in AI innovation. China, in particular, is making significant investments + in AI infrastructure and talent development.\n - International collaborations + and partnerships are emerging to address common challenges in AI research + and application.\n\n7. **Consumer Adoption**:\n - Consumers are increasingly + adopting AI-powered devices and services, including smart assistants, recommendation + engines, and virtual reality experiences.\n - Personalization is becoming + a key differentiator in consumer products, with AI enabling tailored user + experiences across platforms.\n\n8. **Challenges and Limitations**:\n - + Data privacy and security remain major concerns, especially with the collection + and use of personal data for AI training.\n - The high cost of AI implementation + and the need for specialized expertise can be barriers for smaller organizations.\n - + AI systems can sometimes produce biased or inaccurate results if not properly + trained and monitored.\n\n9. **Future Outlook**:\n - The integration of + AI with other emerging technologies such as blockchain, quantum computing, + and the Internet of Things (IoT) is expected to drive further innovation.\n - + AI will continue to play a central role in shaping industries and economies, + with increased focus on sustainability, efficiency, and human-centric design.\n\nIn + conclusion, the AI market is evolving rapidly, with transformative impacts + across multiple sectors. While challenges remain, the potential benefits of + AI adoption are substantial, and the trend is expected to continue in the + coming years.","role":"assistant"}}],"created":1771989482,"id":"chatcmpl-2baabfc6-ad79-9d05-9c83-41a1dcb308f1","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":882,"prompt_tokens":161,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":1043}}' + headers: + content-length: + - '5071' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:18:13 GMT + req-arrive-time: + - '1771989482808' + req-cost-time: + - '11306' + resp-start-time: + - '1771989494114' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '11306' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Research Analyst. + Expert researcher\nYour personal goal is: Conduct thorough research\nTo give + my best complete final answer to the task use the exact following format:\n\nThought: + I now can give a great answer\nFinal Answer: Your final answer must be the great + and the most complete as possible, it must be outcome described.\n\nI MUST use + these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent + Task: Analyze competitor strategies\n\nThis is the expect criteria for your + final answer: Competitor analysis\nyou MUST return the actual complete content + as the final answer, not a summary.\n\nThis is the context you''re working with:\nThe + AI market is experiencing rapid growth and transformation, driven by advancements + in technology, increasing demand for automation, and the need for data-driven + decision-making. Below is a comprehensive report on current AI market trends:\n\n1. + **Market Growth**: The global AI market is projected to grow significantly over + the next few years. According to recent reports, the market size was valued + at around $160 billion in 2023 and is expected to surpass $1.8 trillion by 2030, + with a compound annual growth rate (CAGR) of over 30%.\n\n2. **Sectoral Adoption**:\n - + **Healthcare**: AI is being widely adopted for diagnostics, personalized treatment, + drug discovery, and patient care. AI-powered imaging tools are improving diagnostic + accuracy, while predictive analytics help in managing chronic diseases.\n - + **Finance**: Financial institutions are leveraging AI for fraud detection, algorithmic + trading, customer service chatbots, and risk management. AI is also transforming + the lending industry through automated underwriting processes.\n - **Retail**: + Retailers are using AI for inventory management, personalized marketing, and + customer experience enhancement. AI-driven recommendation systems are becoming + increasingly sophisticated, leading to higher conversion rates.\n - **Manufacturing**: + AI is playing a crucial role in predictive maintenance, quality control, and + supply chain optimization. Smart factories are using AI to streamline production + and reduce downtime.\n\n3. **Technological Advancements**:\n - **Generative + AI**: The rise of large language models (LLMs) such as GPT-4, BERT, and others + has led to breakthroughs in natural language processing (NLP), content generation, + and conversational AI. These models are being integrated into various applications, + from customer service to creative writing.\n - **Computer Vision**: Advances + in computer vision have enabled better object recognition, facial recognition, + and autonomous vehicles. AI-powered cameras and sensors are being used in security, + surveillance, and smart cities.\n - **AI Ethics and Governance**: As AI becomes + more prevalent, there is a growing focus on ethical AI development, bias mitigation, + and regulatory compliance. Governments and organizations are working on frameworks + to ensure responsible AI deployment.\n\n4. **Investment and Funding**:\n - + Venture capital investment in AI startups has surged, with significant funding + going towards AI-driven healthcare, fintech, and enterprise software solutions.\n - + Tech giants such as Google, Microsoft, Amazon, and Meta are heavily investing + in AI research and development, creating new products and services that leverage + AI capabilities.\n\n5. **Workforce Impact**:\n - AI is reshaping the job market, + with some roles being automated while new opportunities emerge in AI development, + data science, and AI ethics.\n - Upskilling and reskilling programs are becoming + essential to prepare the workforce for an AI-driven economy.\n\n6. **Global + Competition**:\n - Countries like the United States, China, and the European + Union are competing to lead in AI innovation. China, in particular, is making + significant investments in AI infrastructure and talent development.\n - International + collaborations and partnerships are emerging to address common challenges in + AI research and application.\n\n7. **Consumer Adoption**:\n - Consumers are + increasingly adopting AI-powered devices and services, including smart assistants, + recommendation engines, and virtual reality experiences.\n - Personalization + is becoming a key differentiator in consumer products, with AI enabling tailored + user experiences across platforms.\n\n8. **Challenges and Limitations**:\n - + Data privacy and security remain major concerns, especially with the collection + and use of personal data for AI training.\n - The high cost of AI implementation + and the need for specialized expertise can be barriers for smaller organizations.\n - + AI systems can sometimes produce biased or inaccurate results if not properly + trained and monitored.\n\n9. **Future Outlook**:\n - The integration of AI + with other emerging technologies such as blockchain, quantum computing, and + the Internet of Things (IoT) is expected to drive further innovation.\n - + AI will continue to play a central role in shaping industries and economies, + with increased focus on sustainability, efficiency, and human-centric design.\n\nIn + conclusion, the AI market is evolving rapidly, with transformative impacts across + multiple sectors. While challenges remain, the potential benefits of AI adoption + are substantial, and the trend is expected to continue in the coming years.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '5580' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I now can give a great answer\nFinal Answer: Competitor analysis\n\nThe AI + market is experiencing rapid growth and transformation, driven by advancements + in technology, increasing demand for automation, and the need for data-driven + decision-making. Below is a comprehensive report on current AI market trends:\n\n1. + **Market Growth**: The global AI market is projected to grow significantly + over the next few years. According to recent reports, the market size was + valued at around $160 billion in 2023 and is expected to surpass $1.8 trillion + by 2030, with a compound annual growth rate (CAGR) of over 30%.\n\n2. **Sectoral + Adoption**:\n - **Healthcare**: AI is being widely adopted for diagnostics, + personalized treatment, drug discovery, and patient care. AI-powered imaging + tools are improving diagnostic accuracy, while predictive analytics help in + managing chronic diseases.\n - **Finance**: Financial institutions are leveraging + AI for fraud detection, algorithmic trading, customer service chatbots, and + risk management. AI is also transforming the lending industry through automated + underwriting processes.\n - **Retail**: Retailers are using AI for inventory + management, personalized marketing, and customer experience enhancement. AI-driven + recommendation systems are becoming increasingly sophisticated, leading to + higher conversion rates.\n - **Manufacturing**: AI is playing a crucial + role in predictive maintenance, quality control, and supply chain optimization. + Smart factories are using AI to streamline production and reduce downtime.\n\n3. + **Technological Advancements**:\n - **Generative AI**: The rise of large + language models (LLMs) such as GPT-4, BERT, and others has led to breakthroughs + in natural language processing (NLP), content generation, and conversational + AI. These models are being integrated into various applications, from customer + service to creative writing.\n - **Computer Vision**: Advances in computer + vision have enabled better object recognition, facial recognition, and autonomous + vehicles. AI-powered cameras and sensors are being used in security, surveillance, + and smart cities.\n - **AI Ethics and Governance**: As AI becomes more prevalent, + there is a growing focus on ethical AI development, bias mitigation, and regulatory + compliance. Governments and organizations are working on frameworks to ensure + responsible AI deployment.\n\n4. **Investment and Funding**:\n - Venture + capital investment in AI startups has surged, with significant funding going + towards AI-driven healthcare, fintech, and enterprise software solutions.\n - + Tech giants such as Google, Microsoft, Amazon, and Meta are heavily investing + in AI research and development, creating new products and services that leverage + AI capabilities.\n\n5. **Workforce Impact**:\n - AI is reshaping the job + market, with some roles being automated while new opportunities emerge in + AI development, data science, and AI ethics.\n - Upskilling and reskilling + programs are becoming essential to prepare the workforce for an AI-driven + economy.\n\n6. **Global Competition**:\n - Countries like the United States, + China, and the European Union are competing to lead in AI innovation. China, + in particular, is making significant investments in AI infrastructure and + talent development.\n - International collaborations and partnerships are + emerging to address common challenges in AI research and application.\n\n7. + **Consumer Adoption**:\n - Consumers are increasingly adopting AI-powered + devices and services, including smart assistants, recommendation engines, + and virtual reality experiences.\n - Personalization is becoming a key differentiator + in consumer products, with AI enabling tailored user experiences across platforms.\n\n8. + **Challenges and Limitations**:\n - Data privacy and security remain major + concerns, especially with the collection and use of personal data for AI training.\n - + The high cost of AI implementation and the need for specialized expertise + can be barriers for smaller organizations.\n - AI systems can sometimes + produce biased or inaccurate results if not properly trained and monitored.\n\n9. + **Future Outlook**:\n - The integration of AI with other emerging technologies + such as blockchain, quantum computing, and the Internet of Things (IoT) is + expected to drive further innovation.\n - AI will continue to play a central + role in shaping industries and economies, with increased focus on sustainability, + efficiency, and human-centric design.\n\nIn conclusion, the AI market is evolving + rapidly, with transformative impacts across multiple sectors. While challenges + remain, the potential benefits of AI adoption are substantial, and the trend + is expected to continue in the coming years.","role":"assistant"}}],"created":1771989494,"id":"chatcmpl-c7e149de-74eb-91c0-938d-da9d439d86ff","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":888,"prompt_tokens":1041,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":1929}}' + headers: + content-length: + - '5104' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:18:25 GMT + req-arrive-time: + - '1771989494513' + req-cost-time: + - '11828' + resp-start-time: + - '1771989506341' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '11773' + x-request-id: + - + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_tool_calls/TestToolCalls.test_agent_with_multiple_tools.yaml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_tool_calls/TestToolCalls.test_agent_with_multiple_tools.yaml new file mode 100644 index 000000000..3f0c98db7 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_tool_calls/TestToolCalls.test_agent_with_multiple_tools.yaml @@ -0,0 +1,689 @@ +interactions: +- request: + body: '{"messages": [{"role": "system", "content": "You are Multi-Tool Assistant. + Expert in using multiple tools\nYour personal goal is: Use various tools to + complete tasks\nYou ONLY have access to the following tools, and should NEVER + make up tools that are not listed here:\n\nTool Name: get_weather\nTool Arguments: + {''location'': {''description'': None, ''type'': ''str''}}\nTool Description: + Get current weather for a location\nTool Name: calculator\nTool Arguments: {''expression'': + {''description'': None, ''type'': ''str''}}\nTool Description: Perform mathematical + calculations\n\nUse the following format:\n\nThought: you should always think + about what to do\nAction: the action to take, only one name of [get_weather, + calculator], just the name, exactly as it''s written.\nAction Input: the input + to the action, just a simple python dictionary, enclosed in curly braces, using + \" to wrap keys and values.\nObservation: the result of the action\n\nOnce all + necessary information is gathered:\n\nThought: I now know the final answer\nFinal + Answer: the final answer to the original input question"}, {"role": "user", + "content": "\nCurrent Task: Get weather and calculate temperature difference\n\nThis + is the expect criteria for your final answer: Weather and calculation results\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '1520' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"I + need to get the current weather for a location and calculate the temperature + difference.\nAction: get_weather\nAction Input: {\"location\": \"New York\"}","role":"assistant"}}],"created":1771988288,"id":"chatcmpl-3c52caae-1ff9-9e34-bf0e-d39f80a5cc05","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":34,"prompt_tokens":301,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":335}}' + headers: + content-length: + - '485' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:58:08 GMT + req-arrive-time: + - '1771988288265' + req-cost-time: + - '602' + resp-start-time: + - '1771988288867' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '601' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Multi-Tool Assistant. + Expert in using multiple tools\nYour personal goal is: Use various tools to + complete tasks\nYou ONLY have access to the following tools, and should NEVER + make up tools that are not listed here:\n\nTool Name: get_weather\nTool Arguments: + {''location'': {''description'': None, ''type'': ''str''}}\nTool Description: + Get current weather for a location\nTool Name: calculator\nTool Arguments: {''expression'': + {''description'': None, ''type'': ''str''}}\nTool Description: Perform mathematical + calculations\n\nUse the following format:\n\nThought: you should always think + about what to do\nAction: the action to take, only one name of [get_weather, + calculator], just the name, exactly as it''s written.\nAction Input: the input + to the action, just a simple python dictionary, enclosed in curly braces, using + \" to wrap keys and values.\nObservation: the result of the action\n\nOnce all + necessary information is gathered:\n\nThought: I now know the final answer\nFinal + Answer: the final answer to the original input question"}, {"role": "user", + "content": "\nCurrent Task: Get weather and calculate temperature difference\n\nThis + is the expect criteria for your final answer: Weather and calculation results\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}, {"role": "assistant", "content": + "I need to get the current weather for a location and calculate the temperature + difference.\nAction: get_weather\nAction Input: {\"location\": \"New York\"}\nObservation: + Weather in New York: Sunny, 72\u00b0F"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '1757' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I need to calculate the temperature difference between New York and another + location.\nAction: get_weather\nAction Input: {\"location\": \"Los Angeles\"}","role":"assistant"}}],"created":1771988289,"id":"chatcmpl-60261994-163f-94ff-a805-9c1d218a5e43","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":34,"prompt_tokens":346,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":380}}' + headers: + content-length: + - '492' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:58:09 GMT + req-arrive-time: + - '1771988289150' + req-cost-time: + - '732' + resp-start-time: + - '1771988289882' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '731' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Multi-Tool Assistant. + Expert in using multiple tools\nYour personal goal is: Use various tools to + complete tasks\nYou ONLY have access to the following tools, and should NEVER + make up tools that are not listed here:\n\nTool Name: get_weather\nTool Arguments: + {''location'': {''description'': None, ''type'': ''str''}}\nTool Description: + Get current weather for a location\nTool Name: calculator\nTool Arguments: {''expression'': + {''description'': None, ''type'': ''str''}}\nTool Description: Perform mathematical + calculations\n\nUse the following format:\n\nThought: you should always think + about what to do\nAction: the action to take, only one name of [get_weather, + calculator], just the name, exactly as it''s written.\nAction Input: the input + to the action, just a simple python dictionary, enclosed in curly braces, using + \" to wrap keys and values.\nObservation: the result of the action\n\nOnce all + necessary information is gathered:\n\nThought: I now know the final answer\nFinal + Answer: the final answer to the original input question"}, {"role": "user", + "content": "\nCurrent Task: Get weather and calculate temperature difference\n\nThis + is the expect criteria for your final answer: Weather and calculation results\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}, {"role": "assistant", "content": + "I need to get the current weather for a location and calculate the temperature + difference.\nAction: get_weather\nAction Input: {\"location\": \"New York\"}\nObservation: + Weather in New York: Sunny, 72\u00b0F"}, {"role": "assistant", "content": "Thought: + I need to calculate the temperature difference between New York and another + location.\nAction: get_weather\nAction Input: {\"location\": \"Los Angeles\"}\nObservation: + Weather in Los Angeles: Sunny, 72\u00b0F"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '2004' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I need to calculate the temperature difference between New York and Los Angeles.\nAction: + calculator\nAction Input: {\"expression\": \"72 - 72\"}","role":"assistant"}}],"created":1771988290,"id":"chatcmpl-259d51a0-5250-946a-91d8-095ea8ef6b73","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":37,"prompt_tokens":392,"prompt_tokens_details":{"cached_tokens":256},"total_tokens":429}}' + headers: + content-length: + - '486' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:58:10 GMT + req-arrive-time: + - '1771988290078' + req-cost-time: + - '585' + resp-start-time: + - '1771988290663' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '583' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Multi-Tool Assistant. + Expert in using multiple tools\nYour personal goal is: Use various tools to + complete tasks\nYou ONLY have access to the following tools, and should NEVER + make up tools that are not listed here:\n\nTool Name: get_weather\nTool Arguments: + {''location'': {''description'': None, ''type'': ''str''}}\nTool Description: + Get current weather for a location\nTool Name: calculator\nTool Arguments: {''expression'': + {''description'': None, ''type'': ''str''}}\nTool Description: Perform mathematical + calculations\n\nUse the following format:\n\nThought: you should always think + about what to do\nAction: the action to take, only one name of [get_weather, + calculator], just the name, exactly as it''s written.\nAction Input: the input + to the action, just a simple python dictionary, enclosed in curly braces, using + \" to wrap keys and values.\nObservation: the result of the action\n\nOnce all + necessary information is gathered:\n\nThought: I now know the final answer\nFinal + Answer: the final answer to the original input question"}, {"role": "user", + "content": "\nCurrent Task: Get weather and calculate temperature difference\n\nThis + is the expect criteria for your final answer: Weather and calculation results\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}, {"role": "assistant", "content": + "I need to get the current weather for a location and calculate the temperature + difference.\nAction: get_weather\nAction Input: {\"location\": \"New York\"}\nObservation: + Weather in New York: Sunny, 72\u00b0F"}, {"role": "assistant", "content": "Thought: + I need to calculate the temperature difference between New York and another + location.\nAction: get_weather\nAction Input: {\"location\": \"Los Angeles\"}\nObservation: + Weather in Los Angeles: Sunny, 72\u00b0F"}, {"role": "assistant", "content": + "Thought: I need to calculate the temperature difference between New York and + Los Angeles.\nAction: calculator\nAction Input: {\"expression\": \"72 - 72\"}\nObservation: + Result: 0\n\n\nYou ONLY have access to the following tools, and should NEVER + make up tools that are not listed here:\n\nTool Name: get_weather\nTool Arguments: + {''location'': {''description'': None, ''type'': ''str''}}\nTool Description: + Get current weather for a location\nTool Name: calculator\nTool Arguments: {''expression'': + {''description'': None, ''type'': ''str''}}\nTool Description: Perform mathematical + calculations\n\nUse the following format:\n\nThought: you should always think + about what to do\nAction: the action to take, only one name of [get_weather, + calculator], just the name, exactly as it''s written.\nAction Input: the input + to the action, just a simple python dictionary, enclosed in curly braces, using + \" to wrap keys and values.\nObservation: the result of the action\n\nOnce all + necessary information is gathered:\n\nThought: I now know the final answer\nFinal + Answer: the final answer to the original input question"}], "model": "qwen-turbo", + "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '3134' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: "{\"choices\":[{\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"content\":\"Thought: + I now know the final answer\\nFinal Answer: Weather in New York: Sunny, 72\xB0F; + Weather in Los Angeles: Sunny, 72\xB0F; Temperature difference: 0\",\"role\":\"assistant\"}}],\"created\":1771988290,\"id\":\"chatcmpl-c0c8d0a6-b2fd-93ba-a39b-5369bb7f74d8\",\"model\":\"qwen-turbo\",\"object\":\"chat.completion\",\"usage\":{\"completion_tokens\":41,\"prompt_tokens\":625,\"prompt_tokens_details\":{\"cached_tokens\":0},\"total_tokens\":666}}" + headers: + content-length: + - '480' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:58:11 GMT + req-arrive-time: + - '1771988290861' + req-cost-time: + - '692' + resp-start-time: + - '1771988291554' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '691' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Multi-Tool Assistant. + Expert in using multiple tools\nYour personal goal is: Use various tools to + complete tasks\nYou ONLY have access to the following tools, and should NEVER + make up tools that are not listed here:\n\nTool Name: get_weather\nTool Arguments: + {''location'': {''description'': None, ''type'': ''str''}}\nTool Description: + Get current weather for a location\nTool Name: calculator\nTool Arguments: {''expression'': + {''description'': None, ''type'': ''str''}}\nTool Description: Perform mathematical + calculations\n\nUse the following format:\n\nThought: you should always think + about what to do\nAction: the action to take, only one name of [get_weather, + calculator], just the name, exactly as it''s written.\nAction Input: the input + to the action, just a simple python dictionary, enclosed in curly braces, using + \" to wrap keys and values.\nObservation: the result of the action\n\nOnce all + necessary information is gathered:\n\nThought: I now know the final answer\nFinal + Answer: the final answer to the original input question"}, {"role": "user", + "content": "\nCurrent Task: Get weather and calculate temperature difference\n\nThis + is the expect criteria for your final answer: Weather and calculation results\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '1520' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"I + need to get the weather for a location and calculate the temperature difference.\nAction: + get_weather\nAction Input: {\"location\": \"New York\"}","role":"assistant"}}],"created":1771989506,"id":"chatcmpl-d48f1b16-4581-9df1-842e-40b9d0b13b3c","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":33,"prompt_tokens":301,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":334}}' + headers: + content-length: + - '477' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:18:27 GMT + req-arrive-time: + - '1771989506707' + req-cost-time: + - '998' + resp-start-time: + - '1771989507706' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '998' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Multi-Tool Assistant. + Expert in using multiple tools\nYour personal goal is: Use various tools to + complete tasks\nYou ONLY have access to the following tools, and should NEVER + make up tools that are not listed here:\n\nTool Name: get_weather\nTool Arguments: + {''location'': {''description'': None, ''type'': ''str''}}\nTool Description: + Get current weather for a location\nTool Name: calculator\nTool Arguments: {''expression'': + {''description'': None, ''type'': ''str''}}\nTool Description: Perform mathematical + calculations\n\nUse the following format:\n\nThought: you should always think + about what to do\nAction: the action to take, only one name of [get_weather, + calculator], just the name, exactly as it''s written.\nAction Input: the input + to the action, just a simple python dictionary, enclosed in curly braces, using + \" to wrap keys and values.\nObservation: the result of the action\n\nOnce all + necessary information is gathered:\n\nThought: I now know the final answer\nFinal + Answer: the final answer to the original input question"}, {"role": "user", + "content": "\nCurrent Task: Get weather and calculate temperature difference\n\nThis + is the expect criteria for your final answer: Weather and calculation results\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}, {"role": "assistant", "content": + "I need to get the weather for a location and calculate the temperature difference.\nAction: + get_weather\nAction Input: {\"location\": \"New York\"}\nObservation: Weather + in New York: Sunny, 72\u00b0F"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '1749' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I need to calculate the temperature difference between New York and another + location.\nAction: get_weather\nAction Input: {\"location\": \"Los Angeles\"}","role":"assistant"}}],"created":1771989508,"id":"chatcmpl-425d7908-37cc-937c-94ce-a5d28a17c0a5","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":34,"prompt_tokens":345,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":379}}' + headers: + content-length: + - '492' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:18:28 GMT + req-arrive-time: + - '1771989507983' + req-cost-time: + - '711' + resp-start-time: + - '1771989508694' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '711' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Multi-Tool Assistant. + Expert in using multiple tools\nYour personal goal is: Use various tools to + complete tasks\nYou ONLY have access to the following tools, and should NEVER + make up tools that are not listed here:\n\nTool Name: get_weather\nTool Arguments: + {''location'': {''description'': None, ''type'': ''str''}}\nTool Description: + Get current weather for a location\nTool Name: calculator\nTool Arguments: {''expression'': + {''description'': None, ''type'': ''str''}}\nTool Description: Perform mathematical + calculations\n\nUse the following format:\n\nThought: you should always think + about what to do\nAction: the action to take, only one name of [get_weather, + calculator], just the name, exactly as it''s written.\nAction Input: the input + to the action, just a simple python dictionary, enclosed in curly braces, using + \" to wrap keys and values.\nObservation: the result of the action\n\nOnce all + necessary information is gathered:\n\nThought: I now know the final answer\nFinal + Answer: the final answer to the original input question"}, {"role": "user", + "content": "\nCurrent Task: Get weather and calculate temperature difference\n\nThis + is the expect criteria for your final answer: Weather and calculation results\nyou + MUST return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}, {"role": "assistant", "content": + "I need to get the weather for a location and calculate the temperature difference.\nAction: + get_weather\nAction Input: {\"location\": \"New York\"}\nObservation: Weather + in New York: Sunny, 72\u00b0F"}, {"role": "assistant", "content": "Thought: + I need to calculate the temperature difference between New York and another + location.\nAction: get_weather\nAction Input: {\"location\": \"Los Angeles\"}\nObservation: + Weather in Los Angeles: Sunny, 72\u00b0F"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '1996' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: "{\"choices\":[{\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"content\":\"Thought: + I now know the final answer\\nFinal Answer: Weather in New York: Sunny, 72\xB0F; + Weather in Los Angeles: Sunny, 72\xB0F; Temperature difference: 0\xB0F\",\"role\":\"assistant\"}}],\"created\":1771989508,\"id\":\"chatcmpl-b6e2951c-3765-9e4c-aad8-0d05898647a7\",\"model\":\"qwen-turbo\",\"object\":\"chat.completion\",\"usage\":{\"completion_tokens\":42,\"prompt_tokens\":391,\"prompt_tokens_details\":{\"cached_tokens\":0},\"total_tokens\":433}}" + headers: + content-length: + - '483' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:18:29 GMT + req-arrive-time: + - '1771989508877' + req-cost-time: + - '727' + resp-start-time: + - '1771989509605' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '727' + x-request-id: + - + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_tool_calls/TestToolCalls.test_agent_with_single_tool.yaml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_tool_calls/TestToolCalls.test_agent_with_single_tool.yaml new file mode 100644 index 000000000..1226c2e63 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_tool_calls/TestToolCalls.test_agent_with_single_tool.yaml @@ -0,0 +1,368 @@ +interactions: +- request: + body: '{"messages": [{"role": "system", "content": "You are Weather Assistant. + Expert in weather forecasting\nYour personal goal is: Provide weather information\nYou + ONLY have access to the following tools, and should NEVER make up tools that + are not listed here:\n\nTool Name: get_weather\nTool Arguments: {''location'': + {''description'': None, ''type'': ''str''}}\nTool Description: Get current weather + for a location\n\nUse the following format:\n\nThought: you should always think + about what to do\nAction: the action to take, only one name of [get_weather], + just the name, exactly as it''s written.\nAction Input: the input to the action, + just a simple python dictionary, enclosed in curly braces, using \" to wrap + keys and values.\nObservation: the result of the action\n\nOnce all necessary + information is gathered:\n\nThought: I now know the final answer\nFinal Answer: + the final answer to the original input question"}, {"role": "user", "content": + "\nCurrent Task: Get the weather for San Francisco\n\nThis is the expect criteria + for your final answer: Weather information\nyou MUST return the actual complete + content as the final answer, not a summary.\n\nBegin! This is VERY important + to you, use the tools available and give your best Final Answer, your job depends + on it!\n\nThought:"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '1323' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I need to get the current weather for San Francisco.\nAction: get_weather\nAction + Input: {\"location\": \"San Francisco\"}","role":"assistant"}}],"created":1771988291,"id":"chatcmpl-167ba67d-5015-9f8f-9638-a2709fdaf130","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":31,"prompt_tokens":262,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":293}}' + headers: + content-length: + - '461' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:58:12 GMT + req-arrive-time: + - '1771988291813' + req-cost-time: + - '498' + resp-start-time: + - '1771988292312' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '498' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Weather Assistant. + Expert in weather forecasting\nYour personal goal is: Provide weather information\nYou + ONLY have access to the following tools, and should NEVER make up tools that + are not listed here:\n\nTool Name: get_weather\nTool Arguments: {''location'': + {''description'': None, ''type'': ''str''}}\nTool Description: Get current weather + for a location\n\nUse the following format:\n\nThought: you should always think + about what to do\nAction: the action to take, only one name of [get_weather], + just the name, exactly as it''s written.\nAction Input: the input to the action, + just a simple python dictionary, enclosed in curly braces, using \" to wrap + keys and values.\nObservation: the result of the action\n\nOnce all necessary + information is gathered:\n\nThought: I now know the final answer\nFinal Answer: + the final answer to the original input question"}, {"role": "user", "content": + "\nCurrent Task: Get the weather for San Francisco\n\nThis is the expect criteria + for your final answer: Weather information\nyou MUST return the actual complete + content as the final answer, not a summary.\n\nBegin! This is VERY important + to you, use the tools available and give your best Final Answer, your job depends + on it!\n\nThought:"}, {"role": "assistant", "content": "Thought: I need to get + the current weather for San Francisco.\nAction: get_weather\nAction Input: {\"location\": + \"San Francisco\"}\nObservation: Weather in San Francisco: Sunny, 72\u00b0F"}], + "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '1541' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: "{\"choices\":[{\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"content\":\"Thought: + I now know the final answer\\nFinal Answer: Weather in San Francisco: Sunny, + 72\xB0F\",\"role\":\"assistant\"}}],\"created\":1771988292,\"id\":\"chatcmpl-7b290e6f-ce2f-9ad7-81cd-9b8320929738\",\"model\":\"qwen-turbo\",\"object\":\"chat.completion\",\"usage\":{\"completion_tokens\":23,\"prompt_tokens\":304,\"prompt_tokens_details\":{\"cached_tokens\":0},\"total_tokens\":327}}" + headers: + content-length: + - '420' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:58:12 GMT + req-arrive-time: + - '1771988292514' + req-cost-time: + - '436' + resp-start-time: + - '1771988292950' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '435' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Weather Assistant. + Expert in weather forecasting\nYour personal goal is: Provide weather information\nYou + ONLY have access to the following tools, and should NEVER make up tools that + are not listed here:\n\nTool Name: get_weather\nTool Arguments: {''location'': + {''description'': None, ''type'': ''str''}}\nTool Description: Get current weather + for a location\n\nUse the following format:\n\nThought: you should always think + about what to do\nAction: the action to take, only one name of [get_weather], + just the name, exactly as it''s written.\nAction Input: the input to the action, + just a simple python dictionary, enclosed in curly braces, using \" to wrap + keys and values.\nObservation: the result of the action\n\nOnce all necessary + information is gathered:\n\nThought: I now know the final answer\nFinal Answer: + the final answer to the original input question"}, {"role": "user", "content": + "\nCurrent Task: Get the weather for San Francisco\n\nThis is the expect criteria + for your final answer: Weather information\nyou MUST return the actual complete + content as the final answer, not a summary.\n\nBegin! This is VERY important + to you, use the tools available and give your best Final Answer, your job depends + on it!\n\nThought:"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '1323' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I need to get the current weather for San Francisco.\nAction: get_weather\nAction + Input: {\"location\": \"San Francisco\"}","role":"assistant"}}],"created":1771989509,"id":"chatcmpl-c568e4ec-0919-9950-b5c6-8fff56e62eb2","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":31,"prompt_tokens":262,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":293}}' + headers: + content-length: + - '461' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:18:30 GMT + req-arrive-time: + - '1771989509831' + req-cost-time: + - '676' + resp-start-time: + - '1771989510508' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '676' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Weather Assistant. + Expert in weather forecasting\nYour personal goal is: Provide weather information\nYou + ONLY have access to the following tools, and should NEVER make up tools that + are not listed here:\n\nTool Name: get_weather\nTool Arguments: {''location'': + {''description'': None, ''type'': ''str''}}\nTool Description: Get current weather + for a location\n\nUse the following format:\n\nThought: you should always think + about what to do\nAction: the action to take, only one name of [get_weather], + just the name, exactly as it''s written.\nAction Input: the input to the action, + just a simple python dictionary, enclosed in curly braces, using \" to wrap + keys and values.\nObservation: the result of the action\n\nOnce all necessary + information is gathered:\n\nThought: I now know the final answer\nFinal Answer: + the final answer to the original input question"}, {"role": "user", "content": + "\nCurrent Task: Get the weather for San Francisco\n\nThis is the expect criteria + for your final answer: Weather information\nyou MUST return the actual complete + content as the final answer, not a summary.\n\nBegin! This is VERY important + to you, use the tools available and give your best Final Answer, your job depends + on it!\n\nThought:"}, {"role": "assistant", "content": "Thought: I need to get + the current weather for San Francisco.\nAction: get_weather\nAction Input: {\"location\": + \"San Francisco\"}\nObservation: Weather in San Francisco: Sunny, 72\u00b0F"}], + "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '1541' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: "{\"choices\":[{\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"content\":\"Thought: + I now know the final answer\\nFinal Answer: Weather in San Francisco: Sunny, + 72\xB0F\",\"role\":\"assistant\"}}],\"created\":1771989510,\"id\":\"chatcmpl-df46a894-4df9-94ed-9673-10f5504e05d6\",\"model\":\"qwen-turbo\",\"object\":\"chat.completion\",\"usage\":{\"completion_tokens\":23,\"prompt_tokens\":304,\"prompt_tokens_details\":{\"cached_tokens\":0},\"total_tokens\":327}}" + headers: + content-length: + - '420' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:18:30 GMT + req-arrive-time: + - '1771989510695' + req-cost-time: + - '422' + resp-start-time: + - '1771989511117' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '422' + x-request-id: + - + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_tool_calls/TestToolCalls.test_tool_call_with_error.yaml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_tool_calls/TestToolCalls.test_tool_call_with_error.yaml new file mode 100644 index 000000000..ca3c4a45a --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/cassettes/test_tool_calls/TestToolCalls.test_tool_call_with_error.yaml @@ -0,0 +1,624 @@ +interactions: +- request: + body: '{"messages": [{"role": "system", "content": "You are Test Assistant. Test + agent\nYour personal goal is: Test error handling\nYou ONLY have access to the + following tools, and should NEVER make up tools that are not listed here:\n\nTool + Name: failing_tool\nTool Arguments: {''input_str'': {''description'': None, + ''type'': ''str''}}\nTool Description: A tool that always fails\n\nUse the following + format:\n\nThought: you should always think about what to do\nAction: the action + to take, only one name of [failing_tool], just the name, exactly as it''s written.\nAction + Input: the input to the action, just a simple python dictionary, enclosed in + curly braces, using \" to wrap keys and values.\nObservation: the result of + the action\n\nOnce all necessary information is gathered:\n\nThought: I now + know the final answer\nFinal Answer: the final answer to the original input + question"}, {"role": "user", "content": "\nCurrent Task: Use the failing tool\n\nThis + is the expect criteria for your final answer: Error handling result\nyou MUST + return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '1275' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"I + need to use the failing tool.\nAction: failing_tool\nAction Input: {\"input_str\": + \"test\"}","role":"assistant"}}],"created":1771988293,"id":"chatcmpl-c13cb06e-6af9-961f-992e-111220ba1725","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":26,"prompt_tokens":260,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":286}}' + headers: + content-length: + - '424' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:58:13 GMT + req-arrive-time: + - '1771988293155' + req-cost-time: + - '608' + resp-start-time: + - '1771988293764' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '608' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Test Assistant. Test + agent\nYour personal goal is: Test error handling\nYou ONLY have access to the + following tools, and should NEVER make up tools that are not listed here:\n\nTool + Name: failing_tool\nTool Arguments: {''input_str'': {''description'': None, + ''type'': ''str''}}\nTool Description: A tool that always fails\n\nUse the following + format:\n\nThought: you should always think about what to do\nAction: the action + to take, only one name of [failing_tool], just the name, exactly as it''s written.\nAction + Input: the input to the action, just a simple python dictionary, enclosed in + curly braces, using \" to wrap keys and values.\nObservation: the result of + the action\n\nOnce all necessary information is gathered:\n\nThought: I now + know the final answer\nFinal Answer: the final answer to the original input + question"}, {"role": "user", "content": "\nCurrent Task: Use the failing tool\n\nThis + is the expect criteria for your final answer: Error handling result\nyou MUST + return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}, {"role": "assistant", "content": + "I need to use the failing tool.\nAction: failing_tool\nAction Input: {\"input_str\": + \"test\"}\nObservation: \nI encountered an error while trying to use the tool. + This was the error: Tool execution failed.\n Tool failing_tool accepts these + inputs: Tool Name: failing_tool\nTool Arguments: {''input_str'': {''description'': + None, ''type'': ''str''}}\nTool Description: A tool that always fails.\nMoving + on then. I MUST either use a tool (use one at time) OR give my best final answer + not both at the same time. To Use the following format:\n\nThought: you should + always think about what to do\nAction: the action to take, should be one of + [failing_tool]\nAction Input: the input to the action, dictionary enclosed in + curly braces\nObservation: the result of the action\n... (this Thought/Action/Action + Input/Result can repeat N times)\nThought: I now can give a great answer\nFinal + Answer: Your final answer must be the great and the most complete as possible, + it must be outcome described"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '2290' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I need to use the failing tool again.\nAction: failing_tool\nAction Input: + {\"input_str\": \"another test\"}","role":"assistant"}}],"created":1771988294,"id":"chatcmpl-6d463a44-e3d4-93ac-84c9-38f42a4891f1","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":30,"prompt_tokens":481,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":511}}' + headers: + content-length: + - '447' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:58:14 GMT + req-arrive-time: + - '1771988294006' + req-cost-time: + - '570' + resp-start-time: + - '1771988294577' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '569' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Test Assistant. Test + agent\nYour personal goal is: Test error handling\nYou ONLY have access to the + following tools, and should NEVER make up tools that are not listed here:\n\nTool + Name: failing_tool\nTool Arguments: {''input_str'': {''description'': None, + ''type'': ''str''}}\nTool Description: A tool that always fails\n\nUse the following + format:\n\nThought: you should always think about what to do\nAction: the action + to take, only one name of [failing_tool], just the name, exactly as it''s written.\nAction + Input: the input to the action, just a simple python dictionary, enclosed in + curly braces, using \" to wrap keys and values.\nObservation: the result of + the action\n\nOnce all necessary information is gathered:\n\nThought: I now + know the final answer\nFinal Answer: the final answer to the original input + question"}, {"role": "user", "content": "\nCurrent Task: Use the failing tool\n\nThis + is the expect criteria for your final answer: Error handling result\nyou MUST + return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}, {"role": "assistant", "content": + "I need to use the failing tool.\nAction: failing_tool\nAction Input: {\"input_str\": + \"test\"}\nObservation: \nI encountered an error while trying to use the tool. + This was the error: Tool execution failed.\n Tool failing_tool accepts these + inputs: Tool Name: failing_tool\nTool Arguments: {''input_str'': {''description'': + None, ''type'': ''str''}}\nTool Description: A tool that always fails.\nMoving + on then. I MUST either use a tool (use one at time) OR give my best final answer + not both at the same time. To Use the following format:\n\nThought: you should + always think about what to do\nAction: the action to take, should be one of + [failing_tool]\nAction Input: the input to the action, dictionary enclosed in + curly braces\nObservation: the result of the action\n... (this Thought/Action/Action + Input/Result can repeat N times)\nThought: I now can give a great answer\nFinal + Answer: Your final answer must be the great and the most complete as possible, + it must be outcome described"}, {"role": "assistant", "content": "Thought: I + need to use the failing tool again.\nAction: failing_tool\nAction Input: {\"input_str\": + \"another test\"}\nObservation: \nI encountered an error while trying to use + the tool. This was the error: Tool execution failed.\n Tool failing_tool accepts + these inputs: Tool Name: failing_tool\nTool Arguments: {''input_str'': {''description'': + None, ''type'': ''str''}}\nTool Description: A tool that always fails.\nMoving + on then. I MUST either use a tool (use one at time) OR give my best final answer + not both at the same time. To Use the following format:\n\nThought: you should + always think about what to do\nAction: the action to take, should be one of + [failing_tool]\nAction Input: the input to the action, dictionary enclosed in + curly braces\nObservation: the result of the action\n... (this Thought/Action/Action + Input/Result can repeat N times)\nThought: I now can give a great answer\nFinal + Answer: Your final answer must be the great and the most complete as possible, + it must be outcome described"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '3328' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I now can give a great answer\nFinal Answer: Error handling result: The tool + \"failing_tool\" was used twice with different input strings (\"test\" and + \"another test\"). In both cases, the tool failed as expected. The error message + indicates that the tool execution failed, confirming its behavior of always + failing regardless of the input provided.","role":"assistant"}}],"created":1771988295,"id":"chatcmpl-6083da56-40e4-98ec-adad-c55916f2804f","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":71,"prompt_tokens":707,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":778}}' + headers: + content-length: + - '689' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 02:58:15 GMT + req-arrive-time: + - '1771988295192' + req-cost-time: + - '879' + resp-start-time: + - '1771988296072' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '877' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Test Assistant. Test + agent\nYour personal goal is: Test error handling\nYou ONLY have access to the + following tools, and should NEVER make up tools that are not listed here:\n\nTool + Name: failing_tool\nTool Arguments: {''input_str'': {''description'': None, + ''type'': ''str''}}\nTool Description: A tool that always fails\n\nUse the following + format:\n\nThought: you should always think about what to do\nAction: the action + to take, only one name of [failing_tool], just the name, exactly as it''s written.\nAction + Input: the input to the action, just a simple python dictionary, enclosed in + curly braces, using \" to wrap keys and values.\nObservation: the result of + the action\n\nOnce all necessary information is gathered:\n\nThought: I now + know the final answer\nFinal Answer: the final answer to the original input + question"}, {"role": "user", "content": "\nCurrent Task: Use the failing tool\n\nThis + is the expect criteria for your final answer: Error handling result\nyou MUST + return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}], "model": "qwen-turbo", "stop": + ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '1275' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"I + need to use the failing tool.\nAction: failing_tool\nAction Input: {\"input_str\": + \"test\"}","role":"assistant"}}],"created":1771989511,"id":"chatcmpl-9d8c563c-5488-967c-baef-85454cd7f0e0","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":26,"prompt_tokens":260,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":286}}' + headers: + content-length: + - '424' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:18:31 GMT + req-arrive-time: + - '1771989511340' + req-cost-time: + - '527' + resp-start-time: + - '1771989511867' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '527' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Test Assistant. Test + agent\nYour personal goal is: Test error handling\nYou ONLY have access to the + following tools, and should NEVER make up tools that are not listed here:\n\nTool + Name: failing_tool\nTool Arguments: {''input_str'': {''description'': None, + ''type'': ''str''}}\nTool Description: A tool that always fails\n\nUse the following + format:\n\nThought: you should always think about what to do\nAction: the action + to take, only one name of [failing_tool], just the name, exactly as it''s written.\nAction + Input: the input to the action, just a simple python dictionary, enclosed in + curly braces, using \" to wrap keys and values.\nObservation: the result of + the action\n\nOnce all necessary information is gathered:\n\nThought: I now + know the final answer\nFinal Answer: the final answer to the original input + question"}, {"role": "user", "content": "\nCurrent Task: Use the failing tool\n\nThis + is the expect criteria for your final answer: Error handling result\nyou MUST + return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}, {"role": "assistant", "content": + "I need to use the failing tool.\nAction: failing_tool\nAction Input: {\"input_str\": + \"test\"}\nObservation: \nI encountered an error while trying to use the tool. + This was the error: Tool execution failed.\n Tool failing_tool accepts these + inputs: Tool Name: failing_tool\nTool Arguments: {''input_str'': {''description'': + None, ''type'': ''str''}}\nTool Description: A tool that always fails.\nMoving + on then. I MUST either use a tool (use one at time) OR give my best final answer + not both at the same time. To Use the following format:\n\nThought: you should + always think about what to do\nAction: the action to take, should be one of + [failing_tool]\nAction Input: the input to the action, dictionary enclosed in + curly braces\nObservation: the result of the action\n... (this Thought/Action/Action + Input/Result can repeat N times)\nThought: I now can give a great answer\nFinal + Answer: Your final answer must be the great and the most complete as possible, + it must be outcome described"}], "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '2290' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I need to use the failing tool again to ensure error handling is properly + tested.\nAction: failing_tool\nAction Input: {\"input_str\": \"another test\"}","role":"assistant"}}],"created":1771989512,"id":"chatcmpl-2ed0fd81-92c6-9042-947e-6d08ced3b105","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":37,"prompt_tokens":481,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":518}}' + headers: + content-length: + - '491' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:18:32 GMT + req-arrive-time: + - '1771989512075' + req-cost-time: + - '548' + resp-start-time: + - '1771989512623' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '548' + x-request-id: + - + status: + code: 200 + message: OK +- request: + body: '{"messages": [{"role": "system", "content": "You are Test Assistant. Test + agent\nYour personal goal is: Test error handling\nYou ONLY have access to the + following tools, and should NEVER make up tools that are not listed here:\n\nTool + Name: failing_tool\nTool Arguments: {''input_str'': {''description'': None, + ''type'': ''str''}}\nTool Description: A tool that always fails\n\nUse the following + format:\n\nThought: you should always think about what to do\nAction: the action + to take, only one name of [failing_tool], just the name, exactly as it''s written.\nAction + Input: the input to the action, just a simple python dictionary, enclosed in + curly braces, using \" to wrap keys and values.\nObservation: the result of + the action\n\nOnce all necessary information is gathered:\n\nThought: I now + know the final answer\nFinal Answer: the final answer to the original input + question"}, {"role": "user", "content": "\nCurrent Task: Use the failing tool\n\nThis + is the expect criteria for your final answer: Error handling result\nyou MUST + return the actual complete content as the final answer, not a summary.\n\nBegin! + This is VERY important to you, use the tools available and give your best Final + Answer, your job depends on it!\n\nThought:"}, {"role": "assistant", "content": + "I need to use the failing tool.\nAction: failing_tool\nAction Input: {\"input_str\": + \"test\"}\nObservation: \nI encountered an error while trying to use the tool. + This was the error: Tool execution failed.\n Tool failing_tool accepts these + inputs: Tool Name: failing_tool\nTool Arguments: {''input_str'': {''description'': + None, ''type'': ''str''}}\nTool Description: A tool that always fails.\nMoving + on then. I MUST either use a tool (use one at time) OR give my best final answer + not both at the same time. To Use the following format:\n\nThought: you should + always think about what to do\nAction: the action to take, should be one of + [failing_tool]\nAction Input: the input to the action, dictionary enclosed in + curly braces\nObservation: the result of the action\n... (this Thought/Action/Action + Input/Result can repeat N times)\nThought: I now can give a great answer\nFinal + Answer: Your final answer must be the great and the most complete as possible, + it must be outcome described"}, {"role": "assistant", "content": "Thought: I + need to use the failing tool again to ensure error handling is properly tested.\nAction: + failing_tool\nAction Input: {\"input_str\": \"another test\"}\nObservation: + \nI encountered an error while trying to use the tool. This was the error: Tool + execution failed.\n Tool failing_tool accepts these inputs: Tool Name: failing_tool\nTool + Arguments: {''input_str'': {''description'': None, ''type'': ''str''}}\nTool + Description: A tool that always fails.\nMoving on then. I MUST either use a + tool (use one at time) OR give my best final answer not both at the same time. + To Use the following format:\n\nThought: you should always think about what + to do\nAction: the action to take, should be one of [failing_tool]\nAction Input: + the input to the action, dictionary enclosed in curly braces\nObservation: the + result of the action\n... (this Thought/Action/Action Input/Result can repeat + N times)\nThought: I now can give a great answer\nFinal Answer: Your final answer + must be the great and the most complete as possible, it must be outcome described"}], + "model": "qwen-turbo", "stop": ["\nObservation:"]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate, zstd + Connection: + - keep-alive + Content-Length: + - '3372' + Content-Type: + - application/json + Host: + - dashscope.aliyuncs.com + User-Agent: + - OpenAI/Python 2.0.0 + X-Stainless-Arch: + - arm64 + X-Stainless-Async: + - 'false' + X-Stainless-Lang: + - python + X-Stainless-OS: + - MacOS + X-Stainless-Package-Version: + - 2.0.0 + X-Stainless-Raw-Response: + - 'true' + X-Stainless-Runtime: + - CPython + X-Stainless-Runtime-Version: + - 3.11.0 + authorization: + - Bearer + x-stainless-read-timeout: + - '600.0' + x-stainless-retry-count: + - '0' + method: POST + uri: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions + response: + body: + string: '{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Thought: + I now can give a great answer\nFinal Answer: Error handling result: The failing + tool was used twice with different input strings (\"test\" and \"another test\"). + Each time, the tool failed as expected, returning the error message \"Tool + execution failed.\" This confirms that the error handling for the failing + tool is functioning correctly. The tool consistently rejects all inputs, as + described in its documentation. No further action is required.","role":"assistant"}}],"created":1771989512,"id":"chatcmpl-39db412b-acae-9153-ab0e-b56ddeb2e54d","model":"qwen-turbo","object":"chat.completion","usage":{"completion_tokens":86,"prompt_tokens":714,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":800}}' + headers: + content-length: + - '788' + content-type: + - application/json + date: + - Wed, 25 Feb 2026 03:18:33 GMT + req-arrive-time: + - '1771989512809' + req-cost-time: + - '1227' + resp-start-time: + - '1771989514037' + server: + - istio-envoy + transfer-encoding: + - chunked + vary: + - Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding + x-dashscope-call-gateway: + - 'true' + x-envoy-upstream-service-time: + - '1227' + x-request-id: + - + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/conftest.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/conftest.py new file mode 100644 index 000000000..7f2e67f20 --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/conftest.py @@ -0,0 +1,51 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pytest + + +def scrub_response_headers(response): + """Clean up common sensitive response headers before recording.""" + headers = response.get("headers", {}) + for secret_header in [ + "Set-Cookie", + "x-request-id", + "x-amz-request-id", + "x-goog-hash", + ]: + if secret_header in headers: + headers[secret_header] = [""] + return response + + +@pytest.fixture(scope="module") +def vcr_config(): + """VCR configuration to mask API keys and sensitive information.""" + return { + "filter_headers": [ + ("authorization", "Bearer "), + ("api-key", ""), + ("api_key", ""), + ("x-api-key", ""), + ("cookie", ""), + ], + "filter_query_parameters": [ + ("api_key", ""), + ], + "filter_post_data_parameters": [ + ("api_key", ""), + ], + "before_record_response": scrub_response_headers, + "decode_compressed_response": True, + } diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_agent_workflow.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_agent_workflow.py index 124393f9c..f9df5cdb7 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_agent_workflow.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_agent_workflow.py @@ -24,6 +24,7 @@ import sys import pysqlite3 +import pytest from crewai import Agent, Crew, Process, Task from opentelemetry.instrumentation.crewai import CrewAIInstrumentor @@ -43,6 +44,7 @@ sys.modules["sqlite3"] = pysqlite3 +@pytest.mark.vcr class TestAgentWorkflow(TestBase): """Test Agent workflow orchestration scenarios.""" diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_error_scenarios.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_error_scenarios.py index b3db76100..fced55710 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_error_scenarios.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_error_scenarios.py @@ -28,6 +28,7 @@ import sys import pysqlite3 +import pytest from crewai import Agent, Crew, Task from opentelemetry.instrumentation.crewai import CrewAIInstrumentor @@ -48,6 +49,7 @@ sys.modules["sqlite3"] = pysqlite3 +@pytest.mark.vcr class TestErrorScenarios(TestBase): """Test error handling scenarios.""" diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_prompt_and_memory.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_prompt_and_memory.py index 7f6bb8ead..5d755d6b6 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_prompt_and_memory.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_prompt_and_memory.py @@ -26,6 +26,7 @@ import sys import pysqlite3 +import pytest from crewai import Agent, Crew, Task from opentelemetry.instrumentation.crewai import CrewAIInstrumentor @@ -45,6 +46,7 @@ sys.modules["sqlite3"] = pysqlite3 +@pytest.mark.vcr class TestPromptAndMemory(TestBase): """Test prompt management and memory scenarios.""" diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_streaming_llm_calls.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_streaming_llm_calls.py index 3c47c3e30..28312f24e 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_streaming_llm_calls.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_streaming_llm_calls.py @@ -26,6 +26,7 @@ import sys import pysqlite3 +import pytest from crewai import Agent, Crew, Task from opentelemetry.instrumentation.crewai import CrewAIInstrumentor @@ -46,6 +47,7 @@ sys.modules["sqlite3"] = pysqlite3 +@pytest.mark.vcr class TestStreamingLLMCalls(TestBase): """Test streaming LLM call scenarios.""" diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_sync_llm_calls.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_sync_llm_calls.py index be596d048..837176ebf 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_sync_llm_calls.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_sync_llm_calls.py @@ -27,6 +27,7 @@ import sys import pysqlite3 +import pytest from crewai import Agent, Crew, Task from opentelemetry.instrumentation.crewai import CrewAIInstrumentor @@ -47,6 +48,7 @@ sys.modules["sqlite3"] = pysqlite3 +@pytest.mark.vcr class TestSyncLLMCalls(TestBase): """Test synchronous LLM call scenarios.""" diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py index 2e022433d..50f7bbbc7 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/test_tool_calls.py @@ -29,6 +29,7 @@ import sys import pysqlite3 +import pytest from crewai import Agent, Crew, Task from crewai.tools.base_tool import BaseTool @@ -101,6 +102,7 @@ def safe_eval(node): return f"Error: {str(e)}" +@pytest.mark.vcr class TestToolCalls(TestBase): """Test tool call scenarios.""" From 4dd5138b12114862b6455bae2fbcbeb8e42799dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=8E=E7=9B=B4?= Date: Wed, 25 Feb 2026 11:53:11 +0800 Subject: [PATCH 10/14] Supplement missing test dependencies. --- .../loongsuite-instrumentation-crewai/test-requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt index 0a2253061..4d05ae368 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/test-requirements.txt @@ -4,6 +4,7 @@ openai>=2.0.0 respx>=0.20.0 pysqlite3 vcrpy>=6.0.0 +opentelemetry-test-utils pytest-recording>=0.13.0 -e util/opentelemetry-util-http -e util/opentelemetry-util-genai From d738c3ca1f26e25372d2364fe26c4a34f78587a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=8E=E7=9B=B4?= Date: Fri, 27 Feb 2026 16:57:32 +0800 Subject: [PATCH 11/14] Set the genai.span.kind extended attribute. --- .../src/opentelemetry/instrumentation/crewai/__init__.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py index c0586f006..7d7fd5e34 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/__init__.py @@ -41,6 +41,9 @@ from opentelemetry.instrumentation.utils import unwrap from opentelemetry.semconv._incubating.attributes import gen_ai_attributes from opentelemetry.trace import SpanKind, Status, StatusCode +from opentelemetry.util.genai._extended_semconv import ( + gen_ai_extended_attributes, +) try: import crewai.agent @@ -166,6 +169,7 @@ def __call__(self, wrapped, instance, args, kwargs): attributes={ gen_ai_attributes.GEN_AI_OPERATION_NAME: OP_NAME_CREW, gen_ai_attributes.GEN_AI_SYSTEM: "crewai", + gen_ai_extended_attributes.GEN_AI_SPAN_KIND: gen_ai_extended_attributes.GenAiSpanKindValues.AGENT.value, }, ) as span: try: @@ -206,6 +210,7 @@ async def __call__(self, wrapped, instance, args, kwargs): attributes={ gen_ai_attributes.GEN_AI_OPERATION_NAME: OP_NAME_CREW, gen_ai_attributes.GEN_AI_SYSTEM: "crewai", + gen_ai_extended_attributes.GEN_AI_SPAN_KIND: gen_ai_extended_attributes.GenAiSpanKindValues.AGENT.value, }, ) as span: try: @@ -246,6 +251,7 @@ def __call__(self, wrapped, instance, args, kwargs): gen_ai_attributes.GEN_AI_OPERATION_NAME: OP_NAME_AGENT, gen_ai_attributes.GEN_AI_SYSTEM: "crewai", "gen_ai.agent.name": agent_role, + gen_ai_extended_attributes.GEN_AI_SPAN_KIND: gen_ai_extended_attributes.GenAiSpanKindValues.AGENT.value, }, ) as span: try: @@ -283,6 +289,7 @@ def __call__(self, wrapped, instance, args, kwargs): attributes={ gen_ai_attributes.GEN_AI_OPERATION_NAME: OP_NAME_TASK, gen_ai_attributes.GEN_AI_SYSTEM: "crewai", + gen_ai_extended_attributes.GEN_AI_SPAN_KIND: gen_ai_extended_attributes.GenAiSpanKindValues.AGENT.value, }, ) as span: try: @@ -325,6 +332,7 @@ def __call__(self, wrapped, instance, args, kwargs): gen_ai_attributes.GEN_AI_OPERATION_NAME: OP_NAME_TOOL, gen_ai_attributes.GEN_AI_SYSTEM: "crewai", gen_ai_attributes.GEN_AI_TOOL_NAME: tool_name, + gen_ai_extended_attributes.GEN_AI_SPAN_KIND: gen_ai_extended_attributes.GenAiSpanKindValues.TOOL.value, }, ) as span: # Set tool description From f782e367f56f67456b59b03de306b076c7d700b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=8E=E7=9B=B4?= Date: Mon, 2 Mar 2026 10:36:51 +0800 Subject: [PATCH 12/14] Modify the version of genai-util as a dependency. --- .../loongsuite-instrumentation-crewai/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml index f2a0c4c6b..4f3dd5b2b 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/pyproject.toml @@ -26,7 +26,7 @@ dependencies = [ "opentelemetry-instrumentation ~= 0.60b0", "opentelemetry-semantic-conventions ~= 0.60b0", "wrapt >= 1.0.0, < 2.0.0", - "opentelemetry-util-genai >= 0.3b0.dev0, == 0.3.*", + "opentelemetry-util-genai >= 0.3b0.dev0", ] [project.optional-dependencies] From be96b92ae0a811153c1cc791abc887628deaa9c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=8E=E7=9B=B4?= Date: Mon, 2 Mar 2026 10:43:59 +0800 Subject: [PATCH 13/14] Fix missing license header --- .../opentelemetry/instrumentation/crewai/utils.py | 14 ++++++++++++++ .../tests/__init__.py | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py index bb1528996..dc931464c 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/utils.py @@ -1,3 +1,17 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import dataclasses import logging from typing import Any, Dict, List, Optional diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/__init__.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/__init__.py index e69de29bb..f87ce79b7 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/__init__.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/tests/__init__.py @@ -0,0 +1,14 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + From 42e177a8c4dcf2c9d52385bf5fab0ab3d744cdba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=8E=E7=9B=B4?= Date: Thu, 5 Mar 2026 11:57:34 +0800 Subject: [PATCH 14/14] 1 This LISENSE file has been removed; 2 The CHANGELOG.md file has been added; 3 Metric is not supported. --- .../CHANGED.md | 17 ++ .../loongsuite-instrumentation-crewai/LICENSE | 201 ------------------ .../instrumentation/crewai/package.py | 2 +- 3 files changed, 18 insertions(+), 202 deletions(-) create mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/CHANGED.md delete mode 100644 instrumentation-loongsuite/loongsuite-instrumentation-crewai/LICENSE diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/CHANGED.md b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/CHANGED.md new file mode 100644 index 000000000..5eb995afd --- /dev/null +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/CHANGED.md @@ -0,0 +1,17 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Unreleased + +## Version 0.1.0 (2026-03-05) + + + +### Added + +- Initialize the instrumentation for CrewAI + ([#87](https://github.com/alibaba/loongsuite-python-agent/pull/87)) diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/LICENSE b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/package.py b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/package.py index a250f595d..a6e9796ff 100644 --- a/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/package.py +++ b/instrumentation-loongsuite/loongsuite-instrumentation-crewai/src/opentelemetry/instrumentation/crewai/package.py @@ -14,4 +14,4 @@ _instruments = ("crewai >= 0.70.0",) -_supports_metrics = True +_supports_metrics = False