mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-09-21 10:26:25 +00:00
feat(tracing): carry task_prompt and output in agent_execution payloads (#7498)
`agent_execution_started` and `agent_execution_completed` are in `complex_events`, so `_build_event_data` hand-builds their payloads. Those payloads shipped only agent_role/goal/backstory and dropped two required bus fields: `AgentExecutionStartedEvent.task_prompt` and `AgentExecutionCompletedEvent.output`. A trace therefore said which agent ran but not what it was asked or what it answered. Add `task_prompt` to the started payload and `output` to the completed one, whole and untruncated. No new event types, no TraceEvent change. Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> Co-authored-by: Vidit Ostwal <110953813+Vidit-Ostwal@users.noreply.github.com>
This commit is contained in:
@@ -1013,12 +1013,14 @@ class TraceCollectionListener(BaseEventListener):
|
||||
"agent_role": event.agent.role,
|
||||
"agent_goal": event.agent.goal,
|
||||
"agent_backstory": event.agent.backstory,
|
||||
"task_prompt": event.task_prompt,
|
||||
}
|
||||
if event_type == "agent_execution_completed":
|
||||
return {
|
||||
"agent_role": event.agent.role,
|
||||
"agent_goal": event.agent.goal,
|
||||
"agent_backstory": event.agent.backstory,
|
||||
"output": event.output,
|
||||
}
|
||||
if event_type == "llm_call_started":
|
||||
event_data = safe_serialize_to_dict(event)
|
||||
|
||||
58
lib/crewai/tests/tracing/test_trace_agent_prompt_output.py
Normal file
58
lib/crewai/tests/tracing/test_trace_agent_prompt_output.py
Normal file
@@ -0,0 +1,58 @@
|
||||
"""The agent_execution_* trace payloads must carry the prompt and the output.
|
||||
|
||||
Both types are in ``TraceCollectionListener.complex_events``, so their payload
|
||||
is hand-built by ``_build_event_data`` rather than serialized from the event:
|
||||
a bus field reaches the trace only if it is named there. ``task_prompt`` and
|
||||
``output`` are required on the bus events but were dropped, leaving a trace
|
||||
that said which agent ran without saying what it was asked or what it said.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from crewai import Agent
|
||||
from crewai.events.listeners.tracing.trace_listener import TraceCollectionListener
|
||||
from crewai.events.types.agent_events import (
|
||||
AgentExecutionCompletedEvent,
|
||||
AgentExecutionStartedEvent,
|
||||
)
|
||||
|
||||
|
||||
# Long and non-repeating, so a truncated or elided copy cannot compare equal.
|
||||
LONG_TEXT = "".join(f"paragraph {i}: the quick brown fox jumps over the lazy dog\n" for i in range(400))
|
||||
assert len(LONG_TEXT) > 20_000
|
||||
|
||||
|
||||
def _listener() -> TraceCollectionListener:
|
||||
"""A bare listener: `_build_event_data` needs no batch manager or bus."""
|
||||
return TraceCollectionListener.__new__(TraceCollectionListener)
|
||||
|
||||
|
||||
def _agent() -> Agent:
|
||||
return Agent(
|
||||
role="Researcher",
|
||||
goal="Find things out",
|
||||
backstory="Curious by nature",
|
||||
llm="openai/gpt-4o-mini",
|
||||
)
|
||||
|
||||
|
||||
def test_started_payload_carries_the_whole_task_prompt() -> None:
|
||||
agent = _agent()
|
||||
event = AgentExecutionStartedEvent(
|
||||
agent=agent, task=None, tools=None, task_prompt=LONG_TEXT
|
||||
)
|
||||
|
||||
data = _listener()._build_event_data("agent_execution_started", event, agent)
|
||||
|
||||
assert data["task_prompt"] == LONG_TEXT
|
||||
assert data["agent_role"] == "Researcher"
|
||||
|
||||
|
||||
def test_completed_payload_carries_the_whole_output() -> None:
|
||||
agent = _agent()
|
||||
event = AgentExecutionCompletedEvent(agent=agent, task=None, output=LONG_TEXT)
|
||||
|
||||
data = _listener()._build_event_data("agent_execution_completed", event, agent)
|
||||
|
||||
assert data["output"] == LONG_TEXT
|
||||
assert data["agent_role"] == "Researcher"
|
||||
Reference in New Issue
Block a user