Съдържание
- AgentCore Identity: кой какво може
- AgentCore Gateway: правилният инструмент, без излишни токени
- AgentCore Memory: какво помни агентът
- AgentCore Runtime: Firecracker, MicroVM и контейнери
- Бонус: cross-account и cross-region без мрежова магия
- Колко струва
- Вместо заключение
AgentCore платформата се базира на повече от 20-годишния опит на AWS в решаването на проблемите на магазина на Amazon и на крайните клиенти. Услугата променя много от вече изградените ни представи за compute, network, storage и database и позволява връзка между акаунти и между различни региони, без да е нужно да познаваш софтуерно дефинираните мрежи в дълбочина. Дава и възможност да интегрираш легаси системи към новите агенти. Платформата се състои от няколко функционалности, които ще разгледаме една по една: Identity, Gateway, Memory и Runtime.
AgentCore Identity: кой какво може
AgentCore Identity управлява самоличността на агента и достъпа му до външни услуги и инструменти чрез абстракция, наречена workload identity. Ключовете за външните услуги се пазят в Secrets Manager с префикс bedrock-agentcore-identity!. На практика услугата управлява потока на идентификация — кой какво иска да прави и дали е одобрено. Така гарантираш липсата на своеволия: агентът има достъп точно толкова, колкото си му дал.
Предлагат се две форми на автентикация и оторизация.
2LO (2-legged OAuth) — агентът се представя пред външната система с предварително издаден токен: нещо като пропуск от твое име, който определя какво точно му е позволено да прави. Секретите се пазят в Secrets Manager. За iGaming сектора 2LO е нещо като табу, което трябва да се избягва на всяка цена — думата PAT предизвиква силно вълнение в инфосек общността, независимо дали токенът е криптиран с KMS ключ със строга политика. Нещо като „дракарис“ при драконите от Game of Thrones.
3LO (3-legged OAuth) — В този случай имаш три партии - агент, потребител и трета система. Агентът сам по себе си няма никакви права в Jira, Confluence или GitHub. Когато за пръв път поиска да работи от твое име, системата ти показва екран за одобрение — както когато приложение те пита дали разрешаваш достъп до камерата. На екрана пише точно какво ще може агентът (например само да чете тикети) и когато натиснеш Allow, системата издава токен само с тези права, който AgentCore Identity пази за теб. Оттам нататък агентът работи с този токен и може да прави единствено одобрените действия — нищо повече. За всяка от системите (Jira, Confluence, GitHub) одобрението е отделно, със собствени права.
Пример с 2LO:
resource "aws_bedrockagentcore_api_key_credential_provider" "github" {
name = "github-pat-token"
api_key_wo = local.envs["GITHUB_PAT"]
api_key_wo_version = var.token_version
}
Самоличността и ключовете обаче са само половината от историята — агентът има нужда и от инструменти, до които да стига с тях. Тук идва Gateway.
AgentCore Gateway: правилният инструмент, без излишни токени
AgentCore Gateway позволява връзка към Lambda функции, Smithy модели, OpenAPI-съвместими API-та и външни MCP сървъри. Решава и един много важен проблем: когато подадеш много инструменти на агент, той често греши и избира неправилния. Това струва токени, които клиентът плаща. Затова Gateway използва семантично търсене, за да открие правилния инструмент.
Terraform кодът дефинира gateway-я и неговата цел (target). OpenAPI схемата може да се подаде inline в JSON формат; ако е в YAML, се преобразува с Terraform функции — jsonencode(yamldecode(...)). Една особеност: ако целта е AgentCore Runtime агент, gateway-ят трябва да е без зададен protocol type — Runtime target-и не могат да се добавят към gateway с protocol_type = "MCP".
data "aws_iam_policy_document" "gtw_plcy" {
statement {
sid = "GetResourceOauth2Token"
effect = "Allow"
actions = ["bedrock-agentcore:GetResourceApiKey"]
resources = ["arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:token-vault/default/apikeycredentialprovider/${aws_bedrockagentcore_api_key_credential_provider.github.name}",
"arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:workload-identity-directory/default/workload-identity/${aws_bedrockagentcore_gateway.gtw.gateway_id}",
"arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:workload-identity-directory/default",
"arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:token-vault/default"
]
}
statement {
sid = "GetWorkloadAccessToken"
effect = "Allow"
actions = ["bedrock-agentcore:GetWorkloadAccessToken"]
resources = [
"arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:workload-identity-directory/default",
"arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:workload-identity-directory/default/workload-identity/${aws_bedrockagentcore_gateway.gtw.gateway_id}"
]
}
statement {
effect = "Allow"
actions = ["secretsmanager:GetSecretValue"]
resources = [
aws_bedrockagentcore_api_key_credential_provider.github.api_key_secret_arn[0].secret_arn
]
}
}
data "aws_iam_policy_document" "assume_role" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["bedrock-agentcore.amazonaws.com"]
}
condition {
test = "StringEquals"
values = [data.aws_caller_identity.current.account_id]
variable = "aws:SourceAccount"
}
}
}
resource "aws_iam_role" "gtw_role" {
name = "bedrock-agentcore-gateway-role"
assume_role_policy = data.aws_iam_policy_document.assume_role.json
}
resource "aws_iam_policy" "gtw_plcy" {
policy = data.aws_iam_policy_document.gtw_plcy.json
name = "bedrock-agentcore-gateway-plcy"
}
resource "aws_iam_role_policy_attachment" "gtw_role_plcy_attach" {
policy_arn = aws_iam_policy.gtw_plcy.arn
role = aws_iam_role.gtw_role.name
}
resource "aws_bedrockagentcore_gateway" "gtw" {
name = "gateway"
role_arn = aws_iam_role.gtw_role.arn
authorizer_type = "AWS_IAM"
protocol_type = "MCP"
exception_level = "DEBUG"
protocol_configuration {
mcp {
search_type = "SEMANTIC"
}
}
}
resource "aws_bedrockagentcore_gateway_target" "github_target" {
name = "api-target"
gateway_identifier = aws_bedrockagentcore_gateway.gtw.gateway_id
description = "External API target with API key authentication"
credential_provider_configuration {
api_key {
provider_arn = aws_bedrockagentcore_api_key_credential_provider.github.credential_provider_arn
credential_location = "HEADER"
credential_parameter_name = "Authorization"
credential_prefix = "Bearer"
}
}
target_configuration {
mcp {
open_api_schema {
inline_payload {
payload = jsonencode(yamldecode(file("${path.module}/github-tools.yaml")))
}
}
}
}
}
Понякога освен достъп до външни услуги искаме агентът да запомня информация за крайния потребител, за да предлага по-ценни решения на база на неговия контекст. Това става с AgentCore Memory.
AgentCore Memory: какво помни агентът
Паметта се дели според стратегията на: потребителски предпочитания (неща, които потребителят харесва), семантична (факти от контекста), обобщаваща и индивидуална (custom). Извличането на дългосрочните записи е асинхронно и отнема време. Има и една особеност при създаването: всяка стратегия блокира създаването на следващата, т.е. ако настройваш повече от една, между тях трябва да се изчака — емпирично около 190 секунди; в кода по-долу съм заложил 300 за спокойствие. В Terraform изглежда по следния начин:
resource "aws_iam_role" "bedrock_memory_role" {
name = "bedrock-agentcore-memory-role"
assume_role_policy = data.aws_iam_policy_document.assume_role.json
}
resource "aws_iam_role_policy_attachment" "bedrock_plcy_attach" {
role = aws_iam_role.bedrock_memory_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonBedrockAgentCoreMemoryBedrockModelInferenceExecutionRolePolicy"
}
resource "aws_bedrockagentcore_memory" "memory" {
name = "agent_memory"
event_expiry_duration = 30
memory_execution_role_arn = aws_iam_role.bedrock_memory_role.arn
}
resource "aws_bedrockagentcore_memory_strategy" "user_preference" {
name = "userpreference_strategy"
memory_id = aws_bedrockagentcore_memory.memory.id
type = "USER_PREFERENCE"
description = "user preference strategy"
namespaces = ["/users/{actorId}/preferences/"]
}
resource "time_sleep" "wait_after_usr_pref_strategy" {
depends_on = [aws_bedrockagentcore_memory_strategy.user_preference]
create_duration = "300s"
destroy_duration = "300s"
triggers = {
strategy_id = aws_bedrockagentcore_memory_strategy.user_preference.memory_strategy_id
}
}
resource "aws_bedrockagentcore_memory_strategy" "semantic" {
name = "semantic_strategy"
memory_id = aws_bedrockagentcore_memory.memory.id
type = "SEMANTIC"
description = "semantic strategy"
namespaces = ["/users/{actorId}/facts/"]
depends_on = [time_sleep.wait_after_usr_pref_strategy]
}
resource "time_sleep" "wait_after_semantic_strategy" {
depends_on = [aws_bedrockagentcore_memory_strategy.semantic]
create_duration = "300s"
destroy_duration = "300s"
triggers = {
strategy_id = aws_bedrockagentcore_memory_strategy.semantic.memory_strategy_id
}
}
resource "aws_bedrockagentcore_memory_strategy" "summarization" {
name = "summarization_strategy"
memory_id = aws_bedrockagentcore_memory.memory.id
type = "SUMMARIZATION"
description = "summarization strategy"
namespaces = ["/summaries/{actorId}/{sessionId}/"]
depends_on = [time_sleep.wait_after_semantic_strategy]
}
Записите се пазят в йерархични namespace-и, в които {actorId} и {sessionId} се заместват с реалните стойности при запис.
Ето как всичко дотук се събира в самия агент — четене от дългосрочната памет, разговор с инструментите през Gateway (MCP със SigV4 подпис) и запис на хода като събитие:
"""Repo Ops agent — AgentCore Runtime entrypoint.
Поток на всяка заявка:
1. recall() -> чете дългосрочна памет (LTM) за този потребител
2. Agent() -> LLM разговор с инструментите от Gateway (MCP през SigV4)
3. create_event() -> записва хода като събитие (STM); стратегиите
извличат LTM асинхронно след ~1 минута
"""
import os
import boto3
import httpx
from botocore.auth import SigV4Auth
from botocore.awsrequest import AWSRequest
from bedrock_agentcore.memory import MemoryClient
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from mcp.client.streamable_http import streamablehttp_client
from strands import Agent
from strands.models import BedrockModel
from strands.tools.mcp import MCPClient
REGION = os.environ.get("AWS_REGION", "eu-central-1")
GATEWAY_URL = os.environ["GATEWAY_URL"] # .../mcp
MEMORY_ID = os.environ["MEMORY_ID"]
MODEL_ID = os.environ["MODEL_ID"]
app = BedrockAgentCoreApp() # вдига HTTP сървър на :8080
memory = MemoryClient(region_name=REGION)
class SigV4HTTPXAuth(httpx.Auth):
"""Подписва всяка MCP заявка със SigV4.
Gateway-ът е с authorizer_type = "AWS_IAM", тоест иска подпис
точно както всяко AWS API извикване. Ролята на Runtime трябва да
има bedrock-agentcore:InvokeGateway върху ARN-а на gateway-а.
"""
requires_request_body = True
def __init__(self, service: str, region: str):
self._creds = boto3.Session().get_credentials()
self._service = service
self._region = region
def auth_flow(self, request: httpx.Request):
aws_req = AWSRequest(
method=request.method,
url=str(request.url),
data=request.content,
headers={"host": request.url.host},
)
SigV4Auth(self._creds, self._service, self._region).add_auth(aws_req)
request.headers.update(dict(aws_req.headers))
yield request
def recall(actor_id: str, query: str) -> str:
"""Семантично търсене в дългосрочната памет.
Namespace-ите трябва да съвпадат ТОЧНО с тези в Terraform
(включително наклонената черта накрая).
"""
namespaces = [
f"/users/{actor_id}/preferences/",
f"/users/{actor_id}/facts/",
]
chunks = []
for ns in namespaces:
try:
records = memory.retrieve_memories(
memory_id=MEMORY_ID,
namespace=ns,
query=query,
top_k=3,
)
for rec in records:
text = rec.get("content", {}).get("text", "")
if text:
chunks.append(f"- {text}")
except Exception as exc:
# Паметта никога не трябва да сваля агента
print(f"[memory] retrieve failed for {ns}: {exc}")
return "\n".join(chunks)
def remember(actor_id: str, session_id: str, prompt: str, answer: str) -> None:
"""Записва хода като събитие в краткосрочната памет."""
try:
memory.create_event(
memory_id=MEMORY_ID,
actor_id=actor_id,
session_id=session_id,
messages=[(prompt, "USER"), (answer, "ASSISTANT")],
)
except Exception as exc:
print(f"[memory] create_event failed: {exc}")
@app.entrypoint
def invoke(payload, context):
prompt = payload.get("prompt", "")
actor_id = payload.get("actor_id", "default")
# session_id идва от --runtime-session-id при извикването
session_id = getattr(context, "session_id", None) or "local-dev-session-0000000000000000"
memories = recall(actor_id, prompt)
system_prompt = (
"Ти си Repo Ops — кратък асистент за GitHub операции. "
"Използвай наличните инструменти за всичко свързано с "
"хранилища, pull request-и и issue-та. Никога не измисляй "
"данни — ако инструмент върне грешка, кажи я на потребителя. "
"Питай за потвърждение преди да създадеш issue."
)
if memories:
system_prompt += f"\n\nКакво помниш за този потребител:\n{memories}"
gateway = MCPClient(
lambda: streamablehttp_client(
GATEWAY_URL,
auth=SigV4HTTPXAuth("bedrock-agentcore", REGION),
)
)
with gateway:
tools = gateway.list_tools_sync()
print(f"[gateway] tools: {[t.tool_name for t in tools]}")
agent = Agent(
model=BedrockModel(model_id=MODEL_ID, region_name=REGION),
tools=tools,
system_prompt=system_prompt,
)
answer = str(agent(prompt))
remember(actor_id, session_id, prompt, answer)
return {"result": answer}
if __name__ == "__main__":
app.run()
Този код обаче трябва да живее някъде. Време е за частта, на която винаги блокирам на интервю.
AgentCore Runtime: Firecracker, MicroVM и контейнери
Винаги съм се чудил как да разкажа какво е AgentCore Runtime. Въпросите за MicroVM, виртуални машини, контейнери и процеси винаги са трудни за разказване. Може би сам не го разбирам докрай, може би заешката дупка е толкова дълбока, че е трудно да се обясни просто. Затова реших да започна отдалеч — може би и защото на интервю винаги блокирам точно на тези въпроси.
За да развенчая мита, започвам от MicroVM.
Две от опциите за деплойване на приложение (включително AI приложение) са виртуална машина и контейнер. Разликата: контейнерите пакетират всички зависимости и библиотеки на приложението и споделят общо ядро и операционна система с хоста, докато всяка виртуална машина има собствено ядро, собствена операционна система и заделена част от ресурсите. Ядрото управлява хардуера чрез драйвери, т.е. има неограничен достъп до процесорно време и памет; приложенията, от друга страна, нямат.
Често се възприема, че виртуалната машина е по-сигурна от контейнерите. Защо? Може би защото контейнерите споделят ядро с хоста.
Дали това прави контейнерите несигурни спрямо виртуалната машина, е спорен въпрос. При виртуалната машина имаш пачване, управление на драйвери и по-бавно стартиране. Има и вариантът distroless контейнер — без шел и пакетни мениджъри, само с необходимото за крайното приложение.
MicroVM се опитва да реши предизвикателствата с бавното стартиране, като освен това предлага по-голяма изолация, характерна за виртуалните машини: всяка машина идва със собствено виртуализирано ядро. Firecracker — MicroVM технологията зад AWS Lambda — позволява да стартираш до 150 MicroVM в секунда, като всяка от тях се вдига за около 125 ms.
Каква е връзката на виртуалните машини и контейнерите с AgentCore Runtime? Firecracker стои зад AgentCore Runtime: ти деплойваш контейнер, а той се изпълнява върху Firecracker виртуална машина. Така получаваш максимална изолация — една Firecracker машина не може да използва ресурси на друга, това е забранено на ниво хипервайзор — и в същото време максимално лесно деплойване на всяко AI приложение под формата на контейнер с всички зависимости. Около самия Firecracker процес на хоста върви и програма на име jailer — втори слой защита (пясъчник), който обвива виртуалната машина, в случай че тя бъде компрометирана.
Технологията гарантира сигурност и изолация на данните, паметта и процесите на всеки клиент. AgentCore Runtime стъпва на опита на Amazon с Lambda, контейнерите и инстанциите.
Runtime дава възможност да деплойнеш всеки AI агент или MCP сървър, независимо от SDK или framework, стига да изложи HTTP на порт 8080 (за MCP сървъри портът е 8000). AWS споделят, че идеята е услугата да е framework agnostic — бъдещият сигурен дом за твоя агент, който пази най-ценното за една фирма: данните. Заедно с паметта, управлението на достъпи, връзката с други услуги и оценката на агенти това оформя цялостна AI платформа.
Подготовката на приложението включва три стъпки.
- Създаване на регистър за контейнерни изображения, в който ще живее приложението:
resource "aws_ecr_repository" "agent_repo" {
name = "agent-repo"
image_tag_mutability = "IMMUTABLE"
image_scanning_configuration {
scan_on_push = false
}
force_delete = true
}
- Docker файл с всички зависимости на приложението:
# AgentCore Runtime работи САМО на Graviton (linux/arm64).
# Затова build-ът задължително минава през buildx с --platform linux/arm64.
FROM public.ecr.aws/docker/library/python:3.13-slim
WORKDIR /app
# Първо зависимостите — така Docker кешира слоя и следващите build-ове са бързи
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
# Контрактът на Runtime: HTTP сървър, който слуша на 8080
EXPOSE 8080
CMD ["python", "app.py"]
- Build и push на изображението:
resource "random_id" "agent_rand_tag" {
keepers = {
agent_img_tag = local.agent_code_hash
}
byte_length = 2
}
resource "null_resource" "build_and_push_agent" {
triggers = {
dockerfile_hash = local.agent_code_hash
}
provisioner "local-exec" {
command = <<-EOT
aws ecr get-login-password --region ${data.aws_region.current.region} | docker login --username AWS --password-stdin ${aws_ecr_repository.agent_repo.repository_url}
docker build -t ${aws_ecr_repository.agent_repo.repository_url}:${random_id.agent_rand_tag.hex} ${path.module}/
docker push ${aws_ecr_repository.agent_repo.repository_url}:${random_id.agent_rand_tag.hex}
EOT
}
}
Terraform кодът се сглобява от съставните елементи: за да вдигнеш AgentCore Runtime, подаваш всичко останало и го създаваш последен — като Волтрон, ако сте го гледали, това е главата — с необходимата роля:
data "aws_iam_policy_document" "runtime_permissions" {
statement {
actions = ["ecr:GetAuthorizationToken"]
effect = "Allow"
resources = ["*"]
}
statement {
actions = [
"ecr:BatchGetImage",
"ecr:GetDownloadUrlForLayer",
]
effect = "Allow"
resources = [aws_ecr_repository.agent_repo.arn]
}
statement {
actions = [
"logs:DescribeLogStreams",
"logs:CreateLogGroup",
]
effect = "Allow"
resources = ["arn:aws:logs:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:log-group:/aws/bedrock-agentcore/runtimes/*"]
}
statement {
actions = [
"logs:DescribeLogGroups"
]
effect = "Allow"
resources = ["arn:aws:logs:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:log-group:*"]
}
statement {
actions = [
"logs:CreateLogStream",
"logs:PutLogEvents"
]
effect = "Allow"
resources = ["arn:aws:logs:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:log-group:/aws/bedrock-agentcore/runtimes/*:log-stream:*"]
}
statement {
actions = [
"cloudwatch:PutMetricData"
]
resources = ["*"]
effect = "Allow"
condition {
test = "StringEquals"
values = ["bedrock-agentcore"]
variable = "cloudwatch:namespace"
}
}
statement {
actions = [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
]
resources = ["arn:aws:bedrock:*::foundation-model/*",
"arn:aws:bedrock:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:*"]
effect = "Allow"
}
statement {
sid = "GetWorkloadAccessToken"
effect = "Allow"
actions = ["bedrock-agentcore:GetWorkloadAccessToken"]
resources = [
"arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:workload-identity-directory/default",
"arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:workload-identity-directory/default/workload-identity/${aws_bedrockagentcore_gateway.gtw.gateway_id}"
]
}
statement {
effect = "Allow"
actions = ["bedrock-agentcore:InvokeGateway"]
resources = [
aws_bedrockagentcore_gateway.gtw.gateway_arn
]
}
statement {
effect = "Allow"
actions = ["bedrock-agentcore:ListEvents",
"bedrock-agentcore:CreateEvent",
"bedrock-agentcore:RetrieveMemoryRecords"]
resources = [
aws_bedrockagentcore_memory.memory.arn
]
}
}
resource "aws_iam_role" "rntime_role" {
name = "bedrock-agentcore-rntime-role"
assume_role_policy = data.aws_iam_policy_document.assume_role.json
}
resource "aws_iam_policy" "rntime_plcy" {
policy = data.aws_iam_policy_document.runtime_permissions.json
name = "bedrock-agentcore-rntime-plcy"
}
resource "aws_iam_role_policy_attachment" "rntime_role_plcy_attach" {
policy_arn = aws_iam_policy.rntime_plcy.arn
role = aws_iam_role.rntime_role.name
}
resource "aws_bedrockagentcore_agent_runtime" "example" {
agent_runtime_name = "gitops_agent_runtime"
role_arn = aws_iam_role.rntime_role.arn
agent_runtime_artifact {
container_configuration {
container_uri = "${aws_ecr_repository.agent_repo.repository_url}:${random_id.agent_rand_tag.hex}"
}
}
network_configuration {
network_mode = "PUBLIC"
}
environment_variables = {
GATEWAY_URL = aws_bedrockagentcore_gateway.gtw.gateway_url
MEMORY_ID = aws_bedrockagentcore_memory.memory.id
MODEL_ID = "eu.anthropic.claude-sonnet-4-5-20250929-v1:0"
}
depends_on = [null_resource.build_and_push_agent]
}
Бонус: cross-account и cross-region без мрежова магия
Освен всичко останало, горните услуги — и в частност Gateway — решават проблем, който обикновено налага по-сложни мрежови конструкции: извикванията между акаунти и между региони. Два примера от реалния живот. И в двата сценарият е един и същ: gateway-ят живее в платформен акаунт А в eu-west-1, а MCP сървърът (mcp-atlassian) и Jira DC — в друг акаунт Б и друг регион, eu-west-2. Разликата е в цената, която плащаш.
Пример 1: Runtime target — мрежата я няма, защото не ти трябва
Gateway без protocol type подава Okta JWT-то нататък и с едно InvokeAgentRuntime по AWS backbone мрежата стига до Runtime в другия акаунт и регион — никакъв peering, никакъв PrivateLink, това е API, а мрежата остава скрита. Runtime-ът върти форкнатия mcp-atlassian (arm64, stateless, MCP на :8000) и излиза през egress ENI-та право към Jira DC с потребителския токен. Цената: Identity трябва да живее в акаунта на Runtime-а — секретите се местят при агента — а губиш и агрегацията, и семантичното търсене, тъй като gateway е просто прокси
Пример 2: MCP target — семантично търсене, но мрежата си я създаваш сам
Тук gateway-ят е с класическият MCP протокол тъй като целта не е аgentcore runtime: MCP, CUSTOM_JWT, агрегация и семантично търсене, а Identity сменя JWT-то срещу потребителския токен — 3LO vault-ът остава при платформата. Цената е мрежата, и тя е цяла верига: Lattice resource gateway (само в региона на gateway-я) → cross-region interface endpoint → PrivateLink → endpoint service в акаунт Б → вътрешен NLB с TLS :443 и публичен ACM сертификат → EC2 с mcp-atlassian на :8000 → Jira DC. Всяко звено е managed — но всяко звено е твое.
Кое кога
Ако ти трябва просто да стигнеш до агент или MCP сървър в друг акаунт и регион — Runtime target: нула мрежова работа, но vault-ът се мести при runtime-а и губиш агрегацията. Ако строиш платформа — един endpoint, семантично търсене, токените и съгласията при теб — MCP target: получаваш всичко това, но Lattice-ът, cross-region PrivateLink-ът и сертификатите са твоя грижа.
Колко струва
AgentCore няма месечен абонамент — всяка функционалност е с отделен брояч и плащаш само каквото ползваш. Цените към юли 2026:
- Runtime — $0.0895 на vCPU-час и $0.00945 на GB-час, на секунда. CPU се таксува само докато агентът реално обработва: I/O чакането е безплатно, а агентите прекарват 30–70% от сесията в чакане на модела и инструментите.
- Gateway — $0.005 на 1000 извиквания (ListTools, InvokeTool), $0.025 на 1000 семантични търсения и $0.02 на 100 индексирани инструмента месечно.
- Memory — $0.25 на 1000 събития (краткосрочна памет); дългосрочната е $0.75 на 1000 записа месечно с вградените стратегии (моделът е включен в цената) и $0.50 на 1000 извличания. Три стратегии значат три отделни извличания от същите събития.
- Identity — $0.010 на 1000 заявки за токен… но безплатна, когато минава през Runtime или Gateway. В нашата архитектура: нула.
- Observability — по тарифите на CloudWatch (около $0.35/GB за span-ове).
Отстрани стоят ECR за образа, Secrets Manager за PAT-а и — най-голямото перо — токените към модела, които често са 50–70% от цялата сметка. Точно затова семантичното търсене на Gateway не е лукс, а FinOps: грешно избраният инструмент струва токени, а токените струват най-много.
Вместо заключение
AgentCore не е просто хостинг за агенти. Identity решава кой какво може, Gateway — кой инструмент е правилният, Memory — какво си струва да се помни, Runtime — къде всичко това живее изолирано. А когато се наложи да прекосиш акаунт и регион, вече имаш избор: плащаш или с функционалност, или с мрежова връзка. Пример 1 изпълнява обещанието от увода буквално — никаква мрежа. Пример 2 показва, че дори когато мрежата ти трябва, тя се сглобява от managed блокчета като lego без нужда от промени по рутингтаблици.




Top comments (0)