Spend Controls
Programmable budgets for your agent wallets. Cap spending per vendor, per task, per API, or across your whole team — with optional time windows.
Scope: one ledger, one policy set. Spend controls cap every paid call Floe settles — x402 vendors through the proxy (
POST /v1/proxy/fetch) and LLM/voice tokens through the keyless gateway (POST /v1/chat/completions, hostcredit-api.floelabs.xyz); the legacy BYOK metered proxy/v1/llm/chat/completionsis capped the same way. Route both through Floe and a single task or session budget bounds the entire conversation cost across every vendor. The one thing a policy can't see is a call you send straight to a provider with your own key, bypassing Floe — so route it through Floe.
Policy Types
Session
Total agent spend
Everything
"$100/day soft cap"
Vendor
Spend to a specific payee wallet
Payment recipient address
"$20/day to Venice AI"
API
Spend to a hostname or domain
Target URL hostname
"$100/week to *.venice.ai"
Task
Spend on a specific task ID
X-Floe-Task-Id header
"$5 budget for task-research-123"
Most types are agent-scoped (one agent wallet) or team-scoped (all your agent wallets combined); the session kind and the session window are team-scoped only (/v1/developer/policies).
Quick Start
Set a daily vendor cap
curl -X POST https://credit-api.floelabs.xyz/v1/developer/agents/1/policies \
-H "Authorization: Bearer $FLOE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"kind": "vendor",
"matchKey": "0xB77561F454F10Ce87C93EfFC4682102017f4CE86",
"limitRaw": "50000000",
"windowKind": "rolling",
"windowSeconds": 86400
}'This creates a $50/day rolling cap for a specific vendor wallet. Any x402 call where the payment recipient matches this address counts against the limit.
Set a per-API hostname cap
This caps all calls to *.venice.ai at $100/week.
Set a team-wide budget
This caps total spend across ALL your agent wallets at $500/month.
Time Windows
Policies can be scheduled with calendar bounds:
effectiveFrom — Policy is inactive before this timestamp (UNIX seconds)
effectiveUntil — Policy auto-expires after this timestamp
Useful for campaign budgets, time-boxed experiments, or scheduled spending windows.
Window Kinds
rolling
Resets every windowSeconds
Daily/weekly/monthly budgets
session
Resets when you call PUT /spend-limit
Manual session caps (team policies only)
once
Single-shot cap, expires at expiresAt
Pre-borrow task holds
Matching Rules
Vendor policies
Match against the payment recipient address (the wallet that receives USDC). Lowercased, exact match.
API policies
Match against the target URL hostname:
host_suffix(default):.venice.aimatchesapi.venice.ai,x402.venice.ai,venice.aihost_exact:api.venice.aimatches onlyapi.venice.ai
Task policies
Match against the X-Floe-Task-Id header sent with each proxy call. Case-insensitive.
Enforcement
Policies are checked on every POST /v1/proxy/fetch call, inside the same transaction as the balance reservation. If any policy would be exceeded, the call is rejected with 402:
When the breached policy is a kill-switch (action: "suspend_agent", see below), the same body additionally carries "auto_suspended": true. The field is present only in that case — a plain breach omits it:
suspendedReason is not part of the 402 body — it lives on the agent record (GET /v1/developer/agents/:agentId) as the audit trail for why the agent is suspended.
Spend is calculated from settled + in-flight payments. Refunded/failed calls automatically drop out of the spend sum.
Breach Action: the Policy Kill-Switch
By default a breach only declines the single call (the agent can keep trying). Set action: "suspend_agent" on a policy to turn it into a kill-switch: the breaching call still gets the 402 above (with "auto_suspended": true), and the whole agent is suspended — every subsequent call is rejected at authentication with 403 until you resume it.
A runaway agent that blows through this $10/day task budget is stopped cold instead of burning retries against a 402 wall.
Notes:
Omitted or
"block"preserves the default decline-one-call behavior.Only a genuine over-limit breach trips the switch. Fail-closed denials (e.g. an
apipolicy that can't resolve the target hostname) decline the call but never suspend.Team-scoped policies:
actionis accepted on team policies too. A breach suspends the single agent whose call crossed the cap — never the whole team. The team cap keeps counting every agent's spend, so once it's saturated, each additional agent trips itself on its next paid call.The suspension is auditable: the agent record's
suspendedReason(GET /v1/developer/agents/:agentId) readspolicy:<id>, and the dashboard's agent page shows which policy tripped it.Resume via the pause/resume endpoint below or the dashboard — the policy stays active, so an unresolved budget breach will trip it again.
Value-Aware Caps (X-Floe-Task-Value)
A static cap treats a $0.10 spam-filter run and a $500-revenue lead-enrichment run the same. Value-aware caps let one policy definition flex with the business value of the task — inside operator-set bounds.
Enable it by giving a policy scaling bounds:
The caller then sends X-Floe-Task-Value (basis points; 10000 = 1×) on its paid calls:
Security model — the header is caller-supplied and untrusted by construction:
A policy without bounds ignores the header completely. Nothing changes for existing policies.
With bounds, the header can only move the cap between
limitFloorRawandlimitCeilingRaw— both operator-set (floor ≤ limitRaw ≤ ceiling, enforced at the API and by DB constraints). A caller can never grant itself more than the operator provisioned.An unset side clamps at
limitRaw: a bare ceiling enables upscaling only, a bare floor downscaling only.Enforcement,
/forecastpreflight, and theX-Floe-Budget-Advisoryheader all report the same effective cap (one shared computation — they cannot drift).
Accepted range for the header: integer 1..100000 (0.0001×–10×); anything else is ignored (1×).
Outcome-Quality Throttle (throttle on value, not just cost)
Cost caps stop an agent from spending too much; the quality throttle stops it from spending too much on work that isn't working. It consumes the caller-reported outcome signal from Outcome-Linked Spend Attribution — Floe never judges quality; your agent's own reports drive it.
How it behaves:
Floe averages the agent's reported outcomes in the window (
scoreBpswhen reported; otherwisesuccess→100%,partial→50%,failure/unknown→0%) into a quality reading.The effective cap is multiplied by
max(quality, qualityThrottleFloorBps)— successive low-quality actions tighten spend toward the floor even under budget; recovering quality relaxes it back to 1×.No reported outcomes in the window → factor 1.0 — behavior unchanged. No signal, no change: the throttle is deliberately fail-open (unlike the fail-closed host/recipient guards) because quality is an optional caller-supplied signal, not a resolvable request fact.
With value scaling on the same policy, quality applies after it; an operator
limitFloorRawstill bounds the result from below.The reading is cached for ~30s, which also damps a flapping signal.
Trust boundary, stated plainly: quality is self-reported. An agent that lies about its own quality can avoid being throttled — the throttle protects you from honest runaway waste (retry loops, degraded upstream output), not from an adversarial agent. Hard caps remain the backstop.
Pause / Resume an Agent (self-serve kill-switch)
Pause one agent without touching the rest of your fleet — no key rotation, no close:
Takes effect on the agent's next call (403 at authentication).
Only
active ↔ suspendedtransitions are allowed. Closed or credit-frozen agents can't be resurrected through this endpoint (409) — those states belong to their own lifecycle flows.Resuming clears
suspendedReason; pausing sets it todeveloper_manual.
API Reference
Per-Agent Policies
GET
/v1/agents/policies
Agent key
List active policies
POST
/v1/agents/policies
Agent key
Create policy
PATCH
/v1/agents/policies/:id
Agent key
Update limit/bounds
DELETE
/v1/agents/policies/:id
Agent key
Revoke policy
POST
/v1/agents/policies/:id/reset
Agent key
Reset rolling window
Same routes available at /v1/developer/agents/:agentId/policies with session cookie auth.
Agent Status (kill-switch)
PATCH
/v1/developer/agents/:agentId/status
Session cookie
Pause (suspended) or resume (active) one agent
Team Policies
GET
/v1/developer/policies
Session cookie
List team policies
POST
/v1/developer/policies
Session cookie
Create team policy
PATCH
/v1/developer/policies/:id
Session cookie
Update
DELETE
/v1/developer/policies/:id
Session cookie
Revoke
Create Policy Body
Dashboard
Policies can also be managed from the Developer Dashboard:
Per-agent: Agent detail page → Policies section
Team-wide: Settings → Team Policies
Last updated
