Skip to main content

Overview

Streaming lets your application receive execution updates while work is still running. Instead of waiting for the final result, you can render LLM tokens, tool activity, Flow lifecycle events, and conversation messages as they happen. CrewAI has two streaming surfaces:
SurfaceUsed byOutput
Frame streamingFlows, direct LLM calls, conversational turnsOrdered StreamFrame objects
Crew chunk streamingCrews with stream=TrueCrewStreamingOutput chunks
For new runtime integrations, UIs, terminal apps, service bridges, and conversational surfaces, use frame streaming. It provides one stable event envelope across the runtime.

StreamFrame

A StreamFrame is the common object emitted by streamable runtimes:
frame.id           # unique frame id
frame.seq          # execution-local order, when available
frame.type         # source event type, such as "llm_stream_chunk"
frame.channel      # "llm", "flow", "tools", "messages", "lifecycle", or "custom"
frame.namespace    # source/runtime namespace
frame.timestamp    # event timestamp
frame.parent_id    # parent event id, when available
frame.previous_id  # previous event id, when available
frame.data         # structured event payload
frame.event        # alias for frame.data
frame.content      # printable text for token-like frames, otherwise ""
The important fields for most consumers are:
FieldUse it for
channelRouting frames to the right UI region
typeHandling a specific event inside a channel
contentPrinting token-like text
eventReading structured metadata, such as tool names or message roles
seqPreserving execution order

Channels

Frames are grouped into high-level channels:
ChannelContains
llmLLM call lifecycle, text chunks, and thinking chunks
flowFlow lifecycle, method execution, routing, pause, and resume events
toolsTool usage start, finish, and error events
messagesConversation transcript events
lifecycleRuntime lifecycle events that do not belong to another channel
customEvents that do not map to a built-in channel
The stream itself remains one ordered timeline. Channel projections let consumers focus on only part of that timeline.

Stream Sessions

Frame streaming returns a stream session:
stream = flow.stream_events(inputs={"topic": "AI agents"})
The session is both an iterator and the holder for the final result:
with stream:
    for frame in stream:
        print(frame.content, end="", flush=True)

result = stream.result
Consume the stream before reading stream.result. Reading the result too early raises an error because the runtime may still be producing frames.

Channel Projections

Use channel projections when you only need one kind of frame:
with flow.stream_events(inputs={"topic": "AI agents"}) as stream:
    for frame in stream.llm:
        print(frame.content, end="", flush=True)

result = stream.result
Available projections:
ProjectionFrames
stream.eventsAll frames
stream.llmLLM frames
stream.flowFlow frames
stream.toolsTool frames
stream.messagesConversation message frames
stream.interleave([...])Selected channels in relative order

Entrypoints

Use the entrypoint that matches the runtime you are streaming:
RuntimeStreaming entrypoint
Flowflow.stream_events(...)
Flow with stream=Trueflow.kickoff(...) returns a stream session
Async Flowflow.astream(...) or await flow.kickoff_async(...) when stream=True
Direct LLM callllm.stream_events(...)
Conversational Flow turnflow.stream_turn(...)
CrewCrew(..., stream=True).kickoff(...) returns CrewStreamingOutput
Direct llm.call(...) still returns the final assembled LLM result. Use llm.stream_events(...) when you want to iterate over LLM chunks as they arrive.