TokenGuard.Core
1.0.1
dotnet add package TokenGuard.Core --version 1.0.1
NuGet\Install-Package TokenGuard.Core -Version 1.0.1
<PackageReference Include="TokenGuard.Core" Version="1.0.1" />
<PackageVersion Include="TokenGuard.Core" Version="1.0.1" />
<PackageReference Include="TokenGuard.Core" />
paket add TokenGuard.Core --version 1.0.1
#r "nuget: TokenGuard.Core, 1.0.1"
#:package TokenGuard.Core@1.0.1
#addin nuget:?package=TokenGuard.Core&version=1.0.1
#tool nuget:?package=TokenGuard.Core&version=1.0.1
TokenGuard.Core
TokenGuard.Core keeps your agent loop conversation inside ConversationContext. That object is the source of truth for the session. Before each model call, TokenGuard reads that history, builds a provider-ready snapshot, and compacts only that snapshot when needed.
// conversationContext is source of truth for this loop.
// System prompt lives there with every other message.
conversationContext.SetSystemPrompt("You are a careful coding assistant.");
// Add user turn to same stored conversation history.
conversationContext.AddUserMessage("Fix this, make no mistake.");
// Build next provider request from that history.
// TokenGuard may compact this snapshot to fit budget.
// Stored history inside conversationContext does not change.
var prepared = await conversationContext.PrepareAsync(cancellationToken);
// Send only prepared snapshot to provider.
var input = prepared.Messages.ForOpenAI();
var response = await chatClient.CompleteChatAsync(input, cancellationToken: cancellationToken);
You keep appending system, user, assistant, and tool messages to ConversationContext. Everything happens inside that object. PrepareAsync() returns a PrepareResult describing what should go to the model right now.
What it does
- tracks token growth across the full turn sequence
- masks stale tool results using a sliding-window strategy when the conversation crosses a configurable soft threshold
- summarizes old history with your LLM when masking alone is not enough
- falls back to emergency truncation as a last resort
- pins durable context that survives all compaction stages
- stays provider-agnostic in core, with adapter helpers for OpenAI and Anthropic
- integrates in minutes via
AddConversationContext(...)and a standard DI factory
Install
dotnet add package TokenGuard.Core
Quick start
1. Register at startup
services.AddConversationContext(builder => builder
.WithMaxTokens(25_000)
.WithCompactionThreshold(0.80));
Default built-in pipeline starts compaction at 80%, always runs sliding-window masking first, and keeps LLM summarization off until you register it explicitly.
Emergency truncation is on by default at 1.0. It fires only at the absolute token limit and acts as a last-resort safety net after the normal compaction pipeline has already run.
Override with WithEmergencyThreshold(0.95) to trigger earlier, or call WithoutEmergencyThreshold() to disable it entirely.
2. Create a context per conversation
using var conversationContext = serviceProvider
.GetRequiredService<IConversationContextFactory>()
.Create();
Configuration is singleton-scoped. Each Create() call returns an independent stateful context, safe to use across concurrent requests.
3. Run the loop
using TokenGuard.Core.Enums;
using TokenGuard.Extensions.OpenAI;
var factory = serviceProvider.GetRequiredService<IConversationContextFactory>();
using var conversationContext = factory.Create();
conversationContext.SetSystemPrompt("You are a precise coding assistant.");
conversationContext.AddPinnedMessage(MessageRole.User, "Repository root is /workspace/project.");
conversationContext.AddUserMessage("Summarize the failing tests.");
while (true)
{
var prepared = await conversationContext.PrepareAsync(cancellationToken);
if (prepared.Outcome == PrepareOutcome.CannotCompact)
throw new InvalidOperationException(prepared.BudgetFailureReason);
var response = await chatClient.CompleteChatAsync(
prepared.Messages.ForOpenAI(),
chatOptions,
cancellationToken);
conversationContext.RecordModelResponse(
response.ResponseSegments(),
response.InputTokens());
if (response.ToolCalls.Count == 0)
break;
foreach (var toolCall in response.ToolCalls)
{
var result = toolExecutor.Execute(toolCall);
conversationContext.RecordToolResult(toolCall.Id, toolCall.FunctionName, result);
}
}
PrepareAsync() returns a PrepareResult, not just a message list. PrepareResult.Messages is the prepared snapshot to send to the provider. ConversationContext.History remains unchanged.
More detail
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
NuGet packages (2)
Showing the top 2 NuGet packages that depend on TokenGuard.Core:
| Package | Downloads |
|---|---|
|
TokenGuard.Extensions.Anthropic
Anthropic integration for TokenGuard on .NET 10. Converts prepared TokenGuard messages to Anthropic request parts and lets TokenGuard use Anthropic to summarize older history when context gets tight. |
|
|
TokenGuard.Extensions.OpenAI
OpenAI integration for TokenGuard on .NET 10. Converts prepared TokenGuard messages to OpenAI chat messages and lets TokenGuard use OpenAI to summarize older history when context gets tight. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Refreshes the package README with clearer getting-started guidance.