Watching a crew work
verbose=True prints a panel for each step of a run. An event listener lets your own code react to the same steps, which is how you trace a crew once it grows.
A crew with one task hides little. From lesson 9 on, agents call tools and pass work to each other, and you want to see each step. CrewAI gives two ways.
from crewai import Agent, Crew, Task
from shop_llm import ShopLLM
agent = Agent(
role="Support agent",
goal="Answer customers of a small online shop",
backstory="You have worked the shop's support desk for years.",
llm=ShopLLM(model="shop"),
)
task = Task(
description="Answer the customer: {question}",
expected_output="One short, friendly sentence.",
agent=agent,
)
crew = Crew(agents=[agent], tasks=[task])The same crew, now taking the question as an input rather than holding it in the task.
verbose
crew = Crew(agents=[agent], tasks=[task], verbose=True)
crew.kickoff(inputs={"question": "Where is my order A17?"})Each panel is one step: the crew starting, the task starting, the agent at work, its final answer, the task completing, the crew completing. The ids change on every run. Verbose output is for reading; code cannot use it.
An event listener
CrewAI emits an event at each of those steps on a shared event bus. A listener is a class that subscribes to the events it cares about.
from crewai.events import BaseEventListener, TaskCompletedEvent, TaskStartedEvent
class Watch(BaseEventListener):
def setup_listeners(self, bus):
@bus.on(TaskStartedEvent)
def started(source, event):
print("task started:", event.task.description)
@bus.on(TaskCompletedEvent)
def finished(source, event):
print("task finished:", event.output.raw)setup_listeners receives the bus, and @bus.on registers a function for one event type. Each function gets the object that emitted the event and the event itself, which carries the task, its output, and more.
watch = Watch()
crew.kickoff(inputs={"question": "Where is my order A17?"})
crew.kickoff(inputs={"question": "Is C40 in stock?"})Creating an instance is what registers it, and it stays registered for every crew in the program. Both runs are traced. There are dozens of event types, for tools, flows, memory and more, each carrying the details of its step.
- Import
CrewKickoffCompletedEvent, subscribe to it and printevent.output.raw. - Print
event.task.agent.roleinstarted. - Set
agent.verbose = Trueas well as the crew's and compare the output.
You understood something today that you didn't yesterday.