# `Jido.AI.Plugins.Quota`
[🔗](https://github.com/agentjido/jido_ai/blob/v2.4.0/lib/jido_ai/plugins/quota.ex#L4)

Cross-cutting quota and budget enforcement plugin.

Tracks rolling request/token usage from `ai.usage` signals and rewrites
budgeted request/query signals to `ai.request.error` when configured limits
are reached.

## Quota State Keys

`mount/2` stores quota runtime state under state key `:quota` with:

- `enabled` - enable/disable quota enforcement
- `scope` - quota counter namespace in `Jido.AI.Quota.Store`
- `window_ms` - rolling quota window size in milliseconds
- `max_requests` - optional request budget for the window
- `max_total_tokens` - optional token budget for the window
- `error_message` - user-facing rejection message

These keys are used by `handle_signal/2` and quota action routes
(`quota.status`, `quota.reset`).

## Usage Accounting

- `ai.usage` increments usage counters (`requests`, `total_tokens`) for the
  active `scope`.
- Token accounting reads `total_tokens` first, then falls back to
  `input_tokens + output_tokens`.
- Counters reset to zero when usage is outside the configured `window_ms`.

## Budget Rejection Contract

When quota `enabled: true` and usage is at/over budget for either
`max_requests` or `max_total_tokens`, budgeted signals (`chat.*`,
`ai.*.query`, `reasoning.*.run`) are rewritten to `ai.request.error` with:

- `request_id` from request/call correlation fields when present
- `reason: :quota_exceeded`
- `message` from `error_message` (default: `"quota exceeded for current window"`)

## Usage

```elixir
use Jido.AI.Agent,
  name: "quota_guarded_assistant",
  plugins: [
    {Jido.AI.Plugins.Quota,
     %{
       enabled: true,
       scope: "assistant_ops",
       window_ms: 60_000,
       max_requests: 50,
       max_total_tokens: 20_000,
       error_message: "quota exceeded for current window"
     }}
  ]
```

# `__plugin_metadata__`

```elixir
@spec __plugin_metadata__() :: map()
```

Returns metadata for Jido.Discovery integration.

This function is used by `Jido.Discovery` to index plugins
for fast lookup and filtering.

# `actions`

```elixir
@spec actions() :: [module()]
```

Returns the list of action modules provided by this plugin.

# `capabilities`

```elixir
@spec capabilities() :: [atom()]
```

Returns the capabilities provided by this plugin.

# `category`

```elixir
@spec category() :: String.t() | nil
```

Returns the plugin's category.

# `config_schema`

```elixir
@spec config_schema() :: Zoi.schema() | nil
```

Returns the Zoi schema for per-agent configuration.

# `description`

```elixir
@spec description() :: String.t() | nil
```

Returns the plugin's description.

# `manifest`

```elixir
@spec manifest() :: Jido.Plugin.Manifest.t()
```

Returns the plugin manifest with all metadata.

The manifest provides compile-time metadata for discovery
and introspection, including capabilities, requirements,
signal routes, and schedules.

# `name`

```elixir
@spec name() :: String.t()
```

Returns the plugin's name.

# `otp_app`

```elixir
@spec otp_app() :: atom() | nil
```

Returns the OTP application for config resolution.

# `plugin_spec`

```elixir
@spec plugin_spec(map()) :: Jido.Plugin.Spec.t()
```

Returns the plugin specification with optional per-agent configuration.

## Examples

    spec = MyModule.plugin_spec(%{})
    spec = MyModule.plugin_spec(%{custom_option: true})

# `requires`

```elixir
@spec requires() :: [tuple()]
```

Returns the requirements for this plugin.

# `schedules`

```elixir
@spec schedules() :: [tuple()]
```

Returns the schedules for this plugin.

# `schema`

```elixir
@spec schema() :: Zoi.schema() | nil
```

Returns the Zoi schema for plugin state.

# `signal_patterns`

```elixir
@spec signal_patterns() :: [String.t()]
```

Returns the signal patterns this plugin handles.

# `signal_routes`

```elixir
@spec signal_routes() :: [tuple()]
```

Returns the signal routes for this plugin.

# `singleton?`

```elixir
@spec singleton?() :: boolean()
```

Returns whether this plugin is a singleton.

# `state_key`

```elixir
@spec state_key() :: atom()
```

Returns the key used to store plugin state in the agent.

# `subscriptions`

```elixir
@spec subscriptions() :: [Jido.Plugin.sensor_subscription()]
```

Returns the sensor subscriptions for this plugin.

# `tags`

```elixir
@spec tags() :: [String.t()]
```

Returns the plugin's tags.

# `vsn`

```elixir
@spec vsn() :: String.t() | nil
```

Returns the plugin's version.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
