Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion agentops/instrumentation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def get_instance(self) -> BaseInstrumentor:
provider_import_name="anthropic",
),
InstrumentorLoader(
module_name="opentelemetry.instrumentation.crewai",
module_name="agentops.instrumentation.crewai",
class_name="CrewAIInstrumentor",
provider_import_name="crewai",
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,4 +198,4 @@
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.
limitations under the License.
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ Copyright notice from the original project:
Copyright (c) Traceloop (https://traceloop.com)

The Apache 2.0 license can be found in the LICENSE file in this directory.

This code has been modified and adapted for use in the AgentOps project.
6 changes: 6 additions & 0 deletions agentops/instrumentation/crewai/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""OpenTelemetry CrewAI instrumentation"""

from agentops.instrumentation.crewai.version import __version__
from agentops.instrumentation.crewai.instrumentation import CrewAIInstrumentor

Check warning on line 4 in agentops/instrumentation/crewai/__init__.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/__init__.py#L3-L4

Added lines #L3 - L4 were not covered by tests

__all__ = ["CrewAIInstrumentor", "__version__"]

Check warning on line 6 in agentops/instrumentation/crewai/__init__.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/__init__.py#L6

Added line #L6 was not covered by tests
330 changes: 330 additions & 0 deletions agentops/instrumentation/crewai/crewai_span_attributes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,330 @@
"""OpenTelemetry instrumentation for CrewAI."""

import json
import logging
from typing import Any
from opentelemetry.trace import Span

Check warning on line 6 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L3-L6

Added lines #L3 - L6 were not covered by tests

from agentops.semconv.span_attributes import SpanAttributes
from agentops.semconv.agent import AgentAttributes
from agentops.semconv.tool import ToolAttributes
from agentops.semconv.message import MessageAttributes

Check warning on line 11 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L8-L11

Added lines #L8 - L11 were not covered by tests

# Initialize logger for logging potential issues and operations
logger = logging.getLogger(__name__)

Check warning on line 14 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L14

Added line #L14 was not covered by tests

def _parse_tools(tools):

Check warning on line 16 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L16

Added line #L16 was not covered by tests
"""Parse tools into a JSON string with name and description."""
result = []
for tool in tools:
res = {}
if hasattr(tool, "name") and tool.name is not None:
res["name"] = tool.name
if hasattr(tool, "description") and tool.description is not None:
res["description"] = tool.description
if res:
result.append(res)
return result

Check warning on line 27 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L18-L27

Added lines #L18 - L27 were not covered by tests

def set_span_attribute(span: Span, key: str, value: Any) -> None:

Check warning on line 29 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L29

Added line #L29 was not covered by tests
"""Set a single attribute on a span."""
if value is not None and value != "":
if hasattr(value, "__str__"):
value = str(value)
span.set_attribute(key, value)

Check warning on line 34 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L31-L34

Added lines #L31 - L34 were not covered by tests


class CrewAISpanAttributes:

Check warning on line 37 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L37

Added line #L37 was not covered by tests
"""Manages span attributes for CrewAI instrumentation."""

def __init__(self, span: Span, instance, skip_agent_processing=False) -> None:
self.span = span
self.instance = instance
self.skip_agent_processing = skip_agent_processing
self.process_instance()

Check warning on line 44 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L40-L44

Added lines #L40 - L44 were not covered by tests

def process_instance(self):

Check warning on line 46 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L46

Added line #L46 was not covered by tests
"""Process the instance based on its type."""
instance_type = self.instance.__class__.__name__
self._set_attribute(SpanAttributes.LLM_SYSTEM, "crewai")
self._set_attribute(SpanAttributes.AGENTOPS_ENTITY_NAME, instance_type)

Check warning on line 50 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L48-L50

Added lines #L48 - L50 were not covered by tests

method_mapping = {

Check warning on line 52 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L52

Added line #L52 was not covered by tests
"Crew": self._process_crew,
"Agent": self._process_agent,
"Task": self._process_task,
"LLM": self._process_llm,
}
method = method_mapping.get(instance_type)
if method:
method()

Check warning on line 60 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L58-L60

Added lines #L58 - L60 were not covered by tests

def _process_crew(self):

Check warning on line 62 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L62

Added line #L62 was not covered by tests
"""Process a Crew instance."""
crew_id = getattr(self.instance, "id", "")
self._set_attribute("crewai.crew.id", str(crew_id))
self._set_attribute("crewai.crew.type", "crewai.crew")
self._set_attribute(SpanAttributes.AGENTOPS_SPAN_KIND, "workflow")

Check warning on line 67 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L64-L67

Added lines #L64 - L67 were not covered by tests

logger.debug(f"CrewAI: Processing crew with id {crew_id}")

Check warning on line 69 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L69

Added line #L69 was not covered by tests

for key, value in self.instance.__dict__.items():
if value is None:
continue

Check warning on line 73 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L71-L73

Added lines #L71 - L73 were not covered by tests

if key == "tasks":
if isinstance(value, list):
self._set_attribute("crewai.crew.max_turns", str(len(value)))
logger.debug(f"CrewAI: Found {len(value)} tasks")
elif key == "agents":
if isinstance(value, list):
logger.debug(f"CrewAI: Found {len(value)} agents in crew")

Check warning on line 81 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L75-L81

Added lines #L75 - L81 were not covered by tests

if not self.skip_agent_processing:
self._parse_agents(value)
elif key == "llms":
self._parse_llms(value)
elif key == "result":
self._set_attribute("crewai.crew.final_output", str(value))
self._set_attribute("crewai.crew.output", str(value))
self._set_attribute(SpanAttributes.AGENTOPS_ENTITY_OUTPUT, str(value))

Check warning on line 90 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L83-L90

Added lines #L83 - L90 were not covered by tests
else:
self._set_attribute(f"crewai.crew.{key}", str(value))

Check warning on line 92 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L92

Added line #L92 was not covered by tests

def _process_agent(self):

Check warning on line 94 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L94

Added line #L94 was not covered by tests
"""Process an Agent instance."""
agent = {}
self._set_attribute(SpanAttributes.AGENTOPS_SPAN_KIND, "agent")

Check warning on line 97 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L96-L97

Added lines #L96 - L97 were not covered by tests

for key, value in self.instance.__dict__.items():
if key == "tools":
parsed_tools = _parse_tools(value)
for i, tool in enumerate(parsed_tools):
tool_prefix = f"crewai.agent.tool.{i}."
for tool_key, tool_value in tool.items():
self._set_attribute(f"{tool_prefix}{tool_key}", str(tool_value))

Check warning on line 105 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L99-L105

Added lines #L99 - L105 were not covered by tests

agent[key] = json.dumps(parsed_tools)

Check warning on line 107 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L107

Added line #L107 was not covered by tests

if value is None:
continue

Check warning on line 110 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L109-L110

Added lines #L109 - L110 were not covered by tests

if key != "tools":
agent[key] = str(value)

Check warning on line 113 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L112-L113

Added lines #L112 - L113 were not covered by tests

self._set_attribute(AgentAttributes.AGENT_ID, agent.get('id', ''))
self._set_attribute(AgentAttributes.AGENT_ROLE, agent.get('role', ''))
self._set_attribute(AgentAttributes.AGENT_NAME, agent.get('name', ''))
self._set_attribute(AgentAttributes.AGENT_TOOLS, agent.get('tools', ''))

Check warning on line 118 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L115-L118

Added lines #L115 - L118 were not covered by tests

if 'reasoning' in agent:
self._set_attribute(AgentAttributes.AGENT_REASONING, agent.get('reasoning', ''))

Check warning on line 121 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L120-L121

Added lines #L120 - L121 were not covered by tests

if 'goal' in agent:
self._set_attribute(SpanAttributes.AGENTOPS_ENTITY_INPUT, agent.get('goal', ''))

Check warning on line 124 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L123-L124

Added lines #L123 - L124 were not covered by tests

self._set_attribute("crewai.agent.goal", agent.get('goal', ''))
self._set_attribute("crewai.agent.backstory", agent.get('backstory', ''))
self._set_attribute("crewai.agent.cache", agent.get('cache', ''))
self._set_attribute("crewai.agent.allow_delegation", agent.get('allow_delegation', ''))
self._set_attribute("crewai.agent.allow_code_execution", agent.get('allow_code_execution', ''))
self._set_attribute("crewai.agent.max_retry_limit", agent.get('max_retry_limit', ''))

Check warning on line 131 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L126-L131

Added lines #L126 - L131 were not covered by tests

if hasattr(self.instance, "llm") and self.instance.llm is not None:
model_name = getattr(self.instance.llm, "model", None) or getattr(self.instance.llm, "model_name", None) or ""
temp = getattr(self.instance.llm, "temperature", None)
max_tokens = getattr(self.instance.llm, "max_tokens", None)
top_p = getattr(self.instance.llm, "top_p", None)

Check warning on line 137 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L133-L137

Added lines #L133 - L137 were not covered by tests

self._set_attribute(SpanAttributes.LLM_REQUEST_MODEL, model_name)
if temp is not None:
self._set_attribute(SpanAttributes.LLM_REQUEST_TEMPERATURE, str(temp))
if max_tokens is not None:
self._set_attribute(SpanAttributes.LLM_REQUEST_MAX_TOKENS, str(max_tokens))
if top_p is not None:
self._set_attribute(SpanAttributes.LLM_REQUEST_TOP_P, str(top_p))

Check warning on line 145 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L139-L145

Added lines #L139 - L145 were not covered by tests

self._set_attribute("crewai.agent.llm", str(model_name))
self._set_attribute(AgentAttributes.AGENT_MODELS, str(model_name))

Check warning on line 148 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L147-L148

Added lines #L147 - L148 were not covered by tests

def _process_task(self):

Check warning on line 150 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L150

Added line #L150 was not covered by tests
"""Process a Task instance."""
task = {}
self._set_attribute(SpanAttributes.AGENTOPS_SPAN_KIND, "workflow.step")

Check warning on line 153 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L152-L153

Added lines #L152 - L153 were not covered by tests

for key, value in self.instance.__dict__.items():
if value is None:
continue
if key == "tools":
parsed_tools = _parse_tools(value)
for i, tool in enumerate(parsed_tools):
tool_prefix = f"crewai.task.tool.{i}."
for tool_key, tool_value in tool.items():
self._set_attribute(f"{tool_prefix}{tool_key}", str(tool_value))

Check warning on line 163 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L155-L163

Added lines #L155 - L163 were not covered by tests

task[key] = json.dumps(parsed_tools)

Check warning on line 165 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L165

Added line #L165 was not covered by tests

elif key == "agent":
task[key] = value.role if value else None
if value:
agent_id = getattr(value, "id", "")
self._set_attribute(AgentAttributes.FROM_AGENT, str(agent_id))

Check warning on line 171 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L167-L171

Added lines #L167 - L171 were not covered by tests
else:
task[key] = str(value)

Check warning on line 173 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L173

Added line #L173 was not covered by tests

self._set_attribute("crewai.task.name", task.get('description', ''))
self._set_attribute("crewai.task.type", "task")
self._set_attribute("crewai.task.input", task.get('context', ''))
self._set_attribute("crewai.task.expected_output", task.get('expected_output', ''))

Check warning on line 178 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L175-L178

Added lines #L175 - L178 were not covered by tests

if 'description' in task:
self._set_attribute(SpanAttributes.AGENTOPS_ENTITY_INPUT, task.get('description', ''))
if 'output' in task:
self._set_attribute(SpanAttributes.AGENTOPS_ENTITY_OUTPUT, task.get('output', ''))
self._set_attribute("crewai.task.output", task.get('output', ''))

Check warning on line 184 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L180-L184

Added lines #L180 - L184 were not covered by tests

if 'id' in task:
self._set_attribute("crewai.task.id", str(task.get('id', '')))

Check warning on line 187 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L186-L187

Added lines #L186 - L187 were not covered by tests

if 'status' in task:
self._set_attribute("crewai.task.status", task.get('status', ''))

Check warning on line 190 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L189-L190

Added lines #L189 - L190 were not covered by tests

self._set_attribute("crewai.task.agent", task.get('agent', ''))
self._set_attribute("crewai.task.human_input", task.get('human_input', ''))
self._set_attribute("crewai.task.processed_by_agents", str(task.get('processed_by_agents', '')))

Check warning on line 194 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L192-L194

Added lines #L192 - L194 were not covered by tests

if 'tools' in task and task['tools']:
try:
tools = json.loads(task['tools'])
for i, tool in enumerate(tools):
self._set_attribute(MessageAttributes.TOOL_CALL_NAME.format(i=i), tool.get("name", ""))
self._set_attribute(MessageAttributes.TOOL_CALL_DESCRIPTION.format(i=i), tool.get("description", ""))
except (json.JSONDecodeError, TypeError):
logger.warning(f"Failed to parse tools for task: {task.get('id', 'unknown')}")

Check warning on line 203 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L196-L203

Added lines #L196 - L203 were not covered by tests

def _process_llm(self):

Check warning on line 205 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L205

Added line #L205 was not covered by tests
"""Process an LLM instance."""
llm = {}
self._set_attribute(SpanAttributes.AGENTOPS_SPAN_KIND, "llm")

Check warning on line 208 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L207-L208

Added lines #L207 - L208 were not covered by tests

for key, value in self.instance.__dict__.items():
if value is None:
continue
llm[key] = str(value)

Check warning on line 213 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L210-L213

Added lines #L210 - L213 were not covered by tests

model_name = llm.get('model_name', '') or llm.get('model', '')
self._set_attribute(SpanAttributes.LLM_REQUEST_MODEL, model_name)
self._set_attribute(SpanAttributes.LLM_REQUEST_TEMPERATURE, llm.get('temperature', ''))
self._set_attribute(SpanAttributes.LLM_REQUEST_MAX_TOKENS, llm.get('max_tokens', ''))
self._set_attribute(SpanAttributes.LLM_REQUEST_TOP_P, llm.get('top_p', ''))

Check warning on line 219 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L215-L219

Added lines #L215 - L219 were not covered by tests

if 'frequency_penalty' in llm:
self._set_attribute(SpanAttributes.LLM_REQUEST_FREQUENCY_PENALTY, llm.get('frequency_penalty', ''))
if 'presence_penalty' in llm:
self._set_attribute(SpanAttributes.LLM_REQUEST_PRESENCE_PENALTY, llm.get('presence_penalty', ''))
if 'streaming' in llm:
self._set_attribute(SpanAttributes.LLM_REQUEST_STREAMING, llm.get('streaming', ''))

Check warning on line 226 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L221-L226

Added lines #L221 - L226 were not covered by tests

if 'api_key' in llm:
self._set_attribute("gen_ai.request.api_key_present", "true")

Check warning on line 229 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L228-L229

Added lines #L228 - L229 were not covered by tests

if 'base_url' in llm:
self._set_attribute(SpanAttributes.LLM_OPENAI_API_BASE, llm.get('base_url', ''))

Check warning on line 232 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L231-L232

Added lines #L231 - L232 were not covered by tests

if 'api_version' in llm:
self._set_attribute(SpanAttributes.LLM_OPENAI_API_VERSION, llm.get('api_version', ''))

Check warning on line 235 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L234-L235

Added lines #L234 - L235 were not covered by tests

def _parse_agents(self, agents):

Check warning on line 237 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L237

Added line #L237 was not covered by tests
"""Parse agents into a list of dictionaries."""
if not agents:
logger.debug("CrewAI: No agents to parse")
return

Check warning on line 241 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L239-L241

Added lines #L239 - L241 were not covered by tests

agent_count = len(agents)
logger.debug(f"CrewAI: Parsing {agent_count} agents")

Check warning on line 244 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L243-L244

Added lines #L243 - L244 were not covered by tests

# Pre-process all agents to collect their data first
agent_data_list = []

Check warning on line 247 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L247

Added line #L247 was not covered by tests

for idx, agent in enumerate(agents):
if agent is None:
logger.debug(f"CrewAI: Agent at index {idx} is None, skipping")
agent_data_list.append(None)
continue

Check warning on line 253 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L249-L253

Added lines #L249 - L253 were not covered by tests

logger.debug(f"CrewAI: Processing agent at index {idx}")
try:
agent_data = self._extract_agent_data(agent)
agent_data_list.append(agent_data)
except Exception as e:
logger.error(f"CrewAI: Error extracting data for agent at index {idx}: {str(e)}")
agent_data_list.append(None)

Check warning on line 261 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L255-L261

Added lines #L255 - L261 were not covered by tests

# Now set all attributes at once for each agent
for idx, agent_data in enumerate(agent_data_list):
if agent_data is None:
continue

Check warning on line 266 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L264-L266

Added lines #L264 - L266 were not covered by tests

for key, value in agent_data.items():
if key == "tools" and isinstance(value, list):
for tool_idx, tool in enumerate(value):
for tool_key, tool_value in tool.items():
self._set_attribute(f"crewai.agents.{idx}.tools.{tool_idx}.{tool_key}", str(tool_value))

Check warning on line 272 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L268-L272

Added lines #L268 - L272 were not covered by tests
else:
self._set_attribute(f"crewai.agents.{idx}.{key}", value)

Check warning on line 274 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L274

Added line #L274 was not covered by tests

def _parse_llms(self, llms):

Check warning on line 276 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L276

Added line #L276 was not covered by tests
"""Parse LLMs into a list of dictionaries."""
for idx, llm in enumerate(llms):
if llm is not None:
model_name = getattr(llm, "model", None) or getattr(llm, "model_name", None) or ""
llm_data = {

Check warning on line 281 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L278-L281

Added lines #L278 - L281 were not covered by tests
"model": model_name,
"temperature": llm.temperature,
"max_tokens": llm.max_tokens,
"max_completion_tokens": llm.max_completion_tokens,
"top_p": llm.top_p,
"n": llm.n,
"seed": llm.seed,
"base_url": llm.base_url,
"api_version": llm.api_version,
}

self._set_attribute(f"{SpanAttributes.LLM_REQUEST_MODEL}.{idx}", model_name)
if hasattr(llm, "temperature"):
self._set_attribute(f"{SpanAttributes.LLM_REQUEST_TEMPERATURE}.{idx}", str(llm.temperature))
if hasattr(llm, "max_tokens"):
self._set_attribute(f"{SpanAttributes.LLM_REQUEST_MAX_TOKENS}.{idx}", str(llm.max_tokens))
if hasattr(llm, "top_p"):
self._set_attribute(f"{SpanAttributes.LLM_REQUEST_TOP_P}.{idx}", str(llm.top_p))

Check warning on line 299 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L293-L299

Added lines #L293 - L299 were not covered by tests

for key, value in llm_data.items():
if value is not None:
self._set_attribute(f"crewai.llms.{idx}.{key}", str(value))

Check warning on line 303 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L301-L303

Added lines #L301 - L303 were not covered by tests

def _extract_agent_data(self, agent):

Check warning on line 305 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L305

Added line #L305 was not covered by tests
"""Extract data from an agent."""
model = getattr(agent.llm, "model", None) or getattr(agent.llm, "model_name", None) or ""

Check warning on line 307 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L307

Added line #L307 was not covered by tests

tools_list = []
if hasattr(agent, "tools") and agent.tools:
tools_list = _parse_tools(agent.tools)

Check warning on line 311 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L309-L311

Added lines #L309 - L311 were not covered by tests

return {

Check warning on line 313 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L313

Added line #L313 was not covered by tests
"id": str(agent.id),
"role": agent.role,
"goal": agent.goal,
"backstory": agent.backstory,
"cache": agent.cache,
"config": agent.config,
"verbose": agent.verbose,
"allow_delegation": agent.allow_delegation,
"tools": tools_list,
"max_iter": agent.max_iter,
"llm": str(model),
}

def _set_attribute(self, key, value):

Check warning on line 327 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L327

Added line #L327 was not covered by tests
"""Set an attribute on the span."""
if value is not None and value != "":
set_span_attribute(self.span, key, value)

Check warning on line 330 in agentops/instrumentation/crewai/crewai_span_attributes.py

View check run for this annotation

Codecov / codecov/patch

agentops/instrumentation/crewai/crewai_span_attributes.py#L329-L330

Added lines #L329 - L330 were not covered by tests
Loading
Loading