A2A(Agent 대 Agent)
Mastra는 버전 0.3.0을 지원합니다.Agent-to-Agent (A2A) protocol크로스 플랫폼 다중 Agent 시스템용. A2A를 사용하여 Mastra Agent를 원격 Agent로 노출하거나, 원격 A2A Agent를 Mastra 하위 Agent로 사용하거나, JavaScript 클라이언트 SDK를 사용하여 A2A 엔드포인트를 호출합니다.
A2A는 네트워크, 프레임워크, 공급업체 및 언어 경계를 넘어 Agent에 작업을 위임하기 위한 개방형 프로토콜입니다. 원격 Agent는 자체 Tool, Prompt, Memory, Workflow 및 인프라를 비공개로 유지하면서 다른 시스템이 검색하고 호출할 수 있는 프로토콜 엔드포인트를 노출합니다.
A2A를 사용해야 하는 경우A2A를 사용해야 하는 경우에 대한 직접 링크
- 상위 Agent는 전문 원격 Agent에게 작업을 위임해야 합니다.
- 원격 Agent는 다른 서비스, 팀, 공급업체 또는 런타임이 소유합니다.
- 백엔드, 브라우저 앱 또는 다른 A2A 호환 시스템에는 프로그래밍 방식으로 Mastra Agent에 액세스해야 합니다.
- 장기 실행 원격 작업에는 작업 ID, 상태 업데이트, 아티팩트, 취소, 재구독 또는 푸시 알림이 필요합니다.
A2A 작동 방식A2A 작동 방식에 대한 직접 링크
A2A는 검색을 위해 Agent 카드를 사용합니다. 카드는 잘 알려진 URL에서 제공되는 JSON 문서입니다. 원격 Agent를 설명하고 A2A JSON-RPC 요청을 수락하는 실행 URL을 포함합니다.
기본 Mastra Server를 사용하는 경우apiPrefix of /api, an agent registered as weather-agent exposes:
- 대리인 카드:
/api/.well-known/weather-agent/agent-card.json - 실행 끝점:
/api/a2a/weather-agent
Agent 카드에는 Agent 이름, 설명, 엔드포인트 URL, 공급자, 기능, 보안 메타데이터 및 기술과 같은 필드가 포함됩니다.
{
"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는 작업을 메시지와 작업으로 나타냅니다. 메시지는 텍스트, 파일 또는 구조화된 데이터 부분을 전달합니다.
작업은 ID 및 수명 주기 상태가 있는 상태 저장 작업 단위입니다. 클라이언트는 장기 실행 작업을 따르고 후속 작업 차례를 보낼 수 있습니다. 연결이 끊어진 후 작업을 취소하거나 다시 구독할 수도 있습니다.
프로토콜 버전프로토콜 버전에 대한 직접 링크
Mastra는 동일한 Agent 카드 및 실행 URL에서 A2A 프로토콜 v0.3 및 v1.0을 지원합니다. 그만큼A2A-Version request header selects the wire protocol:
- 누락되었거나 비어 있거나
0.3: Uses the existing v0.3 API. 1.0: v1.0 API를 사용합니다.- 기타 값: 다음을 반환합니다.
VersionNotSupportedprotocol error.
기존의A2AAgent and MastraClient.getA2A() integrations continue to use v0.3. Use MastraClient.getA2AV1() for v1.0 requests. The v1 client sends A2A-Version: 1.0 automatically and adds the tasks/list operation.
v1.0 프로토콜 유형 및 코덱을 다음에서 가져옵니다.@mastra/core/a2a/v1. The existing @mastra/core/a2a/client export remains on v0.3.
시작하기시작하기에 대한 직접 링크
A2A에는 Mastra에 두 가지 공통 경로가 있습니다.
- 원격 A2A Agent를 Mastra 하위 Agent로 사용합니다.
A2AAgent. - 다음을 사용하여 Mastra A2A 엔드포인트에 요청을 보냅니다.
MastraClient.getA2A().
사용A2AAgent 다른 Mastra Agent가 원격 Agent에 작업을 위임해야 할 때 사용합니다. 애플리케이션 코드에서 A2A가 활성화된 Mastra 엔드포인트를 직접 호출해야 할 때는 클라이언트 SDK를 사용하세요.
A2A Agent를 하위 Agent로 사용A2A Agent를 하위 Agent로 사용에 대한 직접 링크
사용A2AAgent 를 사용하여 원격 A2A Agent를 래핑한 다음, 이를 supervisor agents 패턴으로 상위 Agent에 추가하세요. 원격 서버가 여러 Agent를 호스팅하거나 사용자 지정 well-known 경로를 사용하는 경우에는 Agent 카드 URL을 명시적으로 전달하세요.
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,
},
})
만약에url points to a domain, A2AAgent fetches the agent card from /.well-known/agent-card.json. 해당 검색 경로를 따르는 단일 Agent 서버에는 도메인 URL을 사용하세요. 다중 Agent 서버에는 다음과 같이 전체 카드 URL을 전달하세요: https://agent.example.com/api/.well-known/weather-agent/agent-card.json.
실행 중에는A2AAgent:
- 원격 Agent 카드를 가져오고 캐시합니다.
- 카드에서 실행 URL과 기능을 읽습니다.
- 통화
message/sendfor non-streaming runs ormessage/streamwhen streaming is supported. - 원격 메시지, 작업, 아티팩트 및 상태 업데이트를 Mastra 하위 Agent 결과로 변환합니다.
- 지원
resumeGenerate()andresumeStream()원격 작업에 후속 입력이나 재구독이 필요할 때 사용합니다.
원격 카드가 스트리밍 지원을 광고하지 않는 경우A2AAgent.stream() 는 비스트리밍 생성 경로로 대체 처리하고 버퍼링된 스트림 결과를 반환합니다.
클라이언트 SDK를 사용하여 요청 보내기클라이언트 SDK를 사용하여 요청 보내기에 대한 직접 링크
사용MastraClient.getA2A() 애플리케이션 코드에서 A2A가 활성화된 Mastra Agent를 호출하려는 경우 사용합니다. baseUrl for the server origin and apiPrefix when the server doesn't use the default /api prefix.
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)
사용sendMessageStream() 를 구성하여 메시지를 전송하고 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)
}
}
작업이 계속 실행되는 동안 스트림 연결이 끊어지면 다음을 사용하십시오.resubscribeTask() 를 사용하여 진행 중인 작업의 실시간 업데이트를 수신하세요:
const updates = a2a.resubscribeTask({
id: 'task-123',
})
for await (const event of updates) {
console.log(event)
}
v1.0 클라이언트 사용v1.0 클라이언트 사용에 대한 직접 링크
사용getA2AV1() 를 사용하여 A2A v1.0 유선 프로토콜을 사용하도록 설정하세요. 프로토콜 패키지는 JSON 형태의 입력으로부터 v1 요청 값을 생성하기 위한 코덱을 제공합니다:
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)
}
v1.0 클라이언트는 다음을 지원합니다.getAgentCard(), sendMessage(), sendMessageStream(), getTask(), listTasks(), cancelTask(), and resubscribeTask().
하위 Agent 호출 구성하위 Agent 호출 구성에 대한 직접 링크
A2AAgent인증되거나 제한된 환경에 대한 요청 옵션을 허용합니다.
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,
})
합격하실 수도 있습니다credentials, fetch, and abortSignal 런타임에 사용자 지정 fetch 동작이나 요청 취소가 필요할 때 사용합니다.
인간 참여형인간 참여형에 대한 직접 링크
A2A Model HITL(Human-In-The-Loop)은 다음과 같이 작동합니다.input-required 작업 상태입니다. 입력을 기다리며 작업이 일시 중지되면 클라이언트는 동일한 taskId, and the server continues the task.
Mastra는 Agent 정지 Model을 양방향으로 이 상태에 매핑합니다.
- 서버로서: 노출된 Agent가 일시 중지되면 작업이 다음으로 전환됩니다.
input-required. This includes suspensions caused by tool approval or a tool that callssuspend(). 작업 상태 메시지에는 텍스트 Prompt와 구조화된suspendPayloadandresumeSchema. A follow-upmessage/sendormessage/streamrequest with the sametaskId는 제공된 입력으로 일시 중단된 실행을 재개합니다. - 클라이언트로서: 원격 작업이 도달했을 때
input-requiredorauth-required,A2AAgentreturns a suspended result withfinishReason: 'suspended'and asuspendPayload. CallingresumeGenerate()orresumeStream()는 원래의taskId.
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)
}
다음에 대한 후속 메시지input-required 작업은 재개 데이터를 구조화된 데이터 파트로 전달하거나, 텍스트 파트 내의 JSON 또는 일반 텍스트로 전달할 수 있습니다.
재개된 실행에 추가 입력이 필요한 경우 작업은 다음으로 돌아갑니다.input-required 그리고 이 흐름이 반복됩니다. 일시 중단된 실행을 재개하려면 Mastra 서버에 스토리지가 구성되어 있어야 요청 간에 일시 중단된 실행 상태를 복원할 수 있습니다.
:::참고 A2A 작업 기록은 Memory 내 저장소에 있으므로 일시 중지된 작업은 해당 작업을 일시 중지한 동일한 서버 프로세스에 의해서만 재개될 수 있습니다. 고정 라우팅이 없는 서버 다시 시작 또는 수평 확장 배포에서는 작업 기록이 손실되고 작업을 찾을 수 없다는 오류로 인해 후속 메시지가 실패합니다. :::
푸시 알림푸시 알림에 대한 직접 링크
Mastra는 광고하는 원격 Agent에 대한 A2A 푸시 알림을 지원합니다.capabilities.pushNotifications. 클라이언트가 스트림을 계속 열어 둘 수 없거나, 장기 실행 작업이 원래 요청 종료 후 콜백 URL에 업데이트를 전송해야 하는 경우 푸시 알림을 사용하세요.
클라이언트에 작업 ID가 있으면 해당 작업에 대한 콜백 URL을 등록할 수 있습니다.
await a2a.setTaskPushNotificationConfig({
taskId: 'task-123',
pushNotificationConfig: {
url: 'https://app.example.com/a2a/tasks',
token: process.env.A2A_WEBHOOK_TOKEN,
},
})
Mastra 서버는 작업이 도달하면 현재 작업 스냅샷을 등록된 콜백으로 보냅니다.completed, failed, canceled, rejected, input-required, or auth-required. 푸시 알림 전송은 최선형 방식으로 이루어집니다. 콜백 URL을 보호하고 알림 토큰을 검증하며, 내부 네트워크 대상을 푸시 알림 목적지로 노출하지 마세요.
푸시 알림 구성은 Memory에 저장되며 서버를 다시 시작한 후 다시 등록해야 합니다.
Agent 카드 서명 및 확인Agent 카드 서명 및 확인에 대한 직접 링크
Mastra는 서명된 A2A Agent 카드를 지원하므로 클라이언트는 발견된 카드가 신뢰할 수 있는 게시자로부터 왔으며 전송 중에 변경되지 않았는지 확인할 수 있습니다. 원격 Agent를 노출하는 Mastra 서버에서 서명을 구성합니다.
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',
},
},
},
},
})
서명이 구성되면 Mastra에는 다음이 포함됩니다.signatures 배열에 포함됩니다. 클라이언트 검증은 선택 사항이며, 서명되지 않은 카드도 변경 없이 반환됩니다.
서명된 카드를 확인하세요.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.')
}
클라이언트가 원격 Agent를 호출하기 전에 신뢰할 수 있는 키를 적용해야 하는 경우 클라이언트측 서명 확인을 사용합니다.
하위 대리인 카드 확인하위 대리인 카드 확인에 대한 직접 링크
사용verifyAgentCard 상위 Agent가 작업을 위임하기 전에 원격 Agent를 검증해야 할 때 사용합니다. 검증 훅은 가져온 Agent 카드와 해당 카드를 가져온 위치 및 시점에 관한 컨텍스트를 받습니다.
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}`)
}
},
},
})
상위 Agent가 원격 Agent에 위임하기 전에 이 후크를 사용하여 예상 공급자, 예상 끝점, 인증서 바인딩 ID, 서명된 카드 또는 기타 신뢰 요구 사항을 적용합니다.