A2A (Agent-to-Agent)
Mastra prend en charge la version 0.3.0 du protocole Agent-to-Agent (A2A) pour les systèmes multi-Agents multiplateformes. Utilisez A2A pour exposer des Agents Mastra en tant qu'Agents distants, intégrer des Agents A2A distants comme sous-Agents Mastra ou appeler des endpoints A2A avec le SDK client JavaScript.
A2A est un protocole ouvert permettant de déléguer des tâches à des Agents, indépendamment des réseaux, frameworks, fournisseurs et langages. Un Agent distant garde privés ses propres Tools, prompts, mémoire, Workflows et infrastructure, tout en exposant un endpoint de protocole que d'autres systèmes peuvent découvrir et appeler.
Quand utiliser A2ALien direct vers Quand utiliser A2A
- Un Agent parent doit déléguer une tâche à un Agent distant spécialisé.
- Un Agent distant appartient à un autre service, une autre équipe, un autre fournisseur ou un autre environnement d'exécution.
- Un backend, une application de navigateur ou un autre système compatible A2A doit accéder par programmation à un Agent Mastra.
- Une tâche distante de longue durée nécessite des ID de tâche, des mises à jour d'état, des artefacts, une annulation, une réinscription ou des notifications push.
Fonctionnement d'A2ALien direct vers Fonctionnement d'A2A
A2A utilise une fiche d'Agent pour la découverte. Cette fiche est un document JSON servi depuis une URL bien connue. Elle décrit l'Agent distant et comprend l'URL d'exécution qui accepte les requêtes A2A JSON-RPC.
Lorsque vous utilisez la valeur apiPrefix par défaut /api de Mastra Server, un Agent enregistré sous le nom weather-agent expose :
- Fiche d'Agent :
/api/.well-known/weather-agent/agent-card.json - Endpoint d'exécution :
/api/a2a/weather-agent
Une fiche d'Agent comprend notamment le nom et la description de l'Agent, l'URL de l'endpoint, le Provider, les fonctionnalités, les métadonnées de sécurité et les Skills :
{
"protocolVersion": "0.3.0",
"name": "Weather Agent",
"description": "Provides weather information.",
"url": "https://agent.example.com/api/a2a/weather-agent",
"version": "1.0",
"provider": {
"organization": "Acme",
"url": "https://acme.example.com"
},
"capabilities": {
"streaming": true,
"pushNotifications": true,
"stateTransitionHistory": false
},
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["text/plain"],
"skills": [
{
"id": "weather",
"name": "weather",
"description": "Gets weather conditions for a location.",
"tags": ["tool"]
}
]
}
A2A représente le travail sous forme de messages et de tâches. Les messages transportent des parties de texte, de fichier ou de données structurées.
Les tâches sont des unités de travail avec état, dotées d'ID et d'états de cycle de vie. Les clients peuvent suivre les tâches de longue durée et envoyer des échanges complémentaires. Ils peuvent également annuler une tâche ou se réinscrire après une déconnexion.
Versions du protocoleLien direct vers Versions du protocole
Mastra prend en charge les versions v0.3 et v1.0 du protocole A2A sur les mêmes URL de fiche d'Agent et d'exécution. L'en-tête de requête A2A-Version sélectionne le protocole utilisé sur le réseau :
- Absent, vide ou égal à
0.3: utilise l'API v0.3 existante. 1.0: utilise l'API v1.0.- Toute autre valeur : renvoie une erreur de protocole
VersionNotSupported.
Les intégrations A2AAgent et MastraClient.getA2A() existantes continuent d'utiliser la v0.3. Utilisez MastraClient.getA2AV1() pour les requêtes v1.0. Le client v1 envoie automatiquement A2A-Version: 1.0 et ajoute l'opération tasks/list.
Importez les types et codecs du protocole v1.0 depuis @mastra/core/a2a/v1. L'exportation @mastra/core/a2a/client existante reste en v0.3.
Prise en mainLien direct vers Prise en main
A2A s'utilise principalement de deux manières dans Mastra :
- Intégrer un Agent A2A distant comme sous-Agent Mastra avec
A2AAgent. - Envoyer des requêtes à un endpoint A2A Mastra avec
MastraClient.getA2A().
Utilisez A2AAgent lorsqu'un autre Agent Mastra doit déléguer une tâche à un Agent distant. Utilisez le SDK client lorsque le code de l'application doit appeler directement un endpoint Mastra compatible A2A.
Intégrer des Agents A2A comme sous-AgentsLien direct vers Intégrer des Agents A2A comme sous-Agents
Utilisez A2AAgent pour envelopper un Agent A2A distant, puis ajoutez-le à un Agent parent selon le modèle des Agents superviseurs. Transmettez explicitement l'URL de la fiche d'Agent lorsque le serveur distant héberge plusieurs Agents ou utilise un chemin bien connu personnalisé.
import { Agent } from '@mastra/core/agent'
import { A2AAgent } from '@mastra/core/a2a'
const remoteWeatherAgent = new A2AAgent({
url: 'https://weather.example.com/api/.well-known/weather-agent/agent-card.json',
headers: {
Authorization: `Bearer ${process.env.WEATHER_AGENT_TOKEN}`,
},
})
export const supportAgent = new Agent({
id: 'support-agent',
name: 'Support Agent',
instructions: 'Answer user questions and delegate weather questions when needed.',
model: 'openai/gpt-5.6-sol',
agents: {
remoteWeatherAgent,
},
})
Si url pointe vers un domaine, A2AAgent récupère la fiche d'Agent depuis /.well-known/agent-card.json. Utilisez une URL de domaine pour les serveurs à Agent unique qui suivent ce chemin de découverte. Pour les serveurs multi-Agents, transmettez l'URL complète de la fiche, par exemple https://agent.example.com/api/.well-known/weather-agent/agent-card.json.
Pendant l'exécution, A2AAgent :
- Récupère et met en cache la fiche de l'Agent distant.
- Lit dans la fiche l'URL d'exécution et les fonctionnalités.
- Appelle
message/sendpour les exécutions sans diffusion en continu oumessage/streamlorsque celle-ci est prise en charge. - Convertit les messages, tâches, artefacts et mises à jour d'état distants en résultats de sous-Agent Mastra.
- Prend en charge
resumeGenerate()etresumeStream()lorsque la tâche distante nécessite une entrée complémentaire ou une réinscription.
Si la fiche distante n'annonce pas la prise en charge de la diffusion en continu, A2AAgent.stream() se rabat sur le parcours de génération sans streaming et renvoie un résultat de flux mis en mémoire tampon.
Envoyer des requêtes avec le SDK clientLien direct vers Envoyer des requêtes avec le SDK client
Utilisez MastraClient.getA2A() lorsque le code de l'application doit appeler un Agent Mastra compatible A2A. Configurez baseUrl avec l'origine du serveur et apiPrefix lorsque le serveur n'utilise pas le préfixe /api par défaut.
import { MastraClient } from '@mastra/client-js'
const client = new MastraClient({
baseUrl: 'https://agent.example.com',
headers: {
Authorization: `Bearer ${process.env.AGENT_API_TOKEN}`,
},
})
const a2a = client.getA2A('weather-agent')
const card = await a2a.getAgentCard()
console.log(card.name, card.capabilities)
Utilisez sendMessageStream() pour envoyer un message et recevoir les mises à jour d'état de la tâche et des artefacts par Server-Sent Events (SSE) :
const stream = a2a.sendMessageStream({
message: {
kind: 'message',
role: 'user',
messageId: crypto.randomUUID(),
parts: [{ kind: 'text', text: "What's the weather in Prague?" }],
},
})
for await (const event of stream) {
if (event.kind === 'artifact-update') {
console.log(event.artifact.parts)
}
}
Si un flux se déconnecte alors qu'une tâche est toujours en cours, utilisez resubscribeTask() pour recevoir les mises à jour en direct de cette tâche :
const updates = a2a.resubscribeTask({
id: 'task-123',
})
for await (const event of updates) {
console.log(event)
}
Utiliser le client v1.0Lien direct vers Utiliser le client v1.0
Utilisez getA2AV1() pour adopter le protocole réseau A2A v1.0. Le package du protocole fournit des codecs permettant de créer des valeurs de requête v1 à partir d'entrées au format JSON :
import { ListTasksRequest } from '@mastra/core/a2a/v1'
import { MastraClient } from '@mastra/client-js'
const client = new MastraClient({
baseUrl: 'https://agent.example.com',
})
const a2a = client.getA2AV1('weather-agent')
const response = await a2a.listTasks(
ListTasksRequest.fromJSON({
contextId: 'customer-support',
pageSize: 20,
}),
)
for (const task of response.tasks) {
console.log(task.id, task.status)
}
Le client v1.0 prend en charge getAgentCard(), sendMessage(), sendMessageStream(), getTask(), listTasks(), cancelTask() et resubscribeTask().
Configurer les appels aux sous-AgentsLien direct vers Configurer les appels aux sous-Agents
A2AAgent accepte des options de requête pour les environnements authentifiés ou soumis à des contraintes :
import { A2AAgent } from '@mastra/core/a2a'
const remoteWeatherAgent = new A2AAgent({
url: 'https://weather.example.com/api/.well-known/weather-agent/agent-card.json',
headers: {
Authorization: `Bearer ${process.env.WEATHER_AGENT_TOKEN}`,
},
retries: 2,
backoffMs: 250,
maxBackoffMs: 1000,
timeoutMs: 30_000,
})
Vous pouvez également transmettre credentials, fetch et abortSignal lorsque l'environnement d'exécution nécessite un comportement de récupération personnalisé ou l'annulation des requêtes.
Intervention humaine dans la boucleLien direct vers Intervention humaine dans la boucle
A2A représente les tâches avec intervention humaine (HITL) au moyen de l'état de tâche input-required. Lorsqu'une tâche s'interrompt pour attendre une entrée, le client fournit l'entrée manquante en envoyant un message complémentaire avec le même taskId, puis le serveur poursuit la tâche.
Mastra associe son modèle de suspension des Agents à cet état dans les deux sens :
- En tant que serveur : lorsqu'un Agent exposé est suspendu, la tâche passe à l'état
input-required. Cela comprend les suspensions dues à l'approbation d'un Tool ou à un Tool qui appellesuspend(). Le message d'état de la tâche comprend un prompt textuel et une partie de données avec les valeurs structuréessuspendPayloadetresumeSchema. Une requêtemessage/sendoumessage/streamcomplémentaire avec le mêmetaskIdreprend l'exécution suspendue avec l'entrée fournie. - En tant que client : lorsqu'une tâche distante atteint l'état
input-requiredouauth-required,A2AAgentrenvoie un résultat suspendu avecfinishReason: 'suspended'et unsuspendPayload. L'appel deresumeGenerate()ouresumeStream()renvoie l'entrée ou les identifiants à la tâche distante avec letaskIdd'origine.
import { A2AAgent } from '@mastra/core/a2a'
const agent = new A2AAgent({
url: 'https://agent.example.com/api/.well-known/booking-agent/agent-card.json',
})
const result = await agent.generate('Book a flight to Paris', { runId: 'run-1' })
if (result.finishReason === 'suspended') {
// Inspect result.suspendPayload, collect input from a human,
// then resume the remote task.
const resumed = await agent.resumeGenerate({ approved: true }, { runId: 'run-1' })
console.log(resumed.text)
}
Les messages complémentaires d'une tâche input-required peuvent transporter les données de reprise dans une partie de données structurées, ou sous forme de JSON ou de texte brut dans une partie textuelle.
Lorsqu'une exécution reprise nécessite une entrée supplémentaire, la tâche revient à l'état input-required et le processus se répète. La reprise d'une exécution suspendue nécessite la configuration d'un stockage sur le serveur Mastra afin que son état puisse être restauré d'une requête à l'autre.
Les enregistrements de tâches A2A résident dans un stockage en mémoire. Une tâche mise en pause ne peut donc être reprise que par le processus serveur qui l'a suspendue. Un redémarrage du serveur ou un déploiement avec mise à l'échelle horizontale sans routage persistant perd l'enregistrement de la tâche, et tout message complémentaire échoue avec une erreur indiquant que la tâche est introuvable.
Notifications pushLien direct vers Notifications push
Mastra prend en charge les notifications push A2A pour les Agents distants qui annoncent capabilities.pushNotifications. Utilisez-les lorsqu'un client ne peut pas maintenir un flux ouvert ou lorsqu'une tâche de longue durée doit mettre à jour une URL de rappel après la fin de la requête d'origine.
Une fois qu'un client dispose d'un ID de tâche, il peut enregistrer une URL de rappel pour celle-ci :
await a2a.setTaskPushNotificationConfig({
taskId: 'task-123',
pushNotificationConfig: {
url: 'https://app.example.com/a2a/tasks',
token: process.env.A2A_WEBHOOK_TOKEN,
},
})
Mastra Server envoie l'instantané actuel de la tâche aux fonctions de rappel enregistrées lorsque la tâche atteint l'état completed, failed, canceled, rejected, input-required ou auth-required. L'envoi des notifications push est effectué au mieux. Protégez les URL de rappel, validez les tokens de notification et évitez d'exposer des cibles du réseau interne comme destinations de notifications push.
Les configurations de notifications push sont stockées en mémoire et doivent être réenregistrées après un redémarrage du serveur.
Signer et vérifier les fiches d'AgentLien direct vers Signer et vérifier les fiches d'Agent
Mastra prend en charge les fiches d'Agent A2A signées afin que les clients puissent vérifier qu'une fiche découverte provient d'un éditeur de confiance et n'a pas été modifiée pendant son transfert. Configurez la signature sur le serveur Mastra qui expose l'Agent distant :
import { Mastra } from '@mastra/core/mastra'
export const mastra = new Mastra({
server: {
a2a: {
agentCardSigning: {
privateKey: process.env.A2A_AGENT_CARD_PRIVATE_KEY!,
protectedHeader: {
alg: 'ES256',
kid: 'agent-card-key',
},
},
},
},
})
Lorsque la signature est configurée, Mastra inclut un tableau signatures dans la fiche d'Agent. La vérification côté client doit être activée explicitement, et les fiches non signées sont toujours renvoyées sans modification.
Vérifiez une fiche signée avec MastraClient.getA2A() :
const card = await a2a.getAgentCard({
verifySignature: {
algorithms: ['ES256'],
keyProvider: async ({ kid, jku }) => {
return fetchTrustedPublicJwk({ kid, jku })
},
},
})
if (!card.signatures?.length) {
throw new Error('Expected a signed A2A agent card.')
}
Utilisez la vérification de signature côté client lorsque celui-ci doit imposer l'emploi de clés de confiance avant d'appeler l'Agent distant.
Vérifier les fiches des sous-AgentsLien direct vers Vérifier les fiches des sous-Agents
Utilisez verifyAgentCard lorsqu'un Agent parent doit valider un Agent distant avant de lui déléguer une tâche. Le hook de vérification reçoit la fiche d'Agent récupérée ainsi que le contexte indiquant où et quand elle l'a été.
import { A2AAgent } from '@mastra/core/a2a'
const remoteWeatherAgent = new A2AAgent({
url: 'https://weather.example.com/api/.well-known/weather-agent/agent-card.json',
verifyAgentCard: {
verify: async (card, context) => {
if (card.provider?.organization !== 'Weather Inc') {
throw new Error(`Unexpected provider for ${context.cardUrl}`)
}
},
},
})
Utilisez ce hook pour imposer les Providers et endpoints attendus, les identités liées à un certificat, les fiches signées ou d'autres exigences de confiance avant qu'un Agent parent ne délègue une tâche à l'Agent distant.