Principle:Microsoft Autogen Result Aggregation
| Knowledge Sources | |
|---|---|
| Domains | Multi-Agent Systems, Result Collection, Stream Rendering, Workflow Output, Observability |
| Last Updated | 2026-02-11 00:00 GMT |
Overview
Result aggregation is the practice of collecting, structuring, and presenting the outputs produced by multiple agents during a workflow execution into a coherent final result with associated metadata.
Description
When a multi-agent workflow executes -- whether as a simple sequential chain or a complex graph with parallel branches and conditional routing -- it produces a stream of heterogeneous events. These include agent messages (the primary conversation content), internal agent events (tool calls, intermediate reasoning), streaming chunks (partial outputs), and finally a structured result object that summarizes the execution.
Result aggregation addresses two complementary needs:
Structured Collection
The execution stream must be reduced to a structured result that captures:
- Message history: The ordered sequence of agent output messages, representing the conversation as it unfolded. In graph workflows, this order follows the graph execution topology: sequential messages appear in chain order, parallel fan-out messages appear in the order they completed, and loop messages appear in iteration order.
- Stop reason: A string indicating why execution terminated. Common reasons include natural graph completion ("Digraph execution is complete"), a termination condition being met (e.g., "Maximum number of messages reached"), or a cancellation.
- Exclusions: Streaming chunk events (ModelClientStreamingChunkEvent) are yielded in the stream for real-time display but are excluded from the final message history to avoid duplication with the complete message they represent.
Human-Readable Rendering
For development, debugging, and interactive use, the stream of events must be rendered to a human-readable format. This involves:
- Source attribution: Each message is labeled with its source agent and event type.
- Content formatting: Multi-modal content (images, structured data) is rendered appropriately for the output medium.
- Statistics: Optional output of token usage, message counts, duration, and stop reason for performance monitoring.
- Streaming support: Partial outputs (streaming chunks) are displayed incrementally as they arrive, providing real-time feedback.
Usage
Use result aggregation when:
- You need to capture the complete output of a graph workflow for downstream processing, storage, or analysis.
- You want to display agent execution progress to a user in real time via a console or UI.
- You need to extract the stop reason to determine whether the workflow completed naturally, hit a limit, or was cancelled.
- You want to collect token usage statistics across all agents in the workflow for cost monitoring.
- You are building logging or audit systems that need the full ordered message history from a multi-agent execution.
Theoretical Basis
Stream Reduction
Result aggregation is fundamentally a stream reduction operation. An asynchronous stream of events is consumed and reduced to a single structured result:
stream: AsyncGenerator[Event | Message | Result] -> Result
The reduction maintains two accumulators:
- messages: An ordered list of non-streaming messages.
- stop_reason: The reason extracted from the terminal result event.
Observer Pattern for Rendering
Stream rendering follows the observer pattern: a consumer function subscribes to the event stream and processes each event as it arrives, without buffering the entire stream. This enables:
- Constant memory: Only the current event needs to be in memory for rendering.
- Low latency: Events are displayed as soon as they are produced, not after the entire workflow completes.
- Composability: The same stream can be consumed by multiple observers (e.g., a console renderer and a logging system) via tee or fan-out.
Message Ordering in Graph Workflows
For graph workflows, the message ordering in the result reflects the execution order determined by the graph topology:
- Start nodes produce messages first (they have no dependencies).
- Sequential successors produce messages in chain order.
- Parallel branches (fan-out) produce messages in the order their agents complete (non-deterministic among concurrent agents).
- Fan-in nodes produce messages after all (or any) predecessors complete.
- Loop iterations produce messages in the order of each iteration.
This ordering provides a natural narrative of the workflow execution.
Pseudocode: Stream Consumption and Rendering
async function consume_and_render(stream):
messages = []
total_tokens = {prompt: 0, completion: 0}
start_time = now()
for each event in stream:
if event is TaskResult:
# Terminal event: compute summary
duration = now() - start_time
render_summary(messages.count, event.stop_reason, total_tokens, duration)
return event
elif event is StreamingChunk:
# Display incrementally but do not add to messages
render_chunk(event.content)
else:
# Agent event or message
render_message(event.source, event.type, event.content)
messages.append(event)
if event.models_usage:
total_tokens.prompt += event.models_usage.prompt_tokens
total_tokens.completion += event.models_usage.completion_tokens
return TaskResult(messages=messages, stop_reason=None)