Skip to content

Commit d7acb59

Browse files
fenilfaldudot-agiDwij1704
authored
Crewai tags fix in root span (#992)
* Added span name customization based on default tags * added the tags/default tags in the root span * added the test of tags in the root span * ruff check :) * code refactored * ruff checks * add `TODO` for converting tags to list --------- Co-authored-by: Pratyush Shukla <ps4534@nyu.edu> Co-authored-by: Dwij <96073160+Dwij1704@users.noreply.github.com>
1 parent 9622b06 commit d7acb59

2 files changed

Lines changed: 77 additions & 6 deletions

File tree

agentops/instrumentation/crewai/instrumentation.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
from opentelemetry.sdk.resources import SERVICE_NAME, TELEMETRY_SDK_NAME, DEPLOYMENT_ENVIRONMENT
1414
from agentops.instrumentation.crewai.version import __version__
1515
from agentops.semconv import SpanAttributes, AgentOpsSpanKindValues, Meters, ToolAttributes, MessageAttributes
16+
from agentops.semconv.core import CoreAttributes
1617
from .crewai_span_attributes import CrewAISpanAttributes, set_span_attribute
18+
from agentops import get_client
1719

1820
# Initialize logger
1921
logger = logging.getLogger(__name__)
@@ -159,12 +161,20 @@ def wrap_kickoff(
159161
logger.debug(
160162
f"CrewAI: Starting workflow instrumentation for Crew with {len(getattr(instance, 'agents', []))} agents"
161163
)
164+
165+
config = get_client().config
166+
attributes = {
167+
SpanAttributes.LLM_SYSTEM: "crewai",
168+
}
169+
170+
if config.default_tags and len(config.default_tags) > 0:
171+
tag_list = list(config.default_tags)
172+
attributes[CoreAttributes.TAGS] = tag_list
173+
162174
with tracer.start_as_current_span(
163175
"crewai.workflow",
164176
kind=SpanKind.INTERNAL,
165-
attributes={
166-
SpanAttributes.LLM_SYSTEM: "crewai",
167-
},
177+
attributes=attributes,
168178
) as span:
169179
try:
170180
span.set_attribute(TELEMETRY_SDK_NAME, "agentops")
@@ -381,12 +391,21 @@ def wrap_task_execute(
381391
):
382392
task_name = instance.description if hasattr(instance, "description") else "task"
383393

394+
config = get_client().config
395+
attributes = {
396+
SpanAttributes.AGENTOPS_SPAN_KIND: AgentOpsSpanKindValues.TASK.value,
397+
}
398+
399+
if config.default_tags and len(config.default_tags) > 0:
400+
tag_list = list(config.default_tags)
401+
# TODO: This should be a set to prevent duplicates, but we need to ensure
402+
# that the tags are not modified in place, so we convert to list first.
403+
attributes[CoreAttributes.TAGS] = tag_list
404+
384405
with tracer.start_as_current_span(
385406
f"{task_name}.task",
386407
kind=SpanKind.CLIENT,
387-
attributes={
388-
SpanAttributes.AGENTOPS_SPAN_KIND: AgentOpsSpanKindValues.TASK.value,
389-
},
408+
attributes=attributes,
390409
) as span:
391410
try:
392411
span.set_attribute(TELEMETRY_SDK_NAME, "agentops")

tests/unit/test_session_legacy.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,55 @@ def test_crewai_kwargs_force_flush():
144144

145145
# Explicitly ensure the core isn't already shut down for the test
146146
assert TracingCore.get_instance()._initialized, "TracingCore should still be initialized"
147+
148+
149+
def test_crewai_task_instrumentation(instrumentation):
150+
"""
151+
Test the CrewAI task instrumentation focusing on span attributes and tags.
152+
This test verifies that task spans are properly created with correct attributes
153+
and tags without requiring a session.
154+
"""
155+
import agentops
156+
from opentelemetry.trace import SpanKind
157+
from agentops.semconv import SpanAttributes, AgentOpsSpanKindValues
158+
from opentelemetry import trace
159+
from agentops.semconv.core import CoreAttributes
160+
161+
# Initialize AgentOps with API key and default tags
162+
agentops.init(
163+
api_key="test-api-key",
164+
)
165+
agentops.start_session(tags=["test", "crewai-integration"])
166+
# Get the tracer
167+
tracer = trace.get_tracer(__name__)
168+
169+
# Create a mock task instance
170+
class MockTask:
171+
def __init__(self):
172+
self.description = "Test Task Description"
173+
self.agent = "Test Agent"
174+
self.tools = ["tool1", "tool2"]
175+
176+
task = MockTask()
177+
178+
# Start a span for the task
179+
with tracer.start_as_current_span(
180+
f"{task.description}.task",
181+
kind=SpanKind.CLIENT,
182+
attributes={
183+
SpanAttributes.AGENTOPS_SPAN_KIND: AgentOpsSpanKindValues.TASK.value,
184+
CoreAttributes.TAGS: ["crewai", "task-test"],
185+
},
186+
) as span:
187+
# Verify span attributes
188+
assert span.attributes[SpanAttributes.AGENTOPS_SPAN_KIND] == AgentOpsSpanKindValues.TASK.value
189+
assert "crewai" in span.attributes[CoreAttributes.TAGS]
190+
assert "task-test" in span.attributes[CoreAttributes.TAGS]
191+
192+
# Verify span name
193+
assert span.name == f"{task.description}.task"
194+
195+
# Verify span kind
196+
assert span.kind == SpanKind.CLIENT
197+
198+
agentops.end_session(end_state="Success", end_state_reason="Test Finished", is_auto_end=True)

0 commit comments

Comments
 (0)