Mental Model
Mental Model: How Requests Flow Through OnceOnly
Section titled “Mental Model: How Requests Flow Through OnceOnly”This page explains the mental model of how every request is processed by OnceOnly, from the agent’s perspective to the API gateway’s decision-making.
Simple Request: Check Lock (Idempotency)
Section titled “Simple Request: Check Lock (Idempotency)”An agent wants to execute an action and check if it’s a duplicate.
┌─────────────────────────────────────────┐│ Agent (Claude/GPT-4) ││ POST /v1/check-lock ││ key="payment_invoice_123" ││ ttl=3600 ││ metadata={...} │└────────────────────┬────────────────────┘ │ ┌──────────▼──────────┐ │ OnceOnly API │ │ Validation Layer │ └────────┬────────────┘ │ ┌──────────┴──────────┬──────────┐ ▼ ▼ ▼ ┌─────────┐ ┌──────────┐ ┌──────────┐ │Validate │ │Check API │ │Rate Limit│ │Request │ │Key valid?│ │Check │ │Schema │ │(JWT) │ │(Global) │ └────┬────┘ └────┬─────┘ └────┬─────┘ │ │ │ └───────────┬───────┴─────────────┘ │ ┌──────────▼──────────────────────┐ │ Check Redis for existing lock │ │ key="lock:payment_invoice_123" │ └────────┬─────────────┬──────────┘ │ │ ┌─────────▼──┐ ┌────▼──────────┐ │Lock EXISTS │ │Lock DOESN'T │ │(duplicate) │ │EXIST (new) │ └──────┬─────┘ └────┬──────────┘ │ │ │ ▼ │ Create Redis lock │ key="lock:payment_invoice_123" │ TTL = 3600 seconds │ (expires after 1 hour) │ │ │ ┌────────▼────────┐ │ │Log to Audit │ │ │Trail (DB) │ │ └────────┬────────┘ │ │ └────────┬───────┘ │ ┌────▼────────────────┐ │Return Response │ │status: "duplicate" or│ │status: "locked" │ └─────────────────────┘Response: First Call (New Action)
Section titled “Response: First Call (New Action)”{ "success": true, "status": "locked", "key": "payment_invoice_123", "ttl": 3600, "first_seen_at": null}→ Means: This is a new action. Safe to execute the payment.
Response: Second Call (Duplicate)
Section titled “Response: Second Call (Duplicate)”If you repeat the same request within 1 hour:
{ "success": false, "status": "duplicate", "key": "payment_invoice_123", "ttl": 3600, "first_seen_at": "2025-01-15T10:30:00Z"}→ Means: This action was already attempted. Don’t charge the customer again! Return the cached result instead.
Complex Request: AI Lease (Long-running Tasks)
Section titled “Complex Request: AI Lease (Long-running Tasks)”An agent starts a long task (e.g., customer support chat) and needs a “lease” to hold exclusive execution.
┌──────────────────────────────────────┐│ Agent ││ POST /v1/ai/lease ││ key="support_chat_001" ││ ttl=1800 (30 minutes) │└──────────────┬───────────────────────┘ │ ┌──────────▼─────────────┐ │OnceOnly AI Lease API │ │/v1/ai/lease │ └──────┬────────────────┘ │ ┌──────┴──────┬──────────┐ ▼ ▼ ▼┌────────┐ ┌─────────────┐ ┌──────────┐│Validate│ │Check Policy │ │Rate Limit││API Key │ │(can agent │ │Check ││ │ │run tasks?) │ │ │└───┬────┘ └──────┬──────┘ └────┬─────┘ │ │ │ └──────┬───────┴──────────────┘ │ ┌──────▼──────────────────────┐ │Check Redis for existing │ │lease on key │ └──────┬──────────┬────────────┘ │ │ ┌──────▼──┐ ┌───▼──────────┐ │Lease │ │No lease yet │ │already │ │(new) │ │exists │ └───┬──────────┘ │(in_progress) │ └───┬────┘ │ │ ▼ │ Create new lease: │ • Generate lease_id │ • Store in Redis │ • TTL = 1800 sec │ • Status = "in_progress" │ │ │ ┌────────┴────────┐ │ ▼ ▼ │ Log event Check Agent │"lease: Rate Limit │acquired" │ │ └───┴─────────────────┐ │ ┌─────────▼──────┐ │Return lease │ │info to agent │ └────────────────┘Response: Acquired (This Agent Owns the Lease)
Section titled “Response: Acquired (This Agent Owns the Lease)”{ "ok": true, "status": "acquired", "key": "support_chat_001", "lease_id": "lease_abc123xyz", "ttl": 1800, "first_seen_at": "2025-01-15T10:30:00Z"}→ Means: This agent has exclusive permission to run this task for the next 30 minutes.
Response: Polling (Another Agent Owns It)
Section titled “Response: Polling (Another Agent Owns It)”If another agent already acquired the lease:
{ "ok": true, "status": "polling", "key": "support_chat_001", "lease_id": "lease_abc123xyz", "ttl_left": 1750}→ Means: Another agent is already running this task. Don’t start it again. Wait for the other agent to finish.
Status Checking During Execution
Section titled “Status Checking During Execution”Another process (or monitoring dashboard) wants to check progress:
┌──────────────────────────────────┐│ Monitor / Other Agent ││ GET /v1/ai/status?key=support... │└──────────────┬───────────────────┘ │ ┌──────────▼────────────┐ │Fetch from Redis │ │lease:support_chat_001 │ └──────┬────────────────┘ │ ┌────┴───────────────┐ │ │ ▼ ▼ ┌──────────────┐ ┌──────────────┐ │Lease found │ │Lease not │ │Status check │ │found │ │ │ │→ "not_found" │ └──┬──┬────────┘ └──────────────┘ │ │ │ └──────────────────────┐ ▼ ▼┌──────────┐ ┌──────────┐ ┌─────────┐│in_progress │completed │failed ││(ttl_left:500)│(done_at, │(error_ ││ │result_hash) │code) │└──────────────┴──────────────┴─────────┘Response (In Progress):
{ "ok": true, "status": "in_progress", "key": "support_chat_001", "lease_id": "lease_abc123xyz", "ttl_left": 1500}→ Means: The chat is still running. 25 minutes remaining.
Completing the Lease
Section titled “Completing the Lease”When the agent finishes the task:
┌──────────────────────────────┐│ Agent ││ POST /v1/ai/complete ││ key="support_chat_001" ││ lease_id="lease_abc123xyz" ││ result={...} │└──────────────┬───────────────┘ │ ┌──────────▼──────────────┐ │OnceOnly Complete API │ │/v1/ai/complete │ └──────┬───────────────────┘ │ ┌──────┴──────────┐ │ │ ▼ ▼┌──────────────┐ ┌────────────────┐│Verify owner │ │Verify lease ││(lease_id │ │exists & ││matches) │ │in_progress │└───┬──────────┘ └────────┬───────┘ │ │ └──────┬───────────────┘ │ ┌──────▼──────────────────┐ │Store result in Redis: │ │• status = "completed" │ │• result = {...} │ │• result_hash = "..." │ │• done_at = now │ │• TTL = 7 days │ │(for future checks) │ └──────┬───────────────────┘ │ ┌──────▼────────────────┐ │Log to Audit Trail: │ │event="lease:completed"│ │agent_id, result_hash │ └──────┬────────────────┘ │ ┌──────▼─────────────────┐ │Delete Redis lock │ │(lease no longer blocks)│ └──────┬─────────────────┘ │ ▼ ┌──────────────────┐ │Return "completed"│ └──────────────────┘Response:
{ "ok": true, "status": "completed", "key": "support_chat_001", "version": 1}Now future requests to /v1/ai/status or /v1/ai/result will return the completed status with results.
Failure Handling
Section titled “Failure Handling”If something goes wrong:
┌──────────────────────────┐│ Agent ││ POST /v1/ai/fail ││ key="support_chat_001" ││ lease_id="lease_abc123" ││ error_code="timeout" │└──────────────┬───────────┘ │ ┌──────────▼──────────────┐ │OnceOnly Fail API │ │/v1/ai/fail │ └──────┬──────────────────┘ │ ┌──────┴──────┐ │ │ ▼ ▼┌──────────┐ ┌──────────────┐│Verify │ │Store failure:││ownership │ │• status=fail ││ │ │• error_code ││ │ │• done_at │└────┬─────┘ └────┬─────────┘ │ │ └──────┬──────┘ │ ┌──────▼───────────────┐ │Log: event="lease: │ │failed" │ │error_code, reason │ └──────┬───────────────┘ │ ┌──────▼────────────┐ │Delete lock │ │(release lease) │ └──────┬────────────┘ │ ▼ ┌──────────────┐ │Return failed │ └──────────────┘Response:
{ "ok": true, "status": "failed", "key": "support_chat_001", "version": 2}Policy Enforcement
Section titled “Policy Enforcement”When an agent tries to run an action, policies are checked:
┌──────────────────────────────────┐│ Agent ││ POST /v1/ai/lease ││ agent_id="support_bot" ││ key="send_email_to_user" ││ tool="send_email" │└──────────────┬───────────────────┘ │ ┌──────────▼──────────────────┐ │OnceOnly Lease + Policy │ │Check │ └──────┬───────────────────────┘ │ ┌──────┴──────────────────────┐ │ │ ▼ ▼┌─────────────────────┐ ┌───────────────────┐│Check allowed_tools │ │Check blocked_tools││for "send_email" │ │for "send_email" ││Result: FOUND ✓ │ │Result: NOT FOUND ✓│└──────┬──────────────┘ └────────┬──────────┘ │ │ └──────────┬───────────────┘ │ ┌────────▼─────────────┐ │Check rate limit: │ │max=100/hour │ │used this hour: 95 │ │95 < 100 → Allow ✓ │ └────────┬─────────────┘ │ ┌────────▼──────────────┐ │Check budget: │ │remaining: $450 │ │estimated cost: $10 │ │$450 > $10 → Allow ✓ │ └────────┬──────────────┘ │ ┌────────▼───────────────┐ │Log decision: │ │status="executed" │ │reason="ok" │ └────────┬───────────────┘ │ ▼ ┌──────────────────────┐ │Proceed with lease │ │Return: "acquired" │ └──────────────────────┘Audit Logging
Section titled “Audit Logging”Every action is logged for later review:
{ "ts": 1705324205, "agent_id": "support_bot", "tool": "send_email", "decision": "executed", "policy_reason": "ok", "risk_level": "low", "spend_usd": 0.05}Admin can query:
GET /v1/agents/support_bot/logs?limit=100→ [list of recent decisions for that agent]Request Flow Summary
Section titled “Request Flow Summary”1. Agent wants to do action ↓2. Call /check-lock or /ai/lease ↓3. OnceOnly validates API key ↓4. Check if lock/lease already exists (Redis) ↓5. If new: Create lock/lease ↓6. Check policies (allowed_tools, rate_limit, budget) ↓7. If allowed: Return "locked" or "acquired" ↓8. If blocked: Return error with reason ↓9. Agent executes action (or skips if blocked) ↓10. Agent calls /ai/complete or /ai/fail ↓11. OnceOnly stores result + logs ↓12. Other agents can call /ai/status or /ai/resultKey Concepts Recap
Section titled “Key Concepts Recap”| Concept | Meaning |
|---|---|
| Lock | Redis key protecting idempotency (1-3600 sec) |
| Lease | Redis key for long tasks (up to 24 hours, can extend) |
| TTL | Time to live = how long the lock/lease blocks |
| Policy | Rules: which tools allowed, rate limits, budget |
| Audit | Log of all decisions with timestamps |
| Rate Limit | Max actions per agent per time period |
| Budget | Max USD spend per agent per time period |
Next, read Quickstart to integrate OnceOnly into your application.