Agent loop design — tool permissions, gates, and retries; data and model provenance TODO
Concept
An agent loop is the control structure where a model calls tools, feeds the results back in as input, and repeats until it reaches its goal. Because this loop is inherently non-deterministic, safety has to come from system-level constraints wrapped around the loop, not from the model's own judgment. Concretely, that means granting least privilege per tool, putting an explicit gate — approval, dry run, or a limit — in front of any irreversible action, capping iteration count and cost, and having a retry policy that distinguishes failure types. Retries should only be applied automatically to tools that are guaranteed idempotent, or the same side effect ends up executing twice. Data and model provenance means keeping a traceable record of exactly which inputs and which model version produced a given decision — a prerequisite for debugging after the fact and for accountability.
You can't stop an agent from ever being wrong; what determines whether it's actually operable is whether a mistake can be undone and whether you can tell what caused it.
Code & Formula
# 에이전트 루프 설계 — 읽기 전용/쓰기 도구를 분리하고, 쓰기 도구에는 승인 게이트 +
# 멱등 키를 붙여 "재시도가 부작용을 중복 실행하지 않는지" 검증하는 최소 예시.
executed_writes = {} # idempotency_key -> result (실제로 실행된 부작용의 기록)
call_log = []
def read_balance(account): # 읽기 전용 도구: 언제 재시도해도 안전
call_log.append(("read", account))
return {"acct-1": 100}.get(account, 0)
def send_payment(account, amount, idempotency_key, approved):
# 되돌릴 수 없는 행위 -> 승인 게이트 필수
if not approved:
raise PermissionError("승인 게이트 미통과: 결제 도구는 approved=True 필요")
if idempotency_key in executed_writes:
return executed_writes[idempotency_key] # 재시도여도 재실행하지 않고 이전 결과 반환
call_log.append(("write", account, amount))
result = {"status": "sent", "account": account, "amount": amount}
executed_writes[idempotency_key] = result
return result
def agent_step_with_retry(tool_fn, *args, max_retries=3, **kwargs):
for attempt in range(max_retries):
try:
return tool_fn(*args, **kwargs)
except PermissionError:
raise # 권한 실패는 재시도로 해결되지 않음 -> 즉시 중단
except Exception:
if attempt == max_retries - 1:
raise
return None
balance = agent_step_with_retry(read_balance, "acct-1")
print("잔고 조회:", balance)
key = "payment-req-42" # 이 요청 전체를 대표하는 멱등 키 (네트워크 재시도에도 동일)
r1 = agent_step_with_retry(send_payment, "acct-1", 10, key, True)
r2 = agent_step_with_retry(send_payment, "acct-1", 10, key, True) # 네트워크 재시도 흉내
print("첫 결제 호출:", r1)
print("재시도 호출(동일 idempotency_key):", r2)
write_calls = [c for c in call_log if c[0] == "write"]
print("실제로 실행된 write 부작용 횟수:", len(write_calls), "(재시도에도 1회만 실행됨)")
try:
send_payment("acct-1", 999, "payment-req-99", approved=False)
except PermissionError as e:
print("승인 없는 결제 시도 차단:", e)
docs/code/algorithms/algorithms-99.py
Exercise
Build a simple agent loop that separates tools into read-only and write, attach an approval gate, a call cap, and an idempotency key to the write tools, and verify that a retry doesn't cause duplicate execution.
Practical Connection
A tool that sends on-chain transactions is the textbook example of an irreversible action — without gates like pre-signing simulation, an amount cap, and nonce management, a single automatic retry becomes a duplicate transaction.
Where it lands in Jayverse
- Rabbit: implement the gate for the AA payment agent explicitly. Pre-signing simulation via Tenderly, an amount cap per mandate, and nonce-based idempotency keys so a retry never double-sends — the concrete design the card's exercise asks for.
- Wallet: make simulate-before-sign the mandatory gate the agent loop calls. Not an optional UI step, and log which model version approved each transaction for provenance.
- Auditor: require every irreversible-action tool to declare its gate and idempotency key. Transfers, bridge calls, market-resolution triggers — check this in one place per release.
Key expressions
| Expression | 뜻 · 쓰이는 자리 |
|---|---|
| least privilege | 최소 권한 원칙 · 도구마다 꼭 필요한 권한만 부여하는 보안 설계. "granting least privilege per tool" |
| explicit gate | 명시적인 관문, 뚜렷하게 세워둔 승인 절차 · 되돌릴 수 없는 행동 앞에 반드시 두는 장치. "an explicit gate... in front of any irreversible action" |
| idempotent | 멱등성이 있는, 몇 번을 반복해도 결과가 같은 · 자동 재시도를 허용해도 안전한 조건. "guaranteed idempotent" |
| provenance | 출처, 이력 추적 정보 · 어떤 입력과 모델이 결정을 내렸는지 기록하는 것. "Data and model provenance" |
| be undone | 되돌려질 수 있다, 취소될 수 있다 · 실수가 발생했을 때 복구 가능한지 여부. "whether a mistake can be undone" |
| textbook example | 전형적인 사례, 교과서에 나올 법한 예 · 대표적인 위험 상황을 가리킬 때. "the textbook example of an irreversible action" |
| irreversible | 되돌릴 수 없는 · 실행되면 취소가 불가능한 행동(온체인 송금 등)을 가리킬 때. "in front of any irreversible action" |
If you study this on a given day, add a note link and a ✅ to this line in the source curriculum (docs/knowledge/dev-100-curriculum.md) and this spot will lead straight to the note body. You can also write directly on this page — but regenerating overwrites it, so it's safer to keep anything you want to save as markdown under docs/algorithms/.