Agent systems spend a lot of tokens on small judgments: which agent should take this, is it urgent, is the answer good enough to stop. A generative model answers those in prose, and your code then has to parse the prose.
Google's Gemini Decision 1 (gemini-decision-1) is built for these judgments. You send it some input and a set of typed questions, and it returns calibrated probabilities with zero output tokens. The open-source Swarms framework supports it through DecisionModel, the same class that covers TypeSafe, Cloudflare and OpenAI decision models.
This guide covers the three things most people need: a first call, several questions in one request, and routing between agents.
Setup
Gemini support is on the master branch of Swarms and will ship in the next release, so install from GitHub for now. Then set a key from Google AI Studio.
pip install -U git+https://github.com/kyegomez/swarms.git
export GEMINI_API_KEY="..."
DecisionModel calls Gemini's HTTP API directly, so there is no other package to install.
Your first decision
from swarms import DecisionModel
model = DecisionModel(model_name="gemini-decision-1")
probability = model.noul(
state="The blue mug I ordered on Monday arrived cracked on Wednesday.",
instructions="Did the item arrive damaged?",
)
print(f"Damaged: {probability:.2f}")
noul() returns one float: the probability that the answer is yes. The number is calibrated, so 0.8 is meant to be right about 80% of the time. Gemini keeps it between 0.01 and 0.99.
There are two more question types. choice() picks one option from a set you describe, and score() rates the input against ordered levels. Both return the answer with a probability for every option and a confidence.
Several questions in one request
run() asks any number of questions about the same input in a single request. Gemini answers each one on its own, so adding a question does not change the others. This script triages a support ticket with all three question types, then decides what to do:
from swarms import DecisionModel
model = DecisionModel(model_name="gemini-decision-1")
ticket = {
"message": "The blue mug I ordered on Monday arrived cracked on Wednesday.",
"order": {"id": "8821", "age_days": 2},
}
result = model.run(
state=ticket,
questions={
"queue": {
"type": "choice",
"instructions": "Which support queue should handle this message?",
"criteria": {
"billing": "Payment, invoice or refund questions.",
"replacements": "Damaged, missing or wrong items.",
"general": "Product questions and account updates.",
},
},
"severity": {
"type": "score",
"instructions": "How severe is this issue for the customer?",
"criteria": [
"Minor: the item is usable as it is.",
"Moderate: the item is usable with a workaround.",
"Severe: the item cannot be used.",
],
},
"is_damaged": {
"type": "noul",
"instructions": "Did the item arrive damaged?",
},
"within_window": {
"type": "noul",
"instructions": "Is order.age_days 30 or less?",
},
},
)
answers = result["answers"]
queue = answers["queue"]
print(f"Queue: {queue['choice']} (confidence {queue['confidence']:.2f})")
print(f"Severity: {answers['severity']['score']:.2f} on a 0-2 scale")
print(f"Damaged: {answers['is_damaged']['noul']:.2f}")
print(f"Within window: {answers['within_window']['noul']:.2f}")
approved = (
queue["choice"] == "replacements"
and queue["confidence"] >= 0.7
and answers["is_damaged"]["noul"] >= 0.8
and answers["within_window"]["noul"] >= 0.8
)
if approved:
print("Action: send a replacement")
else:
print("Action: send to a human")
The model gives you numbers and the policy stays in your code, as plain if statements you can read and test. The state is a dict, which is sent as JSON text, so a question can refer to a field by its key path, as within_window does with order.age_days.
Route requests to Swarms agents
A decision model makes a good router for a multi-agent system. It is fast, it costs a fraction of a generative call, and it tells you how sure it is. The agents below run on Gemini too, with the same key:
from swarms import Agent, DecisionModel
agents = [
Agent(
agent_name="Billing-Agent",
agent_description="Refunds, invoices, failed payments and subscription changes.",
system_prompt="You resolve billing questions clearly and briefly.",
model_name="gemini/gemini-2.5-pro",
max_loops=1,
),
Agent(
agent_name="Technical-Agent",
agent_description="Bugs, API errors, integrations and outages.",
system_prompt="You debug technical problems step by step.",
model_name="gemini/gemini-2.5-pro",
max_loops=1,
),
Agent(
agent_name="Sales-Agent",
agent_description="Pricing, plan upgrades and new accounts.",
system_prompt="You answer pricing and plan questions.",
model_name="gemini/gemini-2.5-pro",
max_loops=1,
),
]
agents_by_name = {agent.agent_name: agent for agent in agents}
router = DecisionModel(model_name="gemini-decision-1")
def route(task: str) -> str:
answers = router.run(
state=task,
questions={
"agent": {
"type": "choice",
"instructions": "Which agent should handle this request?",
"criteria": {
agent.agent_name: agent.agent_description
for agent in agents
},
},
"in_scope": {
"type": "noul",
"instructions": "Is this a request a software company's support team should handle?",
},
},
)["answers"]
if answers["in_scope"]["noul"] < 0.5:
return "Declined: out of scope for support."
decision = answers["agent"]
if decision["confidence"] < 0.6:
return "Escalated to a human: the router is unsure who owns this."
print(f"Routing to {decision['choice']}")
return agents_by_name[decision["choice"]].run(task)
print(route("I was charged twice for my March invoice, can you refund one?"))
The options come from the agents themselves: each agent_name is an option and its agent_description says when to pick it. Add an agent to the list and the router can choose it. A second question checks that the request is in scope, and a confidence floor sends unclear requests to a person. Only then does a generative agent run.
The same idea works anywhere a swarm needs a judgment between steps: ending a debate when a round adds nothing new, scoring a group chat reply before it posts, or choosing the next worker in a hierarchy. The reference page has an example of each.
Good to know
- Images, audio, video and PDFs. Pass the state as a list of content blocks, such as a
text block and an image block with base64 data and a mime_type. The example page shows it in full.
- Cost.
model.calculate_cost() prices the tokens used so far. gemini-decision-1 is $0.10 per million input tokens and produces no output tokens.
- Many items.
await model.arun(state, questions) is the async version of run(), for screening a batch with asyncio.gather.
- Always include a catch-all. A choice question spreads its probability across your options even when none fits, so add an option such as
other and check confidence.
- Other providers. Questions and answers have the same shape everywhere, so switching is a one-line change:
model = DecisionModel(model_name="gemini-decision-1") # Google, GEMINI_API_KEY
model = DecisionModel(model_name="gpt-6-luna") # OpenAI, OPENAI_API_KEY
model = DecisionModel(model_name="clef") # Cloudflare Workers AI
model = DecisionModel() # TypeSafe jev-latest
Learn more
- DecisionModel reference: every method, provider and error.
- Gemini decision model example: a return-request decision with a photo check.
- Decision model examples on GitHub: routing, guarded group chats and screening funnels.
- Google's Decisions API guide: the model's own documentation.