The first time agent code confuses a Python developer, it’s rarely the logic — it’s the labels. def get_weather(city: str) -> dict: has two of them before the body even starts, and a tool’s arguments often arrive as a TypedDict or a Pydantic model you’ve never declared. This Python type hints primer names those labels once, so the rest of the code reads cleanly.
Here’s the reassuring part: type hints don’t change what your code does. They’re notes for humans and tools. But agent frameworks read them to figure out how the model should call your functions, so recognising the syntax is the difference between following a tutorial and squinting at it. Let’s clear it up.
- You can read a basic Python function and a dictionary — new to that? The Python for AI agents primer covers both
- That’s it — this primer assumes no prior typing knowledge
- A type hint is a label, not a rule:
city: strdocuments intent, but Python doesn’t enforce it at runtime. - Function hints annotate each argument and the return value (
-> dict) — the most common form you’ll read. TypedDicttypes a dictionary’s shape — exactly the{"role": ..., "content": ...}structure agent messages use.- Frameworks turn your hints into a schema the model reads, which is why tool functions are always carefully typed.
What a type hint is — and what it isn’t
A type hint is an annotation that says what kind of value something holds. You add it with a colon for variables and arguments, and an arrow for return values.
name: str = "Asha"def add(a: int, b: int) -> int:return a + b
The crucial thing to internalise early: Python does not enforce hints at runtime. The function above will happily run add("a", "b") and return "ab" — the hint is documentation, not a guard. Hints exist for people reading the code and for tools that check it. That’s not a weakness; it’s the design (see PEP 484). Enforcement is opt-in, and we’ll get to who opts in.
Function hints: arguments and return values
This is the form you’ll meet most, because every agent tool is a typed function. Read it left to right: each parameter gets name: type, and -> type after the parentheses is what the function gives back.
def get_weather(city: str) -> dict:"""Return the current weather for a city."""return {"city": city, "temp_c": 31}
city: str says the input is a string; -> dict says you get a dictionary back. When an agent framework sees this, it builds a description of the tool from exactly these hints — the model learns the function takes a string called city. That’s why untyped tools misbehave: with no hints, the model is guessing the arguments.
The handful of types you’ll actually see
Beyond str, int, float, and bool, a few container and “maybe” types cover most agent code.
list[str],dict[str, int]— a list of strings, a dict mapping strings to ints. The shape inside the brackets tells you what’s stored.str | None— “a string or nothing.” The| Nonepart marks a value that might be absent (older code writes this asOptional[str]).int | str— a union: either an int or a string. You read|as “or”.
def find_user(user_id: int) -> dict | None:"""Return the user record, or None if not found."""...
That return hint, dict | None, is a tiny but useful signal: it warns you the function can hand back nothing, so your code should check before using the result.
TypedDict: typing the shape of a dictionary
Here’s the one that unlocks agent code. A conversation is a list of dictionaries, each with a role and content. A TypedDict declares that exact shape — which keys exist and what type each value is.
from typing import TypedDictclass Message(TypedDict):role: strcontent: strmessages: list[Message] = [{"role": "system", "content": "You are a helpful agent."},{"role": "user", "content": "What's the weather in Delhi?"},]
Now messages isn’t just “a list of dicts” — it’s a list of Message, and a tool can see at a glance that every entry needs a role and a content (PEP 589). LangGraph uses this exact pattern for an agent’s State, so once you recognise TypedDict, that part of framework code stops being mysterious.
Where hints get teeth: Pydantic
If hints aren’t enforced, how do agents avoid “the model returned garbage”? They bring in a library that chooses to enforce them. Pydantic takes a class of hints and validates real data against it, raising a clear error when the shape is wrong.
from pydantic import BaseModelclass WeatherReport(BaseModel):city: strtemp_c: intreport = WeatherReport(city="Pune", temp_c="hot") # raises a validation error
This is the backbone of type-safe agents: you declare the shape you expect, and Pydantic guarantees you either get it or a loud failure — never silent nonsense three functions later. The Pydantic AI tutorial shows this inside a full agent.
Why Python type hints matter so much to agents
Pulling it together: in ordinary scripts, hints are a nicety. In agent code, Python type hints are load-bearing. A tool’s hints become the schema the model reads to call it; a TypedDict defines the state that flows through the graph; a Pydantic model guarantees the output is shaped the way the rest of your app expects. Strip the hints and an agent framework is flying blind. That’s why every well-written tool you’ll copy is carefully typed — and why reading hints fluently makes all of it legible.
Quick recap
The whole primer, in five lines:
- A type hint is a label (
city: str,-> dict), not a runtime rule. - Function hints annotate each argument and the return — the form you read most.
str | Noneand unions flag “maybe absent” and “either/or” values.TypedDicttypes a dict’s keys and values — the agentmessages/Stateshape.- Pydantic and mypy are how hints get enforced, on purpose.
Frequently Asked Questions
What are type hints? Optional labels for the type of a value (city: str, -> dict). They document intent and feed tools; Python ignores them at runtime.
Do hints change how code runs? No. By default they’re not enforced — a function hinted -> int can still return a string. Enforcement comes from mypy or Pydantic.
What is a TypedDict? A declaration of the exact keys and value types a dictionary should have — the structure agent message lists use.
Do I need hints before building agents? Read them first; tool schemas, LangGraph state, and Pydantic all rely on them. Writing thorough hints is a habit you grow into.
Conclusion
Python type hints look like extra ceremony until you see what they’re for: they’re how agent frameworks learn the shape of your functions and data. Read city: str as “this argument is a string,” -> dict | None as “returns a dict or nothing,” and TypedDict as “a dictionary with these exact keys,” and the typed parts of any agent tutorial turn from noise into signal.
Which typed pattern trips you up most — Optional, unions, or TypedDict? Tell me in the comments and I’ll expand on it.
- Need the Python basics first? The Python for AI agents primer covers dicts, functions, and loops.
- See hints enforced: the Pydantic AI tutorial builds a type-safe agent.
- Ready to build? Tool calling in Python turns typed functions into tools the model can call.