Skip to content

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.

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.

FieldDescription
questionThe 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.
uncertaintyWhether the answer can be Uncertain. See Uncertainty.

A yes/no question returns Truetrue or Falsefalse. A multiple-choice question returns one of its labels, exactly as you wrote it.

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:

SettingEffect
Omitted, or TruetrueThe answer can be Uncertain.
FalsefalseThe decision model must pick one of the choices.
A minimum confidenceThe 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 }, applies only to decision models that report a confidence for each answer. The LLM decision model doesn’t, so it ignores the threshold.

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:
# negative

ask returns a result with the answers, metadata about the call, and token usage:

FieldDescription
answersOne answer per question, keyed by question id.
metadata.latency_msmetadata.latencyMsTime the decision model spent on the call, in milliseconds.
metadata.provider_namemetadata.providerName, metadata.model_idmetadata.modelIdThe provider and model that answered, when the decision model reports them.
metadata.probabilities, metadata.confidenceThe probability of each choice and the confidence of each answer, keyed by question id, when the decision model reports them.
usageInput, output, and total tokens, when the decision model reports them.

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 the Uncertain answer.
  • A minimum confidence is outside [0.0, 1.0].