1. Aperçu du projet
Le SDK A2A (Agent2Agent) .NET est une bibliothèque .NET qui implémente le protocole A2A v0.2.1 de Google, permettant la communication agent-à-agent dans les applications .NET. Ce SDK est conçu pour fonctionner avec les applications ASP.NET Core, offrant un moyen simple d'ajouter le support A2A à vos agents.
Caractéristiques principales
- Compatibilité du protocole : Implémente la plupart des fonctionnalités du protocole A2A v0.2.1
- Support multi-framework : Prend en charge .NET 9.0, .NET 8.0 et .NET Standard 2.0
- Intégration ASP.NET Core : Fournit des méthodes d'intégration simples
- Gestion des tâches : Support standardisé de la gestion et de l'exécution des tâches
- Streaming : Prend en charge les réponses de streaming en temps réel
- OpenTelemetry : Support intégré de la télémétrie et de l'observabilité
Statut du projet
La bibliothèque a implémenté la plupart des fonctionnalités du protocole, mais certains scénarios peuvent encore être incomplets. La plus grande fonctionnalité manquante est le callback client utilisant les notifications push.
2. Architecture A2A .NET Core
2.1 Structure du projet
src/
├── A2A/ # Implémentation principale du protocole A2A
│ ├── Client/ # Composants client
│ ├── JsonRpc/ # Implémentation JSON-RPC
│ ├── Models/ # Modèles de données
│ ├── Server/ # Composants côté serveur
│ └── openapi.yaml # Spécification API
└── A2A.AspNetCore/ # Intégration ASP.NET Core
2.2 Composants principaux
- Bibliothèque A2A Core : Contient l'implémentation principale du protocole
- A2A.AspNetCore : Fournit l'intégration ASP.NET Core
- Projets d'exemple : Code d'exemple démontrant divers scénarios d'utilisation
3. Implémentation du client A2A .NET
3.1 Classe A2AClient
La classe A2AClient
est l'interface client principale pour communiquer avec les agents, implémentant l'interface IA2AClient
.
Fonctions principales :
public class A2AClient : IA2AClient
{
// Envoyer un message
public Task<A2AResponse> SendMessageAsync(MessageSendParams taskSendParams)
// Obtenir une tâche
public Task<AgentTask> GetTaskAsync(string taskId)
// Annuler une tâche
public Task<AgentTask> CancelTaskAsync(TaskIdParams taskIdParams)
// Envoyer un message en streaming
public async IAsyncEnumerable<SseItem<A2AEvent>> SendMessageStreamAsync(MessageSendParams taskSendParams)
// Se réabonner à une tâche
public async IAsyncEnumerable<SseItem<A2AEvent>> ResubscribeToTaskAsync(string taskId)
}
Caractéristiques principales :
- Communication JSON-RPC : Toutes les communications se font via le protocole JSON-RPC
- Réponse en streaming : Prend en charge les Server-Sent Events (SSE) pour le streaming en temps réel
- Optimisation de la sérialisation : Utilise le générateur de source System.Text.Json pour une sérialisation haute performance
- Gestion des erreurs : Gestion complète des erreurs et gestion d'état
3.2 Classe JsonRpcContent
Classe de contenu HTTP spécialement pour les requêtes JSON-RPC :
public class JsonRpcContent : HttpContent
{
public JsonRpcContent(JsonRpcRequest request)
{
_request = request;
Headers.ContentType = new MediaTypeHeaderValue("application/json");
}
}
3.3 Classe A2ACardResolver
Utilisée pour analyser et obtenir les informations de carte d'agent :
public class A2ACardResolver
{
public async Task<AgentCard> GetAgentCardAsync(Uri agentUri)
public async Task<AgentCard> GetAgentCardAsync(string agentUrl)
}
4. Implémentation du serveur A2A .NET
4.1 Classe TaskManager
Le TaskManager
est le composant principal côté serveur responsable de la gestion du cycle de vie des tâches.
Responsabilités principales :
- Gestion du cycle de vie des tâches : Création, mise à jour, annulation des tâches
- Traitement des messages : Gestion des messages entrants et des mises à jour de tâches
- Distribution d'événements : Gestion des événements de changement d'état des tâches
- Abstraction de stockage : Persistance des tâches via l'interface
ITaskStore
Méthodes principales :
public class TaskManager : ITaskManager
{
// Gestionnaires d'événements
public Func<MessageSendParams, Task<Message>>? OnMessageReceived { get; set; }
public Func<AgentTask, Task> OnTaskCreated { get; set; }
public Func<AgentTask, Task> OnTaskCancelled { get; set; }
public Func<AgentTask, Task> OnTaskUpdated { get; set; }
public Func<string, AgentCard> OnAgentCardQuery { get; set; }
// Opérations principales
public async Task<AgentTask> CreateTaskAsync(string? contextId = null)
public async Task<AgentTask?> CancelTaskAsync(TaskIdParams? taskIdParams)
public async Task<A2AResponse?> SendMessageAsync(MessageSendParams messageSendParams)
public async Task<IAsyncEnumerable<A2AEvent>> SendMessageStreamAsync(MessageSendParams messageSendParams)
public async Task UpdateStatusAsync(string taskId, TaskState status, Message? message = null, bool final = false)
public async Task ReturnArtifactAsync(string taskId, Artifact artifact)
}
4.2 Interface ITaskStore
Interface abstraite pour le stockage des tâches :
public interface ITaskStore
{
Task<AgentTask?> GetTaskAsync(string taskId);
Task SetTaskAsync(AgentTask task);
Task UpdateStatusAsync(string taskId, TaskState status);
}
4.3 Intégration ASP.NET Core
Via les méthodes d'extension fournies par la bibliothèque A2A.AspNetCore
:
// Ajouter le support JSON-RPC A2A
app.MapA2A(taskManager, "/echo");
// Ajouter le support HTTP A2A
app.MapHttpA2A(taskManager, "/echo");
5. Modèles de données A2A .NET
5.1 Classes de modèles principales
AgentCard - Carte d'agent
public class AgentCard
{
public string Name { get; set; } // Nom de l'agent
public string Description { get; set; } // Description de l'agent
public string Url { get; set; } // URL de l'agent
public AgentProvider? Provider { get; set; } // Informations du fournisseur
public string Version { get; set; } // Informations de version
public AgentCapabilities Capabilities { get; set; } // Capacités de l'agent
public List<AgentSkill> Skills { get; set; } // Compétences de l'agent
public List<string> DefaultInputModes { get; set; } // Modes d'entrée par défaut
public List<string> DefaultOutputModes { get; set; }// Modes de sortie par défaut
}
AgentTask - Tâche d'agent
public class AgentTask : A2AResponse
{
public string Id { get; set; } // ID de la tâche
public string? ContextId { get; set; } // ID de contexte
public AgentTaskStatus Status { get; set; } // Statut de la tâche
public List<Artifact>? Artifacts { get; set; } // Artefacts de la tâche
public List<Message>? History { get; set; } // Historique des messages
public Dictionary<string, JsonElement>? Metadata { get; set; } // Métadonnées
}
Message - Message
public class Message : A2AResponse
{
public MessageRole Role { get; set; } // Rôle du message (User/Agent)
public List<Part> Parts { get; set; } // Parties du message
public string? MessageId { get; set; } // ID du message
public string? TaskId { get; set; } // ID de la tâche associée
public string? ContextId { get; set; } // ID de contexte
public Dictionary<string, JsonElement>? Metadata { get; set; } // Métadonnées
}
5.2 États des tâches
public enum TaskState
{
Submitted, // Soumis
Working, // En cours
InputRequired, // Entrée requise
Completed, // Terminé
Canceled, // Annulé
Failed, // Échoué
Rejected // Rejeté
}
5.3 Types de parties de message
Prend en charge plusieurs types de parties de message :
TextPart
: Contenu textuelFilePart
: Contenu de fichierDataPart
: Contenu de données
6. Analyse détaillée de l'exemple AgentServer A2A .NET
6.1 Aperçu du projet
L'exemple AgentServer montre comment créer et déployer différents types d'agents, notamment :
- EchoAgent : Agent d'écho simple
- EchoAgentWithTasks : Agent d'écho avec support des tâches
- HostedClientAgent : Agent client hébergé
- ResearcherAgent : Agent de recherche (implémentation de machine d'état)
6.2 Implémentation EchoAgent
public class EchoAgent
{
private ITaskManager? _taskManager;
public void Attach(TaskManager taskManager)
{
_taskManager = taskManager;
taskManager.OnMessageReceived = ProcessMessage;
taskManager.OnAgentCardQuery = GetAgentCard;
}
public Task<Message> ProcessMessage(MessageSendParams messageSendParams)
{
var messageText = messageSendParams.Message.Parts.OfType<TextPart>().First().Text;
var message = new Message()
{
Role = MessageRole.Agent,
MessageId = Guid.NewGuid().ToString(),
ContextId = messageSendParams.Message.ContextId,
Parts = [new TextPart() { Text = $"Echo: {messageText}" }]
};
return Task.FromResult(message);
}
}
6.3 Implémentation ResearcherAgent
ResearcherAgent montre une implémentation de machine d'état plus complexe :
public class ResearcherAgent
{
private enum AgentState
{
Planning, // Phase de planification
WaitingForFeedbackOnPlan, // En attente de retour sur le plan
Researching // Phase de recherche
}
public async Task Invoke(string taskId, string message)
{
switch (_agentStates[taskId])
{
case AgentState.Planning:
await DoPlanning(taskId, message);
break;
case AgentState.WaitingForFeedbackOnPlan:
if (message == "go ahead")
await DoResearch(taskId, message);
else
await DoPlanning(taskId, message);
break;
case AgentState.Researching:
await DoResearch(taskId, message);
break;
}
}
}
7. Comment exécuter l'exemple AgentServer
7.1 Exigences d'environnement
- SDK .NET 9.0 ou supérieur
- Optionnel : OpenTelemetry Collector (pour les données de télémétrie)
7.2 Étapes d'exécution
-
Cloner le projet :
git clone https://github.com/a2aproject/a2a-dotnet cd a2a-dotnet
-
Naviguer vers le répertoire d'exemple :
cd samples/AgentServer
-
Exécuter le projet :
dotnet run
-
Vérifier que le service fonctionne : Le service démarrera sur les ports suivants :
- HTTP : http://localhost:5048
- HTTPS : https://localhost:7014
7.3 Points de terminaison disponibles
/echo
- Agent d'écho simple/echotasks
- Agent d'écho avec support des tâches/hostedclient
- Agent client hébergé/researcher
- Agent de recherche
7.4 Test des appels API
Obtenir la carte d'agent
curl -X GET http://localhost:5048/echo/.well-known/agent.json
Envoyer un message à l'agent d'écho
curl -X POST http://localhost:5048/echo \
-H "Content-Type: application/json" \
-d '{
"id": "1",
"jsonrpc": "2.0",
"method": "message/send",
"params": {
"message": {
"messageId": "12345",
"role": "user",
"parts": [
{
"kind": "text",
"text": "Hello, world!"
}
]
}
}
}'
Créer une tâche d'agent de recherche
curl -X POST http://localhost:5048/researcher \
-H "Content-Type: application/json" \
-d '{
"id": "1",
"jsonrpc": "2.0",
"method": "message/send",
"params": {
"message": {
"messageId": "research-1",
"role": "user",
"parts": [
{
"kind": "text",
"text": "Research the current price of butter"
}
]
}
}
}'
8. Diagrammes de séquence
8.1 Diagramme de séquence de traitement de message simple
sequenceDiagram
participant Client as Client
participant Server as A2A Server
participant Agent as Agent Implementation
participant TaskMgr as TaskManager
Client->>Server: POST /echo (JSON-RPC message/send)
Server->>TaskMgr: SendMessageAsync()
TaskMgr->>Agent: OnMessageReceived()
Agent->>Agent: ProcessMessage()
Agent-->>TaskMgr: Return Message
TaskMgr-->>Server: Return A2AResponse
Server-->>Client: JSON-RPC Response
8.2 Diagramme de séquence de traitement de tâche
sequenceDiagram
participant Client as Client
participant Server as A2A Server
participant TaskMgr as TaskManager
participant Agent as Agent Implementation
participant Store as TaskStore
Client->>Server: POST /researcher (message/send)
Server->>TaskMgr: SendMessageAsync()
TaskMgr->>TaskMgr: CreateTaskAsync()
TaskMgr->>Store: SetTaskAsync()
TaskMgr->>Agent: OnTaskCreated()
Agent->>Agent: State Change (Planning)
Agent->>TaskMgr: UpdateStatusAsync(Working)
TaskMgr->>Store: UpdateStatusAsync()
Agent->>TaskMgr: ReturnArtifactAsync()
Agent->>TaskMgr: UpdateStatusAsync(InputRequired)
TaskMgr-->>Server: Return AgentTask
Server-->>Client: JSON-RPC Response
Note over Client,Store: Client sends follow-up message
Client->>Server: POST /researcher (message/send, taskId)
Server->>TaskMgr: SendMessageAsync()
TaskMgr->>Store: GetTaskAsync()
TaskMgr->>Agent: OnTaskUpdated()
Agent->>Agent: State processing logic
Agent->>TaskMgr: UpdateStatusAsync(Completed)
TaskMgr-->>Server: Return AgentTask
Server-->>Client: JSON-RPC Response
8.3 Diagramme de séquence de traitement en streaming
sequenceDiagram
participant Client as Client
participant Server as A2A Server
participant TaskMgr as TaskManager
participant Agent as Agent Implementation
Client->>Server: POST /echo (JSON-RPC message/stream)
Server->>TaskMgr: SendMessageStreamAsync()
TaskMgr->>Agent: OnMessageReceived()
loop Streaming Response
Agent->>TaskMgr: Generate Event
TaskMgr->>Server: A2AEvent
Server->>Client: Server-Sent Event
end
Agent->>TaskMgr: Complete Processing
TaskMgr->>Server: End Stream
Server->>Client: Close Connection
9. Modèles de conception clés A2A .NET
9.1 Architecture pilotée par les événements
TaskManager utilise le modèle piloté par les événements :
OnMessageReceived
: Gestion des messages entrantsOnTaskCreated
: Événement de création de tâcheOnTaskUpdated
: Événement de mise à jour de tâcheOnTaskCancelled
: Événement d'annulation de tâche
9.2 Modèle de stratégie
Différentes implémentations d'agents peuvent avoir différentes stratégies de traitement :
- Traitement sans état (EchoAgent)
- Traitement avec état (ResearcherAgent)
- Traitement orienté tâche (EchoAgentWithTasks)
9.3 Abstraction de stockage
Abstraction de stockage de tâches via l'interface ITaskStore
:
InMemoryTaskStore
: Implémentation de stockage en mémoire- Extensible pour les implémentations de stockage de base de données
10. Performance et observabilité A2A .NET
10.1 Optimisation des performances
- Sérialisation générée par la source : Utilise le générateur de source System.Text.Json
- Compatibilité AOT : Prend en charge la compilation AOT native
- Traitement asynchrone : Utilisation extensive du modèle async/await
- Traitement en streaming : Prend en charge le streaming de gros volumes de données
10.2 Observabilité
Support OpenTelemetry intégré :
- Traçage distribué : Intégration ActivitySource
- Collecte de métriques : Métriques d'état des tâches et de performance
- Journalisation : Support de journalisation structurée
// Exemple de configuration OpenTelemetry
builder.Services.AddOpenTelemetry()
.WithTracing(tracing => tracing
.AddSource(TaskManager.ActivitySource.Name)
.AddSource(A2AJsonRpcProcessor.ActivitySource.Name)
.AddConsoleExporter()
.AddOtlpExporter());
11. Résumé A2A .NET
Le SDK A2A .NET fournit une solution complète et prête pour la production pour implémenter la communication agent-à-agent dans les applications .NET.
11.1 Avantages principaux
- Protocole standardisé : Basé sur la norme A2A Protocol de Google
- Intégration facile : Intégration ASP.NET Core simple
- Architecture flexible : Prend en charge plusieurs modèles d'implémentation d'agents
- Haute performance : Sérialisation optimisée et traitement asynchrone
- Observabilité : Support intégré de télémétrie et de surveillance
- Extensibilité : Les interfaces abstraites prennent en charge les implémentations personnalisées
11.2 Cas d'utilisation
- Systèmes d'agents IA : Construction de systèmes d'interaction d'agents intelligents
- Architecture de microservices : Communication intelligente entre services
- Moteur de workflow : Traitement basé sur les agents de processus métier complexes
- Chatbots : Système de dialogue collaboratif multi-agents
11.3 Développement futur
- Notifications push : Support complet de callback client
- Plus de backends de stockage : Support de base de données et de stockage distribué
- Améliorations de sécurité : Mécanismes d'authentification et d'autorisation plus complets
- Mises à jour du protocole : Rester à jour avec les dernières versions du protocole A2A
11.4 Recommandations de développement
- Commencer simple : Utiliser EchoAgent pour comprendre les concepts de base
- Comprendre la gestion d'état : Étudier l'implémentation de machine d'état de ResearcherAgent
- Mettre l'accent sur la gestion des erreurs : Implémenter une gestion d'erreur complète et des mécanismes de récupération
- Surveillance et débogage : Utiliser OpenTelemetry pour la surveillance du système
- Piloté par les tests : Écrire des tests unitaires et d'intégration complets
Ce SDK fournit aux développeurs .NET une plateforme puissante et flexible pour construire des systèmes d'agents intelligents de nouvelle génération. Grâce à son architecture claire et ses exemples riches, les développeurs peuvent rapidement commencer et construire des applications de communication agent-à-agent complexes.