액션 경계(The Action Boundary): AI 에이전트를 위한 실용적인 안전 패턴
요약
AI 에이전트가 외부 효과를 발생시키는 지점에서 발생할 수 있는 위험을 방지하기 위한 '액션 경계(Action Boundary)' 패턴을 소개합니다. 제안, 승인, 실행, 중단이라는 명시적 상태를 도입하여 에이전트의 동작을 안전하게 제어하는 방법을 다룹니다.
핵심 포인트
- 프롬프트 기반 제어 대신 명시적인 상태(PROPOSED, APPROVED 등)를 통한 제어 권장
- 자유 형식의 텍스트 대신 구조화된 데이터(dataclass 등)를 사용하여 명령 모델링
- 실행 전 읽기 전용 뷰를 통해 제안된 액션의 정확성을 검증하는 단계 필수
- 불변하는 제안(Immutable Proposal)을 참조하도록 설계하여 보안 경계 강화
AI 에이전트에서 가장 중요한 선은 프롬프트(prompt)가 아닙니다. 그것은 프로그램이 제안을 외부 효과(external effect)로 전환하는 지점입니다.
그 선 이전에는 시스템이 분류(classify), 요약(summarize), 비교(compare), 제안(propose)을 할 수 있습니다. 그 이후에는 시스템이 답장을 보내거나, 티켓을 수정하거나, 배포를 업데이트하거나, 콘텐츠를 게시하거나, 데이터를 삭제할 수 있습니다. 양쪽 모두를 중단 없는 하나의 "에이전트 루프(agent loop)"로 취급하면 검토가 어려워지고 실패 비용이 커집니다.
이 튜토리얼은 PROPOSED(제안됨), APPROVED(승인됨), EXECUTED(실행됨), STOPPED(중단됨)라는 네 가지 명시적인 상태를 가진 작은 액션 경계(action boundary)를 구축합니다. 이 패턴은 의도적으로 단순하게 설계되었습니다. 이는 LLM과 거의 모든 도구 어댑터(tool adapter) 사이에 위치할 수 있습니다.
방지하고자 하는 실패부터 시작하십시오
이슈를 읽고 있는 배포 어시스턴트(deployment assistant)를 상상해 보십시오:
스테이징 상태 확인(staging health check)이 정상(green)입니다. 이전 이미지를 사용하여 고장 난 프로덕션 릴리스를 롤백(roll back)해 주세요.
해당 이슈에는 다른 서비스를 명시하는 오래된 로그 라인이 포함되어 있습니다. 모델은 롤백 도구(rollback tool)를 선택하고, 인증된 리포지토리 컨텍스트(authenticated repository context) 대신 로그에 있는 서비스 이름을 사용합니다. 명령은 구문적으로 유효합니다. 잘못된 서비스가 성공적으로 롤백됩니다.
프롬프트에 "주의하세요"를 추가하는 것은 신뢰할 수 있는 제어 장치를 만들지 못합니다. 시스템에는 타입이 지정된 대상(typed target), 정책 확인(policy check), 최종 제안에 결합된 승인(approval), 그리고 일치하지 않는 컨텍스트를 거부하는 도구가 필요합니다.
명령 대신 제안을 모델링하십시오
자유 형식의 모델 텍스트를 쓰기 권한이 있는 도구에 직접 전달하지 마십시오. 이를 작은 구조체로 변환하십시오:
from dataclasses import dataclass, asdict
from enum import StrEnum
from hashlib import sha256
...
다이제스트(digest) 그 자체로는 보안 경계(security boundary)가 아닙니다. 그것의 목적은 하나의 승인이 하나의 불변하는 제안(immutable proposal)을 참조하도록 만드는 것입니다. 인증(Authentication)과 인가(authorization)는 여전히 주변 애플리케이션과 도구 어댑터의 영역입니다.
첫 번째 구현은 읽기 전용으로 유지하십시오
execute()를 구현하기 전에, ActionProposal을 렌더링하는 뷰(view)를 구축하십시오. 이를 피스처(fixture) 또는 읽기 전용 엔드포인트(read-only endpoint)에 연결하십시오. 사용자에게 다음 사항을 확인하도록 요청하십시오:
- 대상(target)이 모호하지 않은가?
- 현재 상태(current state)가 정확한가?
- 제안된 상태(proposed state)가 정확한가?
- 근거(source evidence)가 관련성이 있는가?
- 어떤 점이 이 액션(action)을 거부하게 만드는가?
이 단계에서는 모델에 필요한 식별자(identifier)가 부족하거나 소스 데이터(source data)가 모호하다는 사실이 자주 드러납니다. 미리보기(preview) 단계에서 이러한 문제를 발견하는 것은 API 응답이 성공한 이후에 발견하는 것보다 훨씬 비용이 적게 듭니다.
신뢰할 수 없는 텍스트를 권한(authority)으로부터 격리하십시오
티켓(Tickets), 문서, 웹 페이지 및 도구 응답(tool responses)에는 공식적으로 보이지만 실제로는 그렇지 않은 지침이 포함되어 있을 수 있습니다. 이를 데이터 필드에 넣고 출처(source)를 표시하십시오. 허용된 액션(allowed actions), 대상 범위(target scopes) 및 권한 규칙(permission rules)은 신뢰할 수 있는 설정(configuration)에서 가져와야 합니다.
도구 어댑터(tool adapter)는 이미 인가(authorization)를 통과한 타입화된 대상(typed target)을 전달받아야 합니다. 어댑터는 자격 증명(credential)을 별도로 획득해야 합니다. 모델이 배포(deployment)를 제안하기 위해 배포 키(deployment key)를 읽을 필요는 없습니다.
자격 증명 별칭(credential alias)이나 권한 범위(permission scope)를 로그에 기록하되, 자격 증명 값(credential value)은 절대 기록하지 마십시오. 프롬프트(prompts)에는 복사된 개인 데이터가 포함될 수 있으므로, 전체 프롬프트를 로그에 덤프(dump)하는 것을 피하십시오.
승인(approval)을 정밀하게 만드십시오
확인 대화 상자(confirmation dialog)는 execute()가 사용할 것과 동일한 제안(proposal)을 보여주어야 합니다. 다음 내용을 포함하십시오:
- 대상(target) 및 환경(environment);
- 관찰된 현재 버전(observed current version);
- 요청된 버전(requested version);
- 출처 참조(source reference);
- 가역성(reversibility);
- 정확한 부작용(exact side effect).
미리보기 이후에 어떤 필드라도 변경된다면, 새로운 다이제스트(digest)를 계산하고 새로운 승인을 요청하십시오. 오래된 승인이 수정된 대상을 인가하도록 허용해서는 안 됩니다.
위험도가 낮은 읽기(reads)의 경우 승인은 불필요합니다. 운영 환경의 쓰기(production write)의 경우, 승인 주체(approval actor)에게 특정 역할(role)이 필요할 수 있습니다. 해당 정책은 모델 외부에 유지하십시오.
해피 패스(happy path) 이전에 재시도(retries)를 설계하십시오
예시의 멱등성 키(idempotency key)는 흔히 발생하는 불확실성, 즉 클라이언트가 타임아웃(timeout)되는 동안 서버가 작업을 완료할 수 있는 상황으로부터 보호합니다. 재시도(retry) 시에는 효과를 반복하는 대신 저장된 결과를 반환할 수 있습니다.
네트워크 시도가 아닌, 의도된 작업(operation)을 위한 멱등성 키를 선택하십시오. 플랫폼에서 반환된 외부 참조(external reference)를 저장하십시오. 구조화된 로그(structured logs)에 작업 키(operation key), 제안 다이제스트(proposal digest), 승인 주체(approval actor), 시도 횟수(attempt count), 그리고 결과 상태(result status)를 포함하십시오.
기본적으로 전체 입력을 로그에 남기지 마십시오. 개인적인 페이로드(payloads)와 자격 증명(credentials)은 제외하면서, 제어 흐름(control flow)을 재구성할 수 있을 만큼의 정보만 기록하십시오.
실제 정지 상태(stop state)를 추가하십시오
STOPPED 상태는 새로운 코드를 배포하지 않고도 도달할 수 있어야 합니다. 서킷 브레이커(circuit breaker)를 사용하면 읽기 전용 제안(read-only proposals)은 유지하면서 쓰기 어댑터(write adapters)를 비활성화할 수 있습니다.
유용한 트리거(triggers)는 다음과 같습니다:
- 대상 버전 불일치(target version mismatch);
- 임계값을 초과하는 유효성 검사 실패(validation failures);
- 반복되는 권한 부여 오류(authorization errors);
- 플랫폼 경고(platform warnings);
- 알 수 없는 대상 유형(unknown target types);
- 너무 많은 재시도(too many retries);
- 롤백(rollback) 정보 누락.
정지 경로(stop path)를 테스트하십시오. 아무도 실행해 본 적 없는 설정 플래그(configuration flag)는 통제 수단이 아니라 희망 사항일 뿐입니다.
복구 지침을 작성하십시오
일부 작업은 되돌릴 수 있습니다. 이전 값을 저장하고, 복구(restore)하기 전에 롤백 대상이 여전히 일치하는지 확인하십시오.
다른 작업들은 되돌릴 수 없습니다(irreversible). 메시지 전송을 취소하거나 공개 게시물이 나타났다는 사실을 지울 수는 없습니다. 이 경우 복구란 시퀀스(sequence)를 중단하고, 영향을 받은 대상(targets)을 식별하며, 책임 있는 사람에게 알리고, 수정 사항을 준비하는 것을 의미합니다.
이를 작업 정의(operation definition) 옆에 기록해 두십시오. 진정한 롤백이 불가능하다면 더 강력한 승인 규칙(approval rule)이 정당화될 수 있습니다.
전체 체인을 검토하십시오
유용한 운영 전 검토(pre-production review)는 입력부터 효과에 이르기까지의 액션을 따릅니다:
- 신뢰할 수 없는 콘텐츠가 라벨링된 데이터 (labeled data)로 유입됩니다;
- 모델이 타입이 지정된 제안 (typed proposal)을 생성합니다;
- 검증 (validation) 단계에서 필수 필드와 대상 범위 (target scope)를 확인합니다;
- 사용자가 정확한 제안 내용을 확인합니다;
- 승인 (approval)은 제안 다이제스트 (proposal digest)에 결합됩니다;
- 어댑터 (adapter)가 현재 상태와 권한 (authorization)을 확인합니다;
- 멱등성 키 (idempotency key)가 중복 실행을 방지합니다;
- 구조화된 로그 (structured logs)가 결정 사항을 기록합니다;
- 중단 및 복구 경로 (stop and recovery paths)가 사용 가능한 상태로 유지됩니다.
이는 도구를 직접 호출하는 것보다 더 많은 작업이 필요합니다. 하지만 이는 무언가 실패했을 때 검사하고, 테스트하고, 개선할 수 있는 설계 방식이기도 합니다.
공개 사항: 저는 아래의 무료 체크리스트를 관리하고 있습니다. 여기에는 AI 지원 어시스턴트가 답변해도 되는지, 인간의 검토가 필요한지, 또는 반드시 에스컬레이션 (escalate)해야 하는지를 결정하기 위한 합성 케이스 (synthetic cases)들이 포함되어 있습니다. 이 라우팅 모델 (routing model)은 여러분만의 액션 경계 (action boundary)를 테스트하기 위한 유용한 시작점입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기