Decision Agents
A decision agent answers small, structured questions about text the model
supplies. When the model calls the decision_agent tool, Polytoken sends the
text plus up to sixteen named questions to your configured decision backend
and returns one typed answer per question. The model decides when a judgment
helps. You decide which backend Polytoken uses. When no backend is configured,
the system prompt tells the model, so it will not attempt the tool and will let
you know if you ask it to use one.
Decision calls are fast and cheap compared with a full model turn, so they suit high-frequency judgments: does this message convey urgency, which team should handle this ticket, how frustrated is the customer. Results are model estimates, not verified facts. Treat them as signals to reason over, never as ground truth.
Question kinds
Section titled “Question kinds”Every question has a name the model chooses. Answers come back under the same names, so one call can carry several unrelated questions.
Predicate
Section titled “Predicate”A yes/no condition over the input text, phrased as a statement.
{ "name": "wants_cancellation", "type": "predicate", "condition": "the customer is asking to cancel their subscription"}The answer carries a boolean value and, when the backend reports one, the
probability behind it. When the backend returns only a probability, Polytoken
derives the boolean at the 0.5 threshold and appends a disclosure warning to
the result so the model knows the boolean was derived.
Choice
Section titled “Choice”A pick-one decision among two or more named options, each with a short description of when it applies.
{ "name": "department", "type": "choice", "prompt": "which team should handle this message?", "options": [ { "name": "billing", "description": "payments, invoicing, refunds" }, { "name": "technical", "description": "bugs, outages, integrations" }, { "name": "sales", "description": "pricing, upgrades, new accounts" } ]}The answer names the selected option and includes the full probability distribution over every option, plus a confidence value when the backend reports one.
Backends report probabilities with different precision. Polytoken judges each backend against its own documented output precision. A strict backend must sum to 1 within 0.000001. The System One family reports four-decimal probabilities, so Polytoken lets a distribution from that family miss 1 by one rounding step per option. Either way, Polytoken renormalizes a distribution that lands inside its backend’s bound so it sums to one (with a warning), and the response keeps the raw probabilities the backend actually sent alongside the normalized ones, so you can always see both. Polytoken rejects a distribution outside the bound as a malformed response.
A rating on an ordered scale you define. Each level has a name, a description, and a numeric value. Levels must be listed in increasing value order.
{ "name": "frustration", "type": "score", "prompt": "how frustrated is the customer?", "levels": [ { "name": "calm", "description": "no frustration expressed", "value": 0 }, { "name": "frustrated", "description": "clear annoyance", "value": 1 }, { "name": "very_angry", "description": "explicit anger or threats to leave", "value": 2 } ]}The answer includes the selected level, the probability distribution over every level, and a probability-weighted value computed over your level values. That weighted value can land between levels. Polytoken recomputes it from the normalized reported probabilities and your level values, never from the backend’s own arithmetic, and appends a warning when it differs from the value the backend reported.
Reading the result
Section titled “Reading the result”A successful call returns one JSON document: backend provenance (the
configured instance, the backend family, and the concrete model that
answered), one answer per question in request order, and a warnings list.
Warnings disclose every transformation Polytoken applied: derived predicate
booleans, distributions that needed renormalization to sum to one, and
score values Polytoken recomputed. A backend can decline to answer a single
question; that answer is a refusal, not an error, and the other answers are
unaffected.
Failures return a short normalized code and message, such as
rate_limited or authentication. Polytoken makes exactly one attempt per
call: there are no retries and no fallback to another backend.
Configuring the backend
Section titled “Configuring the backend”Decision backends live under integrations.decisions in your configuration
file. You may configure several backends, and active names the single one
that serves calls. Selection is exclusive: exactly one backend is active,
and Polytoken never rotates or fails over between backends. This is a
deliberate design choice, so a judgment always comes from the model you
chose.
Polytoken supports two backend families in this release:
- TypeSafe (
type: typesafe): the Jev decision models at docs.typesafe.ai. Get an API key at typesafe.ai.modeldefaults tojev-latest, a rolling alias for the newest release; the result’s provenance reports the concrete version that answered.
integrations: decisions: active: primary backends: primary: type: typesafe key: ${TYPESAFE_API_KEY} model: jev-latest-
System One hosts (
type: systemone): any host that speaks the System One decision contract. The host comes frombase_url, so a provider speaking the same contract is a configuration entry rather than new Polytoken code. Neuralwatt Clef Flash is the first configuration:integrations:decisions:active: neuralwattbackends:neuralwatt:type: systemonebase_url: https://api.neuralwatt.commodel: clef-flashkey: ${NEURALWATT_API_KEY}base_urlis the origin before/v1: Polytoken appends/v1/systemoneto it, so the value above serveshttps://api.neuralwatt.com/v1/systemone. A trailing slash is fine. A value that already ends in a/v1segment fails validation with a message explaining the convention, because it would double the segment. Clef Flash access requires enrollment with Neuralwatt; a model your account cannot reach, and a model name that does not exist, comes back as a not-found rejection. Unliketypesafe, thesystemonefamily has no defaultmodel, so set the host’s model name explicitly. A key configured on an inference provider is never reused for a decision backend; give each decision backend its own key.
The key is usually an environment reference, resolved when Polytoken loads
its configuration. With no active backend, the tool returns an error naming
integrations.decisions.active so the model can tell you what is missing.
Other backend families were evaluated and are not implemented in this release: OpenAI Decisions, Liquid d1, Cloudflare Clef, OpenRouter, and self-hosted System One servers. Configuring one of these types fails configuration validation with a pointer to the compatibility notes, so a typo cannot silently disable your decision calls.
A configuration written for this release can fail to load on an older
Polytoken build: older builds reject the systemone type and the
base_url key instead of ignoring them.
The Decisions pane in the interactive configurator (polytoken config ui)
edits backend instances and selects the active one without editing the file
by hand. The pane offers the backend type as a selector, and a systemone
instance asks for its base URL and model. Saving several backends without
an active selection fails with the same validation message the loader
produces. See Application Configuration for
the full key reference.
Permissions
Section titled “Permissions”The first decision_agent call in a session asks for your approval, because
the tool sends your text to the configured backend. An explicit permission
rule can allow it always:
permissions: allow: - tool: decision_agentSee Permission Rules for rule syntax and scopes.
Related pages
Section titled “Related pages”- Tool Reference: the
decision_agenttool contract. - Application Configuration: the full
integrations.decisionsschema. - Web Search: another hosted integration with its own provider configuration.