DocsAPI reference
Decisions API
Call a saved Jev decision with POST /v1/decisions/{slug}: outcome, confidence band, pins, deadline and fallback, single or batches of up to 500 items.
INFRO is in private early access. Running these examples requires an early-access account, an active trial or subscription entitlement, and your own provider connection. Self-serve purchasing is not generally open. See Early access.
A decision policy is a saved question for Jev with INFRO's thresholds around it. Your application sends only the facts (state); the question, what each outcome means, the confidence bands, pinned outcomes, the deadline and the fallback live in the policy, edited in the console under Decisions and versioned.
Every Jev call runs on your own TypeSafe connection and your TypeSafe account bills it; every other decision model runs on your own account with its provider. INFRO charges nothing per decision; the estimated provider cost of each call is on its row in the request log, separate from your INFRO subscription.
Decide
curl https://api.infro.io/v1/decisions/tool-gate \
-H "Authorization: Bearer $INFRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"state": {
"request": "Tidy up my inbox",
"tool": { "name": "delete_emails", "arguments": { "older_than_days": 30 } }
}
}'statestring | object | arrayrequired- The facts the decision is about. At most 128 KB as JSON. Never stored.
deadline_msinteger- Overrides the policy's deadline for this call, 50–10000 ms.
metadataobject- Attribution and tags, as on every endpoint. Recorded on the row.
{
"id": "req_…",
"object": "decision",
"policy": "tool-gate",
"version": 3,
"outcome": "ask",
"label": "Should run only after the user confirms: it changes or deletes data, spends money, or contacts other people.",
"band": "confirm",
"confidence": 0.71,
"source": "model",
"probabilities": { "allow": 0.12, "ask": 0.81, "deny": 0.07 },
"score": null,
"latency_ms": 150,
"model": "typesafe/jev-1.13",
"usage": { "input_tokens": 412, "output_tokens": 0, "cost": 0.0000173, "price_source": "list" },
"route": "primary",
"route_name": null,
"provider": "typesafe",
"connection": "conn_…"
}| Field | Meaning |
|---|---|
outcome | yes/no for a yes-or-no question, an option key for a choice, a level index for a score. |
label | What the outcome means, in the policy's own words. |
band | act, confirm or human, from the confidence and the policy's thresholds. |
confidence | 0 to 1. A pin answers 1; a fallback answers 0. |
source | model, pin (decided by rule before any model call) or fallback. |
probabilities | Per outcome. Null for a pin or a fallback. |
score | Score questions: the expected level, which can sit between two levels. |
fallback_reason | Present when the fallback answered: the deadline passed or the provider failed. |
import os
import requests
answer = requests.post(
"https://api.infro.io/v1/decisions/inbox-triage",
headers={"Authorization": f"Bearer {os.environ['INFRO_API_KEY']}"},
json={"state": {"from": "dana@customer.example", "subject": "Invoice before Friday", "body": "…"}},
timeout=10,
).json()
if answer["band"] == "act":
route_email(answer["outcome"])
elif answer["band"] == "confirm":
ask_user_to_confirm(answer["outcome"])
else:
send_to_a_person()Pins
A pin decides by rule before any model call: when a dot path into the state (tool.name) is, is one of, starts with, ends with or contains a value, the outcome is fixed. The first matching pin answers with source: "pin", confidence 1 and band act, costs nothing and needs no connection. Use pins for the cases that must never depend on a classifier — a tool that may never run.
Deadline and fallback
A policy can set a deadline. When Jev has not answered by then — or when every connection fails — the policy's fallback answers with source: "fallback", the band the policy chose for it and a fallback_reason. A missed deadline is never counted against the health of your connection. With no fallback, a missed deadline is 408 decision_deadline and a provider failure is the usual chain-exhausted error.
Batches
curl https://api.infro.io/v1/decisions/ticket-labels/batch \
-H "Authorization: Bearer $INFRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"concurrency": 8,
"items": [
{ "id": "t-1001", "state": { "title": "Charged twice", "body": "…" } },
{ "id": "t-1002", "state": { "title": "Export hangs", "body": "…" } }
]
}'Up to 500 items per request, decided on one of your connections at the chosen concurrency (default 8). Each result carries its index and your id. An item your provider rejects is that item's error; the others are still decided. summary counts outcomes, bands and sources (and the mean score for a score question), so a large table is labelled as a series of batches whose summaries add up. A batch is one row in the request log.
List policies
GET /v1/decisions lists the enabled policies the key may call, with each one's question type, outcomes and what they mean, bands, pin count, fallback and deadline. A policy limited to a project is listed only for that project's keys.
Eval monitors
A policy with an eval monitor scores a share of your served chat completions in the background, after the answer has been returned: the policy sees {prompt, response} (the latest user message and the model's answer). Each score is its own call to the policy's decision model, on your own account with its provider, recorded under the request it judged; the policy's console page shows the mean score per served model. Answers served from INFRO's response cache are not scored again.
Errors
| Status | Code | When |
|---|---|---|
| 404 | decision_policy_not_found | No enabled policy with that slug that this key may call. |
| 400 | state_too_large | The state is larger than 128 KB. |
| 400 | batch_too_large | More than 500 items in a batch. |
| 408 | decision_deadline | The deadline passed and the policy has no fallback. |
| 502 | unreadable_decision | The provider answered without a readable decision and the policy has no fallback. |