A Pydantic model works when you know the exact fields ahead of time. What about a meeting where you don't know how many action items the agent will find — two, or twelve?
A class won't fit because the number of fields changes? You'd want something list-shaped?
Exactly. For variable-length outputs, PydanticAI accepts a plain list[str] as result_type. No class definition, no .model_dump(). result.output is already a Python list you can return:
agent = Agent(model, result_type=list[str])
result = agent.run_sync(meeting_notes)
print(result.output) # ['Fix login bug', 'Notify the team', 'Deploy on Friday']So the return type of result.output changes based on whatever I pass to result_type?
That is the whole contract. result_type=Contact makes result.output a Contact instance. result_type=list[str] makes it a list. result_type=Literal[...] makes it one of the allowed strings. The generic shape is the same, the type of .output tracks the type you asked for:
def extract_action_items(text: str) -> list:
agent = Agent(
model,
system_prompt="Extract all action items from the text. Return a list of short, clear action items.",
result_type=list[str],
)
return agent.run_sync(text).outputThe system_prompt and the result_type work together? One shapes what the items are, the other shapes how they come back?
Exactly the split. system_prompt guides the content — what counts as an action item, how to phrase them. result_type enforces the structure — that you get a list of strings and nothing else. Both are necessary: without the prompt you'd get full sentences; without the type you'd get an unstructured paragraph.
And the list length depends on how many items the agent finds — no fixed count to match?
Right — non-deterministic length is the point. A dense handoff yields six items; a short bug report yields two. The test schema only checks {"type": "list"}, not a length. Write extract_action_items(text) now.
TL;DR: result_type=list[str] — result.output is a ready-to-return Python list.
list[str] replaces a Pydantic model.model_dump() — result.output is already the listsystem_prompt shapes content; result_type shapes structure| Shape | result_type |
|---|---|
| Fixed named fields | Pydantic model |
| Fixed closed set of strings | Literal[...] |
| Variable-length list | list[str] |
Length of the returned list is non-deterministic — test schemas validate type, not count.
A Pydantic model works when you know the exact fields ahead of time. What about a meeting where you don't know how many action items the agent will find — two, or twelve?
A class won't fit because the number of fields changes? You'd want something list-shaped?
Exactly. For variable-length outputs, PydanticAI accepts a plain list[str] as result_type. No class definition, no .model_dump(). result.output is already a Python list you can return:
agent = Agent(model, result_type=list[str])
result = agent.run_sync(meeting_notes)
print(result.output) # ['Fix login bug', 'Notify the team', 'Deploy on Friday']So the return type of result.output changes based on whatever I pass to result_type?
That is the whole contract. result_type=Contact makes result.output a Contact instance. result_type=list[str] makes it a list. result_type=Literal[...] makes it one of the allowed strings. The generic shape is the same, the type of .output tracks the type you asked for:
def extract_action_items(text: str) -> list:
agent = Agent(
model,
system_prompt="Extract all action items from the text. Return a list of short, clear action items.",
result_type=list[str],
)
return agent.run_sync(text).outputThe system_prompt and the result_type work together? One shapes what the items are, the other shapes how they come back?
Exactly the split. system_prompt guides the content — what counts as an action item, how to phrase them. result_type enforces the structure — that you get a list of strings and nothing else. Both are necessary: without the prompt you'd get full sentences; without the type you'd get an unstructured paragraph.
And the list length depends on how many items the agent finds — no fixed count to match?
Right — non-deterministic length is the point. A dense handoff yields six items; a short bug report yields two. The test schema only checks {"type": "list"}, not a length. Write extract_action_items(text) now.
TL;DR: result_type=list[str] — result.output is a ready-to-return Python list.
list[str] replaces a Pydantic model.model_dump() — result.output is already the listsystem_prompt shapes content; result_type shapes structure| Shape | result_type |
|---|---|
| Fixed named fields | Pydantic model |
| Fixed closed set of strings | Literal[...] |
| Variable-length list | list[str] |
Length of the returned list is non-deterministic — test schemas validate type, not count.
Create a free account to get started. Paid plans unlock all tracks.