지출 규칙이 존재하는 곳: AWS 대 Sui에서의 에이전트 권한 부여 비교
요약
본 글은 자율 에이전트에게 지출 권한을 부여할 때 발생하는 위험성을 다루며, AWS AgentCore Payments와 Sui Move 모듈의 접근 방식을 비교합니다. AWS는 오프체인 서비스 계층에서 규칙을 처리하는 반면, Sui는 온체인 타입 시스템과 Move 런타임에 예산 및 지출 한도를 강제하여 '규칙 신뢰'라는 공통 목표를 달성하지만 구현 방식이 완전히 다릅니다.
핵심 포인트
- 자율 에이전트에게 지갑을 주는 것은 비결정론적 위험을 초래할 수 있습니다.
- AWS는 오프체인 서비스 계층에서 예산 및 권한을 관리합니다.
- Sui는 온체인 타입 시스템과 Move 런타임에 지출 규칙을 구현하여 강제성을 높입니다.
지출 규칙이 존재하는 곳: AWS 대 Sui에서의 에이전트 권한 부여
당신에게 돈을 지불할 수 있는 봇은 당신을 고갈시킬 수도 있습니다.
그 문장이 전체 문제입니다. 자율 에이전트에게 지갑을 주는 순간, 비결정론적 프로세스(non-deterministic process)에 돈을 움직일 능력을 넘겨준 것입니다. 흥미로운 실패 모드는 에이전트가 느리다는 것이 아닙니다. 에이전트가 틀렸거나, 혼란스럽거나, 혹은 3번의 도구 호출 전에 읽은 오염된 웹 페이지에 의해 조용히 유도되어 결제해서는 안 되는 지불을 서명하는 것입니다.
제가 읽었던 Basecamp 커버리지 중 상당 부분은 처리량(throughput)에 초점을 맞추었습니다. 그리고 네, 헤드라인 숫자가 있었습니다: CertiK에서 검증한 40,614,180 TPS였습니다. 그 주장의 정확한 버전이 중요합니다. 왜냐하면 대부분의 요약본들이 그것을 건너뛰기 때문입니다. 그것은 베이스 레이어(base-layer), 온체인 처리량이 아니었습니다. 그것은 수만 개의 병렬 터널을 가진 오프체인 'Sui tunnels' 에이전트 시뮬레이션 스트레스 테스트였으며, 그 결과는 메인넷에 정산되었습니다. 인상적이지만, 이는 '에이전트가 얼마나 빨리 거래할 수 있는가?'라는 질문에 답하며, 그것은 어려운 질문이 아닙니다.
어려운 질문은 권한 부여(authorization)입니다. 에이전트가 지출하도록 허용될 때, _누가 또는 무엇이 한도를 집행하는지, 그리고 그 집행을 무효화할 수 있는지_입니다. 처리량은 모두가 작성하는 요약본입니다. 권한 부여는 아무도 하고 싶어 하지 않는 부분인데, 왜냐하면 매력이 없고 실제로 돈이 새어나가는 곳이기 때문입니다.
그래서 저는 작은 것을 만들었고, 이전에 출시했던 실제 것과 비교했습니다. 실제 것은 에이전트가 스스로 API에 비용을 지불하는 AWS AgentCore Payments 데모입니다. 작고 새로운 것은 온체인에서 위임된 지출 허용 한도를 강제하는 Sui Move 모듈입니다. 이것들은 같은 질문에 대한 두 가지 신뢰할 수 있는 답변이며, 실제로 완전히 다른 곳에 자리 잡습니다. 이 게시물은 그 비교입니다.
우선, 실제인 것과 그렇지 않은 것을 말씀드리겠습니다. AWS 측은 구축되고 배포되었으며 실제로 (테스트넷) 돈이 지출되었습니다. Sui 측은 전체 단위 테스트 스위트를 컴파일하고 통과했으며, 저는 이를 Sui 테스트넷에 배포하여 온체인에서 실행했습니다. 이는 실제 발행(publish), 실제 성공적인 지출, 그리고 실제 예산 초과로 인한 중단(abort)을 의미하며, 이 모든 과정의 트랜잭션 다이제스트는 직접 확인하실 수 있습니다. 로직은 추측이 아닌 테스트와 라이브 트랜잭션을 통해 증명됩니다. 아래의 모든 다이제스트는 실제입니다.
'규칙 신뢰'에 대한 두 가지 철학
두 시스템 모두 한 가지에 동의합니다. 에이전트를 신뢰하는 것이 아니라, 규칙을 신뢰한다는 것입니다. 하지만 그들은 _규칙이 어디에 존재하는지_에 대해서는 완전히 의견이 다릅니다.
AWS AgentCore Payments는 규칙을 오프체인(off-chain), 서비스 계층에서 처리합니다. 예산은 신뢰할 수 있는 관리자 경로 내의 서버 측 검사입니다. 지갑 키는 Secrets Manager에 보관됩니다. 에이전트는 자격 증명을 절대 보유하지 않으며, 제한 자체를 평가하지도 않습니다. 대신 AWS에게 결제를 요청하고, AWS가 '예' 또는 '아니오'라고 답하는 방식입니다.
Sui는 규칙을 온체인(on-chain), 타입 시스템과 Move 런타임에 구현합니다. 예산은 역량 객체(capability object)의 필드 세트입니다. 검사는 트랜잭션 내부에서 실행되는 바이트코드입니다. 요청할 관리자 서비스가 없으며, 객체를 소유하는 것이 권한이며, 이 객체가 모든 지출에 자체 규칙을 담고 있습니다.
한쪽은 제공업체가 정책을 충실히 집행할 것이라고 신뢰합니다. 다른 쪽은 공개된 바이트코드와 검증자 세트(validator set)를 신뢰합니다. 어느 쪽도 '신뢰가 필요 없는(trustless)' 방식은 아닙니다. 진정한 질문은 _정확히 누구를 신뢰하고 있으며, 그 당사자가 잘못되거나 손상되었을 때 무엇을 할 수 있느냐_입니다. 이 질문을 기억해 주십시오. 이것이 나중에 비교표의 핵심 축이 됩니다.
AWS 측 (배포된 부분과 여기서 문제가 발생한 지점)
이 부분은 제가 실제로 실행해 본 내용입니다. Base Sepolia 테스트넷에서 Stripe/Privy 지갑을 사용하여, 에이전트가 유료화된 엔드포인트(paywalled endpoint)에 접근했고, HTTP 402 오류를 받았으며, 스테이블코인 마이크로 트랜잭션을 정산하고, 증거와 함께 재시도하여 콘텐츠를 되찾았습니다. 이 결제는 약 2초가 걸렸고, $5.00 세션 예산 대비 가짜 USDC $0.002의 비용이 들었습니다.
이 메커니즘은 x402 프로토콜이며, 이는 401 → auth 헤더 → 재시도 과정의 결제 등가물입니다. 서버는 서명된 챌린지(금액, 자산, 수신자, 네트워크)와 함께 402를 반환합니다. 클라이언트는 이를 서명하고 증거와 함께 재시도하여 200 OK를 받습니다. AgentCore는 리소스 계층으로 중간에 위치합니다. 여기에는 결제 관리자(Payment Manager), 결제 커넥터(Payment Connector) (지갑 제공업체 연결), 결제 수단(Payment Instrument) (임베디드 사용자별 지갑), 그리고 결제 세션(Payment Session) (시간 제한 예산)이 있습니다.
이번 비교를 위해 핵심은 한도가 어디에서 강제되는가입니다. 저는 이 내용을 작성한 적이 있습니다:
예산 강제는 프롬프트에 있는 것이 아닙니다. 모델이 무시할 수 있는 가드레일도 아닙니다. 결제가
maxSpendAmount를 초과하거나 세션이 만료되면, AgentCore가 어떤 것도 서명되기 전에ProcessPayment호출을 거부합니다. 모델은 지갑 자격 증명을 절대 볼 수 없으며, 이는 Secrets Manager에 보관되어 있고 AgentCore가 서명 시점에 이를 검색합니다.
이것이 강력한 주장이며, 실제로 유효합니다. 한도는 시스템 프롬프트의 문장이 아니라 API 계층에서의 결정론적 확인입니다. 프롬프트 주입(Prompt injection)은 예산을 초과하여 지출할 수 없습니다. 왜냐하면 모델 자체가 예산을 보유하고 있는 것이 아니기 때문입니다.
이때 제가 문서화했던 한도들은 다음과 같습니다:
- 위임에는 브라우저가 필요합니다. 지갑은 존재하지만, 에이전트가 서명하려면 지갑 소유자가 Privy의 참조 프런트엔드에 로그인하여
AWS 모델은 소유자가 취소할 수 있는 위임된 서명자(delegated signer)와 결정론적인 서버 측 예산(deterministic server-side budget)으로 구성되며, 키는 신뢰하는 관리자 경로(trusted admin path)에 있고 인간이 브라우저에서 개입해야 하는 단계가 있어 스크립트로 처리할 수 없습니다.
Sui의 경우 (새로운 방식)
이제 온체인 버전입니다. 저는 하나의 가설을 테스트하고 싶었습니다. 예산 자체가 객체가 될 수 있을까? 그래야 서비스에 요청하거나 속일 프롬프트가 없을 것입니다?
모듈은 agent_auth::agent_auth입니다. 이 모듈에는 세 가지 객체가 있습니다. **Vault**는 Balance<SUI>를 담고 있는 공유 객체입니다. **OwnerCap**은 소유자가 하나의 금고(vault)에 대해 갖는 권한입니다. **SpendingCap**은 에이전트에게 전송되는 위임되고 제한된 허용액(delegated, bounded allowance)입니다. 규칙은 SpendingCap 위에 실려 이동합니다:
public struct SpendingCap has key, store {
id: UID,
vault_id: ID,
...
주소 목록이나 저장된 키는 어디에도 없습니다. 권한은 객체 소유권에 달려 있습니다. SpendingCap을 보유한 사람은 지출할 수 있지만, 그 안에 내장된 필드 범위 내에서만 가능하며, 해당 vault_id가 바인딩된 하나의 금고를 대상으로만 할 수 있습니다.
강제 집행(enforcement)은 spend 함수입니다. 모든 호출은 모든 규칙을 재확인하고 위반 시 특정 이름의 코드로 중단됩니다. 이 중단 코드들은 소스코드에 실제 상수로 정의되어 있습니다:
const ECapRevoked: u64 = 1;
const ECapExpired: u64 = 2;
const EExceedsPeriodLimit: u64 = 3;
...
그리고 이것이 바로 spend의 실제 본문이며, 순서대로 확인하고 숨겨진 것이 없습니다:
public entry fun spend(
cap: &mut SpendingCap,
vault: &mut Vault,
...
이를 AWS 모델과 비교해 보세요. AWS 예산 검사는 호출하는 서비스 안에 있습니다. 이 예산 검사는 트랜잭션 그 자체인 바이트코드 안에 존재합니다. 잘못된 숫자로 호출할 수 있는 ProcessPayment 엔드포인트도 없고, 루프 내에서 설득될 수 있는 모델도 없습니다. 만약 에이전트가 초과 지출을 시도하면, 트랜잭션은
public entry fun revoke(owner_cap: &OwnerCap, cap: &mut SpendingCap) {
assert!(owner_cap.vault_id == cap.vault_id, ECapVaultMismatch);
cap.revoked = true;
...
이는 Capability를 삭제하는 대신 플래그만 변경하므로, 폐기된 Cap도 여전히 검사 가능하며 다음 spend 호출 시 ECapRevoked로 중단(abort)됩니다. 이는 AWS의 '소유자가 서명자를 폐기할 수 있다'는 속성을 반영하지만, 소유자는 브라우저나 프로바이더가 필요 없습니다. 그들은 이미 보유하고 있는 Capability를 사용하여 하나의 트랜잭션에 서명하기만 하면 됩니다.
실제로 실행됨 (It actually runs)
모듈은 컴파일되고 전체 테스트 스위트가 통과합니다. 이는 sui 1.81.0-bf0c491c17b8에서 얻은 실제 sui move test 출력물이며, 의역이 아닌 원문 그대로 붙여넣은 것입니다:
INCLUDING DEPENDENCY MoveStdlib
INCLUDING DEPENDENCY Sui
BUILDING agent_auth
...
각 예상 실패 테스트는
- 성공적인 지출(Successful spend):
9xbNKenFryZaMqNMAJYqhMDJDTEb37Ww2EFabMugF7K5. 10,000,000 MIST를 지출했으며, 이는 기간별 한도 내에 있었습니다. 금고 잔액은 온체인(on-chain)에서 100,000,000 MIST에서 90,000,000 MIST로 변했고, 지급 코인(payout coin)이 생성되었습니다. - 예산 초과 지출 (취소됨/Over-budget spend (aborted)):
EHm57ZAV2n8p3SgPXTnHEuZFukfiuxoUfoWDU3PRorH8. 15,000,000 MIST를 시도했으나, 이는 기간 총액을 20,000,000 대비 25,000,000으로 만들었을 것이므로 초과했습니다. 이 트랜잭션은 원시 오류(raw error)1st command aborted within function '0x834d12ff622efe5c3b125bf3f28ab6c86c7ba9d3ccdc64de37f80ee2374e6fac::agent_auth::spend' at instruction 95 with code 3와 함께 온체인에서 취소되었습니다. 코드3은 소스에 명시된 정확한 상수인EExceedsPeriodLimit입니다. 금고 잔액은 90,000,000 MIST로 유지되었습니다. 이 취소는 모든 효과를 원자적으로(atomically) 되돌렸습니다.
이 취소가 바로 핵심 논지 전체를 구체화한 것입니다. 초과 지출은
프롬프트 주입(Prompt injection)이 가장 극명한 대비를 이룹니다. 두 시스템 모두 모델이 과지출할 수 없게 하지만, 그 이유가 다릅니다. AWS에서는 모델 자체가 예산을 보유하는 것이 아니라 신뢰할 수 있는 서비스가 보유합니다. Sui에서는 아예 예산 보유 서비스가 없습니다. 한도는 트랜잭션의 속성일 뿐이며, '에이전트'는 단지 PTB(Payment Transaction Bundle)를 구성하는 주체일 뿐입니다. 손상된 AWS 에이전트는 여전히 maxSpendAmount를 초과할 수 없지만, 원칙적으로 잘못 설정될 수 있는 서비스와 상호작용하고 있습니다. 손상된 Sui 위임자(delegate)는 체인이 상태 전이를 거부하기 때문에 한도를 초과할 수 없습니다. 결과는 같지만, 신뢰하는 대상이 다릅니다.
신뢰 가정이 사람들이 생각하는 방향과는 반대입니다. '온체인(On-chain)'은 더 신뢰가 없어 보이는 느낌을 주며, 실제로 집행의 좁은 의미에서는 그렇습니다. 규칙은 공개적이며 일단 게시되면 불변하고, 관리자가 조용히 당신의 한도를 올릴 수 없습니다. 하지만 이제 당신은 Move 코드가 _정확하다_는 것을 신뢰해야 합니다. 왜냐하면 spend에 있는 버그가 곧 법이기 때문입니다. AWS 모델은 제공업체가 버그를 패치할 수 있게 합니다. Sui 모델은 게시하기 전에 정확하게 하거나, 업그레이드 경로를 구축하여 당신이 다시 신뢰하는 관리자를 도입하도록 만듭니다. 불변성은 기능이자 책임(liability)입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기