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

# AI Agent Spending Limit Controls in Synclear Protocol

> How Synclear enforces per-transaction caps, daily rolling limits, lifetime volume ceilings, cooldown periods, and rate limits for AI agent transactions.

Spending limits are the quantitative enforcement layer within a mandate. Where the mandate schema defines *what* an agent is permitted to do, spending limits define *how much* — and they are checked by the `MandateRegistry` contract before every execution, making them a hard constraint rather than a policy advisory. No off-chain system can bypass them.

Synclear implements a multi-tier spending limit model that gives principals fine-grained control over agent capital exposure at different time horizons and transaction patterns.

## Limit Types

<Tabs>
  <Tab title="Per-Transaction Cap">
    The per-transaction cap (`maxTransactionAmount`) is the most granular limit. It constrains the notional value of any single transaction submitted by the agent. The `MandateRegistry` checks the transaction's asset amount against this cap as the first validation step.

    This limit is denominated in the asset's native base units and is asset-specific when a mandate covers multiple assets. For example, a mandate permitting both USDC and USDT operations applies the same `maxTransactionAmount` to each asset independently.

    **Use case:** Prevents a compromised agent or runaway automation loop from draining a position in a single transaction.
  </Tab>

  <Tab title="Daily Rolling Limit">
    The daily rolling limit (`maxDailyVolume`) constrains the total notional volume an agent may execute across all transactions within a 24-hour window. The registry accumulates executed volume against this limit and rejects any transaction that would cause the running total to exceed it.

    <Note>
      Synclear uses a **rolling 24-hour window** for daily limit calculation, not a UTC midnight reset. The window looks back exactly 86,400 seconds from the current block timestamp. This prevents agents from concentrating large volumes at midnight boundaries and provides consistent protection regardless of timezone or scheduling patterns.
    </Note>

    Volume is tracked per asset. An agent operating on both USDC and USDT has separate daily accumulators for each, each subject to the same `maxDailyVolume` value defined in the mandate.
  </Tab>

  <Tab title="Lifetime Limit">
    An optional cumulative lifetime cap can be added to a mandate to impose an absolute ceiling on the total volume an agent may ever execute under that mandate. Once the lifetime limit is reached, all further transactions are rejected regardless of the per-transaction or daily limits.

    Lifetime limits are particularly useful for mandates tied to specific operational campaigns (e.g., a treasury rebalance program with a fixed total budget) where the principal wants an automatic hard stop rather than relying on manual revocation.
  </Tab>

  <Tab title="Cooldown Periods">
    Cooldown periods enforce a minimum time interval between consecutive large transactions. A principal can configure a threshold amount and a cooldown duration: any transaction above the threshold triggers a cooldown window during which the agent cannot submit another transaction above the same threshold.

    For example: transactions above \$25,000 must be separated by at least 1 hour. This limit protects against rapid sequential execution patterns that could indicate a compromised agent or exploit attempt, even if each individual transaction falls within the per-transaction cap.
  </Tab>

  <Tab title="Rate Limiting">
    Rate limiting constrains the *number* of transactions an agent may submit within a rolling time window, regardless of individual transaction size. A mandate can specify a maximum transaction count per hour (e.g., no more than 20 transactions per 60-minute rolling window).

    Rate limits are enforced independently of volume limits — a transaction can satisfy all spending caps and still be rejected if the agent has exhausted its rate allocation for the current window.
  </Tab>
</Tabs>

## On-Chain Enforcement

All spending limits are enforced by the `MandateRegistry` contract in a single validation call that precedes every execution. The contract evaluates limits in the following order:

1. Mandate existence and `ACTIVE` state check
2. Action type is within `permittedActions`
3. Asset is within `allowedAssets`
4. Mandate has not expired (`block.timestamp < expiresAt`)
5. Transaction amount does not exceed `maxTransactionAmount`
6. Adding this transaction would not exceed `maxDailyVolume` for this asset
7. Lifetime limit not exceeded (if configured)
8. Cooldown period has elapsed since last large transaction (if configured)
9. Rate limit window has not been exhausted (if configured)

If any check fails, the entire transaction reverts with a structured error indicating which check failed and the current state of the relevant limit. This allows agent implementations to handle rejections gracefully and schedule retries when appropriate.

## Querying Current Usage

Agents and monitoring systems can query the current spending state for any agent address and asset pair directly from the `MandateRegistry`:

```js theme={null}
const usage = await mandateRegistry.getDailyUsage(agentAddress, assetAddress);
// returns { used: BigInt, limit: BigInt, resetAt: number }
```

The returned object contains:

* `used` — cumulative volume executed by the agent in the current rolling 24-hour window, in the asset's base units
* `limit` — the `maxDailyVolume` defined in the agent's active mandate for this asset
* `resetAt` — the Unix timestamp at which the earliest transaction in the current window will age out, partially restoring available daily capacity

To query the per-transaction cap and rate limit state:

```js theme={null}
const limits = await mandateRegistry.getMandateLimits(agentAddress);
// returns {
//   maxTransactionAmount: BigInt,
//   maxDailyVolume: BigInt,      // nominal limit from mandate
//   effectiveDailyLimit: BigInt, // lower of maxDailyVolume and trust-score tier cap
//   lifetimeLimit: BigInt,
//   lifetimeUsed: BigInt,
//   rateLimit: number,           // max transactions per hour
//   rateWindowUsed: number,      // transactions used in current hour window
//   cooldownThreshold: BigInt,
//   cooldownEndsAt: number       // 0 if no active cooldown
// }
```

## Limit Interactions with Trust Score

Spending limits defined in a mandate represent the *maximum* the agent is authorized to use. However, if an agent's trust score falls below the threshold for its current limit tier, the `MandateRegistry` will apply the lower tier's caps dynamically — even if the mandate nominally permits higher amounts.

This means that a mandate with a `maxDailyVolume` of $500,000 will be operationally constrained to $100,000 if the agent's trust score is in the Standard tier (201–500). See [Trust Scoring](/ai-agents/accountability/trust-scoring) for the full tier table and scoring mechanics.

<Note>
  When a mandate's stated limit exceeds what the agent's current trust score tier permits, the `getMandateLimits` response will reflect the *effective* limit (the lower of the two) in the `effectiveDailyLimit` field, alongside the mandate's `maxDailyVolume` as the nominal limit. Always use `effectiveDailyLimit` when making runtime decisions in agent code.
</Note>
