Kontrakt czasu wykonywania hostowanego agenta

Hostowany agent to kontener, który spełnia określony kontrakt środowiska uruchomieniowego z platformą Microsoft Foundry. W tej dokumentacji opisano oczekiwania platformy z kontenera oraz sposób, w jaki pakiety adapterów SDK pomagają spełnić te wymagania.

Pakiety adaptera ZESTAWU SDK implementują cały kontrakt. Jeśli używasz metody azure-ai-agentserver-responses lub azure-ai-agentserver-invocations, implementujesz tylko logikę obsługi.

Jeśli używasz agenta kodowania, takiego jak GitHub Copilot do implementowania lub przeglądania hostowanego kontenera agenta, Microsoft Umiejętność odnajdywania może pomóc sprawdzić kontrakt środowiska uruchomieniowego, użycie adaptera i założenia wdrożenia.

Wymagania dotyczące kontraktu

Kontener musi:

Wymaganie Szczegół
Nasłuchiwanie na porcie 8088 HTTP/1.1, zwykły protokół HTTP. Platforma kończy protokół TLS.
Obsługa sondy kondycji Wróć 200 OK z GET /readiness.
Implementowanie punktu końcowego protokołu Obsłużyć co najmniej jedną z wartości POST /responses lub POST /invocations.
Korzystanie ze zmiennych środowiskowych platformy Odczytywanie zmiennych, które platforma wprowadza podczas uruchamiania.
Zamykanie z wdziękiem Opróżnij operacje zapisu i zamknij połączenia w programie SIGTERM.

Punkty końcowe protokołu

Protokół definiuje kontrakt HTTP między usługą Foundry i kontenerem agenta. Kontener implementuje co najmniej jeden punkt końcowy protokołu.

Protokół odpowiedzi

Protokół odpowiedzi implementuje interfejs API odpowiedzi OpenAI. Platforma wysyła żądania do POST /responses i oczekuje odpowiedzi JSON lub strumienia Server-Sent Events (SSE).

Aspect Szczegół
Punkt końcowy POST /responses
Dane wejściowe Żądanie interfejsu API odpowiedzi interfejsu OpenAI (input, model, streamitd.)
Output Obiekt odpowiedzi JSON lub strumień SSE zdarzeń odpowiedzi
Historia konwersacji Nawilżane automatycznie przez adapter ZESTAWU SDK, gdy conversation.id jest obecny
Transmisja strumieniowa SSE z typem text/event-stream zawartości

Użyj protokołu odpowiedzi jako standardowego. Jest ona zgodna z ekosystemem interfejsu API openAI.

Protokół wywołań

Protokół wywołań jest minimalnym protokołem przekazywania. Definiujesz strukturę ładunku, a platforma przechodzi przez nią bez interpretacji.

Aspect Szczegół
Punkt końcowy POST /invocations
Dane wejściowe Dowolny ładunek JSON oczekiwany przez program obsługi
Output Dowolny strumień odpowiedzi JSON lub SSE
Historia konwersacji Niezarządzane. Kod obsługuje stan w razie potrzeby.
Transmisja strumieniowa Opcjonalne, za pośrednictwem protokołu SSE

Użyj protokołu wywołań, gdy potrzebujesz pełnej kontroli nad ładunkami żądań i odpowiedzi.

Pakiety adapterów zestawu SDK

Pakiety adapterów są specyficzne dla protokołu i niezależne od platformy. Współpracują one z dowolną strukturą agentów, w tym Microsoft Agent Framework, LangGraph i niestandardowym kodem.

Protocol Pakiet języka Python pakiet .NET
Responses azure-ai-agentserver-responses Azure.AI.AgentServer.Responses
Wywołania azure-ai-agentserver-invocations Azure.AI.AgentServer.Invocations

Adapter obsługuje następujące części kontraktu:

  • Konfiguracja serwera HTTP na porcie 8088.
  • Punkt końcowy sondy kondycji (GET /readiness).
  • Analizowanie żądań specyficznych dla protokołu i formatowanie odpowiedzi.
  • Nawodnienie historii konwersacji (protokół odpowiedzi).
  • Infrastruktura przesyłania strumieniowego SSE.
  • Instrumentacja OpenTelemetry.
  • Graceful shutdown on SIGTERM.
  • Użycie zmiennych środowiskowych platformy.

Implementujesz funkcję obsługi, która odbiera przeanalizowane żądania i zwraca odpowiedzi.

Długotrwałe i odporne wykonywanie (wersja zapoznawcza)

Karty protokołu składają się z odpornych zadań i elementów pierwotnych przesyłania strumieniowego w zależności AgentServer Core. Użyj tych elementów pierwotnych, gdy praca musi przetrwać przerwę w procesie lub klienci muszą ponownie nawiązać połączenie w celu odtworzenia danych wyjściowych.

Karta Odpowiedzi może zarządzać odpornym wykonywaniem przechowywanych odpowiedzi w tle. Serwer decyduje się na odporne przetwarzanie w tle, a procedura obsługi jest bezpiecznie uruchamiana ponownie lub wznawiana z trwałego punktu kontrolnego. Odpowiedzi pierwszego planu nie są wywoływane ponownie po zatrzymaniu procesu.

Adapter Wywołania nie określa stanu ani kontraktu sondowania. Zarejestruj zadania odporne na trwałe wykonywanie, a następnie zdefiniuj odpowiedzi, sondowanie lub punkty końcowe strumienia, które uwidaczniają postęp dla klientów.

Aby zapoznać się z modelem wykonywania, strategiami punktów kontrolnych i zachowaniem odtwarzania klienta, zobacz Odporność dla długotrwałych hostowanych agentów.

Przykłady obsługi

Kompletne przykłady bring-your-own dla obu protokołów i obu języków znajdują się w repozytorium foundry-samples .

Przykład protokołu odpowiedzi

Ta minimalna procedura obsługi przekazuje dane wejściowe użytkownika do modelu z katalogu modeli Foundry za pośrednictwem interfejsu API odpowiedzi. Karta ZESTAWU SDK automatycznie nawilża historię konwersacji za pośrednictwem context.get_history() (Python) lub context.GetHistoryAsync() (C#), dzięki czemu agent zachowuje kontekst po kolei.

Z elementu 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()

Dokumentacja: ResponsesAgentServerHost, AIProjectClient, DefaultAzureCredential

Przykład protokołu wywołań

Dzięki protokołowi wywołań program obsługi otrzymuje dowolny kod JSON, który publikuje obiekt wywołujący, i zwraca dowolny kod JSON, który wybierze. Nie ma wbudowanej historii konwersacji.

Wzorzec z :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()

Pełne przykłady obejmują również nawodnienie historii konwersacji, obsługę błędów, telemetrię, integrację przybornika oraz plik Dockerfile i azure.yaml konfigurację.

Sonda kondycji

Platforma wysyła dane GET /readiness , aby określić, czy kontener jest gotowy do obsługi ruchu. Wróć 200 OK , gdy kontener jest gotowy lub stan inny niż 200, aby zasygnalizować, że platforma powinna ponownie uruchomić wystąpienie. Karty zestawu SDK automatycznie rejestrują ten punkt końcowy.

Sieć i transport

Property Value
Protocol HTTP/1.1
Port domyślny 8088 (przesłaniaj zmienną środowiskową PORT )
Powiązywanie adresu 0.0.0.0 (wszystkie interfejsy)
magazyn lokalny wątku Zakończone przez platformę. Kontener obsługuje zwykły protokół HTTP.

Bezproblemowe zamykanie

Gdy platforma wysyła SIGTERMpolecenie , kontener przestaje akceptować nowe żądania, kończy żądania w locie, opróżnia oczekujące operacje zapisu na $HOME (system plików sesji) i kończy się czystą operacją. Karty zestawu SDK obsługują tę sekwencję automatycznie.

Zmienne środowiskowe platformy

Platforma wprowadza zmienne środowiskowe do kontenera podczas uruchamiania. Kod może odczytywać następujące kluczowe zmienne:

Variable Purpose
FOUNDRY_PROJECT_ENDPOINT Punkt końcowy projektu foundry dla wywołań interfejsu API
FOUNDRY_AGENT_ID Stabilny identyfikator agenta (GUID). Służy do routingu dla agenta, telemetrii lub partycjonowania magazynu.
FOUNDRY_AGENT_NAME Nazwa agenta
FOUNDRY_AGENT_VERSION Wersja agenta
FOUNDRY_AGENT_SESSION_ID Bieżący identyfikator sesji

Nagłówki żądań platformy (protokół kontenera 2.0.0)

Te nagłówki dotyczą tylko hostowanych agentów w protokole kontenera w wersji 2.0.0. W protokole 2.0.0 platforma wprowadza je na każde żądanie do punktów końcowych protokołu, zarówno dla protokołów Responses, jak i Invocations. Nie są one wysyłane do punktów końcowych infrastruktury, takich jak sonda kondycji. Traktuj ich wartości jako nieprzezroczyste i odczytaj, ale nie przesłaniaj ich.

Header Purpose
x-agent-user-id Globalny identyfikator dla bieżącego elementu wywołującego. Użyj go jako podstawowego klucza partycji dla danych poszczególnych użytkowników przechowywanych w kontenerach; jest przeznaczony do użytku własnego kontenera i nie jest przekazywany wychodzący. Ten sam użytkownik daje tę samą wartość dla agentów.
x-agent-foundry-call-id Identyfikator poszczególnych żądań. Przekaż je bez zmian w przypadku wywołań wychodzących do usług Foundry (Storage, Przybornik i innych agentów); platforma rozpoznaje tożsamość obiektu wywołującego. Oficjalne karty ZESTAWU SDK przesyłają je automatycznie po wywołaniu tych usług za pośrednictwem swoich klientów.

Oba nagłówki są godne zaufania — platforma generuje je na podstawie zweryfikowanej tożsamości — i żadna z nich nie jest gwarantowana podczas uruchamiania lokalnego, więc bezpiecznie obsłuż brakujące wartości.

Zestaw SDK AgentServer uwidacznia je jako stałe PlatformHeaders i odczytuje je za Ciebie — za pośrednictwem FoundryAgentRequestContext.Current .NET lub get_request_context() w Python. Aby uzyskać pełną listę nagłówków platformy, w tym nagłówki odpowiedzi, dodaje środowisko uruchomieniowe, takie jak x-agent-session-id, x-platform-serveri x-platform-error-source, zobacz dokumentację biblioteki Azure AI Agent Server Core.

Aby dowiedzieć się, jak protokół 2.0.0 zmienia propagację tożsamości, zobacz Migrowanie hostowanych agentów.

Przykład: partycjonowanie przechowywanych danych na sesję

Gdy kontener będzie utrwalał dane należące do użytkownika, klucz go przez sesję (i, w przypadku sesji udostępnionych, użytkownik), dzięki czemu jeden obiekt wywołujący nie może odczytać danych innego. Przykład agenta tworzenia notatek wykonuje to przez wyprowadzenie ścieżki pliku na sesję w obszarze $HOME, gdzie pliki są również dostępne za pośrednictwem interfejsu API plików sesji:

# 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")

Jeśli więcej niż jeden użytkownik może współużytkować sesję, dodaj x-agent-user-id go do klucza. Zobacz Multiplex wielu użytkowników w jednej hostowanej sesji agenta.

Przekazywanie niestandardowych nagłówków żądań do kontenera

W poprzedniej sekcji omówiono nagłówki wprowadzone przez platformę . Oddzielnie brama przekazuje tylko stały zestaw nagłówków żądań dostarczonych przez obiekt wywołujący do kontenera. Każdy nagłówek obiektu wywołującego poza tym zestawem jest usuwany w bramie przed dotarciem żądania do kontenera, który domyślnie przechowuje poświadczenia i nagłówki wewnętrzne z kontenera.

Aby przekazać własne dane kontekstowe do kontenera, użyj prefiksu nagłówka klienta przekazywanego, x-client-. Platforma przekazuje każdy nagłówek rozpoczynający się bez x-client- zmian, dzięki czemu można wysyłać wartości takie jak identyfikator dzierżawy lub flaga funkcji bez zmieniania treści żądania, a następnie odczytywać je w procedurze obsługi, tak jak każdy inny nagłówek żądania. Zestaw SDK AgentServer definiuje ten prefiks jako PlatformHeaders.ClientHeaderPrefix; aby uzyskać pełną listę nagłówków platformy, zobacz dokumentację biblioteki Azure AI Agent Server Core.

Brama przekazuje te nagłówki wywołujące do punktów końcowych protokołu Odpowiedzi i wywołań:

Nagłówek lub prefiks Purpose
x-client-* Dowolny niestandardowy nagłówek, którego prefiks ma x-client-. Użyj tego prefiksu, aby przekazać własne wartości kontekstowe — takie jak dzierżawa, flagi funkcji lub tokeny korelacji — do kontenera.
accept, , accept-encoding, accept-language, content-type, , content-lengthcontent-encoding Standardowe negocjacje zawartości i nagłówki treści potrzebne do analizowania żądania.
traceparent, tracestate, , baggage, x-ms-client-request-idx-request-id, request-id, , correlation-contextrequest-contextms-cv Identyfikatory śledzenia rozproszonego i korelacji, więc dzienniki kontenera łączą się z żądaniem źródłowym.
user-agent Identyfikuje wywołujący zestaw SDK lub klienta na potrzeby diagnostyki.

Brama nigdy nie przekazuje nagłówków elementu wywołującego Authorization, Host, Cookielub x-forwarded-* . Każdy nagłówek, który nie jest zgodny z listą dozwolonych, jest porzucony, więc nie należy polegać na nagłówkach niestandardowych poza x-client-* prefiksem docierającym do kontenera.

Aby uzyskać dostęp do delegowanego interfejsu API zarządzanego przez aplikację, zobacz Przekazywanie tokenów użytkownika nabytych przez aplikację do kodu hostowanego agenta. Warstwa środkowa uzyskuje token podrzędny i przekazuje go za pośrednictwem nagłówka x-client-* .