엔지니어 약 50명이 AWS 계정 약 30개에 걸쳐 일하는 중견 B2B SaaS 기업에서는 매주 약 40건의 온콜 페이지가 발생하고, 담당자가 실제 답을 얻기까지는 어느 계정인지, 어느 대시보드인지, 어느 런북인지, 그 런북이 아직도 맞는 내용인지를 수작업으로 확인하는 데만 25분에서 35분이 걸린다. 이것은 진단이 시작되기 전 단계이지, 진단을 대체하는 것이 아니다. 이 시리즈는 그 해결책을 만든다. 이 첫 단계를 자동으로 처리하고, 허용된 범위 안에서 모든 것을 읽되, 사람의 승인 없이는 아무것도 바꾸지 않으며, 그 규율을 잃는 순간 쓸모를 잃는 작은 AI 에이전트 플랫폼이다.

이 회사, 그리고 실제로 치르고 있는 잡무의 비용

이 회사를 있는 그대로 부르자면 중견 B2B SaaS 업체다. 엔지니어는 약 50명, AWS 계정은 여러 제품 라인에 걸쳐 약 30개이며, 각 라인마다 개발, 스테이징, 프로덕션 3종 세트를 따로 두고 있다. 처음부터 계정 30개를 목표로 삼은 팀은 없다. 팀 하나하나가 격리를 요청하는 평범한 과정이 쌓이면서, AWS Organizations 구조가 아키텍처보다 조직도를 더 많이 반영하게 된 결과다.

이 잡무는 극적이지 않다. 대신 누적된다. 3개월치 온콜 데이터와 불편했던 회고 한 번에서 나온 숫자 네 개가 그 모양을 분명하게 보여준다.

  • 매주 약 40건의 페이지가 로테이션 담당자에게 도착하며, 30개 계정에 고르지 않게 분산되어 있다.
  • 25분에서 35분은 진단이 시작되기도 전에 컨텍스트를 모으는 데 쓰인다. 올바른 계정, 올바른 대시보드, 올바른 런북을 찾고, 그 런북이 아직 실제와 맞는지 확인하는 시간이다.
  • 월간 FinOps 리뷰는 실제 지출보다 약 3주 뒤처져 있어서, 잘못 설정된 오토스케일링 그룹이나 유휴 GPU 인스턴스가 누군가 읽는 리포트에 나타나기까지 거의 한 달 동안 비용을 태운다.
  • 최근 런북 감사에서는 세 개 중 하나꼴로 런북이 더 이상 존재하지 않는 리소스, ARN, 콘솔 경로를 가리키고 있었다.

이 네 가지 중 어느 것도 그 자체로 비상사태는 아니다. 하지만 합쳐지면 팀에게 상시로 부과되는 세금이 된다. 매주 약 30에서 40 엔지니어 시간이 컨텍스트를 모으고 낡은 지침을 다시 검증하는, 운영의 기계적인 부분에 쓰인다. 그리고 그 비용을 치르는 사람들은 사람 컨텍스트 조립기가 아니라 제품을 만들라고 고용된 이들이다.

왜 에이전트인가, 그리고 왜 지금인가

"왜 지금인가"에 대한 솔직한 답은, 필요한 부품들이 이제야 누군가 계속 돌봐야 하는 사내 프레임워크가 아니라 관리형 서비스로 존재하게 되었기 때문이다. Bedrock은 2023년 11월 일반 공급(GA)에 도달한 이래 관리형 에이전트 오케스트레이션 서비스인 Agents for Amazon Bedrock을 제공해왔고, 이후 오케스트레이션 제어와 추론 트레이스 가시성이 개선되었다. 바뀐 것은 그 위 단계다. Amazon Bedrock AgentCore는 2025년 10월 13일 9개 리전에서 일반 공급되었으며, 예전 같으면 처음부터 직접 만들어야 했던 세션 스토어, 자격 증명 브로커, 트레이싱 파이프라인을 Runtime, Memory, Identity, Gateway, Code Interpreter, Browser, Observability라는 7개 구성 서비스로 패키징했다. 동시에 AWS는 2025년 5월 Strands Agents SDK를 Apache 2.0으로 오픈소스화했고, 이 글의 타임라인이 시작되기 일주일 전인 2026년 5월 21일 Python용 프로덕션 1.0 릴리스를 출시했다. 관리형 인프라와 오픈 오케스트레이션 레이어가 같은 몇 개월 사이에 나란히 프로덕션 준비 기준을 통과한 것이다. 이 플랫폼이 만들어진 것은 바로 그 시기다.

직접 구축할 것인가, 사서 쓸 것인가

팀은 마땅히 그래야 하듯 먼저 구매 옵션을 검토했다. 기성 AIOps나 인시던트 코파일럿 제품이었다면 더 빨리 출시할 수 있었고 Terraform도 필요 없었을 것이다. 하지만 세 가지 이유로 탈락했는데, 이는 에이전트 일반의 문제가 아니라 이 회사만의 사정이었다.

  • 변경 경계는 협상 대상이 아니다. 수정을 실행하는 주체는 반드시 해당 계정 안에서 좁게 범위를 지정한 IAM 역할을 어썸(assume)해야 하고, 내부 승인 단계를 거쳐야 한다. SaaS 제품을 쓰면 광범위한 크로스 계정 접근 권한을 내주거나, 아니면 나중에 자체 승인 플로우를 억지로 끼워 맞춰야 한다. 플랫폼을 직접 소유한다는 것은 승인 게이트가 나중에 통합되는 것이 아니라 처음부터 네이티브로 존재한다는 뜻이다.
  • 계정 30개 분량의 암묵지는 Slack 스레드와 엔지니어들의 머릿속에 있지, 벤더의 수집 파이프라인이 이해할 수 있는 형태로 존재하지 않는다. 기존 런북 코퍼스 위에 Bedrock Knowledge Base를 두고 팀이 청킹과 검색 품질을 직접 통제하는 편이, 그 지식을 제3자에게 넘기고 그쪽의 검색 품질이 충분하기를 바라는 것보다 다루기 쉽다.
  • 회사는 이미 이 규모로 AWS를 운영하고 있다. Terraform, CI, 온콜 로테이션, 계정 구조 모두 이미 존재한다. AWS 네이티브 프리미티브 위에 구축하는 한계 비용은, 두 번째 벤더 관계와 두 번째 청구 항목과 두 번째 보안 검토를 두는 비용보다 낮다.

반론도 타당하다. 구매가 더 빠르고, 잡무가 매주 누적되는 상황에서는 빠른 것도 가치가 있다. 팀의 답은 이것을 플랫폼팀의 영원한 프로젝트로 취급하는 대신, 구축 범위를 빡빡하게 잡는 것이었다(에이전트 4개, 승인 패턴 1개, 처음에는 온디맨드 추론. 사이징 계산은 이후 편에서 다룬다). 시리즈 전체의 동반 코드는 github.com/flightlesstux/agents-on-call에 있으며, 이 글은 그 저장소의 docs/architecture.md가 시작되는 지점이다.

스택 결정: Bedrock에서 에이전트를 실행하는 세 가지 방법

구축하기로 결정한 다음 질문은 어느 레이어 위에 지을 것인가였다. 실제로 존재하는 옵션은 세 가지였고, 그 트레이드오프는 "가장 최신 것을 써라"처럼 단순하지 않았다.

항목Bedrock Agents (클래식)AgentCore + StrandsConverse API로 직접 구축
직접 소유하는 부분콘솔에서 정의하는 액션 그룹, 오케스트레이션은 AWS 소관관리형 런타임, 아이덴티티, 메모리, 게이트웨이. 에이전트 루프는 여러분의 Python 코드전부: 루프, 재시도, 메모리, 도구 라우팅, 트레이싱
현재 시점 성숙도2023년 11월부터 GA, 가장 오래된 트랙 레코드2025년 10월 13일부터 GA, 약 7개월의 프로덕션 사용 이력여러분 자신의 코드만큼 성숙, 그 이상은 아님
모델·프로바이더 이식성Bedrock 모델만Bedrock, Anthropic 다이렉트, Ollama, LiteLLM로 프록시되는 프로바이더직접 연결하는 대로
프레임워크 종속높음: 오케스트레이션 로직이 Bedrock의 액션 그룹 형식 안에 있음낮음: Strands는 Apache 2.0 Python이며, Amazon이 Q Developer, AWS Glue, VPC Reachability Analyzer에 내부적으로 쓰는 것과 같은 SDK없음, 대신 도움도 없음
도구 통합OpenAPI 스키마로 정의하는 액션 그룹AgentCore Gateway가 API, Lambda 함수, 기존 서비스를 MCP 호환 도구로 바꿔줌. MCP 자체는 2024년 11월부터 오픈 표준Converse API에 대해 직접 짠 도구 호출
관측 가능성내장된 추론 트레이스, 내보내는 방식에 대한 제어는 제한적OTEL 트레이스를 CloudWatch 생성형 AI 관측 가능성으로, 직접 만든 대시보드 위에서직접 계측하는 대로
Terraform 지원오래전부터 있던 액션 그룹 리소스2025년 10월 16일부터 네이티브 aws_bedrockagentcore_* 리소스 제공, JSON 형태의 속성 맵 대신 제대로 된 HCL 중첩 블록서비스 전용 리소스 불필요, IAM과 컴퓨트만 있으면 됨
가장 적합한 상황단순한 에이전트 소수, 커스텀 오케스트레이션을 최소로 원할 때루프 제어가 필요한 다중 에이전트, 멀티 프로바이더를 염두에 둔 미래어떤 프레임워크로도 잘 표현되지 않을 만큼 특화된 오케스트레이션

팀은 AgentCore와 Strands 조합을 선택했다. 직접 소유하고 싶지 않았던 관리형 부품들(세션 격리, 자격 증명 브로커링, 크로스 계정 게이트웨이)이, 콘솔에서 리버스 엔지니어링해야 하는 것이 아니라 직접 읽고 디버깅할 수 있는 오케스트레이션 레이어와 함께 딸려왔다. GA 시점의 AgentCore Runtime은 각 에이전트 세션에 완전한 격리와 8시간짜리 실행 윈도우를 제공하며, 이 플랫폼의 에이전트가 언젠가 플랫폼 바깥의 에이전트와 대화할 필요가 생기면 Agent2Agent 프로토콜 지원도 갖추고 있다. 2026년 4월 22일 출시된 @aws/agentcore CLI는 create, dev, deploy, invoke, logs, traces 워크플로를 Strands에 바로 지원하며(LangGraph, LangChain, Google ADK, OpenAI Agents, 직접 만든 것도 지원), 이는 온보딩에서 중요했다. 프로젝트 도중에 새로운 배포 도구를 새로 배울 필요가 없었기 때문이다.

클래식 Bedrock Agents도 나름의 장점으로 진짜 매력적이었다. 2년 반의 프로덕션 트랙 레코드, 직접 소유할 커스텀 코드가 적다는 점, 액션 그룹 하나로 충분한 유스케이스에서의 단순한 사고 모델이 그것이다. 여기서 탈락한 이유는, 하드한 다중 계정 IAM 경계를 가로질러 슈퍼바이저 패턴을 공유하는 에이전트 4개가 액션 그룹이 노출하는 것보다 더 많은 루프 제어를 필요로 했기 때문이다. Converse API 위에 직접 구축하는 방식은 정반대 이유로 배제되었다. AWS가 이미 AgentCore Runtime, Memory, Identity, Observability로 제공하는 것을, 세션 스토어와 자격 증명 브로커와 트레이싱 파이프라인을 처음부터 직접 만들어 재현하는 데는, 프로젝트 첫 두 달을 에이전트를 작성하는 대신 인프라를 재발명하는 데 써버렸을 것이다.

목표 아키텍처: 조직 전체에 걸친 허브 앤 스포크

이 플랫폼은 다중 계정, 허브 앤 스포크 구조이며, 의도적으로 추가적(additive)이다. 플랫폼이 다운되면 조직은 정확히 기존 상태로 되돌아간다. 사람들은 늘 하던 대로 페이지를 받는다. 이 플랫폼은 결코 중요 알림 경로 위에 놓이지 않는다.

graph TD
  MGMT["management account
org root, SCPs, no workloads"] SEC["security account
org CloudTrail, GuardDuty,
Security Hub delegated admin"] OPS["ops-tooling account
the agent platform"] W1["workload account 1"] W2["workload account 2"] WN["workload account N
~30 total"] MGMT -. SCPs .-> SEC MGMT -. SCPs .-> OPS MGMT -. SCPs .-> W1 MGMT -. SCPs .-> W2 MGMT -. SCPs .-> WN W1 -- alarm events --> OPS W2 -- alarm events --> OPS WN -- alarm events --> OPS OPS -- "assume ops-readonly, read-only tools" --> W1 OPS -- "assume ops-readonly, read-only tools" --> W2 OPS -- "assume ops-readonly, read-only tools" --> WN OPS -. "assume ops-mutate, approved executor only" .-> W1

각 워크로드 계정은 ops-tooling에 정확히 두 개의 역할만 노출한다. ops-readonly는 모든 도구 Lambda가 어썸할 수 있으며, AWS 읽기 전용 관리형 정책 위에 명시적 거부(deny)를 겹쳐 쌓아 만든다. ops-mutate는 정확히 하나의 Lambda만 어썸할 수 있는데, 사람이 제안된 작업을 승인한 뒤에만 실행되는 그 Lambda는 특정 SSM Automation 문서들의 허용 목록으로 범위가 제한되어 있다. 그 어떤 에이전트도, 다른 어떤 Lambda도, 그 단일한 승인 후 실행자를 제외한 어떤 코드 경로도 ops-mutate를 어썸할 수 없다. 읽기 전용을 기본값으로 만드는 것은 프롬프트 지시가 아니라 바로 이 분리다. 모델에게 정중히 부탁해서가 아니라 IAM으로 강제된다.

ops-tooling 내부

이 시리즈의 나머지 부분이 살아가는 그 하나의 계정을 확대해서 보자.

graph LR
  subgraph entry["Entry"]
    EB["EventBridge bus
cross-account alarms"] SLACK["Slack app
API Gateway + verifier Lambda"] SCHED["EventBridge Scheduler
daily cost sweep"] end subgraph agents["Agent layer"] SUP["supervisor"] TRI["incident-triage"] RUN["runbook"] COST["cost"] MEM["AgentCore Memory"] ID["AgentCore Identity"] end subgraph models["Model layer"] BR["Bedrock, cross-region
inference profiles"] GR["Bedrock Guardrails"] KB["Knowledge Base
runbook corpus"] end subgraph tools["Tool layer"] GW["AgentCore Gateway"] T1["cloudwatch-read"] T2["logs-read"] T3["cost-read"] T4["ssm-execute"] end subgraph gate["Approval gate"] SF["Step Functions
waitForTaskToken"] EXEC["post-approval executor"] end subgraph obs["Observability"] OTEL["OTEL traces to CloudWatch
GenAI observability"] LOG["invocation logs to S3"] BUD["Budgets + Cost
Anomaly Detection"] end EB --> SUP SLACK --> SUP SCHED --> COST SUP --> TRI SUP --> RUN SUP --> COST TRI --> MEM RUN --> MEM COST --> MEM SUP --> ID TRI --> BR RUN --> BR COST --> BR BR --> GR TRI --> KB RUN --> KB SUP --> GW GW --> T1 GW --> T2 GW --> T3 GW --> T4 T4 --> SF SF -- "context + Slack approval" --> SLACK SF -- approved --> EXEC BR --> OTEL GW --> LOG COST --> BUD

AgentCore Runtime 위에서 슈퍼바이저 뒤에 놓인 Strands 에이전트 4개가 실행된다. 인시던트 트리아지, 런북 실행, 비용 최적화다. AgentCore Memory는 세션과 장기 상태를 보관해서 슈퍼바이저가 매 홉마다 스페셜리스트에게 컨텍스트를 다시 설명하지 않아도 되게 하고, AgentCore Identity는 아웃바운드 자격 증명을 브로커링해서 어떤 에이전트의 코드에도 장기 유효한 시크릿이 들어 있지 않게 한다. 모든 모델 호출은 안정성과 버스트 여유를 위해 크로스 리전 추론 프로필을 거치며, 모든 호출에는 Bedrock Guardrails가 붙고, 런북 코퍼스 위의 Knowledge Base가 트리아지와 런북 에이전트를 뒷받침한다. 도구 레이어는 전부 AgentCore Gateway로 되어 있다. MCP 뒤에 있는 최소 권한 Lambda들 중 셋은 읽기 전용으로 스포크 안에서 ops-readonly를 어썸하고, 나머지 하나인 ssm-execute만 유일하게 변경 작업을 수행하는데, 이 도구는 스포크 계정에 직접 접근할 수 없다. 오직 Step Functions에 제안을 넘길 수 있을 뿐이며, Step Functions는 waitForTaskToken에서 멈추고 전체 컨텍스트(진단 내용, 영향 범위, 정확한 SSM 문서와 파라미터)를 Slack에 게시한 뒤 사람이 승인해야만 재개된다. EventBridge에서 Gateway까지 모든 홉은 OTEL 트레이싱을 CloudWatch 생성형 AI 관측 가능성으로 실어 나르고, Bedrock 호출 로그는 S3에 쌓이며, Budgets와 Cost Anomaly Detection이 에이전트별 비용 할당 태그로 플랫폼 자체의 지출을 감시한다.

읽기 전용이 최우선 지침이다

이 플랫폼의 모든 에이전트는 관련된 모든 것을 볼 수 있지만, 사람이 이미 승낙하지 않는 한 아무것도 바꿀 수 없다. 이것이 이 시리즈의 나머지 부분이 계속 지켜야 할 단 한 문장이다. 이는 하나의 영리한 메커니즘이 아니라 세 가지 개별적이고 화려하지 않은 IAM 결정으로 드러난다. 도구 Lambda들은 AWS 관리형 정책 위에 명시적 거부를 쌓아 만든 읽기 전용 역할을 어썸한다는 것, 유일하게 변경 작업을 수행하는 도구는 스포크 계정에서 그 무엇도 직접 어썸할 수 없다는 것, 그리고 "에이전트가 수정을 제안했다"에서 "그 수정이 실행되었다"로 가는 유일한 경로가 오직 사람의 Slack 클릭으로만 재개되는 Step Functions 대기 상태를 통과한다는 것이다.

읽기 전용은 모델에게 조심하라고 이르는 프롬프트 지시가 아니다. 정중히 부탁받은 모델도 가끔은 조심스럽지 않다. 여기서 읽기 전용은 침해된 프롬프트도, 환각으로 만들어낸 도구 호출도, 단순한 버그도 넘을 수 없는 IAM 경계다. 그것을 넘을 자격 증명이 에이전트가 손댈 수 있는 어디에도 존재하지 않기 때문이다.

완성된 모습

이 시리즈의 마지막 편은 다시 이 숫자들로 돌아온다. 앞서 정리한 잡무 목록을 측정 가능하게 만든 숫자들이다.

  • 페이지 발생부터 보강된 Slack 요약(로그, 대시보드, 가능성 있는 원인)까지의 중앙값 시간이 현재의 수작업 수집 25에서 35분에서 5분 미만으로 줄어든다.
  • Step Functions에 기록된 사람의 승인 없이는 변경 작업이 단 하나도 실행되지 않으며, 이는 매주 CloudTrail로 검증된다.
  • 월간 FinOps 지연은 약 3주에서 당일로 줄어든다. 일일 비용 스윕이 다음 청구 주기가 마감되기 전에 이상 징후를 드러내기 때문이다.
  • 런북의 노후화(깨진 ARN, 죽은 콘솔 경로)는 약 3분의 1에서 20분의 1 미만으로 줄어들며, 연례 감사가 아니라 지속적으로 잡아낸다.
  • 분기별 게임 데이가 ops-tooling을 완전히 비활성화해서, 페이징과 수동 런북 실행이 플랫폼이 존재하기 전과 정확히 똑같이 작동하는지, 은밀한 의존성이 생기지 않았는지 확인한다.
  • 인시던트 트리아지의 진단이 최종 근본 원인과 충분히 자주 일치해서(이후 편에서 정의할 평가 하네스의 수치 임계값으로 측정한다), 온콜 담당자가 조치하기 전에 수작업으로 재검증하는 일을 멈추게 된다.

첫날부터 지켜봐야 할 실패 모드

누군가 Terraform을 건드리기 전에 지켜봐야 할 것이 세 가지 있다. 시나리오를 짜는 이 단계는 프로덕션에서 이런 것들을 뒤늦게 발견하기에는 잘못된 장소이기 때문이다. 읽기 도구가 스포크 계정에 도달하지 못하면, 역할 어썸이 거부되었든 서비스가 저하되었든, 에이전트는 추측하지 말고 그렇다고 말한 뒤 사람에게 넘겨야 한다. 자신 있게 말한 틀린 진단은 진단이 없는 것보다 나쁘다. 승인 게이트 자체가 멈춘다면, 대기 상태와 그것을 감싸는 스테이트 머신 모두에 명시적 타임아웃이 필요하다. 그렇지 않으면 멈춘 제안이 요란하게 실패하는 대신 조용히 늙어간다. 그리고 ops-tooling이 완전히 다운되면, 플랫폼은 정확히 오늘의 프로세스로 되돌아가야 하는데, 이것은 ops-tooling 바깥의 그 무엇도 그것이 존재한다는 사실에 은밀하게 의존하기 시작하지 않을 때만 성립한다.

다음으로 읽을 글

  • Part 2, The Foundation: Terraform Before Tokens, 위 계정 레이아웃이 실제 HCL로 바뀌는 편이다. IAM 베이스라인, Bedrock 모델 접근, 온디맨드 대 프로비저닝드 대 크로스 리전 추론 결정을 다룬다.
  • AWS Multi-party Approval for Organizations (ercan.cloud), 같은 "위험한 작업을 사람들의 정족수 뒤에 가두기" 패턴을 에이전트 쪽이 아니라 순수 AWS Organizations 쪽에서 다룬다.

위의 두 다이어그램과 그것이 설명하는 계정 및 IAM 레이아웃은, 이 시리즈가 편마다 만들어가는 Terraform과 Python 옆에, 동반 저장소인 github.com/flightlesstux/agents-on-call에도 Markdown 형태로 있다. 이런 종류의 플랫폼을 대규모로 운영할 때의 데이터베이스와 인프라 쪽 이야기는 ercan.cloud에, 허브는 ercanermis.com에 있다.