이중 계층 정책 모델
오프체인 MAWS 정책 검사와, 체인이 강제하는 별도의 온체인 PCL 정책으로 이루어집니다.
MAWS는 서명하기 전에 에이전트의 정책을 검사하므로 AI 에이전트는 즉시 피드백을 받습니다. MAWS의 규칙(spendingLimit, allowedTargets, status)은 IdentityRegistry 메타데이터로 온체인에 저장되지만, 이를 강제하는 것은 MAWS뿐이며 체인은 이 값을 읽지 않습니다. 체인이 강제하는 것은 별도의 계층인 프로그래머블 컴플라이언스 레이어(PCL)로, 자체 전역 정책과 컨트랙트 정책으로 설정됩니다. PCL의 에이전트별 한도는 다른 메타데이터 키인 TransferLimit을 읽습니다.
아키텍처
graph LR
A[Agent Intent] --> B{"Preflight (Off-chain)"}
B -- Reject --> C[ToolError to LLM]
B -- Pass --> D[Submit Tx]
D --> E{"PCL (On-chain)"}
E -- Reject --> F[Tx Reverted]
E -- Pass --> G[State Updated]
classDef evm fill:#0096AA,stroke:#0096AA,color:#fff;
classDef precompile fill:#FF8C50,stroke:#FF8C50,color:#fff;
class F evm;
class A,B,C,D,G evm;
class E precompile; 전송이 거치는 두 검사입니다. MAWS 사전 검사(자체 spendingLimit / allowedTargets)와 체인의 PCL 정책(별도 설정)입니다. MAWS를 거치지 않은 트랜잭션에는 두 번째만 적용됩니다.
계층 1: 오프체인 사전 검사
에이전트가
transfer.send를 호출하면 MCP 서버의 AgentManager는 온체인 IdentityRegistry에서 에이전트의 정책을 읽습니다. 트랜잭션 규칙을 로컬에서 시뮬레이션합니다. 전송이 spendingLimit 또는 allowedTargets를 위반하는 경우 서버는 즉시 ToolError(예: POLICY_REJECTED)를 반환합니다. 이는 가스를 절약하고 LLM에게 동작을 조정할 기회를 제공합니다. spendingLimit과 allowedTargets가 강제되는 곳은 여기뿐입니다.const { allowed, reason } = await manager.checkPolicy(onchainId, to, valueWei);
if (!allowed) throw new ToolError("POLICY_REJECTED", reason); 계층 2: 온체인 PCL
사전 검사를 통과하면 MAWS가 트랜잭션에 서명해 제출하고, 체인의 PCL이 이를 평가합니다. 다만 평가 기준은 PCL 자체의 정책이며, 어떤 체인 모듈도 읽지 않는
spendingLimit이나 allowedTargets가 아닙니다. 마루 테스트넷의 전역 정책(IPcl.globalPolicies()로 읽습니다)은 EAS attestation(KYC)이 없는 모든 발신자를 트랜잭션당 200만 OKRW, UTC 기준 하루 1,000만 OKRW로 제한합니다. 에이전트 지갑의 전송은 소유자의 하루 누적 거래량에 더해지므로, 두 한도를 모두 풀려면 소유자의 attestation이 필요합니다. 지갑 자체의 attestation으로는 트랜잭션당 한도만 풀립니다. 에이전트 지갑 키로 MAWS를 거치지 않고 보낸 트랜잭션은 이 PCL 정책은 거치지만 MAWS 규칙은 하나도 거치지 않습니다. 체인이 강제할 수 있는 에이전트별 한도는 TransferLimit 메타데이터(atokrw 단위의 abi.encode(uint256) 값) 하나이며, AGENT_OKRW_TRANSFER_LIMIT_POLICY가 설정된 경우에만 이를 읽습니다. pcl-template-agent-okrw-transfer-limit-policy를 참고합니다.