Agents
An agent is anything in your system that spends on its own: an ad-buying loop, a research assistant, a procurement bot. You register each one in the console (or through the API) with a slug like growth-agent. Each agent has its own key, its own authority and its own mode, and can be paused or revoked at any time — a paused agent is blocked immediately.
Authority
Authority is what you delegate: the rules the agent spends under. It is immutable and versioned — every change creates a new version, and every decision records the exact version (and its hash) it was made under.
{
"purpose": {
"objective": "Acquire qualified enterprise developer leads",
"success_criteria": [
"Leads are platform engineers at enterprise companies",
"Cost per qualified lead under $120"
],
"constraints": [
"No consumer social campaigns",
"Never buy contact lists"
],
"context": "B2B developer-tools company, Q4 pipeline push"
},
"currency": "USD",
"per_transaction_limit_minor": 50000,
"review_threshold_minor": 25000,
"monthly_budget_minor": 500000,
"blocked_merchants": [
"ListBroker"
]
}| Field | What it does |
|---|---|
currency | The agent’s currency. Required. |
per_transaction_limit_minor | Above this, a person decides (or the amount is capped). Required. |
per_transaction_hard_max_minor | Above this, always blocked. |
daily_budget_minor, monthly_budget_minor | Windowed budgets (UTC day and month). At least one is required. |
review_threshold_minor | Above this, a person decides even within every limit. |
velocity | { max_count, window_seconds } — stops a looping agent long before the budget does. |
aggregate_limits | Totals per merchant, category or agent over a sliding window — catches a spend split into small ones. |
allowed_merchants, blocked_merchants | Matched after normalization (case, punctuation, legal suffixes); a payee_id is matched exactly. |
allowed_categories, blocked_categories | Category rules. A category the caller only claims is never trusted to allow. |
allowed_action_types | e.g. purchase, subscription, top_up. |
valid_from, expires_at | When the authority is in force. |
purpose | See below. |
Workspace policy (console → Settings) adds hard rules for every agent — prohibited merchants and blocked categories — checked before any agent’s own authority.
Purpose
Limits say how much; purpose says what for. It has an objective, success_criteria, optional constraints (what the agent must never spend on) and context. For every spend, Neltava assesses whether it serves the purpose, using the agent’s task, the trace of steps it took and the spend itself — as evidence, never as instructions. (Why purpose matters.)
The order of checks
Every decision runs the same stages, in this order, and returns each step in policy_trace:
| Stage | Question |
|---|---|
| Identity | Is the agent active, and whose key is this? |
| Authority | Is there authority in force right now? |
| Action type, currency | Is this kind of spend, in this currency, allowed? |
| Merchant, category | Blocked or outside an allow-list? |
| Transaction | Above the hard maximum or the per-transaction limit? |
| Velocity | Too many spends in the window? |
| Budget | Would it exceed the daily or monthly budget (reserved + spent)? |
| Aggregate | Would it exceed a windowed total for this payee or category? |
| Review threshold | Above what the agent may spend without a person? |
| Purpose | Does it serve what the agent is for? |
Amount checks (transaction, budget, aggregate) don’t block. When a spend would exceed one, it goes to a person — or, if the request is limitable, it is capped to the largest amount that fits every bound: LIMIT.
Verdicts
Each decision has a decision — Neltava’s verdict — and an effective_decision — what the caller should do now.
| decision | In Shadow Mode | In Enforce |
|---|---|---|
| ALLOW | proceed | proceed, for the requested amount |
| LIMIT | proceed | proceed, for at most authorized_amount_minor |
| REVIEW | proceed | wait: a person allows or denies in the console |
| BLOCK | proceed | do not spend |
Branch on effective_decision (the SDK’s proceed), never on the explanation text. The reason_code is stable; reason_codes lists every reason that applied.
Shadow and Enforce
In Shadow Mode every spend is decided and recorded against its own simulated ledger, and effective_decision is always ALLOW: nothing is blocked. The Shadow report shows what would have happened.
In Enforce the verdict takes effect. An allowed spend — and a spend a person approved — carries a capability: a short-lived, single-use token signed by Neltava and bound to the payee, amount ceiling, currency and action. Your payment service pays only after consuming it, so an agent can’t pay around Neltava. See Enforce at the payment point. Enforce is switched on per agent, deliberately, and needs a paid plan.
Reviews and labels
Reviews
A REVIEW goes to the console’s review queue. A person allows or denies it with a reason — the person asking can never review their own request:
- Allow:
SERVES_PURPOSEURGENT_EXCEPTIONPOLICY_TOO_STRICTOTHER - Deny:
OUTSIDE_PURPOSEEXCEEDS_NEEDDUPLICATESUSPICIOUSOTHER
In Enforce the review is the decision. In Shadow it records what you would have done, which is how the report measures Neltava against you. In Enforce, an allow is refused if the agent was paused or its authority changed in the meantime — it must ask again.
Labels
A label is your judgment of purpose — PURPOSE_ALIGNED, PURPOSE_MISALIGNED or PURPOSE_UNCLEAR — on any decision. Labels are the ground truth the Shadow report compares purpose assessments with.
Outcomes and budget
A decision isn’t a payment. Report what actually happened, so budgets reflect reality: SPEND_EXECUTED, SPEND_FAILED, SPEND_CANCELLED, REFUNDED, PARTIALLY_REFUNDED.
- An allowed amount is reserved against the budget until the window ends; usage is the larger of reserved and executed.
- Who reports matters. A payment rail (a payment adapter key) can release a reservation; the agent’s own “it failed” is recorded but never gives budget back — so an agent can’t free up budget by claiming failure.
- Outcomes that contradict the decision are flagged: executed against a block, above the authorized amount, more than once.
Everything — decisions, reviews, labels, outcomes, capability use — is appended to a hash-chained ledger per workspace. GET /v1/ledger/verify re-derives it and reports any edit.
Reason codes
| reason_code | Verdict | Meaning |
|---|---|---|
WITHIN_AUTHORITY | ALLOW | Every check passed. |
LIMIT_APPLIED | LIMIT | Allowed for less: the request was limitable, so the amount was capped to what fits. |
AGENT_INACTIVE | BLOCK | The agent is paused or revoked. |
NO_DELEGATED_AUTHORITY | BLOCK | The agent has no authority yet. |
AUTHORITY_NOT_YET_VALID | BLOCK | The authority starts later (valid_from). |
AUTHORITY_EXPIRED | BLOCK | The authority has expired (expires_at). |
ACTION_TYPE_NOT_ALLOWED | BLOCK | The action type (purchase, subscription, top_up…) isn't among allowed_action_types. |
CURRENCY_NOT_ALLOWED | BLOCK | A currency the agent or workspace doesn't transact in. |
MERCHANT_BLOCKED | BLOCK | The merchant is blocked by the agent's authority or the workspace policy. |
MERCHANT_NOT_ALLOWED | BLOCK | The agent has an allow-list, and this merchant isn't on it. |
CATEGORY_BLOCKED | BLOCK | A blocked category. |
CATEGORY_NOT_ALLOWED | BLOCK | Outside the agent's allowed categories. |
CATEGORY_UNVERIFIED | REVIEW | The agent is limited to categories, and this one is only claimed by the caller. |
CATEGORY_CLAIM_CONFLICT | REVIEW | The claimed category contradicts the trusted one. |
TRANSACTION_HARD_MAX_EXCEEDED | BLOCK | Above per_transaction_hard_max_minor — never, even with a person. |
TRANSACTION_LIMIT_EXCEEDED | REVIEW | Above the per-transaction limit (LIMIT instead, if limitable). |
DAILY_BUDGET_EXCEEDED | REVIEW | Would exceed today's budget (LIMIT instead, if limitable). |
MONTHLY_BUDGET_EXCEEDED | REVIEW | Would exceed this month's budget (LIMIT instead, if limitable). |
AGGREGATE_LIMIT_EXCEEDED | REVIEW | Would exceed a windowed total per payee, category or agent (LIMIT instead, if limitable). |
VELOCITY_EXCEEDED | BLOCK | Too many spends in the window — a looping agent is stopped. |
REVIEW_THRESHOLD_EXCEEDED | REVIEW | Above the amount the agent may spend without a person. |
MINIMUM_AMOUNT_UNSATISFIABLE | REVIEW | Limitable, but what fits is below min_amount_minor. |
PURPOSE_ALIGNED | ALLOW | Assessed as serving the purpose (appears alongside WITHIN_AUTHORITY). |
PURPOSE_UNCERTAIN | REVIEW | The assessment couldn't tell; a person decides. |
PURPOSE_MISALIGNED | REVIEW | Assessed as not serving the purpose; a person decides. |
PURPOSE_UNAVAILABLE | REVIEW | Purpose evaluation failed (timeout, provider error). Never ALLOW, never BLOCK. |
PURPOSE_NOT_EVALUATED | — | Informational: no assessment was attempted (not configured, disabled, or the trial allowance is used up). Changes nothing. |