forked from microsoft/agent-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAIAgentExtensions.cs
More file actions
106 lines (94 loc) · 4.67 KB
/
Copy pathAIAgentExtensions.cs
File metadata and controls
106 lines (94 loc) · 4.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Threading;
using System.Threading.Tasks;
using A2A;
using Microsoft.Agents.AI.Hosting.A2A.Converters;
using Microsoft.Extensions.Logging;
namespace Microsoft.Agents.AI.Hosting.A2A;
/// <summary>
/// Provides extension methods for attaching A2A (Agent2Agent) messaging capabilities to an <see cref="AIAgent"/>.
/// </summary>
public static class AIAgentExtensions
{
/// <summary>
/// Attaches A2A (Agent2Agent) messaging capabilities via Message processing to the specified <see cref="AIAgent"/>.
/// </summary>
/// <param name="agent">Agent to attach A2A messaging processing capabilities to.</param>
/// <param name="taskManager">Instance of <see cref="TaskManager"/> to configure for A2A messaging. New instance will be created if not passed.</param>
/// <param name="loggerFactory">The logger factory to use for creating <see cref="ILogger"/> instances.</param>
/// <param name="agentThreadStore">The store to store thread contents and metadata.</param>
/// <returns>The configured <see cref="TaskManager"/>.</returns>
public static ITaskManager MapA2A(
this AIAgent agent,
ITaskManager? taskManager = null,
ILoggerFactory? loggerFactory = null,
AgentThreadStore? agentThreadStore = null)
{
ArgumentNullException.ThrowIfNull(agent);
ArgumentNullException.ThrowIfNull(agent.Name);
var hostAgent = new AIHostAgent(
innerAgent: agent,
threadStore: agentThreadStore ?? new NoopAgentThreadStore());
taskManager ??= new TaskManager();
taskManager.OnMessageReceived += OnMessageReceivedAsync;
return taskManager;
async Task<A2AResponse> OnMessageReceivedAsync(MessageSendParams messageSendParams, CancellationToken cancellationToken)
{
var contextId = messageSendParams.Message.ContextId ?? Guid.NewGuid().ToString("N");
var thread = await hostAgent.GetOrCreateThreadAsync(contextId, cancellationToken).ConfigureAwait(false);
var options = messageSendParams.Metadata is not { Count: > 0 }
? null
: new AgentRunOptions { AdditionalProperties = messageSendParams.Metadata.ToAdditionalProperties() };
var response = await hostAgent.RunAsync(
messageSendParams.ToChatMessages(),
thread: thread,
options: options,
cancellationToken: cancellationToken).ConfigureAwait(false);
await hostAgent.SaveThreadAsync(contextId, thread, cancellationToken).ConfigureAwait(false);
var parts = response.Messages.ToParts();
return new AgentMessage
{
MessageId = response.ResponseId ?? Guid.NewGuid().ToString("N"),
ContextId = contextId,
Role = MessageRole.Agent,
Parts = parts,
Metadata = response.AdditionalProperties?.ToA2AMetadata()
};
}
}
/// <summary>
/// Attaches A2A (Agent2Agent) messaging capabilities via Message processing to the specified <see cref="AIAgent"/>.
/// </summary>
/// <param name="agent">Agent to attach A2A messaging processing capabilities to.</param>
/// <param name="agentCard">The agent card to return on query.</param>
/// <param name="taskManager">Instance of <see cref="TaskManager"/> to configure for A2A messaging. New instance will be created if not passed.</param>
/// <param name="loggerFactory">The logger factory to use for creating <see cref="ILogger"/> instances.</param>
/// <param name="agentThreadStore">The store to store thread contents and metadata.</param>
/// <returns>The configured <see cref="TaskManager"/>.</returns>
public static ITaskManager MapA2A(
this AIAgent agent,
AgentCard agentCard,
ITaskManager? taskManager = null,
ILoggerFactory? loggerFactory = null,
AgentThreadStore? agentThreadStore = null)
{
taskManager = agent.MapA2A(taskManager, loggerFactory, agentThreadStore);
taskManager.OnAgentCardQuery += (context, query) =>
{
// A2A SDK assigns the url on its own
// we can help user if they did not set Url explicitly.
if (string.IsNullOrEmpty(agentCard.Url))
{
var agentCardUrl = context.TrimEnd('/');
if (!context.EndsWith("/v1/card", StringComparison.Ordinal))
{
agentCardUrl += "/v1/card";
}
agentCard.Url = agentCardUrl;
}
return Task.FromResult(agentCard);
};
return taskManager;
}
}