06-03-04 — Agent Framework 1.0: MCP nativo, A2A, graph workflow engine
MCP — Model Context Protocol nativo
MCP (Anthropic, 2024) define um protocolo padrão para que LLMs descubram e invoquem ferramentas. O AF 1.0 implementa tanto o lado client (consumir tools de servidores MCP) quanto o lado server (expor plugins como servidor MCP).
Consumindo um servidor MCP externo
using Microsoft.AgentFramework.MCP;
// Conecta a um servidor MCP (ex: servidor de acesso a banco de dados)
var mcpClient = new McpClient("https://meu-servidor-mcp.empresa.com");
// AF 1.0 descobre as tools automaticamente e as registra no Kernel
await kernel.AddMcpToolsAsync(mcpClient);
// A partir daqui, o agente pode usar qualquer tool do servidor MCP
// como se fossem plugins nativos — sem código adicional
var resultado = await kernel.InvokePromptAsync(
"Quantos contratos vencem nos próximos 30 dias?",
new KernelArguments(new OpenAIPromptExecutionSettings
{
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
}));
Expondo um agente como servidor MCP
// O agente AF 1.0 pode ser consumido por Claude, Cursor, qualquer cliente MCP
builder.Services.AddMcpServer(options =>
{
options.ServerName = "Assistente Empresarial Impar";
options.ServerVersion = "1.0.0";
options.ExposeKernelFunctions = true; // todos os plugins viram tools MCP
});
app.MapMcpEndpoints("/mcp"); // SSE em /mcp/sse, HTTP em /mcp/messages
A2A — Agent-to-Agent Protocol
A2A (Google, 2025 — adotado pela Microsoft no AF 1.0) permite que agentes de frameworks diferentes se descubram e colaborem:
sequenceDiagram
participant ClientAgent as AF 1.0 Agent (C#)
participant Registry as Agent Registry
participant RemoteAgent as Google ADK Agent (Python)
ClientAgent->>Registry: GET /.well-known/agent.json
Registry-->>ClientAgent: Agent Card (capabilities, endpoint)
ClientAgent->>RemoteAgent: POST /a2a/tasks/send
Note over ClientAgent,RemoteAgent: JSON-RPC sobre HTTPS
RemoteAgent-->>ClientAgent: TaskResult (streaming SSE)
using Microsoft.AgentFramework.A2A;
// Descobrir um agente remoto via URL do Agent Card
var remoteAgent = await A2AClient.DiscoverAgentAsync(
"https://agente-clima.parceiro.com/.well-known/agent.json");
// Delegar tarefa — AF 1.0 trata o agente remoto como qualquer plugin
var resultado = await remoteAgent.SendTaskAsync(new A2ATask
{
Message = new A2AMessage
{
Role = "user",
Parts = [new TextPart("Qual a previsão para SP esta semana?")]
}
});
// Streaming de resposta
await foreach (var evento in remoteAgent.StreamTaskAsync(task))
{
Console.Write(evento.Delta?.Text);
}
Registrando seu agente para ser descoberto
// AF 1.0 gera e serve o Agent Card automaticamente
builder.Services.AddA2AServer(options =>
{
options.AgentName = "Assistente Financeiro Impar";
options.Description = "Análise financeira com acesso ao ERP SAP";
options.Provider = new A2AProvider { Name = "Impar", Url = "https://impar.com.br" };
options.Capabilities = new A2ACapabilities
{
Streaming = true,
PushNotifications = true
};
options.Skills = [
new A2ASkill { Id = "analise-contratos", Name = "Análise de Contratos" },
new A2ASkill { Id = "kpis-financeiros", Name = "KPIs Financeiros" }
];
});
app.MapA2AEndpoints(); // serve /.well-known/agent.json e /a2a/tasks/*
Graph Workflow Engine
Herdado do AutoGen v0.4, o graph engine do AF 1.0 permite fluxos de trabalho com estado que vão além de simples tool calling:
using Microsoft.AgentFramework.Graph;
// Define o estado do workflow
record WorkflowState(string UserQuery, string? ResearchResult, string? FinalReport);
// Cria o grafo de workflow
var workflow = new AgentWorkflow<WorkflowState>()
.AddNode("pesquisa", async (state, ctx) =>
{
var resultado = await ctx.InvokeAgentAsync<PesquisaAgent>(state.UserQuery);
return state with { ResearchResult = resultado };
})
.AddNode("redacao", async (state, ctx) =>
{
var relatorio = await ctx.InvokeAgentAsync<RedacaoAgent>(state.ResearchResult!);
return state with { FinalReport = relatorio };
})
.AddNode("revisao", async (state, ctx) =>
{
// Human-in-the-loop: pausa aguardando aprovação
var aprovado = await ctx.RequestHumanApprovalAsync(
state.FinalReport!,
"Aprovar relatório para envio?");
return state;
})
.AddConditionalEdge("pesquisa", state =>
state.ResearchResult?.Length > 100 ? "redacao" : "pesquisa") // retry se insuficiente
.AddEdge("redacao", "revisao")
.SetEntryPoint("pesquisa");
// Executar com checkpointing
var runner = new WorkflowRunner(workflow, checkpointer: new AzureTableCheckpointer());
var resultado = await runner.RunAsync(new WorkflowState("Analise concorrência Q2 2026"));
Exemplo integrado: MCP + A2A + Graph
// Um workflow que usa MCP para tools locais e A2A para delegar pesquisa
var workflow = new AgentWorkflow<RelatorioState>()
.AddNode("coleta_dados", async (state, ctx) =>
{
// Tools via MCP (servidor de dados SAP)
var kpis = await ctx.Kernel.InvokePromptAsync(
"Busque KPIs do trimestre via MCP");
return state with { KPIs = kpis.ToString() };
})
.AddNode("pesquisa_mercado", async (state, ctx) =>
{
// Delega pesquisa para agente especializado via A2A
var agentePesquisa = await A2AClient.DiscoverAgentAsync(pesquisaAgentUrl);
var pesquisa = await agentePesquisa.SendTaskAsync(
new A2ATask { Message = state.KPIs! });
return state with { MarketResearch = pesquisa.Result };
})
.AddNode("gera_relatorio", async (state, ctx) =>
{
// Geração local com todos os dados
var relatorio = await ctx.Kernel.InvokePromptAsync(
$"Gere relatório executivo com: KPIs={state.KPIs}, Mercado={state.MarketResearch}");
return state with { Report = relatorio.ToString() };
})
.SetEntryPoint("coleta_dados");
MCP vs A2A: MCP é para ferramentas (funções stateless que retornam dados). A2A é para agentes (entidades com estado próprio, raciocínio e capacidade de subdeletar). Use MCP para integrar com APIs e sistemas; use A2A para colaboração entre agentes de diferentes domínios.