09-02-01 — Agent Service GA (março 2026): Responses API, threads, tools, runs
TL;DR
O AI Foundry Agent Service entrou em GA em março de 2026 com a Responses API (evolução da Assistants API da OpenAI). Conceitos centrais: Agent (definição: modelo + instruções + tools), Thread (histórico de conversa persistido), Message (input do usuário ou output do agente), Run (execução síncrona ou assíncrona do agente). Tudo gerenciado pelo serviço — você não precisa manter estado no seu app.
Arquitetura do Agent Service
Agent Service participant Tools as Tools Runtime
(file search, code, web) participant Model as GPT-4o
(Azure OpenAI) participant Storage as Thread Store
(gerenciado) App->>AgentSvc: POST /threads (cria thread) AgentSvc-->>App: thread_id App->>AgentSvc: POST /threads/{id}/messages
(user message) App->>AgentSvc: POST /threads/{id}/runs
(trigger agent) AgentSvc->>Storage: salva mensagem AgentSvc->>Model: prompt (instruções + thread history + tools) Model-->>AgentSvc: tool_call ou resposta final opt Tool call AgentSvc->>Tools: executa tool (file_search, etc.) Tools-->>AgentSvc: resultado da tool AgentSvc->>Model: resultado + continua end Model-->>AgentSvc: resposta final AgentSvc->>Storage: persiste resposta AgentSvc-->>App: run completed App->>AgentSvc: GET /threads/{id}/messages AgentSvc-->>App: lista de mensagens
Conceitos fundamentais
Agent
Definição configurável: qual modelo usar, quais instruções (system prompt), quais tools estão disponíveis, qual vector store usar para file search. Uma vez criado, pode ser reutilizado em múltiplos threads.
Thread
Histórico de conversa persistido no serviço. Você não precisa passar o histórico completo a cada chamada — o serviço gerencia. Threads ficam persistidos até você deletar explicitamente.
Message
Uma mensagem no thread. Pode ser do usuário (role: "user") ou do agente (role: "assistant"). Suporta text, image (multimodal), e file attachments.
Run
A execução do agente sobre o thread. O Run tem status: queued → in_progress → requires_action → completed / failed / cancelled. Pode ser polling ou streaming.
Implementação completa em C#
using Azure.AI.Projects;
using Azure.Identity;
using System.ClientModel.Primitives;
// 1. Conectar ao projeto Foundry
var client = new AgentsClient(
endpoint: "https://seu-projeto.services.ai.azure.com",
credential: new DefaultAzureCredential()
);
// 2. Criar o agente (uma vez; pode reutilizar)
var agent = await client.CreateAgentAsync(
model: "gpt-4o",
name: "customer-support-impar",
instructions: @"Você é o assistente de suporte da Impar,
empresa de consultoria .NET. Responda em português,
seja direto e objetivo. Consulte a base de conhecimento
antes de responder.",
tools: new List
{
new FileSearchToolDefinition()
}
);
// 3. Criar thread para a conversa
var thread = await client.CreateThreadAsync();
// 4. Adicionar mensagem do usuário
await client.CreateMessageAsync(
threadId: thread.Value.Id,
role: MessageRole.User,
content: "Quais são os SLAs do contrato de suporte?"
);
// 5. Executar o agente (streaming)
await foreach (var streamEvent in client.CreateRunStreamingAsync(
threadId: thread.Value.Id,
assistantId: agent.Value.Id))
{
if (streamEvent is MessageContentUpdate contentUpdate)
{
Console.Write(contentUpdate.Text);
}
}
// 6. Cleanup (opcional em produção - threads são baratos)
await client.DeleteThreadAsync(thread.Value.Id);
await client.DeleteAgentAsync(agent.Value.Id);
Responses API vs Assistants API
A Responses API é a nova geração da Assistants API, lançada pela OpenAI em março de 2025 e adotada pelo Azure AI Foundry no GA de março de 2026:
| Aspecto | Assistants API (legado) | Responses API (atual) |
|---|---|---|
| Stateful runs | Polling obrigatório | Polling + streaming nativo |
| Ferramentas | function_calling, code_interpreter, retrieval | web_search, file_search, code_interpreter, MCP, custom |
| Multimodal | Limitado | Nativo (imagem, áudio) |
| Raciocínio | Não | Suporte a modelos o3/o4 com reasoning |
| Thread management | Manual | Managed + automático |
Runs síncronos vs assíncronos
Para APIs web, use streaming para UX responsiva. Para batch processing (relatórios, análise de documentos), use polling assíncrono:
// Polling assíncrono para batch
var run = await client.CreateRunAsync(thread.Value.Id, agent.Value.Id);
do
{
await Task.Delay(1000);
run = await client.GetRunAsync(thread.Value.Id, run.Value.Id);
} while (run.Value.Status == RunStatus.InProgress ||
run.Value.Status == RunStatus.Queued);
if (run.Value.Status == RunStatus.Completed)
{
var messages = client.GetMessages(thread.Value.Id);
// processar mensagens
}