Skip to content

.NET: Terminating a Harness tool loop can omit completed function results from session history #9435

Description

Problem

With Microsoft.Agents.AI / Microsoft.Agents.AI.Harness 1.24.0, stopping a Harness tool loop through the documented FunctionInvocationContext.Terminate flag can leave the serialized session without the results of functions which have completed. A later run on the same session then lacks that evidence.

We discovered this while implementing incoming user corrections for an in-process channel Agent. We now use the existing native MessageInjectingChatClient.EnqueueMessagesAsync path for text steering instead of termination. This report concerns the termination/persistence contract, not a request to add a message injection API that already exists.

Application Reproduction and Evidence

  1. Create a HarnessAgent with an in-memory chat history provider and a real tool.
  2. The first model response requests one or two calls to that tool.
  3. Use function invocation middleware. Await next(context, cancellationToken); only on the final FunctionCallIndex == FunctionCount - 1, set context.Terminate = true when a new user correction is pending.
  4. Await the agent run, serialize its session using the normal agent API, restore it, and start the next run with the user's new messages.
  5. Inspect the next model request.

Our application integration tests against a real HTTP protocol test provider observed both cases fail: the next request retained the original user input and the new messages, but contained zero tool-result messages instead of the expected one/two. The no-tool control passed. This is application-level evidence; we have not yet reduced it to a standalone upstream unit test.

The relevant source explains the apparent gap:

The suspected result is that termination prevents the next service call that would otherwise persist the completed function-result input. Please confirm the intended contract.

Expected Behavior

After a successful run that ends through FunctionInvocationContext.Terminate, serializing/restoring its session preserves complete matching call/result pairs for every function that actually completed. Resuming must not lose those results or cause side-effecting tools to be repeated.

If termination deliberately cannot provide that guarantee with per-service-call persistence, please document that restriction on the public flag and describe a supported checkpoint/resume pattern. The native message injection queue is suitable for ordinary text steering, but does not define the full semantics of deliberate termination.

Alternatives Considered

  • We use native message injection for incoming text corrections. This keeps the function loop and its normal history persistence intact.
  • We did not disable Harness persistence, manually mutate its serialized JSON, recreate tool results, or run concurrent turns on one session.
  • Cancelling tools cannot establish that external side effects stopped and is not a safe substitute for completed result persistence.

Scope

.NET Harness, function middleware, native session serialization and per-service-call persistence. One- and multiple-function batches, with regression coverage for session reuse after termination. No request to cancel already committed effects or to replace application-owned routing and durable admission.

Language

.NET

Activity

  1. added
    .NETUsage: [Issues, PRs], Target: .Net
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 15, 2026
  2. removed
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 15, 2026
  3. changed the title [-].NET: [Feature]: In-process active-run steering at safe tool-batch boundaries[/-] [+].NET: Terminating a Harness tool loop can omit completed function results from session history[/+] on Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

.NETUsage: [Issues, PRs], Target: .NetagentsUsage: [Issues, PRs], Target: Single agent

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions