라이브

자율 결제 에이전트

타이머에 깨어나 스스로 지출 여부를 판단하고, 받은 위임을 넘길 수 없는 에이전트.

만들어졌고, 로컬 체인 위에서 돕니다

에이전트가 뉴스를 읽고, LLM 에게 확률을 묻고, 살아 있는 호가와 비교해, 계정도 없는 예측시장(verex)에서 거래합니다. 상한과 기한은 제 코드가 아니라 온체인 컨트랙트 둘이 강제합니다 — ERC20TransferAmountEnforcerTimestampEnforcer.

조작판은 anvil 과 verex API 가 도는 기계에서만 열립니다. 그래서 이 페이지가 대신 설명합니다.

조작판 열기 →
경계가 진짜라는 증거

verex 도 지갑도 없이 로컬 체인 하나만으로 재현됩니다 (rabbit 저장소에서 pnpm delegation:verify):

1. draw 4 of 10 …………  agent USDC: 4
2. cap exceeded ………  ERC20TransferAmountEnforcer:allowance-exceeded   (still 4)
3. after expiry ………  TimestampEnforcer:expired-delegation             (still 4)

3번이 이 데모의 전부입니다 — 아무도 취소하지 않았습니다. 창이 닫혔을 뿐인데 같은 코드가 같은 키로 계속 돌면서 계속 무해하게 거절당합니다.

아직 무인 운영은 아닙니다

스케줄러가 아직 붙지 않아 지금은 사람이 틱을 누릅니다. 그러니 이 데모가 증명하는 것은 무인 운영이 아니라 경계 지어진 자율성입니다 — 판단은 에이전트가 하고, 피해의 크기는 컨트랙트가 정합니다. 그리고 이 페이지도, 배포된 사이트에서는 체인이 없어 조작판이 열리지 않습니다.

무엇을 보아야 하나
  1. 위임 안에서 아무것도 하지 않는 틱 — 대부분이 이렇다. 결제 성공만 보여주는 페이지였다면 이건 그냥 능력 데모의 반복이었을 것이다.
  2. 위임 안에서 실제로 지출하는 틱 — 한도가 눈앞에서 줄어든다.
  3. 만료 이후 — 같은 코드가 계속 돌면서 계속 무해하게 거부당한다. 안전이 신뢰가 아니라 산수라는 말의 뜻이 여기서 보인다.

아래는 저널의 모양을 보여주는 손으로 쓴 삽화입니다 — 체인 없이도 열리도록. 진짜 저널은 조작판에 있습니다.

위임 (한 번 부여하고 탭을 닫는다)
남은 한도
10.00 / 10.00 USDC
만료 (블록 시간)
16:00
edge 임계치
0.05
에이전트 주소
0x7C4e…21aB

오너 0xA1b2…9F3d가 부여 — 최대 10.00 USDC, 16:00까지. 한도와 기한 모두 에이전트 코드가 아니라 컨트랙트가 강제한다. 무엇을 살지는 강제하지 않는다 — **얼마나 가질 수 있는지**만 강제한다.

결정 저널

마켓: “ETH가 2026년에 $10,000 위에서 마감할까?” (eth-above-10k-2026) — verex 가 실제로 seed 하는 마켓이다. 에이전트는 몇 분마다 깨어나 저장된 뉴스를 읽고, 모델이 확률 p 를 내놓고, 결정론적 규칙이 그 p 를 호가와 비교한다. 지출한 틱만이 아니라 지출하지 않기로 한 틱도 같은 무게로 남는다 — 그래야 판단이 판단으로 읽힌다.

1개 틱 중 1개가 아무것도 하지 않았다.

시각호가 (Yes)모델 pedge판정기록
09:000.45SKIP_NO_ESTIMATE이 마켓에 저장된 뉴스가 없음 — 모델을 아예 부르지 않았다. 순수 사전확률은 학습 시점에 얼어붙어 있고 살아 있는 호가와 겨루면 구조적으로 진다.
여기서 거의 모두가 틀리는 여섯 가지

화면을 보고 자연스럽게 도달하지만 틀린 결론들. 각 항목은 「흔한 읽기 → 실제」다.

  1. 「delegation이 하나다」 → 셋이고 서로 무관하다. EIP-7702의 delegation designator(내 EOA가 어떤 코드로 도는가), ERC-7710의 delegation(에이전트가 받은 위임), 그리고 DelegationManager(에이전트가 호출하는 컨트랙트). 같은 단어일 뿐이다 — 문서에서는 각각 account implementation · mandate · permission manager로 부르는 게 낫다.
  2. 「구현체(DeleGator)가 내 계정을 대신해 돈을 보낸다」 → 대신이 아니라 내 계정으로서다. 구현체는 호출되지 않는다 — EVM이 그 코드를 로드해 내 주소의 컨텍스트로 실행한다. USDC가 보는 msg.sender는 내 EOA이고, 구현체의 USDC 잔액은 영원히 0이다. 코드는 구현체에서, 정체성은 EOA에서.
  3. 「enforcer가 잔액을 들고 있다」 → 정수 하나를 들고 있다. 담보도 에스크로도 없고, 예약되는 자금도 없다. 그리고 그 카운터는 세션 키가 아니라 위임 해시로 키잉된다 — 같은 키에 위임을 둘 부여하면 예산도 둘이고 합산되지 않는다.
  4. 「한도는 표준이 강제한다」 → ERC-7710이 정의하는 건 redeemDelegations() 하나뿐이다. permission context는 bytes[], 즉 불투명 타입으로 선언되어 있어서 caveat이라는 개념 자체가 스펙 범위 밖이다. 실제로 「아니오」라고 말하는 enforcer들은 MetaMask의 delegation-framework다. 「온체인 컨트랙트가 강제」는 참이지만 「표준이 강제」는 거짓이다.
  5. 「위임을 부여하면 체인에 기록된다」 → 아무것도 기록되지 않는다. grantPermissions는 트랜잭션이 아니라 서명된 객체를 돌려줄 뿐이고, 가스도 흔적도 없다. 서명한 수표와 같다 — 은행은 누가 현금화하기 전까지 그게 있는 줄도 모른다. 따라오는 결과 둘: 미사용 위임은 체인 스캔으로 감사할 수 없고, 취소는 부여와 대칭이 아니다(가스가 드는 온체인 트랜잭션이다). 만료가 중요한 진짜 이유가 이것이다 — 아무 행동도 가스도 주의도 필요 없는 유일한 취소다.
  6. 「예산은 하나다」 → 셋이고, 지키는 주체가 다르다. ① 위임 한도 — enforcer가 강제. ② 실제 자금(오너의 USDC) — 토큰 컨트랙트가 강제, 위임과 독립이라 「한도는 남았는데 잔고가 없음」이 가능하다. ③ 세션 계정의 가스 — 강제하는 것이 아무것도 없다. 셋째가 떨어지면 에이전트는 revert도 저널 행도 알림도 없이 조용히 멈춘다. 무인 에이전트가 실제로 죽는 방식이라면, 잔여 가스는 비용 열이 아니라 자체 만료를 가진 두 번째 예산으로 헤더에 있어야 한다.
이 목업이 물었던 것, 그리고 구현이 낸 답

가스·키 보관·스케줄러 호스트·저널 저장소 결정은 docs/features/README.md 의 백로그 B1 에 D1–D5 로 있고, 지금 도는 구조는 docs/features/autonomous-trading-agent.md 에 있다.

이 데모가 증명하지 않는 것

기술 노트

각 항목이 실제로 무엇을 보여주고 어떻게 동작하는지 — 위 카드보다 자세한 기술 설명입니다.

자율 결제 에이전트라이브

목적: 이 페이지의 다른 데모들이 증명하는 건 능력입니다 — 세션 키는 한도 안에서 쓸 수 있고, paymaster는 가스를 대신 낼 수 있고, 배치는 원자적으로 되돌아갈 수 있다. 그런데 전부 사람이 버튼을 눌러야 시작합니다. 그건 에이전트가 아니라 에이전트를 위한 계정 추상화입니다. 이 데모는 빠진 조각 하나로 그 간극을 메웁니다 — 방에 아무도 없을 때 도는 결정 루프. 증명하려는 명제는 "에이전트가 자율적이다"보다 좁고 유용합니다: 무인 에이전트의 안전은 신뢰가 아니라 산수다. 최악의 경우가 금액 한도와 기한으로 미리 고정되어 있고 — 컨트랙트가 강제합니다 — 사후에 로그로 확인됩니다.

동작 방식: 몇 분마다 틱이 돕니다: 해당 마켓에 쌓인 뉴스를 읽고, LLM 에게 확률과 한 줄 근거를 받고, 그 추정을 살아 있는 호가의 **체결되는 쪽**과 비교합니다 — 살 때는 ask, 팔 때는 bid 입니다. 중간값 기준으로 재면 스프레드 절반만큼 edge 가 과대평가되기 때문입니다. 차이가 문턱을 넘으면 위임에서 자금을 뽑아 지정가 주문에 서명하고, 아니면 왜 아무것도 하지 않았는지를 기록합니다. 스킵도 거래만큼 꼼꼼히 남깁니다 — "호가 0.62, 모델 0.64, edge 0.02 는 0.05 미만, 행동 없음"이라 적힌 저널 행이 판단을 판단으로 읽히게 만들고, 이것이야말로 체인이 재구성할 수 없는 유일한 것입니다. 하지 않은 일은 트랜잭션을 남기지 않으니까요. 거절 사유 여섯 갈래는 일부러 서로 구별해 둡니다 — 예산 소진과 만료는 **다른 경계가 닫힌 것**이라 같은 모양으로 그려지면 안 됩니다. 위임은 서로 독립된 두 방향으로 묶여 있고 둘 다 에이전트 자신의 코드가 아니라 바깥이 강제합니다 — ERC20TransferAmountEnforcer 가 누적 합계를 들고, TimestampEnforcer 가 블록 시간을 기한과 비교합니다. 마지막 상태가 가장 흥미롭습니다: 기한을 넘겨도 같은 코드가 계속 돌고 체인은 계속 거절하며, 저널이 enforcer 자신의 문장 expired-delegation 으로 채워집니다. 취소할 게 없었습니다. 창이 닫혔을 뿐입니다. 아직 없는 것도 분명히 적어 둡니다: **스케줄러**. 지금은 사람이 틱을 누르므로, 이 데모가 증명하는 것은 무인 운영이 아니라 경계 지어진 자율성입니다.

한 틱 — 관측·추정·판단·행동·기록
관련 코드:
# 자율 결제 에이전트 — 한 틱: 관측 → 판단 → 행동 → 기록.
# 실제 데모는 온체인 잔고/가격을 읽지만, 여기서는 그 결정 로직만 최소로 떼어낸다.

from dataclasses import dataclass


@dataclass
class Policy:
    max_spend_per_tick: float
    price_ceiling: float


def decide(balance: float, price: float, policy: Policy) -> float:
    """이번 틱에 쓸 금액을 정한다 — 정책 밖이면 0."""
    if price > policy.price_ceiling:
        return 0.0
    return min(balance, policy.max_spend_per_tick)


def tick(balance: float, price: float, policy: Policy) -> tuple[float, str]:
    spend = decide(balance, price, policy)
    if spend == 0:
        return balance, f"skip — price {price} > ceiling {policy.price_ceiling}"
    return balance - spend, f"spend {spend:.2f} @ price {price}"


policy = Policy(max_spend_per_tick=10.0, price_ceiling=100.0)
balance = 50.0
for price in (80.0, 120.0, 95.0):
    balance, log = tick(balance, price, policy)
    print(f"balance={balance:6.2f}  {log}")

docs/code/pocs/agent.py