Contrato en tiempo de ejecución del agente hospedado

Un agente hospedado es un contenedor que cumple un contrato en tiempo de ejecución específico con la plataforma Microsoft Foundry. En esta referencia se describe lo que espera la plataforma del contenedor y cómo los paquetes del adaptador del SDK le ayudan a cumplir esos requisitos.

Los paquetes del adaptador del SDK implementan todo el contrato. Si usa azure-ai-agentserver-responses o azure-ai-agentserver-invocations, solo implementa la lógica del controlador.

Si usa un agente de codificación como GitHub Copilot para implementar o revisar un contenedor de agentes hospedado, la aptitud de Microsoft Foundry puede ayudar a comprobar el contrato en tiempo de ejecución, el uso del adaptador y las suposiciones de implementación.

Requisitos del contrato

El contenedor debe:

Requirement Detalle
Escucha en el puerto 8088 HTTP/1.1, HTTP sin formato. La plataforma finaliza TLS.
Servicio de un sondeo de estado Devuelve 200 OK de GET /readiness.
Implementación de un punto de conexión de protocolo Sirva al menos uno de POST /responses o POST /invocations.
Consumo de variables de entorno de plataforma Lea las variables que la plataforma inserta al iniciarse.
Apagarse correctamente Vacía las escrituras y cierra las conexiones en SIGTERM.

Puntos de conexión de protocolo

Un protocolo define el contrato HTTP entre Foundry y el contenedor del agente. El contenedor implementa al menos un punto de conexión de protocolo.

Protocolo de respuestas

El protocolo de respuestas implementa la API de respuestas de OpenAI. La plataforma envía solicitudes a POST /responses y espera una respuesta JSON o una secuencia de eventos de Server-Sent (SSE).

Aspecto Detalle
Endpoint POST /responses
Entrada Solicitud de API de respuestas de OpenAI (input, model, stream, etc.)
Output Objeto de respuesta JSON o flujo SSE de eventos de respuesta
Historial de la conversación Hidratado automáticamente por el adaptador del SDK cuando conversation.id está presente
Transmisión en línea SSE con el tipo de text/event-stream contenido

Use el protocolo de respuestas como opción estándar. Es compatible con el ecosistema de openAI API.

Protocolo de invocaciones

El protocolo de invocaciones es un protocolo de paso a través mínimo. Defina la estructura de carga y la plataforma la pasa sin interpretación.

Aspecto Detalle
Endpoint POST /invocations
Entrada Cualquier carga JSON que el controlador espera
Output Cualquier respuesta JSON o secuencia SSE
Historial de la conversación No administrado. El código controla el estado si es necesario.
Transmisión en línea Opcional, a través de SSE

Use el protocolo de invocaciones cuando necesite control total sobre las cargas de solicitud y respuesta.

Paquetes de adaptadores del SDK

Los paquetes de adaptador son específicos del protocolo y independientes del marco de trabajo. Funcionan con cualquier marco de agente, incluido Microsoft Agent Framework, LangGraph y código personalizado.

Protocol Paquete de Python paquete de .NET
Responses azure-ai-agentserver-responses Azure.AI.AgentServer.Responses
Invocaciones azure-ai-agentserver-invocations Azure.AI.AgentServer.Invocations

El adaptador controla las siguientes partes del contrato para usted:

  • Configuración del servidor HTTP en el puerto 8088.
  • Punto de conexión de sondeo de estado (GET /readiness).
  • Análisis y formato de respuesta de solicitudes específicos del protocolo.
  • Hidratación del historial de conversaciones (protocolo de respuestas).
  • Infraestructura de streaming de SSE.
  • Instrumentación de OpenTelemetry.
  • Apagado correcto en SIGTERM.
  • Consumo de variables de entorno de plataforma.

Implementa una función de controlador que recibe solicitudes analizadas y devuelve respuestas.

Ejecución prolongada y resistente (versión preliminar)

Los adaptadores de protocolo se componen con las primitivas de streaming y tareas resistentes en su dependencia de AgentServer Core. Use estos primitivos cuando el trabajo debe sobrevivir a una interrupción del proceso o los clientes deben volver a conectarse a la salida reproducida.

El adaptador de respuestas puede administrar la ejecución resistente para las respuestas en segundo plano almacenadas. El servidor opta por el procesamiento en segundo plano resistente y el controlador vuelve a ejecutarse o se reanuda de forma segura desde un punto de control duradero. Las respuestas en primer plano no se vuelven a invocar después de que se detenga el proceso.

El adaptador invocaciones no prescribe un estado ni un contrato de sondeo. Registre tareas resistentes para la ejecución duradera y, a continuación, defina la respuesta, el sondeo o los puntos de conexión de flujo que exponen el progreso a los clientes.

Para ver el modelo de ejecución, las estrategias de punto de control y el comportamiento de reproducción de cliente, consulte Resistencia para agentes hospedados de larga duración.

Ejemplos del controlador

Los ejemplos de bring-your-own completos para los protocolos y ambos lenguajes se encuentran en el repositorio foundry-samples .

Ejemplo del protocolo de respuestas

Este controlador mínimo reenvía la entrada del usuario a un modelo desde el catálogo de modelos foundry a través de la API de respuestas. El adaptador del SDK hidrata automáticamente el historial de conversaciones a través context.get_history() de (Python) o context.GetHistoryAsync() (C#), por lo que el agente mantiene el contexto entre turnos.

Desde bring-your-own/responses/hello-world/main.py:

import asyncio
import os

from azure.ai.agentserver.responses import (
    CreateResponse,
    ResponseContext,
    ResponsesAgentServerHost,
    ResponsesServerOptions,
    TextResponse,
)
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential

# FOUNDRY_PROJECT_ENDPOINT is auto-injected in hosted Foundry containers and
# set by 'azd ai agent run' for local development.
_endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"]
_model = os.environ["FOUNDRY_MODEL_NAME"]

_project_client = AIProjectClient(
    endpoint=_endpoint, credential=DefaultAzureCredential()
)
_responses_client = _project_client.get_openai_client().responses

app = ResponsesAgentServerHost(
    options=ResponsesServerOptions(default_fetch_history_count=20),
)


@app.response_handler
async def handler(
    request: CreateResponse,
    context: ResponseContext,
    _cancellation_signal: asyncio.Event,
):
    user_input = await context.get_input_text() or "Hello!"
    history = await context.get_history()

    # Build the model input from prior conversation turns + the current message.
    input_items = []
    for item in history:
        # Map history items to {"role": ..., "content": ...} dicts; see the
        # full sample for the unpacking helper.
        ...
    input_items.append({"role": "user", "content": user_input})

    response = await asyncio.get_running_loop().run_in_executor(
        None,
        lambda: _responses_client.create(
            model=_model,
            instructions="You are a helpful AI assistant.",
            input=input_items,
            store=False,  # platform manages history; don't store at model level
        ),
    )

    return TextResponse(context, request, text=response.output_text)


app.run()

Referencia: ResponsesAgentServerHost, AIProjectClient, DefaultAzureCredential

Ejemplo del protocolo invocaciones

Con el protocolo de invocaciones, el controlador recibe cualquier JSON que publique el autor de la llamada y devuelva cualquier JSON que elija el código. No hay ningún historial de conversaciones integrado.

Patrón de bring-your-own/invocations/hello-world:

from starlette.requests import Request
from starlette.responses import JSONResponse, Response
from azure.ai.agentserver.invocations import InvocationAgentServerHost

app = InvocationAgentServerHost()


@app.invoke_handler
async def handle_invoke(request: Request) -> Response:
    data = await request.json()
    message = data.get("message", "Hello!")
    return JSONResponse({"echo": message})


if __name__ == "__main__":
    app.run()

Los ejemplos completos también incluyen la hidratación del historial de conversaciones, el control de errores, la telemetría, la integración del cuadro de herramientas y dockerfile y la azure.yaml configuración.

Sondeo de salud

La plataforma envía GET /readiness para determinar si el contenedor está listo para atender el tráfico. Devuelve 200 OK cuando el contenedor está listo o un estado distinto de 200 para indicar que la plataforma debe reiniciar la instancia. Los adaptadores del SDK registran este punto de conexión automáticamente.

Red y transporte

Propiedad Value
Protocol HTTP/1.1
Puerto predeterminado 8088 (invalidación con la variable de PORT entorno)
Dirección de enlace 0.0.0.0 (todas las interfaces)
TLS Finalizado por la plataforma. El contenedor proporciona HTTP sin formato.

Apagado correcto

Cuando la plataforma envía SIGTERM, el contenedor deja de aceptar nuevas solicitudes, finaliza las solicitudes en curso, vacía las escrituras pendientes $HOME en (el sistema de archivos de sesión) y sale limpiamente. Los adaptadores del SDK controlan esta secuencia automáticamente.

Variables de entorno de plataforma

La plataforma inserta variables de entorno en el contenedor al iniciarse. El código puede leer las siguientes variables clave:

Variable propósito
FOUNDRY_PROJECT_ENDPOINT Punto de conexión del proyecto foundry para llamadas API
FOUNDRY_AGENT_ID Identificador estable (GUID) del agente. Úselo para el enrutamiento, la telemetría o la creación de particiones de almacenamiento por agente.
FOUNDRY_AGENT_NAME Nombre del agente
FOUNDRY_AGENT_VERSION Versión del agente
FOUNDRY_AGENT_SESSION_ID Identificador de sesión actual

Encabezados de solicitud de plataforma (protocolo de contenedor 2.0.0)

Estos encabezados solo se aplican a los agentes hospedados en la versión 2.0.0 del protocolo de contenedor. En el protocolo 2.0.0, la plataforma los inserta en cada solicitud a los puntos de conexión de protocolo, tanto para los protocolos de respuestas como de invocaciones. No se envían a puntos de conexión de infraestructura como el sondeo de estado. Trate sus valores como opacos y lea, pero no los invalide.

Header propósito
x-agent-user-id Identificador global por usuario para el autor de la llamada actual. Úselo como clave de partición principal para los datos por usuario que almacena el contenedor; es para el propio uso del contenedor y no se reenvía de salida. El mismo usuario produce el mismo valor entre agentes.
x-agent-foundry-call-id Identificador por solicitud. Reenvíelo sin cambios en las llamadas salientes a los servicios Foundry (Almacenamiento, Cuadro de herramientas y otros agentes); la plataforma resuelve la identidad del autor de la llamada a partir de ella. Los adaptadores oficiales del SDK lo reenvía automáticamente cuando se llama a esos servicios a través de sus clientes.

Ambos encabezados son de confianza( la plataforma los genera a partir de la identidad comprobada) y tampoco se garantiza cuando se ejecuta localmente, por lo que se controla correctamente los valores que faltan.

El SDK de AgentServer expone estas constantes en PlatformHeaders y las lee automáticamente, a través FoundryAgentRequestContext.Current de en .NET o get_request_context() en Python. Para obtener la lista de encabezados de plataforma completa, incluidos los encabezados de respuesta que agrega el entorno de ejecución, como x-agent-session-id, x-platform-servery x-platform-error-source, consulte la referencia de la biblioteca de Azure AI Agent Server Core.

Para obtener información sobre cómo cambia el protocolo 2.0.0 la propagación de identidades, consulte Migración de agentes hospedados.

Ejemplo: partición de datos almacenados por sesión

Cuando el contenedor conserva los datos propiedad del usuario, escárelo por la sesión (y, para las sesiones compartidas, el usuario) para que un autor de la llamada no pueda leer los datos de otro. El ejemplo de agente de toma de notas lo hace derivando una ruta de acceso de archivo por sesión en $HOME, donde también se puede acceder a los archivos a través de la API de archivos de sesión:

# note_store.py - one JSONL file per session, stored under $HOME.
def _get_file_path(session_id: str) -> str:
    safe_id = "".join(c if c.isalnum() or c in "-_" else "_" for c in session_id)
    base_dir = os.environ.get("HOME", os.getcwd())
    return os.path.join(base_dir, f"notes_{safe_id}.jsonl")

Cuando más de un usuario puede compartir una sesión, agregue x-agent-user-id a la clave. Consulte Multiplex multiple users in one hosted agent session (Multiplex multiplex en una sesión del agente hospedado).

Reenvío de encabezados de solicitud personalizados al contenedor

En la sección anterior se tratan los encabezados que inserta la plataforma . Por separado, la puerta de enlace reenvía solo un conjunto fijo de encabezados de solicitud proporcionados por el autor de la llamada al contenedor. Cualquier encabezado de llamador fuera de ese conjunto se quita en la puerta de enlace antes de que la solicitud llegue al contenedor, lo que mantiene las credenciales y los encabezados internos fuera del contenedor de forma predeterminada.

Para pasar sus propios datos contextuales al contenedor, use el prefijo de encabezado de cliente de paso a través, x-client-. La plataforma reenvía todos los encabezados que comienzan sin x-client- cambios, por lo que puede enviar valores como un identificador de inquilino o una marca de característica sin cambiar el cuerpo de la solicitud y, a continuación, leerlos en el controlador como cualquier otro encabezado de solicitud. El SDK de AgentServer define este prefijo como PlatformHeaders.ClientHeaderPrefix; para obtener la lista completa de encabezados de la plataforma, consulte la referencia de la biblioteca principal del agente de IA de Azure.

La puerta de enlace reenvía estos encabezados de llamada a los puntos de conexión del protocolo de respuestas e invocaciones:

Encabezado o prefijo propósito
x-client-* Cualquier encabezado personalizado que prefijo con x-client-. Use este prefijo para pasar sus propios valores contextuales ( como inquilino, marcas de características o tokens de correlación) a través del contenedor.
accept, accept-encoding, accept-language, content-type, , content-length, content-encoding Los encabezados estándar de negociación de contenido y cuerpo necesarios para analizar la solicitud.
traceparent, tracestate, baggage, x-ms-client-request-id, x-request-id, request-id, correlation-context, request-contextms-cv Identificadores de correlación y seguimiento distribuidos, por lo que los registros del contenedor se vinculan a la solicitud de origen.
user-agent Identifica el SDK o el cliente que realiza la llamada para los diagnósticos.

La puerta de enlace nunca reenvía encabezados de credenciales como Authorization, o Host, Cookiey x-forwarded-*. Se quita cualquier encabezado que no coincida con la lista de permitidos, por lo que no se basa en encabezados personalizados fuera del x-client-* prefijo que llega al contenedor.