Skip to main content
A policy is a set of rules that defines what an agent is allowed to do. Policies are stored onchain in the FunctorPolicyHook contract and enforced by the EVM before every transaction executes. The agent gets a policy, not a private key. This is the fundamental security property.

Policy types

PolicyWhat it enforces
allowed_contractsAgent can only interact with whitelisted contract addresses
allowed_functionsAgent can only call whitelisted function selectors
spending_limitRolling, time-windowed cap per token (e.g., 1000 USDC per day)
rate_limitMax transactions per time window, tracked across sessions
expires_atHard expiry - the policy stops working after this timestamp
customPluggable policy contracts for specialized logic (e.g., max slippage on swaps)

How policies are evaluated

Before every transaction, the FunctorPolicyHook runs all policies attached to the signing key. Every policy must pass. Any single failure reverts the transaction.

Rolling time-windowed limits

This is where Functor differs from existing session key modules. Existing tools offer lifetime spending caps - once the limit is hit, the session is dead. The developer must create a new session. There is no “1000 USDC per day that resets tomorrow.” Functor tracks spending per time window. When the window rolls over, the counter resets:
TimeSpent todayLimitAction
9:00 AM0 USDC1000/dayAgent sends 400 USDC - allowed
2:00 PM400 USDC1000/dayAgent sends 500 USDC - allowed (900 total)
5:00 PM900 USDC1000/dayAgent sends 200 USDC - blocked (would exceed 1000)
Next day0 USDC1000/dayCounter resets. Agent can spend again.

Cross-session state

When a developer creates a new session key for the same agent, existing tools reset all counters to zero. The agent gets fresh limits, effectively bypassing the spending cap. Functor tracks policy state per keyId in the KeyStore, not per session. A new session key linked to the same keyId inherits the existing counters. Spending limits are cumulative across sessions.

Policies can be updated live

The developer can add, modify, or remove policies on an existing keyId at any time - without creating a new session key, without resetting counters. This is done through the dashboard or the SDK:
functor.setPolicies(keyId, [
  { type: 'spending_limit', token: USDC, amount: '1000', window: '24h' },
  { type: 'allowed_contracts', addresses: [UNISWAP_ROUTER, AAVE_POOL] },
  { type: 'rate_limit', max: 10, window: '1h' },
])
The transaction writes the policy configuration directly to the FunctorPolicyHook contract onchain.