> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aisky.co.za/llms.txt
> Use this file to discover all available pages before exploring further.

# Rate Limits

> Token-bucket budgets per tenant and per tool.

HTTP Tools is rate-limited at two layers, both using **token buckets**. Each bucket refills at a fixed rate; you spend tokens as you go. When a bucket empties, the next request gets `HTTP_TOOL_RATE_LIMITED` and the AI silently moves on (it does NOT retry).

## Layer 1, Per-tenant budget

|          |                                                                                                |
| -------- | ---------------------------------------------------------------------------------------------- |
| Capacity | 60 invocations                                                                                 |
| Refill   | 60 / minute (1 per second)                                                                     |
| Scope    | All HTTP Tool calls on your tenant, summed across every configured tool and every active agent |

This is the global cap. If your tenant is making 200 calls a minute spread across tools and agents, you'll start hitting this limit and the AI will skip non-essential lookups.

## Layer 2, Per-tool budget

|          |                                                               |
| -------- | ------------------------------------------------------------- |
| Capacity | 30 invocations                                                |
| Refill   | 30 / minute                                                   |
| Scope    | Each tool has its own bucket, keyed by `tenant_http_tools.id` |

Prevents one runaway tool from starving other tools on the same tenant. If your `lookup_routing` tool gets hammered, `check_balance` keeps working.

## How the bucket arithmetic works

```
At t=0:                   tokens=60      ┌─ full bucket
                                         │
At t=0 invocation:        tokens=59      ▼
At t=1 invocation:        tokens=58
At t=2 invocation:        tokens=57
At t=2.5 (refill 2.5s):   tokens=59.5    (refill = elapsed_seconds * 1 token/s, capped at 60)
At t=60 invocation:       tokens=60      ◀── back to full if idle
```

The bucket is **continuously refilling**. You don't have to wait a full second between calls: a full bucket lets you spend up to its capacity at once (60 on the tenant bucket, 30 on a tool bucket), then it refills at the refill rate.

## What the AI sees when limited

The runtime returns:

```json theme={null}
{
  "ok": false,
  "error_code": "HTTP_TOOL_RATE_LIMITED",
  "llm_message": "I've used lookups too many times recently. I'll work with what I have."
}
```

The AI receives the `llm_message` as the tool result and continues the conversation. It does NOT auto-retry. From the caller's perspective the AI just decides it has enough information.

## What the dashboard surfaces

Every invocation row in the **Invocations** panel includes the remaining tenant-bucket count at the time of the call (in the `_meta.rate_limit_remaining` field of the response body). Rows that hit a limit are flagged red with the `HTTP_TOOL_RATE_LIMITED` code.

## Test fires count against your budget

The dashboard's **Send test** button runs a real invocation, so it draws from the **same** per-tenant and per-tool buckets as production calls. There is no separate test allowance. If you hammer Send test while debugging, you can rate-limit your live agent, so test in bursts rather than in a tight loop.

## Asking for a higher quota

Both layers are hard-coded constants in v1. If your use case genuinely needs more (e.g. you run 100+ concurrent calls and every one chains 3-4 HTTP Tool lookups), [open a support ticket](mailto:hello@aisky.co.za) with:

* Your tenant ID.
* Approximate call volume per minute.
* Average HTTP Tool invocations per call.

We can lift the per-tenant cap on a per-tenant basis.

## Implementation note (for the curious)

Buckets live in the edge function's module scope (`Map<string, Bucket>`). Supabase keeps the runtime warm under load, so bucket state survives across requests. Cold starts reset the bucket to full, a corner case where a tenant just over their limit might briefly get one or two extra calls through. We're comfortable with this drift for v1; if you observe surprising behavior, file it under "we'd like to know."

<Card title="Next: Security restrictions" href="/guides/http-tools/security-restrictions">
  What URLs we block and why.
</Card>
