Google launched the Gemini Decisions API on 11 November 2026, powered by a new model called Gemini Decision 1 (gemini-decision-1). It does something unusual for an LLM endpoint: it never writes text. You send one shared input and a set of typed questions, and it returns calibrated probabilities your code can branch on directly. This tutorial shows how to call it from Python, how the three question types work, and how to build a small support-ticket router with a human-review fallback.
What the Decisions API is for
Agents and backends are full of small judgment calls: which tool to use, which department gets a ticket, whether a message breaks a policy, how severe a bug report is. Most teams handle these by asking a chat model to “answer with one word” and then parsing the reply. That adds latency, costs output tokens and breaks when the model gets chatty.
According to Google’s launch post, Gemini Decision 1 scores your candidate options in a single forward pass instead of generating tokens. The headline facts from Google:
- One shared input (text, images, audio, video or PDF) of up to 256K tokens, with up to 1,000 independent questions per request.
- 150-250 ms end-to-end latency, staying nearly flat from 1 to 100 questions (Google’s own figures).
- $0.10 per 1M input tokens, $0 for output tokens, plus a no-cost tier for prototyping in Google AI Studio.
- The shared input is billed once per request, no matter how many questions you ask.
It is available on the Gemini Developer API (v1beta) and needs the google-genai SDK 3.2 or later.
Setup
Install or upgrade the SDK and export an API key from Google AI Studio:
pip install -U google-genai
export GEMINI_API_KEY="your-key-here"
The client must be created with the v1beta API version, because that is where the Decisions endpoint lives.
Your first decision: a yes/no question
This example comes straight from the shape shown in the official Decisions API docs:
from google import genai
client = genai.Client(http_options={"api_version": "v1beta"})
result = client.decisions.create(
model="gemini-decision-1",
input="The blue mug I ordered on Monday arrived cracked on Wednesday.",
questions={
"is_damaged": {
"type": "noul",
"instructions": "Did the item arrive damaged?",
},
},
)
answer = result.answers["is_damaged"]
print(f"P(yes)={answer.noul:.2f} confidence={answer.confidence:.2f}")
The yes/no type is called noul. Its value is the probability that the answer is yes, and it is always between 0.01 and 0.99. That matters when you set thresholds: a rule like if answer.noul > 0.995 will never match.
The raw JSON response also contains a usage block where total_output_tokens is always 0.
The three question types
noul (yes/no)
Use it for checks such as “Is this a refund request?” You can add criteria with a true_description and false_description when the question alone is ambiguous:
"is_defect": {
"type": "noul",
"instructions": "Is the customer reporting a product defect?",
"criteria": {
"true_description": "The product itself is broken or faulty.",
"false_description": "Preference, sizing, shipping, or pricing complaint.",
},
}
choice (pick one option)
A choice question takes 2 to 255 options. criteria maps each option key to a description. The answer has choice (the winner), probabilities for every option (they sum to 1) and confidence.
One detail is easy to miss: the API sorts option keys alphabetically before scoring, and exact ties go to the alphabetically first key. Don’t rely on key order, and avoid positional names like none_of_the_above. Google recommends a catch-all such as other with an explicit description instead.
score (ordered rubric)
A score question rates the input against ordered levels, from lowest to highest, indexed from 0. The returned score is a probability-weighted average of the level indices, so it can land between levels (for example 1.4). The answer also includes probabilities, a legend that maps indices back to your descriptions, and confidence. Keep the scale linear. Google’s docs warn that scales like 1, 10, 100 skew the average.
Build a ticket router with a human fallback
Here is a practical pattern: ask several narrow questions about the same ticket in one call, then combine the answers with plain Python. Low-confidence results go to a person instead of being automated.
from google import genai
client = genai.Client(http_options={"api_version": "v1beta"})
CONFIDENCE_FLOOR = 0.80
def triage(ticket_text: str) -> dict:
result = client.decisions.create(
model="gemini-decision-1",
input=ticket_text,
questions={
"about_order": {
"type": "noul",
"instructions": "Is this message about an existing customer order?",
},
"department": {
"type": "choice",
"instructions": "Which department should handle this request?",
"criteria": {
"billing": "Payments, invoices, and refunds.",
"technical": "Problems using the product or website.",
"shipping": "Delivery, tracking, and damaged parcels.",
"other": "Anything outside these categories.",
},
},
"urgency": {
"type": "score",
"instructions": "How urgent is this request for the customer?",
"criteria": [
"Not urgent: general question or feedback.",
"Moderate: a problem, but the customer can wait a day.",
"Urgent: money lost, order blocked, or safety issue.",
],
},
},
)
a = result.answers
dept = a["department"]
needs_human = (
dept.confidence < CONFIDENCE_FLOOR
or a["about_order"].confidence < CONFIDENCE_FLOOR
)
return {
"queue": "human_review" if needs_human else dept.choice,
"about_order": a["about_order"].noul >= 0.5,
"urgency": round(a["urgency"].score, 2),
"probabilities": dept.probabilities,
}
print(triage("I was charged twice for order #4411 and my card is now over its limit."))
Notice what the code does not do: no prompt asking for JSON, no regex on the reply, no retries for malformed output. The answers are already typed numbers.
Sending images, audio and PDFs
The input field accepts a string or a list of content blocks (text, image, audio, video, document), using the same block format as the Interactions API. Google’s launch example pairs a photo with a text note:
input=[
{"type": "image",
"uri": "https://storage.googleapis.com/generativeai-downloads/images/spill.jpg",
"mime_type": "image/jpeg"},
{"type": "text",
"text": "Breakroom counter check before the 9 AM client meeting."},
]
Per the docs, inline base64 data is accepted up to 100 MB per request (50 MB for PDFs), external HTTPS URLs up to 15 MB each, and the MIME type must match the real file. YouTube URLs and gs:// URIs are not supported, so use the Files API or a signed HTTPS URL.
Limits and best practices
- Keep questions atomic. One decision per question, combined in code. Questions are scored in parallel and cannot see each other.
- Write the full question in
instructions. The model never sees your question keys. - Prefer positive phrasing. Ask “Is the tier Gold?” and compute
1 - noul, rather than asking a negated question. - Do math in code. Compare dates, numbers and durations yourself and pass the result into the input.
- Treat input as untrusted. User text can argue for its own classification, so write explicit criteria and test with adversarial examples.
- Know the limits. Question keys must match
[A-Za-z0-9_-]+(1-64 characters), the context window is 262,144 tokens across input and questions, and an invalid request returns HTTP 400 naming the rule you broke.
Google also says third-party support is rolling out across OpenRouter, LangChain, Vercel, LiteLLM, Pydantic AI, Pipecat, LiveKit and OpenCode, with Gemini in Google Cloud “coming soon”.
When not to use it
The Decisions API is for closed-set questions. If you need an explanation, a summary or generated code, use a generative model. A common setup is to let Decision 1 act as the fast router in front of bigger models. Google says Gemini Notebook uses it that way to pick a model tier and thinking level per request.
Takeaway
If your app already sends “answer yes or no” prompts to a chat model, the Gemini Decisions API is worth a test. You get typed probabilities, a confidence value for deciding when to involve a human, and no output-token bill. Start with one routing or moderation check, log the confidence values for a week, and then pick your thresholds from real data.
Source: Google: Gemini Decisions API and the Decisions API documentation.
