Questions and answers
You describe what you want to know as a map of questions, and every decision model returns the same result shape, so the code that asks and the code that reads the answers stay the same when you change decision models.
Questions
Section titled “Questions”You pass questions to ask as a map from an id to a question. The id is yours: the
result uses the same ids, so you read each answer by the id you gave it. One call can
ask several questions about the same input.
| Field | Description |
|---|---|
question | The question, in plain language. Must not be empty. |
choices | "boolean" for a yes/no answer, or a list of labels for a multiple-choice answer. |
uncertainty | Whether the answer can be Uncertain. See Uncertainty. |
A yes/no question returns TruetrueFalsefalse
Uncertainty
Section titled “Uncertainty”By default, every answer can be Uncertain: the decision model returns it instead of a
choice when it can’t commit. Set uncertainty on a question to change that:
| Setting | Effect |
|---|---|
Omitted, or Truetrue | The answer can be Uncertain. |
Falsefalse | The decision model must pick one of the choices. |
| A minimum confidence | The answer can be Uncertain, and an answer whose confidence is below the threshold (in [0.0, 1.0]) comes back as Uncertain. |
The minimum confidence,
{"min_confidence": 0.8}{ minConfidence: 0.8 }
Uncertain carries an optional reason. Check for it before you use an answer, with
isinstance(answer, Uncertain)answer instanceof Uncertain
The input is what the questions are about. It can be a string, a list of content blocks for a single message, or a full conversation as a list of messages. A conversation lets the decision model answer about the whole exchange, not only the latest message:
import asyncio
from strands import LLMDecisionModel
conversation = [ {"role": "user", "content": [{"text": "Where is my order 1182?"}]}, {"role": "assistant", "content": [{"text": "It shipped yesterday."}]}, {"role": "user", "content": [{"text": "I've asked three times. Cancel it."}]},]
async def main(): decisions = LLMDecisionModel() result = await decisions.ask( conversation, { "sentiment": { "question": "How does the customer feel?", "choices": ["positive", "neutral", "negative"], }, }, ) print(result.answers["sentiment"])
asyncio.run(main())
# Typical output:# negativeimport { LLMDecisionModel, Message, TextBlock } from '@strands-agents/sdk'
const conversation = [ new Message({ role: 'user', content: [new TextBlock('Where is my order 1182?')] }), new Message({ role: 'assistant', content: [new TextBlock('It shipped yesterday.')] }), new Message({ role: 'user', content: [new TextBlock("I've asked three times. Cancel it.")], }),]
const decisions = new LLMDecisionModel()const result = await decisions.ask(conversation, { sentiment: { question: 'How does the customer feel?', choices: ['positive', 'neutral', 'negative'], },})console.log(result.answers.sentiment)
// Typical output:// negativeResults
Section titled “Results”ask returns a result with the answers, metadata about the call, and token usage:
| Field | Description |
|---|---|
answers | One answer per question, keyed by question id. |
metadata.latency_msmetadata.latencyMs | Time the decision model spent on the call, in milliseconds. |
metadata.provider_namemetadata.providerNamemetadata.model_idmetadata.modelId | The provider and model that answered, when the decision model reports them. |
metadata.probabilities, metadata.confidence | The probability of each choice and the confidence of each answer, keyed by question id, when the decision model reports them. |
usage | Input, output, and total tokens, when the decision model reports them. |
Validation
Section titled “Validation”ask checks the questions before it calls any model and raises an error when:
- There are no questions.
- A question’s text is empty or only whitespace.
- A multiple-choice question has no labels, an empty label, or the same label twice.
- A label is
"uncertain", which is reserved for theUncertainanswer. - A minimum confidence is outside
[0.0, 1.0].