Skip to content

Add pressure-based durable history retention and metrics - #97

Draft
Tamir Dresher (tamirdresher) wants to merge 1 commit into
tamirdresher-microsoft-stack-3-history-providerfrom
tamirdresher-microsoft-stack-4-retention-metrics
Draft

Add pressure-based durable history retention and metrics#97
Tamir Dresher (tamirdresher) wants to merge 1 commit into
tamirdresher-microsoft-stack-3-history-providerfrom
tamirdresher-microsoft-stack-4-retention-metrics

Conversation

@tamirdresher

@tamirdresher Tamir Dresher (tamirdresher) commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Add opt-in, deterministic pressure retention for durable conversation transcripts and low-cardinality metrics for retention attempts, while preserving schema 2 mailbox and execution-control state.

What changed

  • Add public KeepAll and Auto retention modes, defaulting to KeepAll so proactive deletion is opt-in.
  • Keep the positive MaxStateBytes budget and activate it only when Auto is selected.
  • Measure the complete extension-controlled serialized entity state, including mailbox results, completion receipts, history binding, opaque continuation, TTL, bookkeeping, media, metadata, and truncation evidence.
  • Evict only eligible conversationHistory transcript groups from the 85% high watermark toward the 70% low watermark.
  • Connect transcript entries conservatively by correlation ID and stable tool-call/result IDs, including cross-entry and cross-correlation tool loops.
  • Protect system transcript groups and the atomic component containing the actual newest transcript entry.
  • Treat mailbox results, completion receipts, fixed history binding, provider/session continuation, TTL, ingestion/workflow bookkeeping, and extension state as a non-evictable protected floor.
  • Fail atomically with DurableAgentStateSizeLimitExceededException when eligible transcript eviction cannot reduce complete state below the safe write threshold.
  • Expose DurableAgentTelemetry.MeterName and record transcript eviction, protected-capacity failure, no-op outcomes, state sizes, entry/message counts, and reclaimed bytes with bounded tags.

Retention is not compaction or mailbox expiry

Retention is a destructive durable-storage policy applied only when an application explicitly selects Auto. It removes persisted transcript groups to keep the complete entity payload within its configured budget.

Model-context compaction is a separate concern that changes context presented to a model. Auto is not FollowCompaction, and stateful compaction remains unsupported.

Mailbox payload expiry is also separate and remains owned by the layer 2 delivery policy. Pressure retention never removes terminal-result envelopes or completion receipts.

KeepAll performs no proactive transcript eviction. Backend or provider size limits can still reject writes.

Schema 2 and ownership invariants

  • Schema 2 terminal-result mailboxes and completion receipts remain authoritative after transcript copies are removed, so duplicate execution and polling return the same retained outcome.
  • Selecting Auto initializes genuinely new sessions directly as mailbox-aware schema 2 state. Persisted legacy state, including an empty transcript, is converted only after independently authoritative complete-history migration is explicitly authorized; otherwise new execution and successful duplicate delivery fail closed.
  • Authorized duplicate migration uses the same retention, capacity, validation, and atomic commit path as a new execution.
  • TTL configuration maintenance uses the same migration, retention, protected-floor, validation, and atomic commit gate; disabling TTL cannot bypass Auto or mutate unauthorized legacy state.
  • External, service, and opaque session owners normally have no mirrored transcript candidates after layer 3; their continuation and fixed binding remain protected.
  • Duplicate non-empty tool IDs conservatively connect entries; missing or empty IDs do not create cross-entry edges.
  • Retention mutates only the isolated working clone and commits atomically with transcript/session/binding/mailbox/TTL finalization.

Metrics caveat

Retention metrics are attempt-level operational telemetry, not authoritative durable-state truth. They are emitted before the final TaskEntity commit, so later scheduling, persistence, rollback, or retry behavior can produce measurements for an uncommitted attempt or duplicate measurements.

Tags are limited to the registered agent name and bounded outcome/reason values. Session IDs, correlation IDs, message IDs, content, and exception text are never tags. Missing or throwing listeners, including publication and measurement callbacks, cannot change retention behavior.

Validate committed behavior by reloading durable state and checking mailbox outcomes and subsequent model input; emitted counters alone do not prove a successful commit.

Tests

  • 95 focused retention, telemetry, entity-history, and TTL tests in Release.
  • 338 broader retention, mailbox, ownership, schema/version, delivery, and workflow trust-boundary tests in Release.
  • 818 tests in the full Microsoft.Agents.AI.DurableTask.UnitTests Release suite.
  • 223 tests in the Microsoft.Agents.AI.Hosting.AzureFunctions.UnitTests Release suite.
  • Full .NET solution Release build.
  • Release package build for Microsoft.Agents.AI.DurableTask.
  • Repository format/analyzer targets and git diff --check.
  • Independent OpenAI gpt-5.6-sol formal review: ACCEPT.

Dependency and stack position

This PR depends on final layer 3, Add durable chat history ownership and session persistence, at d3872e1e122b1462628793e193eb7409761b4728. Layer 3 preserves the shared opaque history-binding contract while applying the C# fixed-owner profile, and prevents external, service, and opaque owners from mirroring transcripts into entity history.

This is product stack layer 4 of 4 and GitHub chain layer 4 of 6. Read the product stack bottom-up:

  1. Schema 2 mailbox, completion receipt, and history-binding foundation.
  2. Mailbox delivery, duplicate handling, rollback, and TTL hardening.
  3. Per-session history ownership and opaque continuation.
  4. Opt-in transcript pressure retention and metrics.

Not in this PR

  • Samples 08, 09, and 10 or sample-verifier/solution wiring.
  • OpenTelemetry SDK/exporter dependencies or exporter setup.
  • Mailbox expiry policy changes.
  • Stateful compaction, FollowCompaction, payload offload, callbacks, outbox behavior, or layer 3 ownership changes.

The automatic-retention sample can follow as the next dependent layer; it is not included here.

@tamirdresher
Tamir Dresher (tamirdresher) added this pull request to stack #96 September 11, 2026 20:07
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@tamirdresher
Tamir Dresher (tamirdresher) force-pushed the tamirdresher-microsoft-stack-4-retention-metrics branch from cbb0a7d to 52f607e Compare September 12, 2026 03:53
Copilot AI lite review requested due to automatic review settings September 12, 2026 03:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

One or more issues must be addressed before approval.

Get a fresh assessment by requesting another Copilot review.

Review tier: Lite
Findings: 1 High severity · 1 Medium severity · 1 Low severity

Open findings (3)
What changed in this PR

Adds opt-in, pressure-based durable transcript retention with protected schema 2 mailbox state and bounded telemetry.

Changes:

  • Adds KeepAll/Auto retention modes, watermarks, eviction, and capacity failures.
  • Integrates retention with entity execution, migration, and TTL handling.
  • Adds metrics, logging, documentation, and comprehensive tests.
File Description
dotnet/​tests/​Microsoft.Agents.AI.DurableTask.UnitTests/​DurableAgentTelemetryTests.cs Updated as part of this pull request.
dotnet/​tests/​Microsoft.Agents.AI.DurableTask.UnitTests/​DurableAgentStateRetentionTests.cs Updated as part of this pull request.
dotnet/​tests/​Microsoft.Agents.AI.DurableTask.UnitTests/​AgentEntityTimeToLiveTests.cs Updated as part of this pull request.
dotnet/​tests/​Microsoft.Agents.AI.DurableTask.UnitTests/​AgentEntityHistoryTests.cs Updated as part of this pull request.
dotnet/​src/​Microsoft.Agents.AI.DurableTask/​RetentionResult.cs Updated as part of this pull request.
dotnet/​src/​Microsoft.Agents.AI.DurableTask/​README.md Updated as part of this pull request.
dotnet/​src/​Microsoft.Agents.AI.DurableTask/​Logs.cs Updated as part of this pull request.
dotnet/​src/​Microsoft.Agents.AI.DurableTask/​DurableAgentTelemetry.cs Updated as part of this pull request.
dotnet/​src/​Microsoft.Agents.AI.DurableTask/​DurableAgentStateSizeLimitExceededException.cs Updated as part of this pull request.
dotnet/​src/​Microsoft.Agents.AI.DurableTask/​DurableAgentStateRetention.cs Updated as part of this pull request.
dotnet/​src/​Microsoft.Agents.AI.DurableTask/​DurableAgentsOptions.cs Updated as part of this pull request.
dotnet/​src/​Microsoft.Agents.AI.DurableTask/​DurableAgentHistoryRetentionMode.cs Updated as part of this pull request.
dotnet/​src/​Microsoft.Agents.AI.DurableTask/​CHANGELOG.md Updated as part of this pull request.
dotnet/​src/​Microsoft.Agents.AI.DurableTask/​AgentEntity.cs Updated as part of this pull request.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.


Assert.DoesNotContain(state.Data.ConversationHistory, entry => entry.CorrelationId == "old");
Assert.DoesNotContain(state.Data.ConversationHistory, entry => entry.CorrelationId == "completed");
Assert.Contains(state.Data.ConversationHistory, entry => entry.CorrelationId == "newest");
Comment on lines +66 to +69
while (GetSerializedSize(state) > lowWatermark)
{
List<DurableAgentStateEntry>? group = FindOldestEligibleExchange(
state.Data.ConversationHistory);

## [Unreleased]

- Added opt-in pressure-based durable transcript retention and low-cardinality operational metrics while protecting schema 2 mailbox and execution-control state.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants