Главная / Статьи

Развертывание агента LangGraph в AWS Bedrock AgentCore: пошаговая инструкция

Запакуйте существующего агента LangGraph для AgentCore, создайте структуру проекта с помощью CLI, протестируйте его локально, разверните на AWS и вызовите его при сохранении сессий и памяти.

Издатель: REACTAPP.TOP8 мин чтения1792 слов

Источники: How to Deploy a LangGraph Agent on AWS Bedrock AgentCore

Многие агенты LangGraph хорошо работают на ноутбуке, но теряют эффективность на этапе внедрения в производство. AWS Bedrock AgentCore устраняет эту проблему за счёт безсерверного хостинга, который позволяет масштабироваться без необходимости переработки кода. В следующих разделах рассматривается процесс адаптации существующего агента под AgentCore, создание проекта, его запуск локально, развертывание на AWS и вызов после внедрения.

Что такое AgentCore

AgentCore — это сервис хостинга от AWS, в котором агенты развертываются, масштабируются и запускаются без необходимости управления серверами. Работают с ним фреймворки вроде LangGraph, Strands, CrewAI и LlamaIndex, а также модели от OpenAI, Google и Anthropic, поэтому код агента остаётся прежним. Встроены функции изоляции сессий, постоянной памяти, мониторинга и управления идентичностями.

Всё управляется средством командной строки AgentCore. Это программа на Node.js, которая создаёт скелет проекта, запускает агента локально и развертывает его в AWS с использованием подкладки CDK.

Предварительные требования

  • Python 3.12 или новее
  • uv или pip для управления пакетами Python
  • Node.js 20 или новее, поскольку средство командной строки распространяется через npm
  • AWSCDK, установленный глобально с помощью команды npm install -g aws-cdk
  • Учётная запись AWS с установленными локально учётными данными через команду aws configure
  • Существующий код LangGraph, генерирующий скомпилированный StateGraph

Шаг 1: установка средства командной строки

Всё управляется одним инструментом командной строки: созданием проекта, запуском приложения локально и его развертыванием в AWS.

npm install -g @aws/agentcore

Подтвердите, что установка прошла успешно:

agentcore --help

Шаг 2: добавление зависимостей

Для зависимостей агента необходимо добавить два пакета. bedrock-agentcore — это Python-SDK, предоставляющий класс-обертку BedrockAgentCoreApp, а aws-opentelemetry-distro — это версия инструментария OpenTelemetry для Python, собранная компанией AWS.

# pyproject.toml
[project]
name = "my-agent"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
    "aws-opentelemetry-distro==0.17.0",
 "bedrock-agentcore>=1.6.3",
    "boto3>=1.42.0",
    "langgraph>=1.1.0",
    "langchain-core>=1.2.0",
    # ... your other existing dependencies
]

Установите с использованием того метода работы, который обычно применяется в проекте:

uv sync
# or: pip install -e .

Шаг 3: написание точки входа в файле main.py

AgentCore ожидает один файл на Python в качестве точки входа, содержащий экземпляр BedrockAgentCoreApp и функцию, декорированную атрибутом @app.entrypoint. Логика LangGraph практически не меняется — она просто оборачивается в небольшую функцию-точку входа во время выполнения.

# main.py
from langchain_core.messages import HumanMessage
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from graphs.my_agent_graph import build_my_agent  # your existing graph builder

# 1. Instantiate the AgentCore app and logger
app = BedrockAgentCoreApp()
log = app.logger

# 2. Build your graph at module load time (startup)
#    AgentCore initialises the module once, then handles concurrent invocations.
#    Any failure here will prevent a broken agent from going live.
def create_agent():
    log.info("Initialising agent...")
    graph = build_my_agent()   # returns your compiled LangGraph StateGraph
    log.info("Agent ready")
    return graph
try:
    graph = create_agent()
except Exception as e:
    log.error(f"Critical failure during agent initialisation: {e}")
    raise  # fail fast - don't let a broken agent start serving requests

# 3. Async helper that drives the LangGraph streaming loop
async def run_agent(user_input: str, session_id: str = "default-session") -> str:
    responses = []
    config = {"configurable": {"thread_id": session_id}}
    async for chunk in graph.astream(
        {"messages": [HumanMessage(content=user_input)]},
        config=config,
        stream_mode="values",
    ):
        messages = chunk.get("messages", [])
        if messages:
            last = messages[-1]
            if getattr(last, "type", None) == "ai":
                responses.append(last)
    if not responses:
        return "No response"
    content = getattr(responses[-1], "content", "")
    return content if isinstance(content, str) else str(content)

# 4. The entrypoint - this is what AgentCore calls on every invocation
@app.entrypoint
async def invoke(payload, context):
    try:
        log.info("Invoke received")
        user_input = payload.get("prompt", "")
        session_id = payload.get("session_id", "default-session")
        if not user_input.strip():
            return {"error": "Prompt cannot be empty"}
        response = await run_agent(user_input, session_id)
        return {"response": response}
    except Exception as e:
        log.error(f"Error: {e}")
        return {"error": str(e)}

# 5. Run the app (only executed when running locally using agentcore dev)
if __name__ == "__main__":
    app.run()

Что важно в этом файле

  • BedrockAgentCoreApp() предоставляет среде выполнения её «оболочку»: HTTP-сервер, маршруты проверки работоспособности и структурированные логи, всё это заранее настроено.
  • Граф строится в масштабе модуля, один раз при импорте, а не при каждом вызове. Поэтому любые проблемы при запуске проявляются сразу, и неисправное приложение никогда не получает трафик.
  • @app.entrypoint обозначает обработчик входящих запросов. Ему передаётся payload — декодированное тело в формате JSON, а также context для запроса AgentCore. Результатом должен стать обычный словарь, который можно сериализовать в JSON. Простая строка или пользовательский класс не подойдут.
  • Полученный session_id становится thread_id в LangGraph, поэтому MemorySaver сохраняет отдельную память для каждой сессии.

Шаг 4: создание проекта

Далее идет планировка проекта. Запустите мастер инициализации из чистой корневой папки и позвольте ему создать структуру проекта:

agentcore create

Маг запросит такие детали, как имя проекта, язык, версия Python и файл входной точки. Входная точка и версия Python должны соответствовать приложению. После этого в папке agentcore появится файл agentcore.json, который указывает AgentCore, где находится код и как его запустить.

{
  "name": "MyAgentOnAgentcore",
    "runtimes": [
    {
      "name": "my-agent",
      "build": "CodeZip",
      "entrypoint": "main.py",
      "codeLocation": "app/my-agent/",
      "runtimeVersion": "PYTHON_3_12",
      "networkMode": "PUBLIC",
      "protocol": "HTTP",
	  "envVars": []
	}
  ]
}

Шаг 5: разместите код там, где ищет AgentCore

Переместите или скопируйте исходный код агента в каталог, указанный в параметре codeLocation в файле agentcore.json. Легко допустить ошибку, и неверное расположение приведёт к ненужным трудностям при развертывании. Распространённая ошибка — помещение кода прямо в папку agentcore, что может занять много времени. Структура должна выглядеть следующим образом:

MyAgentOnAgentcore/
├──agentcore
	└── agentcore.json
├──app/
	└──my-agent/          			 ← codeLocation
		├── main.py                  ← entrypoint (matches agentcore.json)
		├── pyproject.toml           ← or requirements.txt
		├── src/
		│   └── my_agent_graph.py    ← your LangGraph graph builder
		│   └── tools.py             ← your tools, utilities, etc.
		└── .env					 ← your configuration variables

main.py должен находиться на верхнем уровне пути codeLocation и полностью соответствовать указанному точке входа в agentcore.json.

Переменные среды

AgentCore может передавать переменные среды в контейнер среды выполнения. В локальных условиях самым простым способом является использование файла .env. В производственной среде значения могут храниться в agentcore.json в разделе envVars, хотя файл .env тоже подходит. Конфиденциальные данные, такие как пароли и ключи API, лучше хранить в AWS Secrets Manager и загружать их во время выполнения; в этом случае роль выполнения AgentCore должна иметь право на их чтение. Обратите внимание, что envVars — это массив объектов JSON, каждый из которых содержит поля name и value.

Шаг 6: проверка

Прежде чем что-либо запускать, позвольте CLI проверить конфигурацию:

agentcore validate

Простые ошибки, такие как отсутствие файла входной точки или неверный путь в конфигурации, обнаруживаются именно здесь.

Шаг 7: запуск и тестирование локально

Запустите локальную среду выполнения с помощью:

agentcore dev

Он запускает локальный HTTP-сервер, который полностью соответствует производственной версии. При правильной настройке вывод показывает, что приложение готово и прослушивает локальный порт.

Запуск локального сервера

Вызов можно осуществить через CLI:

agentcore invoke "Summarise last month sales"

или с помощью curl:

curl -X POST http://localhost:8080/invocations \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Summarise last month sales", "session_id": "test-001"}'

Хорошим ответом является JSON с ответом агента внутри:

{"response": "Last month, total sales were $1.2M across 3 regions..."}

Шаг 8: развертывание на AWS

Когда локальные тесты пройдены успешно, осуществляйте развертывание в среду AgentCore Runtime:

agentcore deploy

На фоне происходит упаковка кода с помощью CLI, создание бакета S3 для прямой развертки кода, формирование роли выполнения IAM, а также развертывание AgentCore Runtime с использованием CDK. Первая развертка занимает несколько минут, а последующие обычно происходят быстрее.

После завершения проверьте статус среды выполнения. В выводе указываются ARN среды выполнения и HTTP-адрес для вызова развернутого агента.

agentcore status

Шаг 9: запуск развернутого агента

CLI — это самый простой способ протестировать развернутую версию:

agentcore invoke --prompt "Who are the top 5 customers by revenue?" --session-id "session-id-with-length-greater-than-or-equal-33"

Для вызова по HTTP необходимо подписать запрос с помощью AWS SigV4:

curl -X POST "https://bedrock-agentcore.us-east-1.amazonaws.com/runtimes/arn-of-MyAgentOnAgentcore-xxxx/invocations" \
  --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
  --aws-sigv4 "aws:amz:us-east-1:bedrock-agentcore" \
  -H "Content-Type: application/json" \
  -H "x-amzn-bedrock-agentcore-runtime-session-id: session-id-with-length-greater-than-or-equal-33" \
  -d '{"prompt": "Who are the top 5 customers by revenue?"}'

Используйте HTTP-адрес из команды agentcore status.

Для вызовов из другого Python-кода SDK, как правило, является наилучшим вариантом. Храните ARN во время выполнения в переменной окружения, передавайте необходимые параметры и снова отправляйте идентификатор предыдущей сессии при каждом последующем вызове.

# invoke_agent.py
import json
import boto3
import os
from dotenv import load_dotenv

load_dotenv()

client = boto3.client("bedrock-agentcore", region_name="us-east-1")
runtime_arn = os.getenv("AGENTCORE_RUNTIME_ARN")

def invoke(prompt: str, session_id: str) -> str:
    payload = json.dumps({"prompt": prompt, "session_id": session_id})
    response = client.invoke_agent_runtime(
        agentRuntimeArn=runtime_arn,
        payload=payload,
        contentType="application/json"
    )
    body = json.loads(response["response"].read().decode())
    return body["response"]

if __name__ == "__main__":
    session_id = ""
    print("Ready. Type 'exit' to quit.")

    while True:
        prompt = input("Your question: ").strip()
        if prompt == "exit":
            break

        if not prompt:
            continue

        params = {
            "agentRuntimeArn": runtime_arn,
            "payload": json.dumps({"prompt": prompt}),
            "contentType": "application/json"
        }
        if session_id:
            params["runtimeSessionId"] = session_id

        try:
            response = client.invoke_agent_runtime(**params)
            body = json.loads(response["response"].read().decode())
            session_id = response.get("runtimeSessionId", session_id)
            print(f"Agent: {body['response']}\n")
        except Exception as e:
            print(f"Error: {e}")

Установите AGENTCORE_RUNTIME_ARN в файле .env:

AGENTCORE_RUNTIME_ARN=arn:aws:bedrock-agentcore:us-east-1:123456789012:agent-runtime/MyAgentOnAgentcore-xxxx

Сохранение состояния сессии между вызовами

Обратите внимание на runtimeSessionId в примере boto3. AgentCore возвращает его с каждым ответом. Отправка этого значения в следующем запросе позволяет направлять дальнейшие действия в тот же контекст сессии, и в сочетании с MemorySaver от LangGraph агент сохраняет полную память о разговоре между отдельными HTTP-запросами.

Распространённые проблемы

  • Сбои при запуске являются преднамеренными. Когда функция create_agent() вызывает ошибку при импорте, AgentCore не запускает среду выполнения. Такое поведение предотвращает тихий запуск некорректно настроенного агента, например, с отсутствующими учетными данными или неверным URL базы данных.
  • Необходимо добавить разрешения. Роль выполнения AgentCore требует явного доступа ко всем сервисам AWS, которые использует агент, включая Secrets Manager и S3. Добавьте эти разрешения после первой развертки.
  • Версии должны совпадать. Версия Python, указанная в pyproject.toml, должна совпадать с настройкой среды выполнения в agentcore.json.
  • Возвращайте обычные словари. Если точка входа возвращает строку или пользовательский объект, среда выполнения отклонит его.

Что на самом деле меняется

Чтобы перейти от локального агента LangGraph к AgentCore, требуется всего несколько изменений: установить два дополнительных пакета, обернуть граф в BedrockAgentCoreApp, создать структуру проекта, протестировать его локально, затем развернуть и вызвать. Граф, инструменты, вызовы моделей и настройки памяти в основном остаются без изменений. AgentCore отвечает за инфраструктурную часть, тогда как логика агента по-прежнему находится в ведении LangGraph.

Связанные материалы

  • Ворота валидации и мультиагентная маршрутизация для бота поддержки LangGraph — Добавление детерминистических ворот бизнес-логики, самокорректирующегося цикла валидации и системы надзора с тремя специализированными субграфами в агента LangGraph для электронной коммерции.