99 lines
3.1 KiB
Markdown
99 lines
3.1 KiB
Markdown
# Scene 5 — DENY: Rate Limit Exceeded
|
||
|
||
**Policy rule:** Rate limiting (max N calls per minute per agent/tool)
|
||
**Expected result:** First calls ALLOW, then DENY after threshold
|
||
|
||
---
|
||
|
||
## Presentation Rule
|
||
|
||
> **Language:** All AI narration and communication during scenes must be in **English**.
|
||
>
|
||
> The AI must narrate every interaction with the gateway in detail. **Before** calling the gateway, explain what it is about to do, which endpoint it will call, what payload it will send, and what it expects to happen. **After** receiving the response, explain what the gateway returned, what the decision means, and why it matters. The goal is to make the audience understand exactly what is happening between the AI and the gateway at every step.
|
||
|
||
---
|
||
|
||
## Communication Flow
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant AI as AI Agent
|
||
participant GW as Gateway
|
||
participant PE as Policy Engine
|
||
participant DB as Database Service
|
||
|
||
loop Requests 1–30 (within limit)
|
||
AI->>GW: POST /api/gateway/execute<br/>{tool: db.queryReadonly, action: query}
|
||
GW->>PE: Evaluate policy rules
|
||
PE->>PE: Rate limit check: 1/30 → 30/30 ✓
|
||
PE-->>GW: Decision: ALLOW
|
||
GW->>DB: Execute query
|
||
DB-->>GW: Result
|
||
GW-->>AI: 200 OK {decision: ALLOW}
|
||
end
|
||
|
||
AI->>GW: POST /api/gateway/execute<br/>{tool: db.queryReadonly, action: query}
|
||
GW->>PE: Evaluate policy rules
|
||
PE->>PE: Rate limit check: 31/30 ✗
|
||
PE-->>GW: Decision: DENY
|
||
Note over GW,DB: Request never reaches Database
|
||
GW->>GW: Write audit entry
|
||
GW-->>AI: 200 OK {decision: DENY,<br/>reason: "Rate limit exceeded"}
|
||
```
|
||
|
||
## Demo Script
|
||
|
||
> **Presenter says:** "What if the AI enters a loop and hammers the database with queries? Rate limiting kicks in automatically."
|
||
|
||
### Action — Burst Queries
|
||
|
||
Issue multiple requests in quick succession:
|
||
|
||
> "Run these 5 database queries one after another:
|
||
> 1. SELECT * FROM users
|
||
> 2. SELECT * FROM orders
|
||
> 3. SELECT * FROM products
|
||
> 4. SELECT * FROM sessions
|
||
> 5. SELECT * FROM audit_log"
|
||
|
||
Or, for a more dramatic demo, ask Claude to repeatedly query:
|
||
|
||
> "Query the database for active users. Do it 35 times to stress-test."
|
||
|
||
### Expected Response
|
||
|
||
First ~30 calls return ALLOW. Then:
|
||
|
||
```json
|
||
{
|
||
"request_id": "req-...",
|
||
"decision": "deny",
|
||
"reason": "Rate limit exceeded",
|
||
"matched_rule": "rate-limit-default"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## What This Proves
|
||
|
||
- **AI agents are rate-limited** just like any API client
|
||
- State is tracked server-side (in-memory counter) — the AI cannot reset or bypass it
|
||
- The policy engine itself is stateless: the gateway injects `context.rate = { current: N, limit: M }` and the rule just compares
|
||
- Follows OPA pattern: state outside, decision inside
|
||
- Prevents runaway loops, DoS-like behavior, and cost amplification
|
||
|
||
---
|
||
|
||
## Technical Note
|
||
|
||
The rate limit config from `policies.yaml`:
|
||
- Default: 30 calls/minute per agent/tool
|
||
- `db.queryReadonly`: 60 calls/minute (higher threshold for reads)
|
||
|
||
---
|
||
|
||
## Transition to Next Scene
|
||
|
||
> "Rate limits protect against volume. But what about timing? Should we allow deploys at 2 AM?"
|