본문으로 건너뛰기

AgentCore & 메모리 기술 FAQ

AgentCore Runtime, Gateway, 라이브 AWS 조회 경로, Memory Store 등 AI 엔진 내부 동작에 대한 심화 질문과 답변입니다.

AgentCore가 라이브 AWS 조회의 기본(primary) 경로인 이유는?

AWSops의 라이브 AWS 데이터는 AgentCore MCP Lambda 도구를 통해 조회됩니다. 과거 레거시 앱이 임베디드 Steampipe로 직접 쿼리하던 방식을 대체한 것입니다.

핵심 포인트

항목내용
라이브 조회AgentCore MCP Lambda 도구(약 160개, 읽기 전용)가 boto3로 AWS API를 직접 호출
Steampipe의 역할라이브 쿼리 엔진이 아님. steampipe_enabled 플래그로만 켜지는 인벤토리 sync(기본 OFF)일 뿐 — 로컬 9193 서비스/pg Pool 없음
게이트AgentCore 전체는 agentcore_enabled Terraform 플래그로 게이트(기본 OFF → plan = No changes, $0)
읽기 전용모든 도구는 read-only (ADR-041 / 2026-06-11 번복: AWS-리소스 변경+자율은 영구 동결)
Steampipe는 더 이상 라이브 엔진이 아닙니다

라이브 AWS 상태는 항상 AgentCore 도구가 답합니다. Steampipe는 켜질 경우 Fargate에서 워밍업되어 인벤토리를 Aurora로 sync하는 보조 경로일 뿐이며, 기본값은 비활성입니다.

AgentCore Runtime은 무엇이고, Strands Agent와의 관계는?

AgentCore Runtime과 Strands Agent는 서로 다른 레이어에서 동작합니다.

AgentCore Runtime

  • AWS가 관리하는 서버리스 컨테이너 실행 환경
  • Docker 이미지(ECR)를 지정하면 자동으로 컨테이너를 실행/스케일링
  • Cold Start 관리, 네트워크 설정, IAM Role 등을 처리
  • InvokeAgentRuntime으로 호출

Strands Agent Framework

  • Python 기반 AI 에이전트 프레임워크 (agent/agent.py)
  • LLM(Bedrock)에게 도구를 제공하고, 도구 호출 결과를 다시 LLM에 전달하는 루프
  • MCP 프로토콜로 게이트웨이에 연결하여 도구를 사용

관계 정리

항목AgentCore RuntimeStrands Agent
역할컨테이너 실행 환경AI 에이전트 로직
레벨인프라애플리케이션
관리 주체AWS개발자
코드 위치AWS 서비스agent/agent.py
설정Terraform / 멱등 provisionerPython 코드

Gateway와 Lambda는 어떤 관계인가요? 게이트웨이는 몇 개인가요?

Gateway는 MCP 프로토콜 라우터이고, Lambda는 실제 AWS API를 실행하는 읽기 전용 백엔드입니다.

섹션 게이트웨이는 9개입니다 (ADR-004 개정)

network · container · data · security · cost · monitoring · iac · ops · external-obs — 총 9개입니다(9 프로비저닝 / 9 라우트, external-obs 승격 2026-06-24).

항목내용
게이트웨이 수ADR-004에 따라 9개(ADR-004 개정)
도구 수160개, 전부 읽기 전용 — 함대가 확장되면 변동(고정 수치 아님)
외부 관측성Prometheus·ClickHouse 커넥터가 external-obs 게이트웨이(아홉 번째)로 라우팅됨(ADR-004 개정) — 그 외 외부 연동은 별도의 Integrations 축(ADR-007/017)
프로토콜MCP(Model Context Protocol) 표준
  • Agent가 list_tools로 사용 가능한 도구 목록을 조회
  • Agent가 도구를 선택하면 Gateway가 해당 Lambda를 호출
  • Gateway Target 생성 시 mcp.lambda 프로토콜과 credentialProviderConfigurations 지정

왜 Lambda를 사용하나요?

이유설명
격리각 도구가 독립 실행, 하나가 실패해도 다른 도구에 영향 없음
권한 분리Lambda별로 최소 권한 IAM Role 부여 가능
스케일링동시 호출 시 자동 스케일링
비용호출 시에만 과금, 유휴 비용 없음
Gateway Target 생성 시 주의

CLI의 --inline-payload 옵션은 JSON 파싱 이슈가 있습니다. Python/boto3로 생성해야 합니다. 또한 갓 만든 게이트웨이가 READY 전이면 첫 Target 생성이 ValidationException을 던질 수 있는데, provisioner가 멱등하므로 재실행으로 해소됩니다.

단일 계정인데 "cross-account 차단" 오류가 나는 이유는?

AWSops 라이브 환경은 단일 계정(123456789012)입니다. 그런데 챗에서 호스트 계정 자신을 대상 계정으로 고르면, 과거 도구가 호스트에 존재하지 않는 크로스 어카운트 역할을 self-assume하려다 AccessDenied가 발생하고, 에이전트가 이를 "cross-account 차단"으로 오진했습니다.

무엇이 문제였나

  • agent.pytarget_account_id = <호스트 계정>을 강제
  • 도구가 arn:...:role/AWSopsReadOnlyRole을 self-assume 시도
  • 이 역할은 온보딩된 타깃 계정에만 존재하고 호스트에는 없음 → AccessDenied
  • 에이전트가 원인을 오해 → "cross-account 차단" 메시지

수정 (defense-in-depth)

위치동작
cross_account.get_role_arn()대상 == 호스트면 None 반환 → AssumeRole 없이 Lambda 실행 역할 직접 사용
agent.py effective_account_id()호스트 계정을 __all__처럼 blank 처리 → 같은 계정 접근에는 prefix 미부여
호스트 판별AWSOPS_HOST_ACCOUNT_ID env → 없으면 STS GetCallerIdentity 폴백 (웜 컨테이너 캐시)

진짜 다른 계정을 assume하는 정상 경로는 그대로 유지됩니다.

단일 계정에서 "내 계정"을 고른 경우

이제 호스트 계정 선택은 self-assume 없이 실행 역할을 직접 쓰므로 정상 동작합니다. 다른(온보딩된) 계정 선택만 STS AssumeRole 경로를 탑니다.

AgentCore 설정값은 어디에 저장되나요?

SSM Parameter Store가 source of truth입니다. 멱등 provisioner(scripts/v2/agentcore/provision.py)가 생성한 리소스 식별자를 SSM에 기록하고, 웹 thin-BFF가 런타임에 읽습니다.

SSM 경로 (/ops/awsops-v2/agentcore/...)

파라미터
/ops/awsops-v2/agentcore/runtime_arnAgentCore Runtime ARN
/ops/awsops-v2/agentcore/interpreter_idCode Interpreter ID
/ops/awsops-v2/agentcore/memory_idMemory Store ID

왜 SSM인가? (valueFrom 레이스 회피)

  • provisioner가 apply 이후 리소스를 생성 → 식별자를 SSM에 기록
  • 웹 BFF는 런타임에 SSM에서 read (캐싱)
  • ECS task def의 secrets valueFrom을 쓰지 않음 → provision 시점과 task 시작 시점 사이의 레이스 컨디션 회피
SSM 예약 prefix 주의

aws...로 시작하는 SSM 경로는 예약어로 거부됩니다. 그래서 /ops/${project}/... 형태를 사용합니다.

Docker arm64 빌드가 필수인 이유는? (EC2 빌드 호스트는 없습니다)

AgentCore Runtime은 AWS Graviton(ARM64) 프로세서에서 실행됩니다.

# 올바른 빌드 명령 — buildx로 arm64 크로스 빌드
docker buildx build --platform linux/arm64 -t awsops-agent .

# ECR 푸시
docker tag awsops-agent:latest $ECR_URI:latest
docker push $ECR_URI:latest

x86(amd64)로 빌드하면?

컨테이너가 시작되지 않거나 exec format error가 발생합니다. Runtime 상태가 FAILED로 전환됩니다.

전용 EC2 빌드 인스턴스는 없습니다

레거시 앱과 달리 AWSops에는 별도의 t4g 빌드 호스트가 없습니다. web/agent/worker 이미지 모두 docker buildx --platform linux/arm64로 빌드합니다. Apple Silicon(M1/M2/M3)은 네이티브 ARM64이지만, Intel Mac 등 amd64 환경에서도 --platform linux/arm64만 명시하면 동일하게 arm64 이미지를 만들 수 있습니다.

agent.py를 수정하면 어떻게 재배포하나요?

make agentcore가 arm64 이미지를 빌드/푸시하고 멱등 provisioner를 실행합니다. make migrate 를 먼저 실행해야 합니다awsops_sql_reader 롤 생성 + 비밀번호 동기화는 migrate 가 하고 agentcore 는 하지 않으므로, 생략하면 execute_sql·inventory-read 가 Data API auth 실패로 떨어집니다(docs/runbooks/agent-sql-reader.md).

절차

make agentcore          # arm64 agent 이미지 빌드/푸시 + 멱등 provisioner
make agentcore --smoke # 추가로 호출 검증

provisioner는 멱등하므로 안전하게 재실행할 수 있습니다(예: 첫 Target 생성이 게이트웨이 미준비로 실패했을 때).

게이트웨이 라우팅은 환경변수로 주입

agent.py는 게이트웨이 URL을 코드에 하드코딩하지 않고 GATEWAYS_JSON 환경변수로 주입받습니다. 따라서 게이트웨이 라우팅 변경이 곧바로 Docker 재빌드를 요구하지는 않습니다.

MCP 프로토콜이란? 도구 디스커버리는 어떻게 동작하나요?

MCP (Model Context Protocol)

MCP는 AI 에이전트가 외부 도구를 표준화된 방식으로 호출하기 위한 프로토콜입니다. AWSops에서는 Strands Agent가 MCP를 통해 게이트웨이의 읽기 전용 도구에 접근합니다.

SigV4 서명 통신

Gateway 연결은 AWS SigV4 서명이 필요합니다(agent/streamable_http_sigv4.py). 에이전트의 자격증명으로 서명한 MCP StreamableHTTP 전송을 사용합니다.

도구 디스커버리 (Tool Discovery)

Agent가 Gateway에 연결하면 페이지네이션으로 전체 도구 목록을 조회한 뒤, 이를 LLM에 제공합니다. LLM(Bedrock)이 사용자 질문을 보고 어떤 도구를 호출할지 스스로 결정하므로, 개발자가 도구 선택 로직을 작성할 필요가 없습니다.

Gateway에 새 도구(Lambda)를 추가하려면?

전체 흐름

Step 1: Lambda 함수 작성

agent/lambda/ 디렉토리에 MCP 핸들러 패턴을 따르는 Python 파일을 생성합니다:

# agent/lambda/my_new_mcp.py
import json
import boto3

def lambda_handler(event, context):
params = event if isinstance(event, dict) else json.loads(event)
t = params.get("tool_name", "")
args = params.get("arguments", params)

if t == "my_new_tool":
client = boto3.client('ec2')
result = client.describe_instances(**args) # 읽기 전용
return {"statusCode": 200, "body": json.dumps(result, default=str)}

return {"statusCode": 400, "body": "Unknown tool"}

Step 2: Gateway Target 생성

agent/lambda/create_targets.py에 도구 스키마를 추가하고 boto3로 Target을 생성합니다:

client.create_gateway_target(
gatewayIdentifier=gw_id,
targetConfiguration={
'mcp': {'lambda': {
'lambdaArn': arn,
'toolSchema': {'inlinePayload': tools} # {name, description, inputSchema}
}}
},
credentialProviderConfigurations=[
{'credentialProviderType': 'GATEWAY_IAM_ROLE'} # 필수
]
)

Step 3: 자동 발견

새 도구가 추가되면 Agent가 list_tools로 자동 발견합니다. Docker 재빌드는 agent.py 자체를 수정한 경우에만 필요합니다.

크로스 어카운트 지원

create_targets.py가 모든 도구에 target_account_id 파라미터를 주입합니다. Lambda에서 cross_account.pyget_client()를 사용하면 STS AssumeRole로 다른 계정의 리소스에 접근할 수 있습니다(대상이 호스트면 self-assume 없이 실행 역할 직접 사용).

Lambda 도구 함수는 어떤 구조인가요?

모든 도구 Lambda는 동일한 MCP 핸들러 패턴을 따릅니다:

# 공통 패턴 (예: agent/lambda/aws_cost_mcp.py)
def lambda_handler(event, context):
# 1. 이벤트 파싱 + 도구 라우팅
params = event if isinstance(event, dict) else json.loads(event)
t = params.get("tool_name", "")
args = params.get("arguments", params)

# 2. 크로스 어카운트 지원 (대상==호스트면 role_arn=None)
target_account_id = args.pop('target_account_id', None)
role_arn = get_role_arn(target_account_id) if target_account_id else None

# 3. 도구별 분기
if t == "get_cost_and_usage":
ce = get_client('ce', 'us-east-1', role_arn)
resp = ce.get_cost_and_usage(...)
return ok(resp)
else:
return err("Unknown tool")

공유 모듈: cross_account.py

크로스 어카운트 접근을 위한 STS AssumeRole 헬퍼입니다. 자격증명을 50분 캐싱하여 반복 호출을 최적화하고, 대상이 호스트 계정과 같으면 None을 반환해 self-assume을 방지합니다.

규칙

  • 모든 Lambda는 읽기 전용 (도달성 경로 생성 등 일부 예외)
  • VPC Lambda(Istio, Steampipe)는 psycopg2 대신 pg8000 사용
  • 도구 스키마 형식: {name, description, inputSchema: {type, properties, required}}

Code Interpreter나 Memory 이름에 하이픈을 쓰면 안 되는 이유는?

AgentCore API의 네이밍 규칙 제약 때문입니다 — 이름에는 언더스코어만 허용됩니다.

영향받는 리소스

리소스잘못된 예올바른 예
Code Interpreterawsops-code-interpreterawsops_code_interpreter
Memory Storeawsops-memoryawsops_memory

증상

하이픈이 포함된 이름으로 생성 시 ValidationException이 발생하거나, 생성은 되지만 호출 시 실패할 수 있으며 에러 메시지가 불명확할 수 있습니다.

Memory Store 추가 제약

  • eventExpiryDuration: 최대 365일
  • 만료된 이벤트는 자동 삭제

AWS가 붙이는 -XXXXX suffix는 자동 생성 부분이며, 네이밍 제약은 사용자가 지정하는 이름 부분(awsops_code_interpreter, awsops_memory)에만 적용됩니다.

AI 대화 이력은 어디에 저장되고, 사용자별로 어떻게 분리되나요?

대화 이력은 Aurora(PostgreSQL 17)에 영속됩니다. 레거시의 로컬 JSON 파일 방식이 아닙니다.

동작

항목내용
저장소Aurora Serverless v2(PG 17), node-pg 풀(web/lib/db.ts)
사용자 식별Cognito JWT의 sub
UIClaude 앱 스타일 사이드바 — /assistant 전체 페이지와 리사이즈 가능한 드로어가 동일 히스토리 공유
렌더링스트리밍 + 마크다운

인증 흐름

  1. Lambda@Edge가 CloudFront에서 JWT를 RS256 JWKS 서명 검증
  2. 검증 통과한 요청이 ECS Fargate 웹에 도달
  3. BFF가 JWT payload에서 sub를 사용자 식별자로 사용
  4. 미인증 요청은 BFF가 401로 거부합니다(fail-closed) — 식별자는 항상 검증된 Cognito sub입니다

AgentCore Runtime 상태는 어떻게 모니터링하나요?

웹 BFF가 Runtime / Gateway / Code Interpreter 상태를 조회합니다. SSM에서 식별자를 읽은 뒤 AgentCore API로 상태를 가져옵니다.

Runtime 상태

상태의미조치
READY정상 작동-
CREATING최초 생성 중수 분 대기
UPDATING업데이트 중 (Docker 이미지 변경 등)수 분 대기
FAILED오류 — 컨테이너 시작 실패Docker 이미지(arm64)/IAM Role/네트워크 확인

어시스턴트 페이지

AI 어시스턴트는 /assistant(전체 페이지)와 어디서나 열 수 있는 리사이즈 드로어에서 사용하며, 두 곳이 동일한 Aurora 대화 이력을 공유합니다.

라우팅은 하이브리드(ADR-038)

질문은 정규식 fast-path + Haiku 4.5 분류기 + 프롬프트 캐싱으로 적절한 섹션 에이전트에 라우팅됩니다(LIVE, 캐시 적중 ~59%). 레거시의 고정 다중-라우트 Sonnet 레지스트리가 아닙니다.