Skip to content

Documentation navigation

Using Decisions

Choose finite answers with explicit privacy requirements and conservative fallbacks.

#Using Decisions

Use a decision when an application needs one answer from a small, declared set: route a public ticket, decide whether a full review is needed, or choose among already retrieved public candidates. Keep your existing implementation as the fallback.

These pages describe the prepared decision-feature release. Use an SDK build containing maivn.decisions and a platform deployment with the decision API available. See the complete API reference and examples.

#Choose the workflow

NeedPublic APIWhat remains under your control
One categoryDecisionClient.decide / adecideComplete request, local authorization and async fallback
Several answersbatch / abatchOrder, concurrency and optional native packet grouping
Decisions around an invocationAgent.decide / Swarm.decideBefore/after stages, gates and explicit input mapping
Boolean or string argumentsDecisionArgumentPreparerExact choice-to-value mapping and unresolved-field handling
Function/local-tool dependenciesdepends_on_decision, DecisionStep, decision_flowDependency order, execution gates and result injection
Matching after retrievalDecisionCandidateMatcherAuthorized candidates and exact baseline selection
Separate token counterssummarize_decision_usageReceipt ownership and unknown usage

These developer opt-ins do not imply every engine optimization is enabled. Ordinary generation still runs unless an accepted, explicitly declared gate skips it. A decision adds work; cost or latency improves only if it avoids enough other work. Measure the entire workflow rather than assuming every invocation becomes cheaper.

#Authorize complete requests

Declare 2–32 unique choices, bounded state and clear instructions. privacy defaults to unknown, preventing primary dispatch. Use privacy='public' only when the exported packet is appropriate to send through the platform. A synchronous authorize(request) callback must return exactly True for the complete request. Fixed requests can use an exact allowlist; dynamic questions need an application policy reviewing their full proposed content.

Builders and decorators are lazy. Terminal methods execute the workflow. Use sync methods outside an active event loop; use adecide, abatch, ainvoke, astream, aprepare and amatch inside async applications.

#Privacy is explicit

Plain messages and unmarked public decision text receive no automatic redaction, placeholders or privacy refusal solely because they resemble personal data. Declaring privacy='public' is an export permission, not automatic detection.

For known private values in otherwise public text, declare DecisionRequest(private_data={'customer_name': value}, ...). The declaration goes to the platform, which shields marked values before the decision model sees the packet and refuses unsafe shielding. Returned private placeholders are resolved locally. The original request still holds the values in your application; do not log or persist it.

privacy='private' or unknown retains the fallback without primary dispatch. Local authorization cannot override those gates. For agent messages, declare private_data or use RedactedMessage; see Private Data. Each decision checks its own exported request. A surrounding private context does not authorize exporting its raw values.

Matching requests have no private_data field. Supply approved public excerpts or keep the baseline. Retrieval does not grant export permission.

#Preserve the incumbent on abstention

Your async fallback returns a declared DecisionAnswer. Wrap the existing model-based implementation or a local rule. A local rule uses token_category=None; an ordinary-model fallback uses llm.

Disabled, unauthorized, private/unknown, refused, malformed, low-confidence, unavailable and timed-out attempts use the fallback at most once per question. Invalid fallback answers and fallback exceptions propagate. Cancellation propagates instead of starting another route. Primary timeout does not bound the fallback or establish an invoice limit.

A before-stage require gate skips execution only when an accepted primary answer differs from its required choice. Every fallback preserves the normal invocation/function, even if its returned choice differs. After stages annotate completed output and cannot gate it. Messages are unchanged unless explicitly mapped with map_input.

Argument preparation includes only accepted primary values; absent fields keep your existing preparation in control. It does not inject tool arguments automatically. Dependency decorators declare metadata: execute through decision_flow or SDK-local tool registration; a direct Python call is ordinary. Factories receive a local bound-argument snapshot, including defaults; optional state narrows it. The factory must explicitly build and authorize the exported request.

#Batching and usage

Batches preserve order and bound concurrency. native_batch=True groups equal state/private declarations and splits at max_batch_questions. Every member of a shared packet must pass authorization.

One native packet has one receipt: the first result owns it; followers expose batch scope/size without duplicating usage. Aggregate the complete result set. Missing counts stay unknown, with known subtotals available separately. Decision and LLM counters are distinct categories, not interchangeable prices or a dollar-cost estimate.

#Matching preserves the baseline

Matching is disabled by default. candidate_match_questions constructs complete public questions for authorization without inference. When enabled, selection changes only if every question has an accepted primary yes/no answer and at least one candidate matches. Accepted matches keep candidate order and the result cap. Refusal, uncertainty, errors, oversize input, timeout and no-match retain the exact baseline keys without truncating or reordering them.

#Responses and streaming

A plan returns DecisionInvocationResult with the separate InvokeResponse, nested decisions and completed/skipped status. A managed function returns DecisionCallResult with its native value.

Streams add content-free stage/plan events to normal invocation events. Read DecisionStreamEvent.outcome locally; it is excluded from serialized data.

Ordinary InvokeResponse.privacy_guidance is separate advisory feedback, not a decision result. It may include actual delivered values. Display it only to a trusted developer and never log or persist it. It neither removes redaction nor changes a whitelist automatically. See over-redaction guidance.