Skip to content

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.

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" │
└─────────────────────┘
{
"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.

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.

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.


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.


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.


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
}

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" │
└──────────────────────┘

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:

Terminal window
GET /v1/agents/support_bot/logs?limit=100
[list of recent decisions for that agent]

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/result

ConceptMeaning
LockRedis key protecting idempotency (1-3600 sec)
LeaseRedis key for long tasks (up to 24 hours, can extend)
TTLTime to live = how long the lock/lease blocks
PolicyRules: which tools allowed, rate limits, budget
AuditLog of all decisions with timestamps
Rate LimitMax actions per agent per time period
BudgetMax USD spend per agent per time period

Next, read Quickstart to integrate OnceOnly into your application.