AWS Bedrock AgentCore agenci AI GenAI

AWS Bedrock AgentCore Runtime: timeout wywołania, błędy 504 i limit inicjalizacji

Napraw timeouty wywołań AgentCore Runtime: limit inicjalizacji przy zimnym starcie, kontrakt kontenera (port 8080 i /invocations), architektura ARM64 i 15-minutowy timeout sesji.

Jerzy Kopaczewski ·
Twój agent na Amazon Bedrock AgentCore Runtime zawodzi przy wywołaniu: 504 Gateway Timeout, RuntimeClientError dotyczący inicjalizacji albo wywołanie po prostu się zawiesza. Ten runbook pokazuje, jak rozróżnić te przypadki i naprawić każdy z nich, od kontraktu kontenera przez limit zimnego startu po timeout sesji.

Ten runbook dotyczy błędów wywołania AgentCore Runtime. Szerszy obraz nadzoru nad agentami na AWS znajdziesz w artykule AWS Loom i nadzór nad agentami AI. W sprawie bieżącego utrzymania agentów umów konsultację.

Objawy

Błąd przyjmuje jedną z trzech postaci. Najpierw ustal, którą, bo naprawa się różni.

# 1. Timeout inicjalizacji (zimny start)
An error occurred (RuntimeClientError) when calling the InvokeAgentRuntime
operation: Runtime initialization time exceeded. Please make sure that
initialization completes in 60s.

# 2. Timeout bramy w trakcie wywołania
HTTP 504 Gateway Timeout

# 3. Ciche zawieszenie / pętla ponowień
# Entrypoint jest wywoływany ponownie mniej więcej co 60 sekund, a klient
# nigdy nie dostaje wyniku. CloudWatch pokazuje powtarzające się starty.

Widoczny wpływ:

  • Pierwsze wywołanie po wdrożeniu lub okresie bezczynności zawodzi, kolejne czasem przechodzą (klasyczny zimny start)
  • Długie tury agenta są przerywane w połowie
  • Logi runtime w CloudWatch pokazują powtarzające się starty entrypointu bez zakończenia

Przyczyna

AgentCore Runtime nakłada na kontener agenta trzy twarde ograniczenia, a każde odpowiada jednemu z objawów powyżej.

  1. Inicjalizacja musi zakończyć się w 60 sekund. Wszystko, co kontener robi, zanim będzie gotowy obsłużyć ruch (ładowanie klienta modelu, rozgrzewanie cache, import ciężkich bibliotek), liczy się do tego okna. Przekroczenie kończy wywołanie błędem RuntimeClientError.
  2. Kontrakt kontenera jest ścisły. Obraz musi udostępniać port 8080 i obsługiwać ścieżkę /invocations, a do tego być zbudowany dla ARM64. Kontener, który startuje, ale nie spełnia tego kontraktu, zwraca 504, bo platforma nie może dostarczyć do niego żądania.
  3. Sesje kończą się po 15 minutach bezczynności (900 sekund). Długie wywołanie narzędzia lub wolna odpowiedź modelu, które wypychają pojedynczą turę poza limit, zostają przerwane.

Częste przyczyny:

  • Ciężka praca przy imporcie - klienci modeli, embeddingi lub duże zależności ładowane przy starcie modułu zamiast leniwie
  • Zła architektura - obraz x86_64 wdrożony na runtime obsługujący tylko ARM64
  • Brak kontraktu kontenera - aplikacja nasłuchuje na innym porcie niż 8080 albo nie obsługuje /invocations
  • Długie synchroniczne tury - pojedyncza tura agenta, która blokuje ponad limit bezczynności sesji

Naprawa

Krok 1: Ustal, który to przypadek

Sprawdź logi runtime w CloudWatch. Treść błędu wskazuje przypadek wprost.

# Podglądaj grupę logów runtime (podstaw swoje runtime id)
aws logs tail /aws/bedrock-agentcore/runtimes/your-agent-runtime-id \
  --since 30m --follow --region us-west-2

Jeśli widzisz “Runtime initialization time exceeded”, przejdź do kroku 2. Jeśli widzisz 504 bez błędu inicjalizacji, przejdź do kroku 3. Jeśli entrypoint restartuje się w rytmie około 60 sekund bez zakończenia, potraktuj to jako problem z kontraktem kontenera (krok 3) plus problem długiej tury (krok 4).

Krok 2: Przenieś ciężką pracę poza ścieżkę inicjalizacji

Inicjalizacja musi zmieścić się w 60 sekundach. Odłóż wszystko kosztowne do pierwszego wywołania zamiast robić to przy imporcie.

# Antywzorzec: ciężka praca przy ładowaniu modułu liczy się do limitu 60s
# model_client = load_large_client()   # wykonuje się przy imporcie

# Lepiej: leniwa inicjalizacja przy pierwszym użyciu
_model_client = None

def get_model_client():
    global _model_client
    if _model_client is None:
        _model_client = load_large_client()
    return _model_client

Jeśli inicjalizacja jest naprawdę ciężka, zmniejsz liczbę warstw obrazu, wbuduj artefakty w obraz zamiast pobierać je przy starcie i usuń nieużywane zależności.

Krok 3: Zweryfikuj kontrakt kontenera

Obraz musi udostępniać port 8080, obsługiwać /invocations i być zbudowany dla ARM64.

# Potwierdź, że architektura obrazu to arm64
docker inspect your-image:tag --format '{{.Architecture}}'
# Oczekiwane: arm64

# Zbuduj jawnie dla ARM64, jeśli tak nie jest
docker buildx build --platform linux/arm64 -t your-image:tag .

Upewnij się, że aplikacja w kontenerze nasłuchuje na 8080 i obsługuje ścieżkę /invocations (oraz /ping dla health check, zgodnie z kontraktem runtime). Kontener, który zgłasza “Ready”, ale nigdy nie dostaje wywołania handlera, prawie zawsze nie spełnia jednego z tych warunków.

Krok 4: Utrzymaj pojedynczą turę w limicie sesji

Sesje kończą się po 15 minutach bezczynności. Przy długiej pracy strumieniuj postęp, aby sesja pozostała aktywna, albo podziel pracę na kroki zamiast jednego blokującego wywołania.

  • Strumieniuj częściowy wynik do klienta, aby sesja nie była bezczynna
  • Naprawdę długie zadania przenieś do procesu asynchronicznego, a agent niech odpytuje o wynik
  • Nie projektuj pojedynczej tury agenta, która blokuje dłużej niż kilka minut

Krok 5: Dodaj ponowienie po stronie klienta dla zimnych startów

Zimny start po bezczynności jest oczekiwany. Ponów pierwsze wywołanie z odczekaniem, zamiast pokazywać błąd użytkownikowi.

import time, random
from botocore.exceptions import ClientError

def invoke_with_retry(client, runtime_id, payload, max_retries=3):
    for attempt in range(max_retries):
        try:
            return client.invoke_agent_runtime(
                agentRuntimeId=runtime_id, payload=payload
            )
        except ClientError as e:
            code = e.response["Error"]["Code"]
            if code == "RuntimeClientError" and attempt < max_retries - 1:
                time.sleep((2 ** attempt) + random.uniform(0, 1))
            else:
                raise

Weryfikacja

Potwierdź, że zimne wywołanie kończy się teraz sukcesem w oknie inicjalizacji.

# Wywołaj i zmierz pierwszy czas po okresie bezczynności
time aws bedrock-agentcore invoke-agent-runtime \
  --agent-runtime-id your-agent-runtime-id \
  --payload '{"prompt":"health check"}' \
  --region us-west-2 /dev/stdout

Oczekiwane: poprawna odpowiedź bez RuntimeClientError i bez 504. Następnie potwierdź, że logi pokazują jedno czyste wywołanie, a nie pętlę restartów:

aws logs tail /aws/bedrock-agentcore/runtimes/your-agent-runtime-id \
  --since 5m --region us-west-2

Oczekiwane: jeden start entrypointu, po którym następuje zakończenie, a nie powtarzające się starty.

Powiązane