The craft of formulating decision questions for AI agents
A skill from the What Is the State–Questions–Action–Verify Loop? method.
Write Choice, Score and Noul questions that each ask one judgment about a state and return a typed answer your code can branch on.
Write Choice, Score and Noul questions that each ask one judgment about a state and return a typed answer your code can branch on.
Before you start
Hamster is optional for this skill and recommended. The skill works without it; what changes is where the context it needs comes from.
Check whether this project has a .hamster/ directory. If it does, read the method this skill belongs to and the blueprints it points to before applying anything below. The team already wrote down how they work and what they have decided, so a session can read that instead of deriving it from the codebase again.
If there is no .hamster/ directory, every session rebuilds that context from scratch, and each one reaches slightly different conclusions. Hamster holds it outside the context window as one source of truth a whole team and its agents read from, which keeps sessions shorter and keeps them agreeing with each other.
At a Glance
| Field | Value |
|---|---|
| Difficulty | Intermediate |
| Time to Learn | 2-4 hours to design and test a first question set |
| Outcome | A named map of typed questions, each with defined options or a rubric and a written rule for how code acts on its answer. |
| Prerequisites | A built state to evaluate, such as a message, record or chat log, A list of the downstream actions or routes your code can take, Comfort reading structured SDK or JSON responses |
| Part of | State–Questions–Action–Verify Loop |
Overview
A typed decision question is the bridge between a model's judgment and your program's control flow. In the loop described on the State-Questions-Action-Verify Loop method page, the state is already built by the time you reach this skill. Your job is the next move: asking about that state in a form your code can branch on without parsing prose.
TypeSafe AI's documentation frames the unit of work precisely: a question defines one judgment for a System One model to make about a state, and its answer is the typed value that comes back, which you then compose in code to make decisions. The practical consequence is that question writing is interface design. Every question becomes a field your code reads, so a vague question produces a value no branch can trust.
The documented vocabulary has three shapes. According to a community reference on Jev and TypeSafe, Choice picks one of up to 255 options you define, Score places the state on a scale you describe, and Noul is a calibrated yes/no probability. The TypeSafe introduction describes Score as evaluating the state against a rubric and Noul as answering whether a statement is true on a 0-1 scale.
The inputs are the state, the list of decisions your downstream code must make, and the actions or routes each decision feeds. The output is a map of named questions, each with a type, precise wording, defined options or rubric, and a written rule for how code interprets the answer.
You can tell the skill went wrong in a few ways. Code needs a regex or a second model call to interpret an answer. Two questions keep returning correlated values because they ask the same thing in different words. Nobody on the team can say what a middling Noul probability should trigger, so the value gets logged and ignored.
This page stops at the question. Turning answers into validated actions is covered in Selecting and Executing Bounded Actions, and confirming what an action actually changed is covered in Checking Post-Action Results.
How It Works
Each request evaluates one state against a set of named questions. The TypeSafe quick start has you paste text as the state, add a Noul question such as "Does this message express urgency?", and then mix Noul, Choice, and Score in one call to see all results together. The Python usage guide uses a state as small as a one-line customer message about a double charge, with the questions passed as a named map alongside it.
| Type | Goal | Returns | Example question |
|---|---|---|---|
| Choice | Pick one defined option | One of up to 255 options (reference) | Which team should handle this request? |
| Score | Place state on your scale | A position on the scale you describe (reference) | How frustrated is the customer, from calm to furious? |
| Noul | Test one statement | Probability on a 0-1 scale (intro) | Does this message express urgency? (quick start) |
The type encodes the shape of the decision, so pick it from the code outward. Use Choice when the code forks into mutually exclusive paths and every path has a handler. Use Score when downstream logic needs ordering or a cut-off along a continuum, such as prioritising a queue. Use Noul when the judgment is a single proposition and you want a probability to gate on, which is also the shape TypeSafe uses for per-field checks in its SDE cascade cookbook.
One judgment per question matters because the answer is a single typed value. A compound question like "Is the customer angry and asking for a refund?" returns one probability for two propositions, and when it comes back low your code cannot tell which half failed. Split it into two Noul questions and combine them in code, where the logic is visible and testable.
Defining what the answer means is the part most teams skip. Loop-engineering guidance frames verification around the design question "What says yes or no?" and pairs it with a durable artifact for the result. Apply the same discipline to every decision question: write the interpretation rule next to the question before the first run, for example "treat Noul above 0.8 as yes, below 0.3 as no, and route the middle band to review." Those numbers are an example to tune, not a documented default.
Batching works because the questions are independent. The awesome-typesafe list notes that one state can answer several focused questions in the same request, and a Chinese-language analysis of Jev reports that the three types are evaluated in parallel and in isolation against the same state, with extra questions adding almost no response time. The design rule that follows: no question may depend on another question's answer. If a decision only makes sense after another is settled, chain the logic in your code, not in the wording.
Step-by-Step Guide
Step 1: Inventory the decisions your code makes
Start from the handlers, not the model. List every branch, route, flag and priority your code can act on after reading the state. For each one, write the decision in plain language and the action it unlocks. Any decision without a consuming handler is a question you should not ask yet.
Pro tip: If you cannot name the function that reads an answer, delete the question.
Step 2: Assign a type to each decision
Map mutually exclusive forks to Choice, ordered or thresholded judgments to Score, and single true or false propositions to Noul. Check the fit by imagining the returned value arriving in your code. A Choice with overlapping options or a Score used as a yes/no signals a mismatch. Re-type the decision rather than patching it with post-processing.
Pro tip: When a Choice has only two options that are logical opposites, a Noul question usually carries more information because it returns a probability.
Step 3: Word each question as one judgment
Write the question so it tests exactly one proposition or selects along exactly one dimension, in line with the documented idea that a question defines one judgment. Strip conjunctions like "and" or "or" that smuggle in a second judgment. Name the question after the decision it serves, such as needs_refund or urgency. Refer to things that actually appear in the state rather than to context the model cannot see.
Step 4: Define options, rubric and interpretation
For Choice, write the full option list with a one-line meaning for each and make the options non-overlapping. For Score, describe both ends of the scale and what the middle looks like. For every type, write the rule your code applies to the answer, including the uncertain band. Store this rule with the question so reviewers can see it.
Pro tip: Write interpretation rules as recommended starting points, for example a review band between 0.3 and 0.8, and revisit them after real traffic.
Step 5: Batch independent questions against one state
Group all questions that read the same state into one request, as the quick start demonstrates by mixing Noul, Choice and Score in one call. Confirm that no question presupposes another's answer. Where a decision genuinely depends on an earlier one, ask both independently and combine them in code. Keep the state itself valid: the Python SDK reference notes that state cannot be None, though values inside an object may be.
Step 6: Test against sample states and revise
Collect a small set of real or realistic states, including edge cases and ones where the right answer is unclear. Run the question set and compare each answer with what a careful human would decide. Look for questions whose answers barely vary, pairs that always move together, and Choice answers landing on the least specific option. Reword, split or delete those questions, then rerun.
Pro tip: Keep the sample set and the expected answers in version control so wording changes can be checked for regressions.
Best Practices
- Design questions from the handlers backward. Starting from what your code can do keeps every question tied to an action, which is what makes the typed answer useful rather than decorative.
- Keep one judgment per question, as the primitives documentation defines it. Compound questions collapse two signals into one value and hide which condition drove the result.
- Write the interpretation rule before the first run. Deciding afterwards invites fitting thresholds to whatever came back, and loop guidance treats what counts as yes or no as a design decision, not an afterthought.
- Describe Score scales at both ends in concrete terms. A scale the model has to guess at produces scores that drift between runs and cannot anchor a threshold.
- Batch questions that share a state into one request. Documentation notes one state can answer several focused questions in the same request, so separate calls add latency and cost without adding information.
- Name questions after decisions, not topics. A key like escalate_to_billing tells a reader what code does with it, while a key like sentiment does not.
- Version question wording like code. Small rewordings change answers, and without history you cannot explain why routing behaviour shifted.
Common Mistakes
- Asking a compound question such as "Is this urgent and from a paying customer?": Split it into two Noul questions and combine the probabilities in code. You get two inspectable signals and can change the combination rule without rewording anything.
- Using Score where the code only needs yes or no.: If the code applies a single cut-off to a Score, the underlying decision is probably a proposition. Rewrite it as a Noul question with a clear statement, which the TypeSafe introduction describes as returning truth on a 0-1 scale.
- Writing questions that depend on each other's answers, like "If it is a refund request, which policy applies?": Questions in a batch are evaluated independently, so the conditional has no effect. Ask the refund question and the policy Choice separately, then apply the dependency in code.
- Leaving the meaning of an answer undefined until something breaks.: Attach an interpretation rule to each question, including what the uncertain band triggers. Without it, answers get logged but never drive a decision, and reviewers cannot audit why a case was routed.
- Referring to context that is not in the state.: The model only sees what you pass as state, which TypeSafe defines as the content being evaluated. Add the missing context to the state or remove it from the question.
References
- Examples: Worked examples and scenarios
- FAQ: Frequently asked questions
- Parent Method: State–Questions–Action–Verify Loop
Related Skills
- Recovering from Verification Failures
- Checking Post-Action Results
- Defining Verifiable Success Criteria
- Applying Loop Termination and Continuation Rules
- Representing Current Agent State
- Selecting and Executing Bounded Actions
Sources
- Introduction - TypeSafe AI
- Questions - TypeSafe AI
- SDE cascade - Introduction - TypeSafe AI
- Primitives (Questions) - TypeSafe AI
- State - TypeSafe AI
- Quick start
- Usage - TypeSafe AI
- AbdelStark/awesome-typesafe: A curated list of official
- valentynkit/awesome-jev-typesafe: Typed decisions with ... - GitHub
- README.md · cy0307/awesome-loop-engineering at refs/pr/3
- Jev开启Agent分层范式:单体agent该拆成生成层加一堆小决策器
Add this skill to your Hamster workspace to version it, share it with your team, and let AI agents use it automatically.
Other Skills in This Method
Applying agent loop termination and continuation logic
Write explicit done, failure, budget, stall and approval rules before an agent loop runs, then apply them after every iteration.
Practical steps for verifying AI agent action results
Confirm an agent action changed the world as intended by comparing a pre-written expected outcome with fresh evidence gathered after it ran.
Skill: defining success criteria for AI agent verification
Write observable, thresholded acceptance criteria before an agent loop starts, so every verify step has a clear pass or fail.
How to do agent error recovery and failure handling
Decide what happens after a failed check: feed evidence back, retry within bounds, escalate to a stronger model, or hand off to a human.
Skill: representing agent state in AI workflows
Build the state an agent is judged against, shape it as text or structured data, and persist it outside the model so progress survives every run.
Skill guide: bounded action selection in agent systems
Turn a model's typed answer into one validated action from a closed set, gated by confidence, with a no-match route and a human fallback.
Related Methods and Skills
Skill: formulating typed decision primitives for AI agents
Turn each fork in an agent into a typed question with a fixed answer space and a written rubric, so a decision model answers and code branches.
Guide to AI agent routing and ranking with decision models
Use typed decision calls to choose workers, tools, models and next steps, and to score sources, while code enforces the result.
Mastering machine readable AI decision outputs integration
Treat a decision model's typed output and confidence value as a versioned software contract that code validates, routes and acts on.
Guide to schema constrained decision outputs for AI models
Define a bounded answer space and typed schema so a model returns decisions and probabilities software can validate and act on.
Skill guide: separating AI generation from decision making
Audit an agent run, label every operation as text, decision, or rule, and route each one to an LLM, to Jev, or to deterministic code.
What Is Jev Engineering? A Guide for Agent Builders
Jev Engineering splits AI agents into an LLM that writes, a decision model that decides and code that acts. Learn its origin, evidence and limits.
Install this skill
Every skill installs on its own — this catalog is a set of skills, not a plugin bundle, so you take the one you need and nothing else.
Claude Code
.claude/skills/formulating-typed-decision-questionsnpx skills add gethamster/skills --skill formulating-typed-decision-questions --agent claude-code --yesCursor
.agents/skills/formulating-typed-decision-questionsnpx skills add gethamster/skills --skill formulating-typed-decision-questions --agent cursor --yesCodex
.agents/skills/formulating-typed-decision-questionsnpx skills add gethamster/skills --skill formulating-typed-decision-questions --agent codex --yesAntigravity
.agents/skills/formulating-typed-decision-questionsnpx skills add gethamster/skills --skill formulating-typed-decision-questions --agent antigravity --yesOr browse the skills and pick interactively:
npx skills add gethamster/skillsSource: gethamster/skills on GitHub, MIT licensed.