A2A 에이전트

이를 통해 애플리케이션은 A2AAgentA2A(에이전트 간) 프로토콜을 통해 노출되는 원격 에이전트에 연결할 수 있습니다. A2A 규격 엔드포인트를 표준 AIAgent으로 래핑하므로 빌드된 프레임워크 또는 기술에 관계없이 익숙한 메서드를 RunAsyncRunStreamingAsync 사용하고 원격 에이전트와 상호 작용할 수 있습니다.

Getting Started

프로젝트에 필요한 NuGet 패키지를 추가합니다.

dotnet add package Microsoft.Agents.AI.A2A --prerelease

에이전트 검색

원격 A2A 에이전트와 통신하기 전에 이를 검색하고 인스턴스를 AIAgent 만들어야 합니다. A2A 프로토콜은 각각 에이전트 프레임워크에서 지원하는 세 가지 검색 전략을 정의합니다.

Well-Known URI

A2A 에이전트는 표준화된 경로에서 https://{domain}/.well-known/agent-card.json 검색할 수 있도록 할 수 있습니다. 카드를 A2ACardResolver 가져오고 한 번의 호출로 에이전트를 만들려면 다음을 사용합니다.

using A2A;
using Microsoft.Agents.AI;

// Initialize a resolver pointing at the remote agent's host.
A2ACardResolver resolver = new(new Uri("https://a2a-agent.example.com"));

// Resolve the agent card and create an AIAgent in one step.
AIAgent agent = await resolver.GetAIAgentAsync();

// Use the agent.
Console.WriteLine(await agent.RunAsync("Hello!"));

팁 (조언)

GetAIAgentAsync또한 A2AClientOptions 대한 선택적 매개 변수를 허용합니다.

Catalog-Based 검색

엔터프라이즈 환경 또는 공용 마켓플레이스에서 에이전트 카드는 종종 중앙 레지스트리에서 관리됩니다. 이러한 레지스트리에서 이미 AgentCard 가져온 경우 다음으로 직접 AIAgent변환합니다.

using A2A;
using Microsoft.Agents.AI;

// Assume agentCard was retrieved from a registry or catalog.
AgentCard agentCard = await GetAgentCardFromRegistryAsync("travel-planner");

AIAgent agent = agentCard.AsAIAgent();

Console.WriteLine(await agent.RunAsync("Plan a trip to Paris."));

직접 구성

에이전트 엔드포인트가 미리 알려진 긴밀하게 결합된 시스템 또는 개발 시나리오의 경우 직접 만들고 A2AClient 다음으로 AIAgent변환합니다.

using A2A;
using Microsoft.Agents.AI;

// Create a client pointing at the known agent endpoint.
A2AClient a2aClient = new(new Uri("https://a2a-agent.example.com"));

AIAgent agent = a2aClient.AsAIAgent(name: "my-agent", description: "A helpful assistant.");

Console.WriteLine(await agent.RunAsync("What can you help me with?"));

프로토콜 선택

A2A 에이전트는 HTTP+JSON 및 JSON-RPC와 같은 여러 프로토콜 바인딩을 노출할 수 있습니다. 기본적으로 HTTP+JSON은 JSON-RPC보다 선호됩니다. 사용되는 프로토콜 바인딩을 명시적으로 제어하는 데 사용합니다 A2AClientOptions.PreferredBindings .

메모

선택한 프로토콜 바인딩을 지원하는 엔드포인트에서 원격 A2A 에이전트를 사용할 수 있어야 합니다.

using A2A;
using Microsoft.Agents.AI;

A2ACardResolver agentCardResolver = new(new Uri("https://a2a-agent.example.com"));

AgentCard agentCard = await agentCardResolver.GetAgentCardAsync();

// Prefer HTTP+JSON protocol binding. For JSON-RPC, set PreferredBindings = [ProtocolBindingNames.JsonRpc]
A2AClientOptions options = new()
{
    PreferredBindings = [ProtocolBindingNames.HttpJson]
};

AIAgent agent = agentCard.AsAIAgent(options: options);

Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));

스트리밍

A2A는 Server-Sent 이벤트를 통해 스트리밍 응답을 지원합니다. 원격 에이전트가 요청을 처리할 때 실시간으로 업데이트를 수신하는 데 사용합니다 RunStreamingAsync .

using A2A;
using Microsoft.Agents.AI;

A2ACardResolver resolver = new(new Uri("https://a2a-agent.example.com"));
AIAgent agent = await resolver.GetAIAgentAsync();

await foreach (var update in agent.RunStreamingAsync("Write a short story about a robot."))
{
    if (!string.IsNullOrEmpty(update.Text))
    {
        Console.Write(update.Text);
    }
}

백그라운드 응답

A2A 에이전트는 장기 실행 작업을 처리하기 위한 백그라운드 응답을 지원합니다. 원격 A2A 에이전트가 즉각적인 메시지 대신 작업을 반환하는 경우 에이전트 프레임워크는 결과를 폴링하거나 중단된 스트림에 다시 연결하는 데 사용할 수 있는 연속 토큰을 제공합니다.

작업 완료를 위한 폴링

비 스트리밍 시나리오의 경우 연속 토큰을 수신하고 태스크가 완료될 때까지 폴링하는 데 사용합니다 AllowBackgroundResponses .

using A2A;
using Microsoft.Agents.AI;

A2ACardResolver resolver = new(new Uri("https://a2a-agent.example.com"));
AIAgent agent = await resolver.GetAIAgentAsync();

AgentSession session = await agent.CreateSessionAsync();

// AllowBackgroundResponses must be true so the server returns immediately with a continuation token
// instead of blocking until the task is complete.
AgentRunOptions options = new() { AllowBackgroundResponses = true };

// Start the initial run with a long-running task.
AgentResponse response = await agent.RunAsync(
    "Conduct a comprehensive analysis of quantum computing applications in cryptography.",
    session,
    options: options);

// Poll until the response is complete.
while (response.ContinuationToken is { } token)
{
    // Wait before polling again.
    await Task.Delay(TimeSpan.FromSeconds(2));

    // Continue with the token.
    response = await agent.RunAsync(session, options: new AgentRunOptions { ContinuationToken = token });
}

Console.WriteLine(response);

스트림 다시 연결

스트리밍 시나리오에서 각 업데이트에는 연속 토큰이 포함될 수 있습니다. 스트림이 중단되면 토큰을 사용하여 다시 연결하고 처음부터 응답 스트림을 가져옵니다.

using A2A;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

A2ACardResolver resolver = new(new Uri("https://a2a-agent.example.com"));
AIAgent agent = await resolver.GetAIAgentAsync();

AgentSession session = await agent.CreateSessionAsync();

ResponseContinuationToken? continuationToken = null;

await foreach (var update in agent.RunStreamingAsync(
    "Conduct a comprehensive analysis of quantum computing applications in cryptography.",
    session))
{
    // Save the continuation token to reconnect later if the stream is interrupted.
    // Continuation tokens are only returned for long-running tasks. If the A2A agent
    // returns a message instead of a task, the continuation token will not be initialized.
    if (update.ContinuationToken is { } token)
    {
        continuationToken = token;
    }
}

// If the stream was interrupted and a continuation token was captured,
// reconnect to the response stream using the saved continuation token.
if (continuationToken is not null)
{
    await foreach (var update in agent.RunStreamingAsync(
        session,
        options: new() { ContinuationToken = continuationToken }))
    {
        if (!string.IsNullOrEmpty(update.Text))
        {
            Console.WriteLine(update.Text);
        }
    }
}

메모

A2A 에이전트는 스트림의 특정 지점에서 다시 시작을 스트림하는 것이 아니라 스트림 다시 연결을 지원합니다(처음부터 동일한 응답 스트림 가져오기).

Tools

A2AAgent 는 원격 A2A 에이전트를 둘러싼 전송 수준 래퍼입니다. 원격 에이전트가 사용하는 도구는 원격 쪽에서 라이브로 사용되며 코드에 표시되지 않습니다. 에이전트 프레임워크 도구 형식(함수 도구, 코드 인터프리터, 파일 검색, 호스트/로컬 MCP 등)은 자체에 A2AAgent 구성되지 않으므로 원격 에이전트의 기능을 확장하고 원격 에이전트의 구성을 변경합니다.

Getting Started

A2A 패키지를 설치합니다.

pip install agent-framework-a2a --pre

초기화

A2AAgent 는 원격 에이전트에 대해 미리 알고 있는 양에 따라 세 가지 방법으로 초기화할 수 있습니다.

직접 URL

엔드포인트가 알려진 개발 또는 긴밀하게 결합된 시스템의 경우:

from agent_framework.a2a import A2AAgent

async with A2AAgent(name="remote", url="https://a2a-agent.example.com") as agent:
    response = await agent.run("Hello!")
    print(response.messages[0].text)

URL만 제공되면 A2AAgent 내부적으로 최소 에이전트 카드를 만들고 JSON-RPC를 사용하여 연결합니다.

에이전트 카드

레지스트리 또는 카탈로그가 AgentCard 있는 경우 직접 전달합니다.

from agent_framework.a2a import A2AAgent

async with A2AAgent(agent_card=agent_card) as agent:
    response = await agent.run("Plan a trip to Paris.")
    print(response.messages[0].text)

제공 AgentCard 되면 A2AAgent 기본값 namedescription 카드에서 가져옵니다. 카드로 전송을 협상합니다 supported_interfaces.

Well-Known URI(A2ACardResolver)

표준 잘 알려진 경로(A2ACardResolver)에서 원격 에이전트를 검색하려면 다음 a2a-sdk 을 사용합니다/.well-known/agent.json.

import httpx
from a2a.client import A2ACardResolver
from agent_framework.a2a import A2AAgent

async with httpx.AsyncClient(timeout=60.0) as http_client:
    resolver = A2ACardResolver(httpx_client=http_client, base_url="https://a2a-agent.example.com")
    agent_card = await resolver.get_agent_card()

async with A2AAgent(agent_card=agent_card) as agent:
    response = await agent.run("What can you help me with?")
    print(response.messages[0].text)

스트리밍

원격 에이전트가 요청을 처리할 때 실시간으로 업데이트를 수신하는 데 사용합니다 stream=True .

from agent_framework.a2a import A2AAgent

async with A2AAgent(name="remote", url="https://a2a-agent.example.com") as agent:
    async with agent.run("Write a short story about a robot.", stream=True) as stream:
        async for update in stream:
            for content in update.contents:
                if content.text:
                    print(content.text, end="", flush=True)

        final = await stream.get_final_response()
        print(f"\n({len(final.messages)} message(s))")

장시간 실행 작업

기본적으로 A2AAgent 원격 에이전트가 완료되기를 기다린 후 반환합니다. 장기 실행 작업의 경우 나중에 폴링하거나 구독하는 데 사용할 수 있는 연속 토큰을 표시하도록 설정합니다 background=True .

from agent_framework.a2a import A2AAgent

async with A2AAgent(name="worker", url="https://a2a-agent.example.com") as agent:
    # Start a long-running task
    response = await agent.run("Process this large dataset", background=True)

    if response.continuation_token:
        # Poll for completion later
        result = await agent.poll_task(response.continuation_token)
        print(result)

폴링 대신 SSE 스트림을 다시 구독할 수도 있습니다.

# Resubscribe to the task's event stream
response = await agent.run(continuation_token=response.continuation_token)

대화 식별자(context_id)

A2AAgent.run()AgentSession와 함께 호출할 때 발신 메시지에 이미 포함되어 있지 않은 경우, 에이전트는 context_id에서 A2A session.service_session_id를 자동으로 추출합니다. 이렇게 하면 여러 A2A 호출에서 대화 연속성을 유지할 수 있습니다.

from agent_framework import AgentSession
from agent_framework.a2a import A2AAgent

async with A2AAgent(name="remote", url="https://a2a-agent.example.com") as agent:
    session = AgentSession(service_session_id="my-conversation-1")

    # context_id is automatically set to "my-conversation-1"
    response = await agent.run("Hello!", session=session)

    # Subsequent calls with the same session continue the conversation
    response = await agent.run("Follow-up question", session=session)

메시지에 명시적 context_id 항목이 있으면, additional_properties의 해당 값이 세션 파생 대체 값보다 우선합니다.

인증

A2A 보안 엔드포인트에 AuthInterceptor를 사용합니다.

from a2a.client.auth.interceptor import AuthInterceptor
from agent_framework.a2a import A2AAgent

class BearerAuth(AuthInterceptor):
    def __init__(self, token: str):
        self.token = token

    async def intercept(self, request):
        request.headers["Authorization"] = f"Bearer {self.token}"
        return request

async with A2AAgent(
    name="secure-agent",
    url="https://secure-a2a-agent.example.com",
    auth_interceptor=BearerAuth("your-token"),
) as agent:
    response = await agent.run("Hello!")

시간 제한 구성

A2AAgenttimeout 요청 시간 제한을 제어하기 위한 매개 변수를 허용합니다.

import httpx
from agent_framework.a2a import A2AAgent

# Simple timeout (applies to all components)
async with A2AAgent(name="remote", url="https://example.com", timeout=120.0) as agent:
    ...

# Fine-grained timeout
async with A2AAgent(
    name="remote",
    url="https://example.com",
    timeout=httpx.Timeout(connect=10.0, read=120.0, write=10.0, pool=5.0),
) as agent:
    ...

시간 제한을 지정하지 않으면 기본값은 10대 연결, 60년대 읽기, 10s 쓰기, 5s 풀입니다.

Tools

A2AAgent 는 원격 A2A 에이전트를 둘러싼 전송 수준 래퍼입니다. 원격 에이전트가 사용하는 도구는 원격 쪽에서 라이브로 사용되며 코드에 표시되지 않습니다. 에이전트 프레임워크 도구 형식(함수 도구, 코드 인터프리터, 파일 검색, 호스트/로컬 MCP 등)은 자체에 A2AAgent 구성되지 않으므로 원격 에이전트의 기능을 확장하고 원격 에이전트의 구성을 변경합니다.

Foundry 에이전트가 A2A 에이전트를 도구로 호출하도록 하려면 <a0/>의 팩터리를 참조하세요.

다음 단계