diff --git a/BotSharp.sln b/BotSharp.sln
index b87060e96..5d3ce6b54 100644
--- a/BotSharp.sln
+++ b/BotSharp.sln
@@ -153,7 +153,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.MMPEmbeddin
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.Membase", "src\Plugins\BotSharp.Plugin.Membase\BotSharp.Plugin.Membase.csproj", "{13223C71-9EAC-9835-28ED-5A4833E6F915}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MultiTenancy", "MultiTenancy", "{7C64208C-8D11-4E17-A3E9-14D7910763EB}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Core.A2A", "src\Infrastructure\BotSharp.Core.A2A\BotSharp.Core.A2A.csproj", "{E8D01281-D52A-BFF4-33DB-E35D91754272}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.MultiTenancy", "src\Plugins\BotSharp.Plugin.MultiTenancy\BotSharp.Plugin.MultiTenancy.csproj", "{9BC8DF43-88D1-4C57-A678-AC0153BDF4EB}"
EndProject
@@ -653,6 +653,14 @@ Global
{13223C71-9EAC-9835-28ED-5A4833E6F915}.Release|Any CPU.Build.0 = Release|Any CPU
{13223C71-9EAC-9835-28ED-5A4833E6F915}.Release|x64.ActiveCfg = Release|Any CPU
{13223C71-9EAC-9835-28ED-5A4833E6F915}.Release|x64.Build.0 = Release|Any CPU
+ {E8D01281-D52A-BFF4-33DB-E35D91754272}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E8D01281-D52A-BFF4-33DB-E35D91754272}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E8D01281-D52A-BFF4-33DB-E35D91754272}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E8D01281-D52A-BFF4-33DB-E35D91754272}.Debug|x64.Build.0 = Debug|Any CPU
+ {E8D01281-D52A-BFF4-33DB-E35D91754272}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E8D01281-D52A-BFF4-33DB-E35D91754272}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E8D01281-D52A-BFF4-33DB-E35D91754272}.Release|x64.ActiveCfg = Release|Any CPU
+ {E8D01281-D52A-BFF4-33DB-E35D91754272}.Release|x64.Build.0 = Release|Any CPU
{9BC8DF43-88D1-4C57-A678-AC0153BDF4EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9BC8DF43-88D1-4C57-A678-AC0153BDF4EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9BC8DF43-88D1-4C57-A678-AC0153BDF4EB}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -735,7 +743,7 @@ Global
{E7C243B9-E751-B3B4-8F16-95C76CA90D31} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
{394B858B-9C26-B977-A2DA-8CC7BE5914CB} = {4F346DCE-087F-4368-AF88-EE9C720D0E69}
{13223C71-9EAC-9835-28ED-5A4833E6F915} = {53E7CD86-0D19-40D9-A0FA-AB4613837E89}
- {7C64208C-8D11-4E17-A3E9-14D7910763EB} = {2635EC9B-2E5F-4313-AC21-0B847F31F36C}
+ {E8D01281-D52A-BFF4-33DB-E35D91754272} = {E29DC6C4-5E57-48C5-BCB0-6B8F84782749}
{9BC8DF43-88D1-4C57-A678-AC0153BDF4EB} = {7C64208C-8D11-4E17-A3E9-14D7910763EB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 35f37271c..1c198a828 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -3,6 +3,7 @@
true
+
diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentType.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentType.cs
index 3b9767845..9f79ef333 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentType.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentType.cs
@@ -23,5 +23,10 @@ public static class AgentType
/// Agent that cannot use external tools
///
public const string Static = "static";
+
+ ///
+ /// A2A remote agent for Microsoft Agent Framework integration
+ ///
+ public const string A2ARemote = "a2a-remote";
}
diff --git a/src/Infrastructure/BotSharp.Core.A2A/A2APlugin.cs b/src/Infrastructure/BotSharp.Core.A2A/A2APlugin.cs
new file mode 100644
index 000000000..f8a5553c0
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Core.A2A/A2APlugin.cs
@@ -0,0 +1,36 @@
+using BotSharp.Abstraction.Agents;
+using BotSharp.Abstraction.Conversations;
+using BotSharp.Abstraction.Functions;
+using BotSharp.Abstraction.Plugins;
+using BotSharp.Abstraction.Settings;
+using BotSharp.Core.A2A.Functions;
+using BotSharp.Core.A2A.Hooks;
+using BotSharp.Core.A2A.Services;
+using BotSharp.Core.A2A.Settings;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace BotSharp.Core.A2A;
+
+public class A2APlugin : IBotSharpPlugin
+{
+
+ public string Id => "058cdf87-fcf3-eda9-915a-565c04bc9f56";
+
+ public string Name => "A2A Protocol Integration";
+
+ public string Description => "Enables seamless integration with external agents via the Agent-to-Agent (A2A) protocol.";
+
+ public void RegisterDI(IServiceCollection services, IConfiguration config)
+ {
+ services.AddScoped(provider =>
+ {
+ var settingService = provider.GetRequiredService();
+ return settingService.Bind("A2AIntegration");
+ });
+
+ services.AddScoped();
+ services.AddScoped();
+ services.AddScoped();
+ }
+}
diff --git a/src/Infrastructure/BotSharp.Core.A2A/BotSharp.Core.A2A.csproj b/src/Infrastructure/BotSharp.Core.A2A/BotSharp.Core.A2A.csproj
new file mode 100644
index 000000000..c91cc0d54
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Core.A2A/BotSharp.Core.A2A.csproj
@@ -0,0 +1,21 @@
+
+
+
+ $(TargetFramework)
+ $(LangVersion)
+ $(BotSharpVersion)
+ $(GeneratePackageOnBuild)
+ $(SolutionDir)packages
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Infrastructure/BotSharp.Core.A2A/Functions/A2ADelegationFn.cs b/src/Infrastructure/BotSharp.Core.A2A/Functions/A2ADelegationFn.cs
new file mode 100644
index 000000000..959267e57
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Core.A2A/Functions/A2ADelegationFn.cs
@@ -0,0 +1,65 @@
+using BotSharp.Abstraction.Conversations;
+using BotSharp.Abstraction.Conversations.Models;
+using BotSharp.Abstraction.Functions;
+using BotSharp.Core.A2A.Services;
+using BotSharp.Core.A2A.Settings;
+using System.Text.Json;
+
+namespace BotSharp.Core.A2A.Functions;
+
+public class A2ADelegationFn : IFunctionCallback
+{
+ public string Name => "delegate_to_a2a";
+ public string Indication => "Connecting to external agent network...";
+
+ private readonly IA2AService _a2aService;
+ private readonly A2ASettings _settings;
+ private readonly IConversationStateService _stateService;
+
+ public A2ADelegationFn(IA2AService a2aService, A2ASettings settings, IConversationStateService stateService)
+ {
+ _a2aService = a2aService;
+ _settings = settings;
+ _stateService = stateService;
+ }
+
+ public async Task Execute(RoleDialogModel message)
+ {
+ var args = JsonSerializer.Deserialize(message.FunctionArgs);
+ string queryText = string.Empty;
+ if (args.TryGetProperty("user_query", out var queryProp))
+ {
+ queryText = queryProp.GetString();
+ }
+
+ var agentId = message.CurrentAgentId;
+ var agentConfig = _settings.Agents.FirstOrDefault(x => x.Id == agentId);
+
+ if (agentConfig == null)
+ {
+ message.Content = "System Error: Remote agent configuration not found.";
+ message.StopCompletion = true;
+ return false;
+ }
+
+ var conversationId = _stateService.GetConversationId();
+
+ try
+ {
+ var responseText = await _a2aService.SendMessageAsync(
+ agentConfig.Endpoint,
+ queryText,
+ conversationId,
+ CancellationToken.None
+ );
+
+ message.Content = responseText;
+ return true;
+ }
+ catch (Exception ex)
+ {
+ message.Content = $"Communication failure with external agent: {ex.Message}";
+ return false;
+ }
+ }
+}
diff --git a/src/Infrastructure/BotSharp.Core.A2A/Hooks/A2AAgentHook.cs b/src/Infrastructure/BotSharp.Core.A2A/Hooks/A2AAgentHook.cs
new file mode 100644
index 000000000..48aae9727
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Core.A2A/Hooks/A2AAgentHook.cs
@@ -0,0 +1,85 @@
+using BotSharp.Abstraction.Agents;
+using BotSharp.Abstraction.Agents.Enums;
+using BotSharp.Abstraction.Agents.Models;
+using BotSharp.Abstraction.Agents.Settings;
+using BotSharp.Abstraction.Functions.Models;
+using BotSharp.Core.A2A.Services;
+using BotSharp.Core.A2A.Settings;
+using System.Text.Json;
+
+namespace BotSharp.Core.A2A.Hooks;
+
+public class A2AAgentHook : AgentHookBase
+{
+ public override string SelfId => string.Empty;
+
+ private readonly A2ASettings _settings;
+ private readonly IA2AService _iA2AService;
+
+ public A2AAgentHook(IServiceProvider services, IA2AService a2AService, A2ASettings settings)
+ : base(services, new AgentSettings())
+ {
+ _iA2AService = a2AService;
+ _settings = settings;
+ }
+
+ public override bool OnAgentLoading(ref string id)
+ {
+ var agentId = id;
+ var remoteConfig = _settings.Agents.FirstOrDefault(x => x.Id == agentId);
+ if (remoteConfig != null)
+ {
+ return true;
+ }
+ return base.OnAgentLoading(ref id);
+ }
+
+ public override void OnAgentLoaded(Agent agent)
+ {
+ // Check if this is an A2A remote agent
+ if (agent.Type != AgentType.A2ARemote)
+ {
+ return;
+ }
+
+ var remoteConfig = _settings.Agents.FirstOrDefault(x => x.Id == agent.Id);
+ if (remoteConfig != null)
+ {
+ var agentCard = _iA2AService.GetCapabilitiesAsync(remoteConfig.Endpoint).GetAwaiter().GetResult();
+ agent.Name = agentCard.Name;
+ agent.Description = agentCard.Description;
+ agent.Instruction = $"You are a proxy interface for an external intelligent service named '{agentCard.Name}'. " +
+ $"Your ONLY goal is to forward the user's request verbatim to the external service. " +
+ $"You must use the function 'delegate_to_a2a' to communicate with it. " +
+ $"Do not attempt to answer the question yourself.";
+
+ var properties = new Dictionary
+ {
+ {
+ "user_query",
+ new
+ {
+ type = "string",
+ description = "The exact user request or task description to be forwarded."
+ }
+ }
+ };
+
+ var propertiesJson = JsonSerializer.Serialize(properties);
+ var propertiesDocument = JsonDocument.Parse(propertiesJson);
+
+ agent.Functions.Add(new FunctionDef
+ {
+ Name = "delegate_to_a2a",
+ Description = $"Delegates the task to the external {remoteConfig.Name} via A2A protocol.",
+ Parameters = new FunctionParametersDef()
+ {
+ Type = "object",
+ Properties = propertiesDocument,
+ Required = new List { "user_query" }
+ }
+ });
+ }
+ base.OnAgentLoaded(agent);
+ }
+}
diff --git a/src/Infrastructure/BotSharp.Core.A2A/Services/A2AService.cs b/src/Infrastructure/BotSharp.Core.A2A/Services/A2AService.cs
new file mode 100644
index 000000000..7b654eba9
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Core.A2A/Services/A2AService.cs
@@ -0,0 +1,158 @@
+using A2A;
+using Microsoft.Extensions.Logging;
+using System.Net.ServerSentEvents;
+using System.Text.Json;
+
+namespace BotSharp.Core.A2A.Services;
+
+public class A2AService : IA2AService
+{
+ private readonly IHttpClientFactory _httpClientFactory;
+ private readonly ILogger _logger;
+ private readonly IServiceProvider _services;
+
+ private readonly Dictionary _clientCache = new Dictionary();
+
+ public A2AService(IHttpClientFactory httpClientFactory, IServiceProvider serviceProvider, ILogger logger)
+ {
+ _httpClientFactory = httpClientFactory;
+ _services = serviceProvider;
+ _logger = logger;
+ }
+
+ public async Task GetCapabilitiesAsync(string agentEndpoint, CancellationToken cancellationToken = default)
+ {
+ var resolver = new A2ACardResolver(new Uri(agentEndpoint));
+ return await resolver.GetAgentCardAsync();
+ }
+
+ public async Task SendMessageAsync(string agentEndpoint, string text, string contextId, CancellationToken cancellationToken)
+ {
+
+ if (!_clientCache.TryGetValue(agentEndpoint, out var client))
+ {
+ HttpClient httpclient = _httpClientFactory.CreateClient();
+
+ client = new A2AClient(new Uri(agentEndpoint), httpclient);
+ _clientCache[agentEndpoint] = client;
+ }
+
+ var messagePayload = new AgentMessage
+ {
+ Role = MessageRole.User,
+ ContextId = contextId,
+ Parts = new List
+ {
+ new TextPart { Text = text }
+ }
+ };
+
+ var sendParams = new MessageSendParams
+ {
+ Message = messagePayload
+ };
+
+ try
+ {
+ _logger.LogInformation($"Sending A2A message to {agentEndpoint}. ContextId: {contextId}");
+ var responseBase = await client.SendMessageAsync(sendParams, cancellationToken);
+
+ if (responseBase is AgentMessage responseMsg)
+ {
+ if (responseMsg.Parts != null && responseMsg.Parts.Any())
+ {
+ var textPart = responseMsg.Parts.First() as TextPart;
+ return textPart?.Text ?? string.Empty;
+ }
+ }
+ else if( responseBase is AgentTask atask)
+ {
+ return $"Task created with ID: {atask.Id}, Status: {atask.Status}";
+ }
+ else
+ {
+ return "Unexpected task type.";
+ }
+
+ return string.Empty;
+ }
+ catch (HttpRequestException ex)
+ {
+ _logger.LogError(ex, $"Network error communicating with A2A agent at {agentEndpoint}");
+ throw new Exception($"Remote agent unavailable: {ex.Message}");
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, $"A2A Protocol error: {ex.Message}");
+ throw;
+ }
+ }
+
+ public async Task SendMessageStreamingAsync(string endPoint, List parts, Func, Task>? onStreamingEventReceived, CancellationToken cancellationToken = default)
+ {
+ A2ACardResolver cardResolver = new(new Uri(endPoint));
+ AgentCard agentCard = await cardResolver.GetAgentCardAsync();
+ A2AClient client = new A2AClient(new Uri(agentCard.Url));
+
+ AgentMessage userMessage = new()
+ {
+ Role = MessageRole.User,
+ Parts = parts
+ };
+
+ await foreach (SseItem sseItem in client.SendMessageStreamingAsync(new MessageSendParams { Message = userMessage }))
+ {
+ await onStreamingEventReceived?.Invoke(sseItem);
+ }
+
+ Console.WriteLine(" Streaming completed.");
+ }
+
+ public async Task ListenForTaskEventAsync(string endPoint, string taskId, Func, ValueTask>? onTaskEventReceived = null, CancellationToken cancellationToken = default)
+ {
+
+ if (onTaskEventReceived == null)
+ {
+ return;
+ }
+
+ A2ACardResolver cardResolver = new(new Uri(endPoint));
+ AgentCard agentCard = await cardResolver.GetAgentCardAsync();
+ A2AClient client = new A2AClient(new Uri(agentCard.Url));
+
+ await foreach (SseItem sseItem in client.SubscribeToTaskAsync(taskId))
+ {
+ await onTaskEventReceived.Invoke(sseItem);
+ Console.WriteLine(" Task event received: " + JsonSerializer.Serialize(sseItem.Data));
+ }
+
+ }
+
+ public async Task SetPushNotifications(string endPoint, PushNotificationConfig config, CancellationToken cancellationToken = default)
+ {
+ A2ACardResolver cardResolver = new(new Uri(endPoint));
+ AgentCard agentCard = await cardResolver.GetAgentCardAsync();
+ A2AClient client = new A2AClient(new Uri(agentCard.Url));
+ await client.SetPushNotificationAsync(new TaskPushNotificationConfig()
+ {
+ PushNotificationConfig = config
+ });
+ }
+
+ public async Task CancelTaskAsync(string endPoint, string taskId, CancellationToken cancellationToken = default)
+ {
+ A2ACardResolver cardResolver = new(new Uri(endPoint));
+ AgentCard agentCard = await cardResolver.GetAgentCardAsync();
+ A2AClient client = new A2AClient(new Uri(agentCard.Url));
+ return await client.CancelTaskAsync(taskId);
+ }
+
+ public async Task GetTaskAsync(string endPoint, string taskId, CancellationToken cancellationToken = default)
+ {
+ A2ACardResolver cardResolver = new(new Uri(endPoint));
+ AgentCard agentCard = await cardResolver.GetAgentCardAsync();
+ A2AClient client = new A2AClient(new Uri(agentCard.Url));
+ return await client.GetTaskAsync(taskId);
+ }
+
+}
diff --git a/src/Infrastructure/BotSharp.Core.A2A/Services/IA2AService.cs b/src/Infrastructure/BotSharp.Core.A2A/Services/IA2AService.cs
new file mode 100644
index 000000000..47f921c2e
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Core.A2A/Services/IA2AService.cs
@@ -0,0 +1,26 @@
+using A2A;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.ServerSentEvents;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BotSharp.Core.A2A.Services;
+
+public interface IA2AService
+{
+ Task SendMessageAsync(string agentEndpoint, string text, string contextId, CancellationToken cancellationToken = default);
+
+ Task GetCapabilitiesAsync(string agentEndpoint, CancellationToken cancellationToken = default);
+
+ Task SendMessageStreamingAsync(string endPoint, List parts, Func, Task>? onStreamingEventReceived,CancellationToken cancellationToken = default);
+
+ Task ListenForTaskEventAsync(string endPoint, string taskId, Func, ValueTask>? onTaskEventReceived = null, CancellationToken cancellationToken = default);
+
+ Task SetPushNotifications(string endPoint, PushNotificationConfig config, CancellationToken cancellationToken = default);
+
+ Task CancelTaskAsync(string endPoint, string taskId, CancellationToken cancellationToken = default);
+
+ Task GetTaskAsync(string endPoint, string taskId, CancellationToken cancellationToken);
+}
diff --git a/src/Infrastructure/BotSharp.Core.A2A/Settings/A2ASettings.cs b/src/Infrastructure/BotSharp.Core.A2A/Settings/A2ASettings.cs
new file mode 100644
index 000000000..3aa9ec7a8
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Core.A2A/Settings/A2ASettings.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BotSharp.Core.A2A.Settings;
+
+public class A2ASettings
+{
+ public bool Enabled { get; set; }
+ public int DefaultTimeoutSeconds { get; set; } = 30;
+ public List Agents { get; set; } = new List();
+}
+
+public class RemoteAgentConfig
+{
+ public string Id { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ public string Endpoint { get; set; }
+ public List Capabilities { get; set; }
+}
diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs
index 398f0c40d..4ac3f7314 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs
@@ -105,7 +105,7 @@ public RoutableAgent[] GetRoutableAgents(List profiles)
};
var agents = db.GetAgents(filter).ConfigureAwait(false).GetAwaiter().GetResult();
- var routableAgents = agents.Where(x => x.Type == AgentType.Task || x.Type == AgentType.Planning).Select(x => new RoutableAgent
+ var routableAgents = agents.Where(x => x.Type == AgentType.Task || x.Type == AgentType.Planning || x.Type == AgentType.A2ARemote).Select(x => new RoutableAgent
{
AgentId = x.Id,
Description = x.Description,
diff --git a/src/WebStarter/WebStarter.csproj b/src/WebStarter/WebStarter.csproj
index 07dba6efd..2c0478c5b 100644
--- a/src/WebStarter/WebStarter.csproj
+++ b/src/WebStarter/WebStarter.csproj
@@ -35,6 +35,7 @@
+
diff --git a/src/WebStarter/appsettings.json b/src/WebStarter/appsettings.json
index e0aca50d8..5d917523d 100644
--- a/src/WebStarter/appsettings.json
+++ b/src/WebStarter/appsettings.json
@@ -1006,10 +1006,22 @@
"Language": "en"
}
},
-
+ "A2AIntegration": {
+ "Enabled": true,
+ "DefaultTimeoutSeconds": 30,
+ "Agents": [
+ {
+ "Id": "cdd9023f-a371-407a-43bf-f36ddccce340",
+ "Name": "SportKiosk",
+ "Description": "test",
+ "Endpoint": "http://localhost:5020/"
+ }
+ ]
+ },
"PluginLoader": {
"Assemblies": [
"BotSharp.Core",
+ "BotSharp.Core.A2A",
"BotSharp.Core.SideCar",
"BotSharp.Core.Crontab",
"BotSharp.Core.Realtime",
diff --git a/tests/BotSharp.Plugin.PizzaBot/BotSharp.Plugin.PizzaBot.csproj b/tests/BotSharp.Plugin.PizzaBot/BotSharp.Plugin.PizzaBot.csproj
index c056982df..bec357f4c 100644
--- a/tests/BotSharp.Plugin.PizzaBot/BotSharp.Plugin.PizzaBot.csproj
+++ b/tests/BotSharp.Plugin.PizzaBot/BotSharp.Plugin.PizzaBot.csproj
@@ -95,4 +95,10 @@
PreserveNewest
+
+
+
+ PreserveNewest
+
+
diff --git a/tests/BotSharp.Plugin.PizzaBot/PizzaBotPlugin.cs b/tests/BotSharp.Plugin.PizzaBot/PizzaBotPlugin.cs
index 6fa37ce67..15345b56f 100644
--- a/tests/BotSharp.Plugin.PizzaBot/PizzaBotPlugin.cs
+++ b/tests/BotSharp.Plugin.PizzaBot/PizzaBotPlugin.cs
@@ -15,7 +15,8 @@ public class PizzaBotPlugin : IBotSharpPlugin
"b284db86-e9c2-4c25-a59e-4649797dd130",
"c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd",
"dfd9b46d-d00c-40af-8a75-3fbdc2b89869",
- "fe8c60aa-b114-4ef3-93cb-a8efeac80f75"
+ "fe8c60aa-b114-4ef3-93cb-a8efeac80f75",
+ "cdd9023f-a371-407a-43bf-f36ddccce340"
};
public void RegisterDI(IServiceCollection services, IConfiguration config)
diff --git a/tests/BotSharp.Plugin.PizzaBot/data/agents/cdd9023f-a371-407a-43bf-f36ddccce340/agent.json b/tests/BotSharp.Plugin.PizzaBot/data/agents/cdd9023f-a371-407a-43bf-f36ddccce340/agent.json
new file mode 100644
index 000000000..ce963da82
--- /dev/null
+++ b/tests/BotSharp.Plugin.PizzaBot/data/agents/cdd9023f-a371-407a-43bf-f36ddccce340/agent.json
@@ -0,0 +1,14 @@
+{
+ "id": "cdd9023f-a371-407a-43bf-f36ddccce340",
+ "name": "SportKiosk",
+ "description": "Answers questions about sport events",
+ "type": "a2a-remote",
+ "disabled": false,
+ "isPublic": true,
+ "profiles": [ "pizza" ],
+ "labels": [ "experiment" ],
+ "llmConfig": {
+ "provider": "openai",
+ "model": "gpt-5-nano"
+ }
+}
\ No newline at end of file