Aggregation
Aggregation extracts structured knowledge from raw events and writes it to the KnowledgeStore. It is the knowledge-organizing counterpart to Compaction.
Compaction removes. Aggregation creates. They are separate concerns.
Aggregation is how an agent builds up persistent state between conversations — the material that WorkingMemoryPolicy and EpisodicMemoryPolicy read back in on subsequent runs.
When to use it#
| You want the agent to | Use |
|---|---|
| Carry stable facts across conversations (user prefs, role, timezone) | WorkingMemoryAggregate + WorkingMemoryPolicy |
| Remember summaries of what happened in past sessions | ConversationSummaryAggregate + EpisodicMemoryPolicy |
| Index artifacts for later retrieval | Write a custom strategy |
Each built-in is one half of a producer/consumer pair: the aggregate writes a file, the assembly policy reads it back on the next turn.
AggregateStrategy protocol#
Every strategy implements the same shape:
Aggregation returns nothing — its output lives in the knowledge store. Unlike CompactStrategy, the store is required (not optional).
AggregateTrigger#
A dataclass describing when aggregation should fire.
Each condition is independent. Setting a counter to 0 disables it. AggregateTrigger() with no arguments fires nothing — every condition is opt-in. on_end defaults to False because each strategy costs one LLM call per fire, and a typical setup pairs ConversationSummaryAggregate with WorkingMemoryAggregate (so on_end=True doubles the per-conversation cost).
Like CompactTrigger, this is a plain data object — it records when you want aggregation to fire, but does not fire it. Strategies are invoked explicitly via await strategy.aggregate(...).
Built-in strategies#
Both built-ins are importable from autogen.beta.aggregate and both take a ModelConfig for a summarization LLM call. Use a smaller / cheaper model than the agent's main model.
ConversationSummaryAggregate#
Writes a timestamped summary of the conversation to /memory/conversations/. The companion to EpisodicMemoryPolicy, which reads from that directory.
Filenames are {ISO timestamp}_{stream id}.md, so lexicographic sort matches chronological sort — which is why EpisodicMemoryPolicy(max_episodes=N) can simply take the trailing N entries.
Token usage is recorded on the strategy instance as strategy.last_usage.
WorkingMemoryAggregate#
Updates /memory/working.md — the actor's single persistent state document. Reads the existing file, merges in context from recent events, writes the updated version back. The companion to WorkingMemoryPolicy.
Unlike ConversationSummaryAggregate, this one is destructive toward its own prior output — each call overwrites /memory/working.md with the merged version. That is the point: working memory is a rolling single-file state, not an append log.
Pairing with assembly policies#
The intended pattern: aggregate at the end of a conversation (or on a cadence), then read back in on the next turn via the matching assembly policy.
flowchart LR
A[Conversation events] --> B[Aggregate]
B --> C[/KnowledgeStore/]
C --> D[Policy]
D --> E[Next LLM turn] | Aggregate | File | Policy |
|---|---|---|
ConversationSummaryAggregate | /memory/conversations/{ts}_{id}.md | EpisodicMemoryPolicy |
WorkingMemoryAggregate | /memory/working.md | WorkingMemoryPolicy |
The path constants (WORKING_MEMORY_PATH, CONVERSATIONS_PREFIX) are defined in autogen.beta.knowledge. Both sides of each pair use those constants so the producer/consumer contract is held together by types, not magic strings.
Driving aggregation#
Pattern for invoking a strategy against an AggregateTrigger:
Writing a custom strategy#
Any object with an async aggregate(events, ctx, store) method satisfies the protocol. Use it to extract domain-specific knowledge:
- Extract facts. Scan events for entity mentions, write
/memory/facts/{entity}.md. - Build an index. On each aggregation, append a row to
/memory/index.jsonlfor later RAG lookup. - Classify and tag. Read events, ask the LLM for a category, store under
/memory/tags/{tag}/{timestamp}.md.
Tip
Aggregation strategies and assembly policies often come in pairs: the strategy writes a path, the policy reads that same path. If you add a new aggregate, consider also adding the reader policy — otherwise the data sits on disk with no way back into the prompt.