Docs menu · TypeScript SDK

TypeScript SDK

npm install neltava: authorize a spend, attach the steps that led to it, report the outcome, and choose what happens when Neltava can't be reached.

Updated

Install

terminal
npm install neltava

Zero dependencies; Node 18+, Bun, Deno and edge runtimes. The client reads NELTAVA_AGENT_KEY and NELTAVA_API_URL from the environment when you don’t pass them. Use the agent’s own key — it can only ask for decisions as that agent.

Authorize a spend

One call, right before the agent pays:

agent.ts
import { Neltava } from "neltava";

const neltava = new Neltava(); // NELTAVA_AGENT_KEY

const d = await neltava.authorize({
  task: "Q4 pipeline: enterprise developer leads",
  action: {
    merchant: "Platform Weekly",
    amount: 90.00,
    currency: "USD",
    description: "Sponsored slot reaching platform engineers at enterprise companies",
  },
});

if (d.proceed) {
  // pay d.amount — in Enforce, through your payment adapter with d.capability
}
Parameter
action.merchantWho would be paid. Required.
action.amount / action.amountMinorMajor units (49.99) or exact minor units (4999). Required.
action.currencyISO-4217. Required.
action.descriptionWhat, and why it serves the task.
action.typepurchase (default), subscription, top_up…
action.payeeIdThe payee’s id at your rail (domain:clearbit.com, stripe:acct_…).
action.categoryA declared category — recorded as a claim, never trusted to allow.
taskWhat the agent is working on in this run.
limitableMay Neltava cap the amount instead of sending it to a person? Then over-limit spends come back as LIMIT.
minAmountMinorWith limitable: below this, a capped spend isn’t useful — send it to a person instead.
agentOnly with a non-agent key: the agent’s slug.
idempotencyKeyRetries with the same key return the same decision. Generated if omitted.

The decision

Field
proceedGo ahead: effective ALLOW or LIMIT. In Shadow Mode, always true.
needsReviewA person must decide (effective REVIEW, Enforce only).
amount / amountMinorWhat may be spent — the capped amount on LIMIT; null when it may not.
decision / effectiveDecisionNeltava’s verdict / what applies now.
reasonCode, reasonCodesStable codes to branch on — all of them.
explanationA sentence for people. Don’t parse it.
modeSHADOW or ENFORCE.
decisionIdThe record in your console; use it to report the outcome.
capabilityEnforce: the single-use token for this payment. Null in Shadow Mode.
sourceneltava, or fallback when onUnavailable decided.

Attach the steps

Purpose checks are sharper with the agent’s own account of how it got here. A run collects steps (kinds: search, evaluate, select, tool_call, purchase, other) and sends them with the request. They are evidence, never instructions.

with a run
const run = neltava.run("Find enterprise developer leads");
run
  .step("Compared three data vendors", "evaluate")
  .step("Picked Clearbit", "select", "vendor_search");

const d = await run.authorize({
  action: { merchant: "Clearbit", amount: 49, currency: "USD", description: "Enrichment credits" },
});

Report outcomes

After paying — or failing to — report what happened, so budgets and the report reflect real spend:

after the payment
await neltava.reportOutcome(d.decisionId!, {
  type: "SPEND_EXECUTED",   // SPEND_FAILED · SPEND_CANCELLED · REFUNDED · PARTIALLY_REFUNDED
  amount: 49,
  currency: "USD",
  externalReference: charge.id, // makes a retried report idempotent
});

An agent’s report is recorded as CLIENT_REPORTED. It never releases reserved budget; a payment adapter’s PAYMENT_RAIL report does. See outcomes and budget.

When Neltava can’t be reached

Requests retry network errors, timeouts, 429 and 5xx with the same idempotency key, so a retry never creates a second decision. After that, onUnavailable decides:

onUnavailable
"throw" (default)Throws NeltavaUnavailableError — you decide.
"review"Treated as needing a person; does not proceed.
"deny"Does not proceed.
"allow"Proceeds only while Neltava has confirmed, in this process, that the agent is in Shadow Mode. In Enforce, when the mode isn’t known yet, or on a rate limit, it acts as "review". There is no fail-open in Enforce.

A response that doesn’t look like a decision is treated as unavailable — it never lets money move. Fallback decisions carry source: "fallback" and reasonCode: "NELTAVA_UNAVAILABLE".

Errors

errors
import { Neltava, NeltavaError, NeltavaUnavailableError } from "neltava";

try {
  const d = await neltava.authorize({ action });
} catch (err) {
  if (err instanceof NeltavaUnavailableError) {
    // network, timeout, 5xx or 429 after retries (err.rateLimited on 429)
  } else if (err instanceof NeltavaError) {
    // the API refused the request: err.status, err.code, err.requestId
  }
}

Error codes are listed in the HTTP API reference.

Options

new Neltava({…})Default
apiKeyNELTAVA_AGENT_KEY (or NELTAVA_API_KEY)
baseUrlNELTAVA_API_URL or https://api.neltava.com
timeoutMs10000
maxRetries2
onUnavailable"throw"
fetchthe global fetch

amount follows the currency’s minor unit (USD 49.99, JPY 5000, KWD 1.250); pass amountMinor for exact integers.

More methods

neltava.authority(slug)

The agent’s current authority and its version — for an agent that plans within its limits.

neltava.agent(slug)

The agent’s record: status, mode, current authority version.

neltava.consumeCapability(…)

For your payment service, with a Payment adapter key — never the agent’s: spends the capability for the exact payment you’re about to make, or throws (capability_used, payee_mismatch, amount_exceeds_capability…). See Enforce at the payment point.