Microsoft.Agents.AI.DurableTask 1.16.0-preview.261029.1

Prefix Reserved
This is a prerelease version of Microsoft.Agents.AI.DurableTask.
dotnet add package Microsoft.Agents.AI.DurableTask --version 1.16.0-preview.261029.1
                    
NuGet\Install-Package Microsoft.Agents.AI.DurableTask -Version 1.16.0-preview.261029.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Microsoft.Agents.AI.DurableTask" Version="1.16.0-preview.261029.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Microsoft.Agents.AI.DurableTask" Version="1.16.0-preview.261029.1" />
                    
Directory.Packages.props
<PackageReference Include="Microsoft.Agents.AI.DurableTask" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Microsoft.Agents.AI.DurableTask --version 1.16.0-preview.261029.1
                    
#r "nuget: Microsoft.Agents.AI.DurableTask, 1.16.0-preview.261029.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Microsoft.Agents.AI.DurableTask@1.16.0-preview.261029.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Microsoft.Agents.AI.DurableTask&version=1.16.0-preview.261029.1&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Microsoft.Agents.AI.DurableTask&version=1.16.0-preview.261029.1&prerelease
                    
Install as a Cake Tool

Microsoft.Agents.AI.DurableTask

The Microsoft Agent Framework provides a programming model for building agents and agent workflows in .NET. This package, the Durable Task extension for the Agent Framework, extends the Agent Framework programming model with the following capabilities:

  • Stateful, durable execution of agents in distributed environments
  • Automatic conversation history management
  • Long-running agent workflows as "durable orchestrator" functions
  • Tools and dashboards for managing and monitoring agents and agent workflows

These capabilities are implemented using foundational technologies from the Durable Task technology stack:

This package can be used by itself or in conjunction with the Microsoft.Agents.AI.Hosting.AzureFunctions package, which provides additional features via Azure Functions integration.

Install the package

From the command-line:

dotnet add package Microsoft.Agents.AI.DurableTask

Or directly in your project file:

<ItemGroup>
  <PackageReference Include="Microsoft.Agents.AI.DurableTask" Version="[CURRENTVERSION]" />
</ItemGroup>

You can alternatively just reference the Microsoft.Agents.AI.Hosting.AzureFunctions package if you're hosting your agents and orchestrations in the Azure Functions .NET Isolated worker.

Usage Examples

For a comprehensive tour of all the functionality, concepts, and APIs, check out the .NET Durable Task samples.

Durable completion and delivery

An invocation correlation ID is an idempotency key, not a transcript position. Do not reuse it for different work. Legacy state resolves terminal responses and errors from the retained transcript. Schema 2.0 resolves only the result mailbox and permanent completion receipts: pruning the transcript does not make a completed correlation runnable again. A recorded completion with an expired or removed payload is completed but result unavailable, not pending and not a new invocation.

Recorded state Client behavior
No terminal evidence Pending; a polling handle continues waiting
Successful completion with a result Return the original response and its retained metadata
Supported committed terminal failure Throw DurableAgentTerminalException with its code and details
Completion without an available payload Throw DurableAgentResultUnavailableException, retaining whether the completion succeeded or failed
Inconsistent or unsupported state Fail closed; do not invoke the model as a recovery fallback

These failure semantics also apply to direct orchestration calls and workflow agent executors. A committed duplicate failure (including a legacy errorResponse and an empty retry) throws before validation, agent construction, history/tool work, or migration; it cannot become downstream success. This intentionally changes mixed-runtime schema-1 delivery: a Python-written errorResponse is surfaced as DurableAgentTerminalException instead of an HTTP 200/ordinary response, and duplicate correlated legacy responses fail closed as corrupt rather than selecting the first entry. The Durable Task SDK serializes exception type, message, and inner failures, but drops custom exception properties. The entity therefore includes a versioned metadata snapshot in a DurableAgentFailureMetadataException inner exception. DurableAIAgent restores the typed terminal or unavailable exception from either EntityOperationFailedException or TaskFailedException, retaining the SDK failure as a nested cause. Only these framework exception types select this contract; model/user text is never used to infer outcomes. Unsupported metadata remains an SDK failure. This is an additive failure-only transport change: Run/RunAgentAsync operation names, request and successful-response wire formats, and entity-state schemas are unchanged. Older orchestration clients still receive an SDK exception, not an ordinary successful response. Historical message-only failures remain typed failures, without inventing metadata that was not recorded.

One successful outer entity operation stages the immutable result and its receipt in an independent working copy with the existing session/continuation, ingestion, entity transcript, whole-entity TTL, binding, and other local state. Publishing that copy participates in the Durable Task entity commit. Appending transcript text alone is not delivery acknowledgement. External history-provider writes and tool effects are not part of this entity-local transaction; tool implementations still need their own idempotency guarantees.

Only a successfully committed outer invocation creates a new success receipt. Validation failures, cancellation, ordinary model/provider errors, serialization/capacity failures, and failed entity commits remain retryable; they are not converted into terminal receipts. A separate internal capability can commit a provider failure only when a certified adapter explicitly attests the provider phase (Load, Invoke, or Store), finality (NonRetryable or RetriesExhausted), and accepted input. The runtime then serializes the resulting session, validates sanitized error metadata, and commits the failed result and receipt through the same finalization path. No adapter is registered and the capability is disabled by default. Exception messages, HTTP status codes, factory/session creation failures, cancellation, reconciliation, serialization, scheduling, state replacement, or uncertain commit acknowledgement never establish finality. Existing explicitly committed terminal failure evidence can be read and migrated, but a transient exception does not establish such a contract. Legacy conversion is evidence-only and idempotent. It never calls the model or tools and cannot reconstruct receipts for results already evicted from legacy state.

The Agent Framework 1.13 .NET abstractions do not expose a provider-neutral structured classifier for previous_response_not_found. Provider-specific clients can expose raw response content, but this generic durable layer does not infer service codes from exception messages or HTTP status. The ADR 0032 bounded 0.5/1.0/1.5-second pre-progress retry therefore remains a provider-adapter dependency: a certified adapter must expose the structured code and prove that no streaming, tool, session, or continuation progress occurred before this layer can implement that retry safely.

Completion receipts last until entity deletion. DurableAgentsOptions.ResultRetentionPeriod defaults to the shared 60-second delivery window and accepts another positive duration or null for no payload expiry. Result-payload retention and whole-entity TTL are separate policies. Deleting the entity also deletes its idempotency evidence. New sessions target dafx-v2-{agent} entities and persist schema 2.0.0 state by default, while DurableAgentsOptions.ProcessLegacyEntities = true (or DURABLE_AGENTS_PROCESS_LEGACY_ENTITIES=true) enables Phase 2 registration of legacy dafx-{agent} entities and upgrades loaded schema 1.x state in-place to schema 2.0.0 on the next turn. Explicit agent or default TTL configurations can delete receipt-bearing entities after expiry, while the unconfigured legacy idle default does not delete revised state automatically. See state compatibility.

A successful new run also removes already-expired mailbox payloads and maintains one logical entity-local CheckAndExpireResults schedule for the earliest remaining expiry. The optional version-1 runtime profile extensionData["Microsoft.Agents.AI.DurableTask.resultExpiry"] stores the entity identity, UTC scheduled deadline, and an unpredictable token. It uses the existing root extension map, not a new shared schema field or historyBinding. The replacement state, profile and signal outbox participate in the same entity operation commit. Cleanup preserves each completion's outcome, completion/expiry timestamps and unknown receipt metadata, marks its result unavailable, and records the first cleanup time. It does not delete receipts, invoke the agent/factory/tools, create a session, or refresh entity TTL.

Entity operations are serialized. New runs reuse a pending check that already covers the earliest deadline; an earlier deadline replaces it once with a new token. Moving the earliest expiry later reuses the earlier check, which will schedule one successor when consumed. Superseded physical signals may still arrive, but only an exact entity/token/deadline match can consume the logical schedule. Stale, duplicate, timestamp-only pre-profile, and previous-generation signals are no-ops: no state setter, outgoing signal, model invocation or TTL update. A signal against a deleted entity does not recreate it. A matching cleanup deep-clones and validates authoritative current state and uses the host's TimeProvider, not the signal, to decide expiry. Consuming it atomically clears or rotates the token. Early matching checks schedule at most one successor, at least one minute after both the current clock and the prior scheduled check, avoiding repeated scheduling at the same timestamp when the worker clock moves backward. Duplicates of that early check cannot advance the chain again. This scheduling floor is not a default retention period. Physical cleanup can lag logical expiry by that floor and scheduler delivery/clock skew; polling reports unavailability at the recorded expiry without mutating state. Repeated successful cleanup preserves the original unavailable timestamp.

Serialization, scheduling, cancellation, and commit failures leave hydrated state unchanged; operation errors propagate rather than being acknowledged as cleanup. Recovery/retry uses the same idempotent operation. There is no background entity scan: for an imported state with no signal, or a signal lost/failed during rollout, the host can explicitly invoke the CheckAndExpireResults entity operation (no input required) on the known entity. One successful turn sweeps its existing due payloads and installs a missing schedule or supersedes an overdue/stuck token once. A valid future schedule is reused, so repeated recovery cannot multiply the chain. An early failed check retains its token and can be retried with the same input, or recovered without input once its persisted deadline is due. A later successful new run also performs this recovery. A host requiring a cleanup-time bound for otherwise idle imported entities must enqueue that operation as part of import/recovery and monitor failed operations. Read-only polling and terminal duplicate calls do not provide durable cleanup. Cleanup never migrates legacy state.

Malformed/unsupported scheduling profiles fail closed before a new model invocation or cleanup. Other extensions and unknown fields in a supported profile are preserved. This is a .NET-local profile, not a shared-schema requirement: foreign runtimes preserve it opaquely but need not honor it. Compatible .NET writers honor its scheduling contract; preserving unknown JSON alone does not make another scheduler safe to deploy alongside this writer.

Backend atomicity verification: the gated integration test checks state plus outgoing delayed signals, worker restart, duplicate delivery and a failure after state/outbox staging against a real backend in an explicitly isolated environment. A skipped test or passing mock tests does not verify backend atomicity.

response.GetDurableResult() returns the canonical retained terminal-response JSON for a durable delivery, including optional value and unknown metadata that the native AgentResponse cannot represent. An absent value remains absent, not explicit null. The registered DurableDataConverter transports this JSON-only snapshot in additive namespaced response metadata, preserving native response fields and plain legacy response reads. Direct native serialization does not preserve this association. The metadata is result data, never a workflow control envelope or a runtime type selector. When complete legacy history is independently authorized for promotion, the retained mailbox snapshot also preserves declared response extension data and unknown response fields independently of the transcript. First delivery, cold polling, and repeated duplicates retain that canonical metadata; JSON-looking response text never supplies a missing canonical value.

Workflow output trust boundary

Agent/model output and request-port responses are data, never workflow control envelopes. The framework wraps their exact text in result-only values, including text that happens to be valid JSON or matches an activity envelope. Only trusted regular activity/subworkflow results may supply state updates, scope clears, events, routed messages, or halt requests. Invalid known activity-envelope fields fail closed to plain result text without applying partial controls. Legacy plain-text activity results remain supported. Each trusted activity or child-workflow sentMessages entry must contain a nonblank string typeName and data; null entries or missing/null/empty/whitespace fields reject the whole collection before any routing. Activity JSON also rejects ambiguous repeated known fields and invalid field kinds. An invalid child collection discards all its messages, events and halt controls, matching the all-or-nothing activity trust boundary. Its exact Result text, not the serialized invalid envelope, is the fallback; it is never decoded again as controls. Child shared state is always isolated. These are CLR string fields: serialized JSON payloads such as null, false, 0, and "" remain valid inside the data string. Payload text is not recursively interpreted as controls or required to resolve a runtime type during envelope validation. Unknown fields cannot override known controls. A nonblank unknown type name is structurally valid and travels unchanged to the target activity. If that activity cannot resolve it or match a registered input type by name, it fails rather than choosing the first handler. Resolution alone does not authorize a type: every selected non-string input type must be in the receiving executor's InputTypes before payload deserialization, including fan-in array elements. Rejected hints cannot invoke payload constructors, JSON converters, or handlers; the executor factory may run to obtain its registered contract. Type resolution is not added to orchestration code. Existing registered-name/version matching and string/string-array adaptation to a registered type remain supported. Absent, null, and empty hints retain legacy default-type selection; whitespace-only or surrounding-whitespace names do not. A recognized top-level inputTypeName (case-insensitive) identifies an activity input envelope: duplicate hints, invalid hint field kinds, and malformed envelopes cannot discard that provenance and retry as untyped payloads. Legacy raw input without a recognized top-level hint remains supported, including opaque non-JSON string input. The child runner tags its non-empty final result as a CLR string when routing it to parent successors, so an executor supporting several input types receives the original text through its string handler even when another supported type is listed first. Child result-only fallback (including legacy missing, null or empty message collections) also retains string provenance. Whitespace-only Result text is preserved exactly, even though a whitespace-only typed data field is invalid. Null/empty results do not enqueue a fallback message. Legacy absent collections preserve trusted events/halt; invalid entries discard those controls. Valid typed child halt requests and superstep limits are unchanged.

This is a structural provenance boundary, not a signing/authenticity mechanism. No new discriminator or entity-state schema field is needed. The C# workflow output format is not asserted to match Python's workflow format; shared entity-state fixture compatibility is a separate contract.

C# history ownership profile

The shared schema 2 historyBinding remains optional, provisional configuration metadata. It does not pin an effective owner or prohibit Python or other runtimes from supporting per-run transitions. When writing schema 2 state, the C# durable-agent runtime applies a stricter profile: after the first successful turn it marks and seals one logical owner using the binding version, owner kind, and a stable non-secret provider key. Later C# turns must restore the same continuation and resolve the same identity; mismatches fail instead of silently resetting, migrating, or starting another logical conversation.

New durable sessions write schema 2.0.0 state to dafx-v2-{agent} entities by default. During a two-phase rolling upgrade from 1.x:

  • Phase 1 (side-by-side): leave DurableAgentsOptions.ProcessLegacyEntities set to false (default) while v1 workers are still active so v2 workers register and filter only dafx-v2-{agent} entities and in-flight dafx-{agent} sessions remain on v1 workers.
  • Phase 2 (cutover): once all v1 workers are stopped, set DurableAgentsOptions.ProcessLegacyEntities = true (or DURABLE_AGENTS_PROCESS_LEGACY_ENTITIES=true) so v2 workers also register dafx-{agent} entities and migrate loaded schema 1.x state in-place to schema 2.0.0 on the next turn.

For side-by-side rolling upgrades, standalone workers automatically register work-item filters via UseWorkItemFilters() for dafx-v2-{agent} (Phase 1) and add dafx-{agent} when DurableAgentsOptions.ProcessLegacyEntities = true (or DURABLE_AGENTS_PROCESS_LEGACY_ENTITIES=true) in Phase 2 after all v1 workers are stopped. On Azure Functions, distinct entity trigger names alone do not isolate dispatch unless the Functions host also enables work-item filtering: reference Microsoft.Azure.Functions.Worker 2.52.0+, Microsoft.Azure.Functions.Worker.Extensions.DurableTask 1.19.0+, and Microsoft.Azure.Functions.Worker.Extensions.DurableTask.AzureManaged 1.10.0+ (which resolves Microsoft.Azure.WebJobs.Extensions.DurableTask.AzureManaged 1.8.0+), and enable "workItemFilteringEnabled": true under extensions.durableTask.storageProvider in host.json:

{
  "version": "2.0",
  "extensions": {
    "durableTask": {
      "hubName": "default",
      "storageProvider": {
        "type": "AzureManaged",
        "connectionStringName": "DURABLE_TASK_SCHEDULER_CONNECTION_STRING",
        "workItemFilteringEnabled": true
      }
    }
  }
}

If host-side work-item filtering is not enabled on both old and new Azure Functions deployments, perform an offline cutover instead of running v1 and v2 Functions hosts side by side on the same Task Hub.

The default in-memory history pipeline is entity-owned and appends its model transcript to conversationHistory. Custom providers, model services, and opaque CurrentRequestOnly agents remain authoritative for their own transcripts. They append no new request or response mirrors to conversationHistory; durable delivery still uses the schema 2 terminal-result mailbox and completion receipts, and the opaque serialized session preserves provider state, conversation IDs, approvals, and other continuation. Mailbox results are never replayed as model history.

Configure non-entity owners with a stable logical key:

DurableAgentHistoryProviderKey historyProviderKey = new("contoso.support-history.v1");

services.ConfigureDurableAgents(options =>
{
  options.AddAIAgent(
    agent,
    timeToLive: null,
    configureHistory: history => history.ProviderKey = historyProviderKey);
});

The key must not contain credentials or be inferred from CLR type names, process instances, or opaque session keys. Legacy non-entity adoption requires owner-specific public evidence: a normal service conversation ID or a custom provider's declared StateKeys. Opaque CurrentRequestOnly and legacy per-service-call sessions cannot prove their prior owner through the pinned public contracts and require a new durable session. When an imported provisional binding already supplies a valid key, C# intentionally uses that persisted key if registration omits one, then seals the same identity; a later explicit key must match it.

Provider/model/session work, mailbox completion, TTL preparation, and entity transcript updates share one isolated working-state commit boundary. External provider and model-service stores are outside that transaction. Their adapters must make writes idempotent and treat an exception or lost acknowledgement as an uncertain outcome rather than assuming that the remote write did not occur. Remote services can still observe a call before a genuinely response-discovered ownership transition or later serialization failure; those transition errors report that limitation explicitly. Owner, key, and continuation conflicts that are determinable from registration options and the restored session are rejected before provider/model callbacks. Local per-service-call provider persistence remains unsupported because public callbacks do not identify the final outer tool-loop response.

CompactionProvider remains supported for model-input compaction. Its opaque provider state is serialized inside the durable session and therefore counts toward the complete entity-state size budget, while the authoritative durable transcript is not pruned or rewritten to follow that compaction. Store-pruning FollowCompaction behavior remains deferred. Explicitly configured InMemoryChatHistoryProvider instances are rejected only by the active fixed-owner profile because the pinned public API does not expose their initializer and message-filter delegates for faithful transfer to the durable adapter. Use the implicit default in-memory provider for schema 2 entity-owned history, or a custom external provider with a key. The pinned Agent Framework API cannot universally inspect builder-installed or privately nested provider decorators; this implementation does not use reflection, type-name scanning, guessed session keys, or factory double invocation.

DurableAgentsOptions.HistoryRetentionMode defaults to KeepAll, which performs no proactive history eviction (backend or provider size limits can still reject a write). Set HistoryRetentionMode to DurableAgentHistoryRetentionMode.Auto to enable automatic pressure-based transcript retention. DurableAgentsOptions.MaxStateBytes defaults to 1 MiB (1,048,576 bytes; null also resolves to 1 MiB under Auto), and MaxStateBytes and the watermark properties are inert while HistoryRetentionMode remains KeepAll.

The high and low watermarks default to 0.85 and 0.70 and can be overridden only with finite values satisfying 0 < low < high <= 1. The high watermark starts a retention attempt, which removes the oldest eligible transcript groups toward the low watermark. Measurement serializes the complete extension state through the durable converter and then measures its JSON-string storage envelope, including quote, backslash, and non-ASCII escaping. The state includes terminal-result mailboxes, completion receipts, fixed history binding, opaque provider or agent continuation, TTL, ingestion and workflow bookkeeping, truncation evidence, media, and metadata. Backend framing outside that stored string remains backend-specific.

When a legacy 1.x entity is processed in Phase 2 (ProcessLegacyEntities = true), its state is converted to schema 2.0.0 before automatic retention runs. A deterministically impossible protected floor, including the accepted request for entity-owned history, is rejected before model/provider invocation.

Only conversationHistory transcript entries are eligible for pressure eviction. Mailbox result envelopes, completion receipts, fixed history binding, serialized continuation, TTL, and other execution controls are protected. Protection is a fixed-point connected-component closure over correlation membership and tool-call/result links. The actual newest entry and every entry containing a system message seed protection. Every entry in any reached non-null correlation is protected, and every occurrence of a reached non-empty tool ID is protected; newly reached entries recursively expand protection through their own correlation and tool links until closure. Missing or empty tool IDs create no cross-entry edge. Eviction removes only an oldest prefix of atomic components that remain disconnected from the protected closure. A component containing the newest entry or a system message can therefore connect to older history and raise the protected floor above the budget, in which case retention fails atomically without committing the working state.

In long client-side tool or approval flows, transitive correlation and tool links can connect most or all of the transcript to the protected newest component. If the protected floor reaches the configured budget, later writes fail atomically without corrupting the session. Use KeepAll or increase MaxStateBytes as a workaround while linked-flow support remains tracked under #4.

Schema 2 mailbox results remain authoritative after their transcript copies are removed, so duplicate execution and polling return the same retained result. Legacy state is converted to schema 2 before entity retention once history ownership can be resolved. Retention itself fails closed if legacy transcript terminals are still the only completion evidence.

If all eligible transcript is removed and the protected floor still reaches the high watermark, the operation fails with an InvalidOperationException describing the protected floor without committing the working state. Auto does not expire mailbox payloads; delivery expiry is a separate mailbox policy. Large inline image and tool-result offload is not part of this implementation.

Retention telemetry uses the agent_framework.durabletask meter and nine durable.retention.* instruments. These instrument names align with the Python retention implementation proposed in microsoft/agent-framework-durable-extension#123. Retention measurements carry mechanism, outcome, and commit_status; size measurements add phase, while write attempts add stage and operations identify whether deletion was staged. A host state setter returning is reported as commit status unknown, never as durable commit confirmation. Metrics contain no agent, session, correlation, or payload dimensions. Persisted evictedMessageCount evidence is a nonnegative signed Int64. Automatic retention uses the shared exact integer projection for recognized JSON integer spellings and checks every increment. If the selected eviction would exceed Int64.MaxValue, the operation fails atomically without committing transcript deletion, mailbox changes, receipts, or serialized session state. Sizing-only probes may project a larger hypothetical prefix at the maximum value so they do not reject a smaller feasible eviction; persisted evidence is never wrapped, clamped, saturated, or left stale. Telemetry continues to report the bounded message count removed by the current attempt rather than substituting for cumulative durable evidence.

Retention is separate from model-context compaction: retention destructively removes durable history only under storage pressure, while compaction changes the context supplied to the model. Auto is not FollowCompaction, and stateful compaction remains unsupported.

Retention metrics

The package emits automatic-retention metrics through the agent_framework.durabletask meter, with the package assembly version as its instrumentation scope version. Applications can subscribe by using the public DurableAgentTelemetry.MeterName constant. The OpenTelemetry SDK and exporter remain application choices; the product package depends only on System.Diagnostics.Metrics.

Instrument Type Unit Tags Meaning
durable.retention.evaluations Counter {evaluation} mechanism, outcome, commit_status Local pressure-retention evaluations.
durable.retention.budget Histogram By mechanism, outcome, commit_status Requested resolved whole-entity pressure budget.
durable.retention.state.size Histogram By mechanism, outcome, commit_status, phase Exact escaped storage-envelope bytes before and after the attempt.
durable.retention.removed_messages Counter {message} mechanism, outcome, commit_status Transcript messages removed from staged state by this attempt.
durable.retention.removed_entries Counter {entry} mechanism, outcome, commit_status Transcript entries removed from staged state, including zero-message entries.
durable.retention.reclaimed_bytes Counter By mechanism, outcome, commit_status Positive net serialized bytes reclaimed in staged state.
durable.retention.capacity_failures Counter {failure} mechanism, outcome, commit_status Attempts whose protected floor cannot reach the safe threshold.
durable.retention.write_attempts Counter {attempt} stage, outcome, commit_status, deletion_staged Serialization and host set-state outcomes, not durable commit confirmation.
durable.retention.operations Counter {operation} outcome, commit_status, deletion_staged Entity-operation outcome and the strongest host write status observed.

Pressure evaluation outcomes are below_threshold, staged, and protected_floor; write and operation outcomes are returned or failed. commit_status is not_attempted until a host state setter is reached and unknown afterward because this layer cannot observe durable confirmation. phase is before or after, and stage is serialization or set_state. Removing a zero-message entry increments the entry counter without incrementing the message counter, and reclaimed bytes are emitted only for a positive net reduction so truncation metadata never creates a negative measurement. KeepAll emits no retention metrics. Session IDs, correlation IDs, message IDs, content, exception text, and provider paths are never tags.

These are attempt-level operational metrics, not durable-state truth. Retention is evaluated before the entity operation commits, so a later scheduling, persistence, or retry failure can leave measurements for state that was not committed; retries can also record an attempt more than once. Exporters can buffer or drop telemetry. Reload persisted state and inspect model input or mailbox outcomes when validating committed behavior; do not rely on emitted counters alone or exact-once metric delivery. A metric observation is never evidence that the corresponding retained state committed.

Feedback & Contributing

We welcome feedback and contributions in our GitHub repo.

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Microsoft.Agents.AI.DurableTask:

Package Downloads
Microsoft.Agents.AI.Hosting.AzureFunctions

Provides durable agent hosting and orchestration support for Microsoft Agent Framework workloads.

ANcpLua.Agents.Hosting.Azure

Preview-channel Azure Functions hosting facades for Microsoft Agent Framework consumers.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.16.0-preview.261029.1 380 10/30/2026
1.16.0-preview.260922.1 4,265 9/24/2026
1.16.0-preview.260730.1 20,212 7/30/2026
1.15.0-preview.260722.1 1,388 7/22/2026
1.14.0-preview.260721.1 200 7/21/2026
1.13.0-preview.260703.1 5,510 7/3/2026
1.12.0-preview.260629.1 444 6/30/2026
1.11.1-preview.260625.1 269 6/25/2026
1.11.0-preview.260623.1 5,486 6/23/2026
1.10.0-preview.260610.1 6,628 6/10/2026
1.9.0-preview.260603.1 3,025 6/3/2026
1.8.0-preview.260528.1 762 5/28/2026
1.7.0-preview.260526.1 242 5/26/2026
1.6.2-preview.260521.1 294 5/22/2026
1.6.1-preview.260514.1 1,928 5/14/2026
1.6.0-preview.260512.1 124 5/13/2026
1.5.0-preview.260507.1 1,638 5/8/2026
1.4.0-preview.260505.1 7,501 5/5/2026
1.3.0-preview.260423.1 1,702 4/24/2026
1.2.0-preview.260421.1 177 4/21/2026
Loading failed