콘텐츠로 이동

M1. 에이전트 배포 — AgentCore CLI (도구 없는 환각 관찰)

첫 모듈에서는 새 AgentCore CLI(@aws/agentcore)로 Claude Fable 5 기반 보안 트리아지 에이전트를 스캐폴드하고, 로컬에서 테스트한 뒤 AgentCore Runtime에 배포합니다. 이 단계의 에이전트는 아직 로그 조회 도구가 없습니다 — 401 폭증 알림을 던졌을 때 LLM의 사전 지식만으로 답하는 모습을 관찰해 두는 것이 M1의 핵심입니다. M2에서 도구가 붙은 뒤와 나란히 놓고 비교합니다.

M1 아키텍처 — 참가자가 AgentCore CLI로 Runtime의 Strands 에이전트를 호출하고, Runtime이 Bedrock(Claude Fable 5 inference profile)로 추론하는 구성. Gateway·도구 연결은 M2에서 채워집니다.

M1에서 만드는 부분입니다. 흐리게 표시된 Gateway·도구 연결은 M2에서, Memory 회상은 M3에서 다룹니다 — 모듈이 진행될수록 이 그림이 채워집니다.

전체 명령 시퀀스는 lab-src/m1/commands.sh에 있으며, 아래 단계는 그 파일을 순서대로 풀어낸 것입니다.

이 모듈의 학습 포인트 — “도구 없는 에이전트”

섹션 제목: “이 모듈의 학습 포인트 — “도구 없는 에이전트””

M1의 에이전트는 판정 티어(Claude Fable 5) 하나만 붙어 있습니다. 로그 조회 도구가 없으므로, “동일 IP에서 401 응답 500회 발생 — 크리덴셜 스터핑인가요?” 같은 질문에 사전 지식으로 그럴듯한 대답을 만들어 냅니다. 이 응답은 “합리적으로 보이지만 실제 로그로 검증되지 않은 진술”입니다. M2에서 도구를 붙인 뒤 같은 프롬프트를 다시 넣어 두 응답을 비교하면, 환각 vs 근거 기반 응답의 차이가 그대로 드러납니다.

  1. AgentCore CLI를 설치하고 버전을 확인합니다.

    Terminal window
    npm install -g @aws/agentcore
    which agentcore # npm 전역 경로(예: /opt/homebrew/bin/agentcore)여야 합니다
    agentcore --version
  2. Bedrock API 키를 환경변수로 준비합니다.

    M0에서 발급한 키를 사용합니다. M1의 판정 티어(Claude Fable 5)는 Bedrock 표준 IAM으로 호출되므로 API 키 자체가 아직 필요하지는 않지만, M2 조사 티어(Luna)를 위해 미리 등록해 둡니다.

    Terminal window
    export BEDROCK_API_KEY="<발급한 키>"
  3. 프로젝트를 생성합니다 (Strands, HTTP, Bedrock 프로바이더, 메모리 없음).

    프로젝트 이름은 영숫자만 허용됩니다 — 하이픈이나 언더스코어를 넣으면 “Project name must start with a letter and contain only alphanumeric characters” 오류가 납니다.

    Terminal window
    agentcore create \
    --name aiopstriageagent \
    --framework Strands \
    --protocol HTTP \
    --model-provider Bedrock \
    --memory none
    cd aiopstriageagent

    실측 출력 원문입니다 — 2026-07-16, us-east-1 기준(합성 데모 값):

    $ agentcore create --project-name aiopstriageagent --name aiopstriageagent \
    --framework Strands --protocol HTTP --model-provider Bedrock \
    --memory none --language Python --build CodeZip --region us-east-1
    ...
    Project created successfully!
    Project directory: ./aiopstriageagent
    Agent name: aiopstriageagent
    Framework: Strands (Python)
    Model provider: Bedrock
    Region: us-east-1
    Next steps:
    1. cd aiopstriageagent
    2. edit app/aiopstriageagent/main.py
    3. agentcore dev --logs
  4. app/aiopstriageagent/main.pylab-src/m1/main.py 내용으로 전체 교체합니다.

    일부만 고치지 말고 파일 전체를 교체해야 합니다. lab-src/m1/main.py의 핵심은 판정 티어 모델 정의입니다.

    # lab-src/m1/main.py 발췌 — 판정 티어 (Claude 계열은 inference profile 필수)
    from strands.models import BedrockModel
    JUDGE_MODEL_ID = "global.anthropic.claude-fable-5" # fallback: global.anthropic.claude-opus-4-8
    AWS_REGION = "us-east-1"
    def build_agent() -> Agent:
    model = BedrockModel(
    model_id=JUDGE_MODEL_ID,
    region_name=AWS_REGION,
    # 실측 기준일 2026-07-16 — Fable 5는 `temperature` 파라미터를 거부합니다
    # (ValidationException: "`temperature` is deprecated for this model.").
    # 파라미터를 지정하지 않고 모델 기본값을 사용합니다.
    )
    return Agent(model=model, system_prompt=SYSTEM_PROMPT)

    SYSTEM_PROMPT는 M2 이후에도 그대로 재사용되는 4대 원칙(자율 탐색 / 직접 확인 우선 / 증거 기반 응답 / 5 Whys)을 담고 있습니다. 전체 내용은 lab-src/m1/main.py 파일을 참고해 주세요.

  5. 의존성에 [openai] extra를 미리 붙여 둡니다.

    app/aiopstriageagent/pyproject.tomldependencies에서 strands-agents 항목을 아래처럼 바꿔 주세요. M1에서는 필수가 아니지만, M2의 OpenAIResponsesModel 도입을 매끄럽게 하기 위해 지금 붙여 둡니다.

    dependencies = [
    "aws-opentelemetry-distro",
    "bedrock-agentcore >= 1.9.1",
    "botocore[crt] >= 1.43.0",
    "mcp >= 1.19.0",
    "strands-agents[openai] >= 1.15.0",
    ]

    의존성을 바꾼 뒤에는 venv를 재생성해야 dev 서버가 새 패키지를 설치합니다.

    Terminal window
    rm -rf app/aiopstriageagent/.venv
  6. Identity token vault에 API 키를 등록합니다 (Runtime 배포용, M2에서 사용).

    Terminal window
    agentcore add credential \
    --name aiops-bedrock-api-key \
    --type api-key \
    --api-key "$BEDROCK_API_KEY"

    실측 출력 원문입니다 — 2026-07-16 (합성 데모 값):

    $ agentcore add credential --name aiops-bedrock-api-key --type api-key --api-key "$BEDROCK_API_KEY"
    ...
    Added credential 'aiops-bedrock-api-key' (type=api-key)
    Provider ARN: arn:aws:bedrock-agentcore:us-east-1:<ACCOUNT>:token-vault/default/apikeycredentialprovider/aiops-bedrock-api-key
    Stored in: AgentCore Identity token vault (ApiKeyCredentialProvider)

    실제 토큰 값은 vault에 저장될 뿐 CLI 출력·로그에 나타나지 않습니다.

  7. 로컬 실행용 .env.local을 작성합니다 (로컬에서는 vault 대신 이 값을 사용합니다).

    Terminal window
    echo "BEDROCK_API_KEY=$BEDROCK_API_KEY" >> agentcore/.env.local
  8. 로컬에서 “도구 없는 응답”을 관찰합니다.

    실측 기준 agentcore dev는 웹 UI 모드로 떠서 8080 포트에 리슨하지 않는 경우가 있으므로, 터미널 1은 반드시 --logs 모드로 띄워 주세요.

    Terminal window
    # 터미널 1 — 런타임 서버(8080) + 로그 출력 (종료: Ctrl+C)
    agentcore dev --logs
    # 터미널 2 — 떠 있는 서버에 프롬프트 전송
    agentcore dev "지난 10분간 동일 IP에서 401 응답이 500회 이상 발생했습니다. 크리덴셜 스터핑인가요?"

    응답을 그대로 저장해 두세요. M2에서 도구가 붙은 뒤 같은 질문에 답하는 응답과 나란히 놓고 비교합니다.

    실측 출력 원문입니다 — 2026-07-16, global.anthropic.claude-fable-5 판정 티어(도구 미부착 상태). latency 39.4s, tokens in 523 / out 1689 (합성 데모 값):

    $ agentcore dev --logs
    [server] listening on http://127.0.0.1:8080 (logs mode)
    [runtime] loaded agent: aiopstriageagent (framework=Strands, provider=Bedrock)
    [runtime] system prompt: 4 principles loaded (autonomous / direct-verify /
    evidence-based / 5 Whys)
    ...
    # (다른 터미널에서)
    $ agentcore dev "지난 10분간 동일 IP 203.0.113.17에서 401 응답이 500회 이상
    발생했습니다. 크리덴셜 스터핑 공격인지 판단해 주세요."
    ### 중요: 도구 접근 제한 고지
    현재 이 세션에서는 로그 조회 도구(query_security_logs, get_waf_blocked_requests
    등)에 접근할 수 없는 상태입니다. 원칙 2(직접 확인 우선)에 따라, 아래 내용은
    로그로 직접 검증된 것이 아니라 알림에 포함된 정보만을 근거로 한 분석임을
    먼저 밝힙니다.
    ...
    ### 2. 판단: 크리덴셜 스터핑인가?
    [추정] 크리덴셜 스터핑일 가능성이 높으나, 아직 확정할 수 없습니다.
    401 대량 발생은 다음 세 가지 시나리오 모두에 부합하기 때문입니다.
    - [추정] 크리덴셜 스터핑
    - [추정] 브루트포스
    - [추정] API 토큰 만료/봇 오작동
    tracking_id: 6d21f367-...

    시스템 프롬프트의 “도구가 없을 때는 그 사실을 먼저 밝힙니다” 지시 덕분에 완전한 환각까지는 가지 않고 [추정] 태그로 정직하게 처리되지만, 로그 근거 없이 시나리오를 나열·서술한다는 M1의 한계는 그대로 드러납니다. M2에서 실제 로그 도구가 붙는 순간 결정이 어떻게 바뀌는지 나란히 두고 보게 됩니다.

  9. AgentCore Runtime에 배포합니다.

    Terminal window
    agentcore deploy

    첫 실행 시 Identity Provider Setup 프롬프트가 뜹니다 — “How would you like to provide the credentials?” 질문에 방향키로 Use credentials from .env.local 을 선택하면 Step 7의 .env.local의 API 키가 Identity provider에 연결됩니다.

  10. 배포된 에이전트를 호출합니다.

    Terminal window
    agentcore invoke '{"prompt": "동일 IP에서 401 응답 500회 발생. 대응 절차를 알려주세요."}'

    이 응답도 M2와의 비교를 위해 저장해 두세요.

무슨 일이 일어났나 — CodeZip에서 Runtime까지

섹션 제목: “무슨 일이 일어났나 — CodeZip에서 Runtime까지”

agentcore deploy 한 줄 뒤에서 일어난 일을 요약하면 다음과 같습니다.

  1. 패키징 (CodeZip) — 에이전트 코드와 의존성이 CodeZip 아티팩트로 패키징되어 S3 CDK staging 버킷에 업로드됩니다.
  2. 인프라 생성 (CDK) — CLI가 CDK로 CloudFormation 스택을 합성·배포합니다. IAM 실행 롤과 CloudWatch 로깅(/aws/bedrock-agentcore/runtimes/{agent-id}-DEFAULT)이 이때 구성됩니다.
  3. Runtime 엔드포인트 — AgentCore Runtime에 에이전트 엔드포인트가 만들어지고, agentcore invoke(또는 SDK의 invoke_agent_runtime)로 호출할 수 있게 됩니다. agentcore status로 ARN과 상태를 확인할 수 있습니다.

이 단계가 끝나면 다음이 보여야 합니다.

  • 로컬 agentcore dev --logs 서버가 401 폭증 질문에 그럴듯한 응답을 반환합니다 — 이 응답은 M2에서 대비쌍으로 사용됩니다.
  • agentcore deploy가 성공하고, agentcore status에서 Runtime의 agent-id와 ARN이 확인됩니다. agent-id는 M4의 세션 스팬 조회에서 다시 사용하니 반드시 기록해 두세요.
  • Identity token vault에 aiops-bedrock-api-key가 등록되어 있습니다 — M2 조사 티어(Luna) 호출에 사용됩니다.

다음은 M2. 도구 연결과 4단계 조사입니다.