Partilhar via


OpenAI-Compatible Pontos finais

O Agent Framework suporta protocolos compatíveis com OpenAI tanto para alojar agentes por APIs padrão como para se conectar a qualquer endpoint compatível com OpenAI.

O que são os protocolos OpenAI?

São suportados dois protocolos OpenAI:

  • API de Completação de Chat — Formato padrão de pedido/resposta sem estado para interações de chat
  • API de Respostas — Formato avançado que suporta conversas, streaming e processos de agente de longa duração

A API Respostas é agora a abordagem padrão e recomendada segundo a documentação da OpenAI. Oferece uma interface mais abrangente e rica em funcionalidades para construir aplicações de IA, com gestão de conversas integrada, capacidades de streaming e suporte para processos de longa duração.

Use a API de Respostas quando:

  • Desenvolvimento de novas aplicações (padrão recomendado)
  • Precisas de gestão de conversas do lado do servidor. No entanto, isso não é um requisito: pode continuar a usar a API de Respostas em modo sem estado.
  • Queres um histórico de conversas persistente
  • Estás a desenvolver processos de longa duração para agentes
  • Precisas de capacidades avançadas de streaming com tipos de eventos detalhados
  • Quer acompanhar e gerir respostas individuais (por exemplo, recuperar uma resposta específica por ID, verificar o seu estado ou cancelar uma resposta em curso)

Use a API de Completação de Chat quando:

  • Migração de aplicações existentes que dependem do formato Chat Completions
  • Precisas de interações simples e sem estado de pedido/resposta
  • A gestão do estado é inteiramente gerida pelo seu cliente
  • Estás a integrar-te com ferramentas existentes que só suportam Chat Completions
  • Precisa de máxima compatibilidade com sistemas legados

Hospedagem de Agentes como Endpoints da OpenAI (.NET)

A Microsoft.Agents.AI.Hosting.OpenAI biblioteca permite-lhe expor agentes de IA através de endpoints HTTP compatíveis com OpenAI, suportando tanto as APIs Chat Completions como Responses. Isto permite-lhe integrar os seus agentes com qualquer cliente ou ferramenta compatível com OpenAI.

Pacote NuGet:

API de conclusão de bate-papo

A API Chat Completions fornece uma interface simples e sem estado para interagir com agentes usando o formato padrão de chat OpenAI.

Configurar um agente no ASP.NET Core com integração com o ChatCompletions

Aqui está um exemplo completo que expõe um agente usando a API Chat Completions:

Pré-requisitos

1. Criar um projeto ASP.NET Core Web API

Crie um novo projeto ASP.NET Core Web API ou use um já existente.

2. Instalar as dependências necessárias

Instale os seguintes pacotes:

Execute os seguintes comandos no diretório do seu projeto para instalar os pacotes NuGet necessários:

# Hosting.A2A.AspNetCore for OpenAI ChatCompletions/Responses protocol(s) integration
dotnet add package Microsoft.Agents.AI.Hosting.OpenAI --prerelease

# Libraries to connect to Azure OpenAI
dotnet add package Azure.AI.OpenAI --prerelease
dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.AI
dotnet add package Microsoft.Extensions.AI.OpenAI --prerelease

# Swagger to test app
dotnet add package Microsoft.AspNetCore.OpenApi
dotnet add package Swashbuckle.AspNetCore

3. Configurar a ligação Azure OpenAI

A aplicação requer uma ligação Azure OpenAI. Configura o endpoint e o nome da implementação usando dotnet user-secrets ou variáveis de ambiente. Também podes simplesmente editar o appsettings.json, mas isso não é recomendado para as aplicações implementadas em produção, pois alguns dados podem ser considerados secretos.

dotnet user-secrets set "AZURE_OPENAI_ENDPOINT" "https://<your-openai-resource>.openai.azure.com/"
dotnet user-secrets set "AZURE_OPENAI_DEPLOYMENT_NAME" "gpt-4o-mini"

4. Adicionar o código à Program.cs

Substitua o conteúdo do Program.cs pelo seguinte código:

using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI.Hosting;
using Microsoft.Extensions.AI;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenApi();
builder.Services.AddSwaggerGen();

string endpoint = builder.Configuration["AZURE_OPENAI_ENDPOINT"]
    ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
string deploymentName = builder.Configuration["AZURE_OPENAI_DEPLOYMENT_NAME"]
    ?? throw new InvalidOperationException("AZURE_OPENAI_DEPLOYMENT_NAME is not set.");

// Register the chat client
IChatClient chatClient = new AzureOpenAIClient(
        new Uri(endpoint),
        new DefaultAzureCredential())
    .GetChatClient(deploymentName)
    .AsIChatClient();
builder.Services.AddSingleton(chatClient);

builder.AddOpenAIChatCompletions();

// Register an agent
var pirateAgent = builder.AddAIAgent("pirate", instructions: "You are a pirate. Speak like a pirate.");

var app = builder.Build();

app.MapOpenApi();
app.UseSwagger();
app.UseSwaggerUI();

// Expose the agent via OpenAI ChatCompletions protocol
app.MapOpenAIChatCompletions(pirateAgent);

app.Run();

Testando o endpoint de Chat Completions

Depois de a aplicação estar a correr, pode testar o agente usando o SDK OpenAI ou pedidos HTTP:

Utilização de Pedido HTTP

POST {{baseAddress}}/pirate/v1/chat/completions
Content-Type: application/json
{
  "model": "pirate",
  "stream": false,
  "messages": [
    {
      "role": "user",
      "content": "Hey mate!"
    }
  ]
}

Nota: Substitua {{baseAddress}} pelo endpoint do seu servidor.

Aqui está um exemplo de resposta:

{
	"id": "chatcmpl-nxAZsM6SNI2BRPMbzgjFyvWWULTFr",
	"object": "chat.completion",
	"created": 1762280028,
	"model": "gpt-5",
	"choices": [
		{
			"index": 0,
			"finish_reason": "stop",
			"message": {
				"role": "assistant",
				"content": "Ahoy there, matey! How be ye farin' on this fine day?"
			}
		}
	],
	"usage": {
		"completion_tokens": 18,
		"prompt_tokens": 22,
		"total_tokens": 40,
		"completion_tokens_details": {
			"accepted_prediction_tokens": 0,
			"audio_tokens": 0,
			"reasoning_tokens": 0,
			"rejected_prediction_tokens": 0
		},
		"prompt_tokens_details": {
			"audio_tokens": 0,
			"cached_tokens": 0
		}
	},
	"service_tier": "default"
}

A resposta inclui o ID da mensagem, conteúdo e estatísticas de utilização.

O Chat Completions também suporta streaming, onde a saída é devolvida em blocos assim que o conteúdo está disponível. Esta capacidade permite exibir a saída de forma progressiva. Pode ativar o streaming especificando "stream": true. O formato de saída consiste em blocos de Eventos Enviados pelo Servidor (SSE), como definido na especificação OpenAI Chat Completions.

POST {{baseAddress}}/pirate/v1/chat/completions
Content-Type: application/json
{
  "model": "pirate",
  "stream": true,
  "messages": [
    {
      "role": "user",
      "content": "Hey mate!"
    }
  ]
}

E o resultado que obtemos é um conjunto de blocos ChatCompletions:

data: {"id":"chatcmpl-xwKgBbFtSEQ3OtMf21ctMS2Q8lo93","choices":[],"object":"chat.completion.chunk","created":0,"model":"gpt-5"}

data: {"id":"chatcmpl-xwKgBbFtSEQ3OtMf21ctMS2Q8lo93","choices":[{"index":0,"finish_reason":"stop","delta":{"content":"","role":"assistant"}}],"object":"chat.completion.chunk","created":0,"model":"gpt-5"}

...

data: {"id":"chatcmpl-xwKgBbFtSEQ3OtMf21ctMS2Q8lo93","choices":[],"object":"chat.completion.chunk","created":0,"model":"gpt-5","usage":{"completion_tokens":34,"prompt_tokens":23,"total_tokens":57,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0}}}

A resposta em streaming contém informações semelhantes, mas entregues como Server-Sent Events.

API de Respostas

A API Respostas oferece funcionalidades avançadas, incluindo gestão de conversas, streaming e suporte para processos de agentes de longa duração.

Configurar um agente no ASP.NET Core com integração da API Responses

Aqui está um exemplo completo usando a API Responses:

Pré-requisitos

Siga os mesmos pré-requisitos do exemplo de Completar o Chat (passos 1-3).

4. Adicionar o código à Program.cs

using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI.Hosting;
using Microsoft.Extensions.AI;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenApi();
builder.Services.AddSwaggerGen();

string endpoint = builder.Configuration["AZURE_OPENAI_ENDPOINT"]
    ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
string deploymentName = builder.Configuration["AZURE_OPENAI_DEPLOYMENT_NAME"]
    ?? throw new InvalidOperationException("AZURE_OPENAI_DEPLOYMENT_NAME is not set.");

// Register the chat client
IChatClient chatClient = new AzureOpenAIClient(
        new Uri(endpoint),
        new DefaultAzureCredential())
    .GetChatClient(deploymentName)
    .AsIChatClient();
builder.Services.AddSingleton(chatClient);

builder.AddOpenAIResponses();
builder.AddOpenAIConversations();

// Register an agent
var pirateAgent = builder.AddAIAgent("pirate", instructions: "You are a pirate. Speak like a pirate.");

var app = builder.Build();

app.MapOpenApi();
app.UseSwagger();
app.UseSwaggerUI();

// Expose the agent via OpenAI Responses protocol
app.MapOpenAIResponses(pirateAgent);
app.MapOpenAIConversations();

app.Run();

Testando a API de Respostas

A API de Respostas é semelhante ao Chat Completions, mas é com estado, permitindo-lhe passar um parâmetro conversation. Tal como o Chat Completions, suporta o stream parâmetro que controla o formato de saída: uma única resposta JSON ou um fluxo de eventos. A API Respostas define os seus próprios tipos de eventos de streaming, incluindo response.created, response.output_item.added, response.output_item.done, response.completed, e outros.

Crie uma Conversa e Resposta

Pode enviar um pedido de Respostas diretamente, ou pode primeiro criar uma conversa usando a API de Conversas e depois ligar os pedidos subsequentes a essa conversa.

Para começar, crie uma nova conversa:

POST http://localhost:5209/v1/conversations
Content-Type: application/json
{
  "items": [
    {
        "type": "message",
        "role": "user",
        "content": "Hello!"
      }
  ]
}

A resposta inclui o ID da conversa:

{
  "id": "conv_E9Ma6nQpRzYxRHxRRqoOWWsDjZVyZfKxlHhfCf02Yxyy9N2y",
  "object": "conversation",
  "created_at": 1762881679,
  "metadata": {}
}

De seguida, envie um pedido e especifique o parâmetro de conversa. (Para receber a resposta como eventos de streaming, defina "stream": true no pedido.)

POST http://localhost:5209/pirate/v1/responses
Content-Type: application/json
{
  "stream": false,
  "conversation": "conv_E9Ma6nQpRzYxRHxRRqoOWWsDjZVyZfKxlHhfCf02Yxyy9N2y",
  "input": [
    {
      "type": "message",
      "role": "user",
      "content": [
        {
            "type": "input_text",
            "text": "are you a feminist?"
        }
      ]
    }
  ]
}

O agente devolve a resposta e guarda os itens da conversa para armazenamento para recuperação posterior:

{
  "id": "resp_FP01K4bnMsyQydQhUpovK6ysJJroZMs1pnYCUvEqCZqGCkac",
  "conversation": "conv_E9Ma6nQpRzYxRHxRRqoOWWsDjZVyZfKxlHhfCf02Yxyy9N2y",
  "object": "response",
  "created_at": 1762881518,
  "status": "completed",
  "incomplete_details": null,
  "output": [
    {
      "role": "assistant",
      "content": [
        {
          "type": "output_text",
          "text": "Arrr, matey! As a pirate, I be all about respect for the crew, no matter their gender! We sail these seas together, and every hand on deck be valuable. A true buccaneer knows that fairness and equality be what keeps the ship afloat. So, in me own way, I’d say I be supportin’ all hearty souls who seek what be right! What say ye?"
        }
      ],
      "type": "message",
      "status": "completed",
      "id": "msg_1FAQyZcWgsBdmgJgiXmDyavWimUs8irClHhfCf02Yxyy9N2y"
    }
  ],
  "usage": {
    "input_tokens": 26,
    "input_tokens_details": {
      "cached_tokens": 0
    },
    "output_tokens": 85,
    "output_tokens_details": {
      "reasoning_tokens": 0
    },
    "total_tokens": 111
  },
  "tool_choice": null,
  "temperature": 1,
  "top_p": 1  
}

A resposta inclui identificadores de conversas e mensagens, conteúdo e estatísticas de uso.

Para recuperar os itens da conversa, envie este pedido:

GET http://localhost:5209/v1/conversations/conv_E9Ma6nQpRzYxRHxRRqoOWWsDjZVyZfKxlHhfCf02Yxyy9N2y/items?include=string

Isto devolve uma resposta JSON contendo mensagens de entrada e saída:

{
  "object": "list",
  "data": [
    {
      "role": "assistant",
      "content": [
        {
          "type": "output_text",
          "text": "Arrr, matey! As a pirate, I be all about respect for the crew, no matter their gender! We sail these seas together, and every hand on deck be valuable. A true buccaneer knows that fairness and equality be what keeps the ship afloat. So, in me own way, I’d say I be supportin’ all hearty souls who seek what be right! What say ye?",
          "annotations": [],
          "logprobs": []
        }
      ],
      "type": "message",
      "status": "completed",
      "id": "msg_1FAQyZcWgsBdmgJgiXmDyavWimUs8irClHhfCf02Yxyy9N2y"
    },
    {
      "role": "user",
      "content": [
        {
          "type": "input_text",
          "text": "are you a feminist?"
        }
      ],
      "type": "message",
      "status": "completed",
      "id": "msg_iLVtSEJL0Nd2b3ayr9sJWeV9VyEASMlilHhfCf02Yxyy9N2y"
    }
  ],
  "first_id": "msg_1FAQyZcWgsBdmgJgiXmDyavWimUs8irClHhfCf02Yxyy9N2y",
  "last_id": "msg_lUpquo0Hisvo6cLdFXMKdYACqFRWcFDrlHhfCf02Yxyy9N2y",
  "has_more": false
}

Exposição de Múltiplos Agentes

Pode expor múltiplos agentes simultaneamente usando ambos os protocolos:

var mathAgent = builder.AddAIAgent("math", instructions: "You are a math expert.");
var scienceAgent = builder.AddAIAgent("science", instructions: "You are a science expert.");

// Add both protocols
builder.AddOpenAIChatCompletions();
builder.AddOpenAIResponses();

var app = builder.Build();

// Expose both agents via Chat Completions
app.MapOpenAIChatCompletions(mathAgent);
app.MapOpenAIChatCompletions(scienceAgent);

// Expose both agents via Responses
app.MapOpenAIResponses(mathAgent);
app.MapOpenAIResponses(scienceAgent);

Os agentes estarão disponíveis em:

  • Conclusões do Chat: /math/v1/chat/completions e /science/v1/chat/completions
  • Respostas: /math/v1/responses e /science/v1/responses

Endpoints Personalizados

Pode personalizar os caminhos dos endpoints:

// Custom path for Chat Completions
app.MapOpenAIChatCompletions(mathAgent, path: "/api/chat");

// Custom path for Responses
app.MapOpenAIResponses(scienceAgent, responsesPath: "/api/responses");

Conectar a Endpoints Compatíveis com OpenAI (Python)

O Python OpenAIChatClient e OpenAIResponsesClient ambos suportam um base_url parâmetro, permitindo que se ligue a qualquer endpoint compatível com OpenAI — incluindo agentes auto-hospedados, servidores de inferência locais (Ollama, LM Studio, vLLM) ou APIs de terceiros compatíveis com OpenAI.

pip install agent-framework --pre

Cliente de Conclusão de Chat

Use OpenAIChatClient com base_url para apontar para qualquer servidor compatível com Chat Completions:

import asyncio
from agent_framework import tool
from agent_framework.openai import OpenAIChatClient

@tool(approval_mode="never_require")
def get_weather(location: str) -> str:
    """Get the weather for a location."""
    return f"Weather in {location}: sunny, 22°C"

async def main():
    # Point to any OpenAI-compatible endpoint
    agent = OpenAIChatClient(
        base_url="http://localhost:11434/v1/",  # e.g. Ollama
        api_key="not-needed",                   # placeholder for local servers
        model_id="llama3.2",
    ).as_agent(
        name="WeatherAgent",
        instructions="You are a helpful weather assistant.",
        tools=get_weather,
    )

    response = await agent.run("What's the weather in Seattle?")
    print(response)

asyncio.run(main())

Cliente de Respostas

Use OpenAIResponsesClient com base_url para endpoints que suportam a API de Respostas:

import asyncio
from agent_framework.openai import OpenAIResponsesClient

async def main():
    agent = OpenAIResponsesClient(
        base_url="https://your-hosted-agent.example.com/v1/",
        api_key="your-api-key",
        model_id="gpt-4o-mini",
    ).as_agent(
        name="Assistant",
        instructions="You are a helpful assistant.",
    )

    # Non-streaming
    response = await agent.run("Hello!")
    print(response)

    # Streaming
    async for chunk in agent.run("Tell me a joke", stream=True):
        if chunk.text:
            print(chunk.text, end="", flush=True)

asyncio.run(main())

Servidores Compatíveis com OpenAI Comuns

A base_url abordagem funciona com qualquer servidor que exponha o formato OpenAI Chat Completions:

Server Base URL Observações
Ollama http://localhost:11434/v1/ Inferência local, sem necessidade de chave API
LM Studio http://localhost:1234/v1/ Inferência local com interface gráfica
vLLM http://localhost:8000/v1/ Serviço de alta capacidade de processamento
Azure AI Foundry O seu endpoint de implementação Utiliza credenciais Azure
Agentes do Sistema de Agentes Hospedados O endpoint do seu agente agentes .NET expostos via MapOpenAIChatCompletions

Observação

Também podes definir a OPENAI_BASE_URL variável de ambiente em vez de passar base_url diretamente. O cliente vai usá-lo automaticamente.

Utilização de Clientes Azure OpenAI

As variantes Azure OpenAI (AzureOpenAIChatClient, AzureOpenAIResponsesClient) conectam-se aos endpoints Azure OpenAI utilizando credenciais da Azure — não é necessário base_url.

from agent_framework.azure import AzureOpenAIResponsesClient

agent = AzureOpenAIResponsesClient().as_agent(
    name="Assistant",
    instructions="You are a helpful assistant.",
)

Configurar com variáveis de ambiente:

export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"
export AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME="gpt-4o-mini"

Ver também

Próximos passos