Skip to content

.NET: Require TODO finish reason and rename SubAgents to BackgroundAgents#5902

Open
westey-m wants to merge 1 commit into
microsoft:mainfrom
westey-m:todo-finish-reason-async-background-rename
Open

.NET: Require TODO finish reason and rename SubAgents to BackgroundAgents#5902
westey-m wants to merge 1 commit into
microsoft:mainfrom
westey-m:todo-finish-reason-async-background-rename

Conversation

@westey-m
Copy link
Copy Markdown
Contributor

Motivation and Context

SubAgents are not well named, since it can be confused with cases where we merely delegate to a sub agent in a synchronous way.

Description

  • Renaming SubAgents to BackgroundAgents to clarify that they provide background asynchronous processing.
  • Adding a reason when completing a TODO, to improve user output.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR follows the Contribution Guidelines
  • All unit tests pass, and I have added new tests where possible
  • Is this a breaking change? If yes, add "[BREAKING]" prefix to the title of the PR.

Copilot AI review requested due to automatic review settings May 15, 2026 18:25
@moonbox3 moonbox3 added documentation Improvements or additions to documentation .NET labels May 15, 2026
@github-actions github-actions Bot changed the title Require TODO finish reason and rename SubAgents to BackgroundAgents .NET: Require TODO finish reason and rename SubAgents to BackgroundAgents May 15, 2026
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Automated Code Review

Reviewers: 4 | Confidence: 85%

✓ Correctness

No actionable issues found in this dimension.

✓ Security Reliability

No actionable issues found in this dimension.

✓ Test Coverage

The BackgroundAgents rename is thoroughly tested across all tool name references and instruction strings. For the TodoProvider changes, existing tests are updated to use the new TodoCompleteInput type and a new test verifies the Reason parameter is accepted. However, the new CompleteTodos_AcceptsReasonParameterAsync test only asserts that the item is marked complete and the count is correct—it does not verify that the provided Reason is actually used or surfaced in any output, which is a gap given the PR states the reason is meant to 'improve user output'. Since TodoItem.cs is not in the changed file list, the Reason appears not to be stored on the model, making the observable impact of the Reason field untested.

✓ Design Approach

First, the SubAgents→BackgroundAgents rename also changes the persisted state keys, so any existing session that already has queued/running sub-agent work will be treated as empty after upgrade instead of being recoverable or marked lost. Second, the new Todo completion shape does not actually require a completion reason: the new input model makes reason nullable and the handler ignores it entirely, so calls without a reason still succeed despite the new contract text. I found two design mismatches in the updated tests. First, the TodoList completion flow is still being specified as succeeding without any finish reason, which conflicts with the PR’s stated goal of requiring one. Second, the BackgroundAgents rename appears incomplete on the custom-instructions surface: the tests still use the old {sub_agents} placeholder, which would leave {background_agents} callers with an unreplaced literal unless the provider supports both tokens.


Automated review by westey-m's agents

_ => new SubAgentState(),
this._sessionState = new ProviderSessionState<BackgroundAgentState>(
_ => new BackgroundAgentState(),
this.GetType().Name,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The rename changes the session-state key from SubAgentsProvider to BackgroundAgentsProvider. Since ProviderSessionState.GetOrInitializeState initializes fresh state when the exact key is missing, an upgraded app will silently lose all previously persisted sub-agent task metadata instead of surfacing it or marking it lost. Consider preserving the legacy key or adding a migration/fallback path.

}

/// <summary>
/// Verify that CompleteTodos accepts an optional reason parameter.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This test completes a TODO without providing a reason and asserts success, effectively blessing the old TodoList_Complete(items:[{ id }]) path. If the PR's intent is to require a reason, this test should instead assert that missing reasons are rejected.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the .NET Harness to (1) rename “SubAgents” to “BackgroundAgents” to better reflect asynchronous background execution, and (2) extend Todo completion calls to include an optional “reason” payload for improved UI output.

Changes:

  • Renames SubAgents provider/types/tool names to BackgroundAgents across src, tests, and samples.
  • Changes TodoList_Complete input shape from ids to items[] (with optional reason) and updates tests/JSON source-gen registration accordingly.
  • Updates Harness sample Step02 and console tool formatters to reflect the new names and richer Todo completion formatting.

Reviewed changes

Copilot reviewed 18 out of 19 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
dotnet/tests/Microsoft.Agents.AI.UnitTests/Harness/Todo/TodoProviderTests.cs Updates tests for new TodoList_Complete argument shape and adds reason acceptance test.
dotnet/tests/Microsoft.Agents.AI.UnitTests/Harness/BackgroundAgents/BackgroundAgentsProviderTests.cs Renames tests and tool names from SubAgents to BackgroundAgents.
dotnet/src/Microsoft.Agents.AI/Harness/Todo/TodoProvider.cs Updates TodoList_Complete tool signature/description and default instructions.
dotnet/src/Microsoft.Agents.AI/Harness/Todo/TodoCompleteInput.cs Adds new input model for todo completion (id + optional reason).
dotnet/src/Microsoft.Agents.AI/Harness/BackgroundAgents/BackgroundTaskStatus.cs Renames status enum to BackgroundTaskStatus and updates docs.
dotnet/src/Microsoft.Agents.AI/Harness/BackgroundAgents/BackgroundTaskInfo.cs Renames task metadata type and updates status type usage.
dotnet/src/Microsoft.Agents.AI/Harness/BackgroundAgents/BackgroundAgentState.cs Renames serializable state container and task list type.
dotnet/src/Microsoft.Agents.AI/Harness/BackgroundAgents/BackgroundAgentsProviderOptions.cs Renames options type and updates docs for BackgroundAgents.
dotnet/src/Microsoft.Agents.AI/Harness/BackgroundAgents/BackgroundAgentsProvider.cs Renames provider and tool names; updates instructions and implementation text.
dotnet/src/Microsoft.Agents.AI/Harness/BackgroundAgents/BackgroundAgentRuntimeState.cs Renames runtime state type and session dictionary name.
dotnet/src/Microsoft.Agents.AI/AgentJsonUtilities.cs Registers new TodoCompleteInput types and renamed BackgroundAgents types for STJ source gen.
dotnet/samples/02-agents/Harness/README.md Updates sample list entry and link to BackgroundAgents sample.
dotnet/samples/02-agents/Harness/Harness_Step02_Research_WithBackgroundAgents/README.md Updates sample docs and instructions to BackgroundAgents terminology.
dotnet/samples/02-agents/Harness/Harness_Step02_Research_WithBackgroundAgents/Program.cs Updates sample code to use BackgroundAgentsProvider.
dotnet/samples/02-agents/Harness/Harness_Step02_Research_WithBackgroundAgents/Harness_Step02_Research_WithBackgroundAgents.csproj Adds the renamed/new sample project file.
dotnet/samples/02-agents/Harness/Harness_Shared_Console/ToolFormatters/ToolCallFormatter.cs Switches default formatter list to BackgroundAgentToolFormatter.
dotnet/samples/02-agents/Harness/Harness_Shared_Console/ToolFormatters/TodoToolFormatter.cs Adds formatting for new TodoList_Complete(items[]) payload including reason.
dotnet/samples/02-agents/Harness/Harness_Shared_Console/ToolFormatters/BackgroundAgentToolFormatter.cs Renames formatter/class and switches matching to BackgroundAgents_*.
dotnet/agent-framework-dotnet.slnx Updates solution to reference the renamed Step02 sample project.
Comments suppressed due to low confidence (2)

dotnet/src/Microsoft.Agents.AI/Harness/BackgroundAgents/BackgroundAgentsProvider.cs:40

  • This change renames/removes the public SubAgentsProvider API (and tool names) in favor of BackgroundAgentsProvider, which is a breaking change for any consumers. Please either preserve backward compatibility (e.g., keep SubAgentsProvider/old tool names as [Obsolete] shims) or mark the PR as breaking (title/release notes) so downstream users can migrate deliberately.
    dotnet/src/Microsoft.Agents.AI/Harness/BackgroundAgents/BackgroundAgentsProviderOptions.cs:22
  • The instructions/template placeholder is still named {sub_agents} even though the feature has been renamed to BackgroundAgents. This is likely to confuse users authoring custom instructions. Consider supporting a {background_agents} placeholder (while still honoring {sub_agents} for compatibility), and update the docs/comments accordingly.

Comment on lines +80 to +83
int id = item.TryGetProperty("id", out JsonElement idElement) ? idElement.GetInt32() : 0;
string? reason = item.TryGetProperty("reason", out JsonElement reasonElement)
? reasonElement.GetString()
: null;
Use these tools to manage your tasks:
- Use TodoList_Add to break down complex work into trackable items (supports adding one or many at once).
- Use TodoList_Complete to mark items as done when finished (supports one or many at once).
- Use TodoList_Complete to mark items as done when finished (supports one or many at once). Include a reason describing how the items were completed.
Comment on lines 235 to 246
}),

AIFunctionFactory.Create(
async (List<int> ids) =>
async (List<TodoCompleteInput> items) =>
{
SemaphoreSlim sessionLock = this.GetSessionLock(session);
await sessionLock.WaitAsync().ConfigureAwait(false);
try
{
TodoState state = this._sessionState.GetOrInitializeState(session);
var idSet = new HashSet<int>(ids);
var idSet = new HashSet<int>(items.Select(i => i.Id));
int completed = 0;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation .NET

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants