Skip to content

Get structured output

Get a typed result instead of text. There are two ways.

Way When to use
agent.ask(state, prompt, returns=Type) During or after a run, to extract a result without changing the run
A tool that calls state.finish(value) When the model should decide when it is done, and hand over the result as JSON data (a dataclass or Pydantic model comes back as a read-only dict)

ask

from dataclasses import dataclass
from pathlib import Path

from alpineagents import Agent, Message, State


@dataclass
class Review:
    approved: bool
    reason: str


agent = Agent(model="claude-sonnet-5", system="You review code changes.")

state = State(messages=[Message.user("Review this change:\n" + Path("change.diff").read_text())])
agent.run(state)
review = agent.ask(state, "Should this change be merged?", returns=Review)
print(review.approved, review.reason)
  1. agent.run(state) does the work on a State that starts with the person's message.
  2. agent.ask(...) asks the model one more question about the same context.
  3. returns=Review makes the answer a Review object.

About ask:

  • returns accepts str, a dataclass or a Pydantic model.
  • The question and answer are recorded in state.history, but not added to the context. The run continues as if the question was never asked.
  • The model cannot call tools while answering.
  • If the answer does not fit returns, ask asks again up to retries times (default 2), then raises OutputError.
  • After state.finish(), ask raises ValueError. So do not combine it with a submit tool on the same State.

A submit tool

The model fills the tool's typed parameters, and the tool ends the run with them. See Stop a run: stop from a tool. The answer is stored as JSON, so a dataclass or Pydantic model passed to finish() comes back as a dict. For a typed object, use ask with returns=.