Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,56 @@ This sample demonstrates how to use a `CompactionProvider` with a `PipelineCompa

## Concepts

### Choosing between `CompactionProvider` and `IChatReducer`

Both abstractions reduce the messages sent to a model, but they run at different layers and have different effects on stored history.

| Choose | When you need | Effect on stored history | Function-calling loop |
|---|---|---|---|
| `CompactionProvider` on `ChatClientBuilder.UseAIContextProviders(...)` | Request-context management that preserves the original conversation | The compacted view is forwarded to the inner chat client; the source history remains unchanged | Runs for each inner chat-client call, including calls made while tools are being invoked |
| `CompactionProvider` in `ChatClientAgentOptions.AIContextProviders` | Agent-specific compaction without decorating a shared chat client | Runs before chat history is stored, so generated replacement messages can become part of the persisted history | Runs at the agent boundary, not for each call inside the tool loop |
| `IChatReducer` in `InMemoryChatHistoryProviderOptions.ChatReducer` | Storage management where the reduced list should replace the session's in-memory history | Permanently replaces the provider's stored message list with the reducer output | Runs at the configured history-provider event, not for each call inside the tool loop |
Comment on lines +21 to +25

Use a builder-level `CompactionProvider` when the primary goal is to fit each model request within a context window while retaining the complete conversation for auditing, replay, or a different downstream policy. Use an `IChatReducer` when the primary goal is to bound the history retained in `InMemoryChatHistoryProvider` itself. If the reduced history is serialized with the session, the discarded messages are no longer present after the session is restored.

`InMemoryChatHistoryProvider` can run its reducer at either of these events:

- `BeforeMessagesRetrieval` (the default) reduces stored history immediately before it is supplied to the agent.
- `AfterMessageAdded` reduces stored history after each request/response pair is added.

The event controls *when* reduction occurs; the `IChatReducer` implementation controls *how* messages are reduced. By contrast, a `CompactionStrategy` supplies its own `CompactionTrigger` and operates on message groups that preserve tool-call/result pairs.

#### Adapting between the abstractions

The adapters support existing implementations at either integration point. Pick the direction that matches the layer where you want reduction to run.

To use a `CompactionStrategy` for persistent in-memory history reduction, adapt it to `IChatReducer`:

```csharp
CompactionStrategy strategy =
new SlidingWindowCompactionStrategy(CompactionTriggers.TurnsExceed(20));

InMemoryChatHistoryProvider historyProvider = new(new()
{
ChatReducer = strategy.AsChatReducer(),
ReducerTriggerEvent = InMemoryChatHistoryProviderOptions.ChatReducerTriggerEvent.BeforeMessagesRetrieval
});
Comment on lines +46 to +50
```

To use an existing `IChatReducer` in a compaction pipeline or for in-run request compaction, adapt it to `CompactionStrategy`:

```csharp
IChatReducer existingReducer = /* your MEAI reducer */;

CompactionStrategy strategy = new ChatReducerCompactionStrategy(
existingReducer,
CompactionTriggers.TokensExceed(4000));

CompactionProvider provider = new(strategy);
```

Do not wrap a strategy with `AsChatReducer()` and immediately wrap that reducer in `ChatReducerCompactionStrategy`. That round trip adds no capability; choose the original strategy directly and register it at the appropriate layer.

### Message groups

The compaction engine organizes messages into atomic *groups* that are treated as indivisible units during compaction. A group is either:
Expand Down
2 changes: 1 addition & 1 deletion dotnet/samples/02-agents/Agents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Before you begin, ensure you have the following prerequisites:
|[Deep research with an agent](./Agent_Step15_DeepResearch/)|This sample demonstrates how to use the Deep Research Tool to perform comprehensive research on complex topics|
|[Declarative agent](./Agent_Step16_Declarative/)|This sample demonstrates how to declaratively define an agent.|
|[Providing additional AI Context to an agent using multiple AIContextProviders](./Agent_Step17_AdditionalAIContext/)|This sample demonstrates how to inject additional AI context into a ChatClientAgent using multiple custom AIContextProvider components that are attached to the agent.|
|[Using compaction pipeline with an agent](./Agent_Step18_CompactionPipeline/)|This sample demonstrates how to use a compaction pipeline to efficiently limit the size of the conversation history for an agent.|
|[Using compaction pipeline with an agent](./Agent_Step18_CompactionPipeline/)|This sample demonstrates how to use a compaction pipeline and how to choose between request-level `CompactionProvider` and persistent-history `IChatReducer` integration.|
|[In-function-loop checkpointing](./Agent_Step19_InFunctionLoopCheckpointing/)|This sample demonstrates how to persist chat history after each service call during a tool-calling loop, enabling crash recovery and mid-run observability.|
|[Dynamic function tools](./Agent_Step20_DynamicFunctionTools/)|This sample demonstrates how to dynamically expand the set of function tools available to an agent during a function-calling loop using the ambient FunctionInvocationContext.|
|[Shell tool with environment-aware system prompt](./Agent_Step21_ShellWithEnvironment/)|This sample demonstrates how to use the shell tool together with the ShellEnvironmentProvider to run commands in stateless and persistent modes, injecting environment-aware instructions so the agent emits commands in the right shell idiom.|
Expand Down
Loading