Skip to content
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
9f5a02c
implement task support?
DeagleGross Feb 6, 2026
0e642e1
some metadata + session store impl
DeagleGross Feb 6, 2026
a4238c2
address PR comments x1
DeagleGross Feb 11, 2026
f7ce096
API reivew
DeagleGross Feb 11, 2026
d1e5f99
llast changes
DeagleGross Feb 11, 2026
6ec30f0
More test
DeagleGross Feb 11, 2026
ed0fb38
Merge branch 'main' into dmkorolev/a2a-tasks
DeagleGross Feb 11, 2026
256121e
remove unsued import
DeagleGross Feb 11, 2026
45622d5
Merge branch 'dmkorolev/a2a-tasks' of https://github.com/microsoft/ag…
DeagleGross Feb 11, 2026
124407e
fix moq override
DeagleGross Feb 11, 2026
cef0b21
Merge branch 'main' into dmkorolev/a2a-tasks
DeagleGross Feb 12, 2026
2d30ce8
Merge branch 'main' into dmkorolev/a2a-tasks
DeagleGross Feb 20, 2026
1dceb1d
Merge branch 'dmkorolev/a2a-tasks' of https://github.com/microsoft/ag…
DeagleGross Feb 20, 2026
9966c42
refactoring
DeagleGross Feb 20, 2026
4c3b19c
ontaskupdated
DeagleGross Feb 20, 2026
febd97e
adjust to delegate
DeagleGross Feb 20, 2026
4a3b642
Merge branch 'main' into dmkorolev/a2a-tasks
DeagleGross Feb 20, 2026
b400bd8
Merge branch 'dmkorolev/a2a-tasks' of https://github.com/microsoft/ag…
DeagleGross Feb 20, 2026
5bb5939
fix encoding
DeagleGross Feb 20, 2026
5f63b8e
address PR comments: rework
DeagleGross Feb 23, 2026
579faaf
init 1
DeagleGross Feb 23, 2026
3de0627
renaming
DeagleGross Feb 23, 2026
ea428fb
fix tests
DeagleGross Feb 23, 2026
a2b47ac
fix comment
DeagleGross Feb 23, 2026
797f234
Merge branch 'main' into dmkorolev/a2a-tasks
DeagleGross Feb 23, 2026
d84213f
runmode rename
DeagleGross Feb 23, 2026
3aba021
rename
DeagleGross Feb 23, 2026
da94d01
rename
DeagleGross Feb 24, 2026
732900e
use exxperimental api, allow experimental on project level
DeagleGross Feb 24, 2026
a59ae7b
throw on refereceTaskIds
DeagleGross Feb 24, 2026
8f1836b
Merge branch 'main' into dmkorolev/a2a-tasks
DeagleGross Feb 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ public static class MicrosoftAgentAIHostingA2AEndpointRouteBuilderExtensions
public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpoints, IHostedAgentBuilder agentBuilder, string path)
=> endpoints.MapA2A(agentBuilder, path, _ => { });

/// <summary>
/// Attaches A2A (Agent2Agent) communication capabilities via Message processing to the specified web application.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the A2A endpoints to.</param>
/// <param name="agentBuilder">The configuration builder for <see cref="AIAgent"/>.</param>
/// <param name="path">The route group to use for A2A endpoints.</param>
/// <param name="agentRunMode">Controls the response behavior of the agent run.</param>
/// <returns>Configured <see cref="ITaskManager"/> for A2A integration.</returns>
public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpoints, IHostedAgentBuilder agentBuilder, string path, AgentRunMode agentRunMode)
{
ArgumentNullException.ThrowIfNull(agentBuilder);
return endpoints.MapA2A(agentBuilder.Name, path, agentRunMode);
}

/// <summary>
/// Attaches A2A (Agent2Agent) communication capabilities via Message processing to the specified web application.
/// </summary>
Expand All @@ -43,6 +57,21 @@ public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpo
public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpoints, string agentName, string path)
=> endpoints.MapA2A(agentName, path, _ => { });

/// <summary>
/// Attaches A2A (Agent2Agent) communication capabilities via Message processing to the specified web application.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the A2A endpoints to.</param>
/// <param name="agentName">The name of the agent to use for A2A protocol integration.</param>
/// <param name="path">The route group to use for A2A endpoints.</param>
/// <param name="agentRunMode">Controls the response behavior of the agent run.</param>
/// <returns>Configured <see cref="ITaskManager"/> for A2A integration.</returns>
public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpoints, string agentName, string path, AgentRunMode agentRunMode)
{
ArgumentNullException.ThrowIfNull(endpoints);
var agent = endpoints.ServiceProvider.GetRequiredKeyedService<AIAgent>(agentName);
return endpoints.MapA2A(agent, path, _ => { }, agentRunMode);
}

/// <summary>
/// Attaches A2A (Agent2Agent) communication capabilities via Message processing to the specified web application.
/// </summary>
Expand Down Expand Up @@ -109,6 +138,37 @@ public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpo
public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpoints, string agentName, string path, AgentCard agentCard)
=> endpoints.MapA2A(agentName, path, agentCard, _ => { });

/// <summary>
/// Attaches A2A (Agent2Agent) communication capabilities via Message processing to the specified web application.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the A2A endpoints to.</param>
/// <param name="agentBuilder">The configuration builder for <see cref="AIAgent"/>.</param>
/// <param name="path">The route group to use for A2A endpoints.</param>
/// <param name="agentCard">Agent card info to return on query.</param>
/// <param name="agentRunMode">Controls the response behavior of the agent run.</param>
/// <returns>Configured <see cref="ITaskManager"/> for A2A integration.</returns>
public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpoints, IHostedAgentBuilder agentBuilder, string path, AgentCard agentCard, AgentRunMode agentRunMode)
{
ArgumentNullException.ThrowIfNull(agentBuilder);
return endpoints.MapA2A(agentBuilder.Name, path, agentCard, agentRunMode);
}

/// <summary>
/// Attaches A2A (Agent2Agent) communication capabilities via Message processing to the specified web application.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the A2A endpoints to.</param>
/// <param name="agentName">The name of the agent to use for A2A protocol integration.</param>
/// <param name="path">The route group to use for A2A endpoints.</param>
/// <param name="agentCard">Agent card info to return on query.</param>
/// <param name="agentRunMode">Controls the response behavior of the agent run.</param>
/// <returns>Configured <see cref="ITaskManager"/> for A2A integration.</returns>
public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpoints, string agentName, string path, AgentCard agentCard, AgentRunMode agentRunMode)
{
ArgumentNullException.ThrowIfNull(endpoints);
var agent = endpoints.ServiceProvider.GetRequiredKeyedService<AIAgent>(agentName);
return endpoints.MapA2A(agent, path, agentCard, agentRunMode);
}

/// <summary>
/// Attaches A2A (Agent2Agent) communication capabilities via Message processing to the specified web application.
/// </summary>
Expand Down Expand Up @@ -144,10 +204,28 @@ public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpo
/// discovery mechanism.
/// </remarks>
public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpoints, string agentName, string path, AgentCard agentCard, Action<ITaskManager> configureTaskManager)
=> endpoints.MapA2A(agentName, path, agentCard, configureTaskManager, AgentRunMode.NonBackground);

/// <summary>
/// Attaches A2A (Agent2Agent) communication capabilities via Message processing to the specified web application.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the A2A endpoints to.</param>
/// <param name="agentName">The name of the agent to use for A2A protocol integration.</param>
/// <param name="path">The route group to use for A2A endpoints.</param>
/// <param name="agentCard">Agent card info to return on query.</param>
/// <param name="configureTaskManager">The callback to configure <see cref="ITaskManager"/>.</param>
/// <param name="agentRunMode">Controls the response behavior of the agent run.</param>
/// <returns>Configured <see cref="ITaskManager"/> for A2A integration.</returns>
/// <remarks>
/// This method can be used to access A2A agents that support the
/// <see href="https://github.com/a2aproject/A2A/blob/main/docs/topics/agent-discovery.md#2-curated-registries-catalog-based-discovery">Curated Registries (Catalog-Based Discovery)</see>
/// discovery mechanism.
/// </remarks>
public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpoints, string agentName, string path, AgentCard agentCard, Action<ITaskManager> configureTaskManager, AgentRunMode agentRunMode)
{
ArgumentNullException.ThrowIfNull(endpoints);
var agent = endpoints.ServiceProvider.GetRequiredKeyedService<AIAgent>(agentName);
return endpoints.MapA2A(agent, path, agentCard, configureTaskManager);
return endpoints.MapA2A(agent, path, agentCard, configureTaskManager, agentRunMode);
}

/// <summary>
Expand All @@ -160,6 +238,17 @@ public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpo
public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpoints, AIAgent agent, string path)
=> endpoints.MapA2A(agent, path, _ => { });

/// <summary>
/// Attaches A2A (Agent2Agent) communication capabilities via Message processing to the specified web application.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the A2A endpoints to.</param>
/// <param name="agent">The agent to use for A2A protocol integration.</param>
/// <param name="path">The route group to use for A2A endpoints.</param>
/// <param name="agentRunMode">Controls the response behavior of the agent run.</param>
/// <returns>Configured <see cref="ITaskManager"/> for A2A integration.</returns>
public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpoints, AIAgent agent, string path, AgentRunMode agentRunMode)
=> endpoints.MapA2A(agent, path, _ => { }, agentRunMode);

/// <summary>
/// Attaches A2A (Agent2Agent) communication capabilities via Message processing to the specified web application.
/// </summary>
Expand All @@ -169,13 +258,25 @@ public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpo
/// <param name="configureTaskManager">The callback to configure <see cref="ITaskManager"/>.</param>
/// <returns>Configured <see cref="ITaskManager"/> for A2A integration.</returns>
public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpoints, AIAgent agent, string path, Action<ITaskManager> configureTaskManager)
=> endpoints.MapA2A(agent, path, configureTaskManager, AgentRunMode.NonBackground);

/// <summary>
/// Attaches A2A (Agent2Agent) communication capabilities via Message processing to the specified web application.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the A2A endpoints to.</param>
/// <param name="agent">The agent to use for A2A protocol integration.</param>
/// <param name="path">The route group to use for A2A endpoints.</param>
/// <param name="configureTaskManager">The callback to configure <see cref="ITaskManager"/>.</param>
/// <param name="agentRunMode">Controls the response behavior of the agent run.</param>
/// <returns>Configured <see cref="ITaskManager"/> for A2A integration.</returns>
public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpoints, AIAgent agent, string path, Action<ITaskManager> configureTaskManager, AgentRunMode agentRunMode)
{
ArgumentNullException.ThrowIfNull(endpoints);
ArgumentNullException.ThrowIfNull(agent);

var loggerFactory = endpoints.ServiceProvider.GetRequiredService<ILoggerFactory>();
var agentSessionStore = endpoints.ServiceProvider.GetKeyedService<AgentSessionStore>(agent.Name);
var taskManager = agent.MapA2A(loggerFactory: loggerFactory, agentSessionStore: agentSessionStore);
var taskManager = agent.MapA2A(loggerFactory: loggerFactory, agentSessionStore: agentSessionStore, runMode: agentRunMode);
var endpointConventionBuilder = endpoints.MapA2A(taskManager, path);

configureTaskManager(taskManager);
Expand All @@ -198,6 +299,23 @@ public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpo
public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpoints, AIAgent agent, string path, AgentCard agentCard)
=> endpoints.MapA2A(agent, path, agentCard, _ => { });

/// <summary>
/// Attaches A2A (Agent2Agent) communication capabilities via Message processing to the specified web application.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the A2A endpoints to.</param>
/// <param name="agent">The agent to use for A2A protocol integration.</param>
/// <param name="path">The route group to use for A2A endpoints.</param>
/// <param name="agentCard">Agent card info to return on query.</param>
/// <param name="agentRunMode">Controls the response behavior of the agent run.</param>
/// <returns>Configured <see cref="ITaskManager"/> for A2A integration.</returns>
/// <remarks>
/// This method can be used to access A2A agents that support the
/// <see href="https://github.com/a2aproject/A2A/blob/main/docs/topics/agent-discovery.md#2-curated-registries-catalog-based-discovery">Curated Registries (Catalog-Based Discovery)</see>
/// discovery mechanism.
/// </remarks>
public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpoints, AIAgent agent, string path, AgentCard agentCard, AgentRunMode agentRunMode)
=> endpoints.MapA2A(agent, path, agentCard, _ => { }, agentRunMode);

/// <summary>
/// Attaches A2A (Agent2Agent) communication capabilities via Message processing to the specified web application.
/// </summary>
Expand All @@ -213,13 +331,31 @@ public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpo
/// discovery mechanism.
/// </remarks>
public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpoints, AIAgent agent, string path, AgentCard agentCard, Action<ITaskManager> configureTaskManager)
=> endpoints.MapA2A(agent, path, agentCard, configureTaskManager, AgentRunMode.NonBackground);

/// <summary>
/// Attaches A2A (Agent2Agent) communication capabilities via Message processing to the specified web application.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the A2A endpoints to.</param>
/// <param name="agent">The agent to use for A2A protocol integration.</param>
/// <param name="path">The route group to use for A2A endpoints.</param>
/// <param name="agentCard">Agent card info to return on query.</param>
/// <param name="configureTaskManager">The callback to configure <see cref="ITaskManager"/>.</param>
/// <param name="agentRunMode">Controls the response behavior of the agent run.</param>
/// <returns>Configured <see cref="ITaskManager"/> for A2A integration.</returns>
/// <remarks>
/// This method can be used to access A2A agents that support the
/// <see href="https://github.com/a2aproject/A2A/blob/main/docs/topics/agent-discovery.md#2-curated-registries-catalog-based-discovery">Curated Registries (Catalog-Based Discovery)</see>
/// discovery mechanism.
/// </remarks>
public static IEndpointConventionBuilder MapA2A(this IEndpointRouteBuilder endpoints, AIAgent agent, string path, AgentCard agentCard, Action<ITaskManager> configureTaskManager, AgentRunMode agentRunMode)
{
ArgumentNullException.ThrowIfNull(endpoints);
ArgumentNullException.ThrowIfNull(agent);

var loggerFactory = endpoints.ServiceProvider.GetRequiredService<ILoggerFactory>();
var agentSessionStore = endpoints.ServiceProvider.GetKeyedService<AgentSessionStore>(agent.Name);
var taskManager = agent.MapA2A(agentCard: agentCard, agentSessionStore: agentSessionStore, loggerFactory: loggerFactory);
var taskManager = agent.MapA2A(agentCard: agentCard, agentSessionStore: agentSessionStore, loggerFactory: loggerFactory, runMode: agentRunMode);
var endpointConventionBuilder = endpoints.MapA2A(taskManager, path);

configureTaskManager(taskManager);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Text.Json;

namespace Microsoft.Agents.AI.Hosting.A2A;

/// <summary>
/// Provides JSON serialization options for A2A Hosting APIs to support AOT and trimming.
/// </summary>
public static class A2AHostingJsonUtilities
Comment thread
SergeyMenshykh marked this conversation as resolved.
{
/// <summary>
/// Gets the default <see cref="JsonSerializerOptions"/> instance used for A2A Hosting serialization.
/// </summary>
public static JsonSerializerOptions DefaultOptions { get; } = CreateDefaultOptions();

private static JsonSerializerOptions CreateDefaultOptions()
{
JsonSerializerOptions options = new(global::A2A.A2AJsonUtilities.DefaultOptions);

// Chain in the resolvers from both AgentAbstractionsJsonUtilities and the A2A SDK context.
// AgentAbstractionsJsonUtilities is first to ensure M.E.AI types (e.g. ResponseContinuationToken)
// are handled via its resolver, followed by the A2A SDK resolver for protocol types.
options.TypeInfoResolverChain.Clear();
options.TypeInfoResolverChain.Add(AgentAbstractionsJsonUtilities.DefaultOptions.TypeInfoResolver!);
options.TypeInfoResolverChain.Add(global::A2A.A2AJsonUtilities.DefaultOptions.TypeInfoResolver!);

options.MakeReadOnly();
return options;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) Microsoft. All rights reserved.

using A2A;

namespace Microsoft.Agents.AI.Hosting.A2A;

/// <summary>
/// Provides context for a custom A2A run mode decision.
/// </summary>
public sealed class A2ARunDecisionContext
{
internal A2ARunDecisionContext(MessageSendParams messageSendParams)
{
this.MessageSendParams = messageSendParams;
}

/// <summary>
/// Gets the parameters of the incoming A2A message that triggered this run.
/// </summary>
public MessageSendParams MessageSendParams { get; }
}
Loading
Loading