InfoWok
Categories
AI EngineeringTech Career Growth
HomeAuthorsAboutContact
Beginner

Python Decorators: A Primer for Reading AI Agent Code (2026)

A Python decorators primer for reading AI agent code: what the @ symbol does, how @tool and @app.get work, and why frameworks hand you decorators to apply.

SK
Sukhveer Kaur
Published June 22, 2026 · Updated June 23, 2026
3 min read
On this page +
What a decorator actually isThe @ is just shorthandWhat a decorator looks like insideWhy agent code is full of Python decoratorsQuick recapFrequently Asked QuestionsConclusion

The first @tool line in an agent tutorial stops a lot of beginners cold. There’s an @, a word, and then a normal-looking function — and somehow that function is now a tool the model can call. This Python decorators primer explains that one symbol, so the @ lines scattered through agent and web code read as ordinary Python instead of syntax you skip past.

You will apply decorators constantly in agent code and write your own rarely, if ever. So the goal here is recognition: know what @something does to the function beneath it, and the framework quickstarts stop hiding a step. It’s a smaller idea than it looks.

🟢 Beginner⏱️ 11 min readStack: Python 3.10+ (reading level — no agent code needed)
Before you start
  • You can read a basic Python function — new to that? The Python for AI agents primer covers functions
  • That’s the whole list — no prior decorator experience assumed
🎯 Key takeaways
  • A decorator wraps a function to add behaviour, applied with an @ line directly above the definition.
  • The @ is pure shorthand: @log above greet means exactly greet = log(greet).
  • In agent code you mostly apply, not author, decorators@tool, @agent.tool, @app.get.
  • Same syntax, different registrar: @tool registers a tool; @app.get registers a web route.

What a decorator actually is

A decorator is a function that takes another function, wraps it with some extra behaviour, and gives you back a function to use in its place. You attach one with an @ line sitting directly above a definition.

python
@log
def greet(name):
return f"Hi, {name}"

That @log line says: “before you bind the name greet, pass this function through log first.” The function still looks normal; the decorator adds something around it — logging, timing, registration — without you editing the body (Python glossary).

The @ is just shorthand

Here’s the demystifying part. The @ syntax is sugar for one plain assignment. These two snippets are identical:

python
@log
def greet(name):
return f"Hi, {name}"
# ...is exactly the same as:
def greet(name):
return f"Hi, {name}"
greet = log(greet) # pass greet to log, rebind the name to the result

Read @log as ”greet = log(greet)” and every decorator stops being mysterious. The decorator receives your function, and whatever it returns becomes the new greet. That’s the entire mechanism — there is nothing hidden underneath (PEP 318).

🔑 The one-line mental model@thing above a function means func = thing(func). Whenever a decorator confuses you, rewrite it as that assignment and it becomes obvious what's being passed where.

What a decorator looks like inside

You’ll rarely write one, but seeing the shape once removes the mystery for good. A decorator takes a function and returns a new function that calls the original with extra behaviour around it.

python
import functools
def log(func):
@functools.wraps(func) # keeps func's name and docstring
def wrapper(*args, **kwargs):
print(f"calling {func.__name__}")
return func(*args, **kwargs) # the original still runs
return wrapper

The *args, **kwargs just means “accept whatever arguments the original took and pass them straight through.” The @functools.wraps(func) line is a small courtesy that keeps the original function’s name and docstring intact — which matters more than you’d think for agents, since frameworks read the docstring to describe your tool to the model.

Why agent code is full of Python decorators

Now the payoff. In agent code, a decorator is how you register a plain function with a framework. The function stays ordinary; the @ line tells the framework what role it plays.

python
@tool
def get_weather(city: str) -> str:
"""Return the current weather for a city."""
return f"It's 31C in {city}."

@tool doesn’t change what get_weather does — it registers it as a tool the model is allowed to call, building the schema from the type hints and docstring. You’ll see the same pattern everywhere: @agent.tool in Pydantic AI, and @app.get("/") in FastAPI to run a function when a URL is hit. Same @ syntax, different registrar. Recognise that, and the tool-calling step and the FastAPI deploy both read cleanly.

💡 You apply far more than you writeFor your first dozen agents you'll only ever *use* decorators the framework hands you. Treat @tool as a label you stick on a function, not a thing you need to build. Authoring your own is a later, optional skill.

Quick recap

The whole primer, in five lines:

  • A decorator wraps a function to add behaviour, applied with an @ line above it.
  • @thing means func = thing(func) — pure shorthand for one assignment.
  • Inside, a decorator returns a new function that calls the original with extras around it.
  • @functools.wraps preserves the name and docstring frameworks read.
  • In practice you apply framework decorators (@tool, @app.get), rarely write your own.

Frequently Asked Questions

What is a decorator? A function that wraps another to add behaviour, applied with an @ line above the definition (e.g. @tool registers a tool).

What does @ do? It’s shorthand: @log above greet equals greet = log(greet).

Do I need to write my own? Rarely. You mostly apply the ones a framework gives you.

@tool vs @app.get? Both are decorators that register your function — one with an agent framework, one with a web framework.

Conclusion

Python decorators are just a function wrapping a function, and the @ is a tidy way to write func = thing(func). Once you read it that way, the @tool and @app.get lines that open every agent and API tutorial turn from strange punctuation into a plain label: “register this function, leave its body alone.” That’s all you need to follow the code — and almost all you’ll ever need to write.

Which @ line first made you pause — @tool, @app.get, or something else? Tell me in the comments.

🧭 Where to go from here

Frequently asked questions

What is a decorator in Python? +
A decorator is a function that wraps another function to add behaviour, applied with an @ line directly above the definition. `@tool` above a function, for example, registers it as a tool the model can call without changing the function's own code.
What does the @ symbol do in Python? +
The @ line is shorthand. Writing `@log` above `def greet(): ...` is exactly the same as `greet = log(greet)` — it passes your function to the decorator and rebinds the name to whatever the decorator returns. That's the whole mechanism.
Do I need to write my own decorators to build AI agents? +
Almost never at first. You mostly apply decorators the framework gives you — `@tool`, `@agent.tool`, `@app.get`. Reading and applying them is enough to build real agents; writing your own comes later, if at all.
What is the difference between @tool and @app.get? +
Both are decorators, but they register your function with different systems. `@tool` tells an agent framework the function is a callable tool; `@app.get("/")` tells a web framework like FastAPI to run the function when that URL is requested. Same syntax, different registrar.

References

  1. Glossary: decorator — Python documentation
  2. PEP 318 — Decorators for Functions and Methods
  3. Primer on Python Decorators — Real Python
  4. functools.wraps — Python documentation

Tags

#PythonForAI#PythonDecorators#PythonBasics#AIAgents#FastAPI#AIForDevelopers

Share

Keep reading

One email when something good ships

New guides the day they publish. No digest spam.

InfoWokCode-first AI engineering, in Python.
SeriesAboutEditorial standardsContactRSS