An AGENTS.md file gives your AI coding agent the context it needs to write code that fits your project’s guidelines. It’s a plain Markdown file at your project root where you can pin your Python version, dependency manager, coding conventions, and constraints.
In this tutorial, you’ll build one of these files section by section and watch your agent go from sloppy output to clean, idiomatic code.
By the end of this tutorial, you’ll understand that:
- An
AGENTS.mdfile at your project root loads into the agent’s context window at the start of a session and stays there on every turn. - The file’s format is freeform Markdown with no required schema, and many coding agents read it.
- Pinning things like your dependency manager, coding style, and quality gates stops the agent from guessing.
- Constraints and ignore rules keep the agent away from files it shouldn’t touch.
- A good
AGENTS.mdfile helps your agent produce idiomatic code on the first try, with no re-prompting.
To follow along, you should be comfortable with Python and have used an AI coding assistant like Claude Code, Codex CLI, or Cursor before. If working with an agent is new to you, Real Python’s Getting Started With Claude Code video course covers the basics of the workflow.
Get Your Code: Click here to download the free sample code you’ll use to build an AGENTS.md file that steers your AI coding agent toward clean, idiomatic Python that fits your project.
Take the Quiz: Test your knowledge with our interactive “How to Write an AGENTS.md File for a Python Project” quiz. You’ll receive a score upon completion to help you track your learning progress:
Interactive Quiz
How to Write an AGENTS.md File for a Python ProjectCheck your understanding of how an AGENTS.md file gives your AI coding agent the project context it needs to write code that fits your project.
Running an AI Agent in Your Python Project
Before you can improve how an AI agent behaves, you need to see it misbehave. First, you’ll work with a small FastAPI project and ask the agent to add two endpoints to the API, with no AGENTS.md file in the repository to guide it. Then you’ll save the resulting code to compare against a second run.
You’ll start with a read-only REST API for a collection of cars, built with FastAPI. It loads its data from a cars.json file and exposes two endpoints: one to list every car and one to fetch a single car by its id.
The complete file holds ten cars. An engine_cc of 0 marks a fully electric car, like the Tesla. Expand the section below to see the whole file and get familiar with the data’s shape:
cars.json
[
{
"id": 1,
"make": "Ford",
"model": "Mustang",
"year": 1969,
"horsepower": 290,
"engine_cc": 5752,
"transmission": "Manual"
},
{
"id": 2,
"make": "Chevrolet",
"model": "Corvette",
"year": 2020,
"horsepower": 490,
"engine_cc": 6162,
"transmission": "Automatic"
},
{
"id": 3,
"make": "Dodge",
"model": "Charger",
"year": 2023,
"horsepower": 370,
"engine_cc": 5654,
"transmission": "Automatic"
},
{
"id": 4,
"make": "Tesla",
"model": "Model S",
"year": 2022,
"horsepower": 670,
"engine_cc": 0,
"transmission": "Automatic"
},
{
"id": 5,
"make": "Jeep",
"model": "Wrangler",
"year": 2021,
"horsepower": 285,
"engine_cc": 3604,
"transmission": "Automatic"
},
{
"id": 6,
"make": "Ford",
"model": "F-150",
"year": 2024,
"horsepower": 400,
"engine_cc": 3496,
"transmission": "Automatic"
},
{
"id": 7,
"make": "Cadillac",
"model": "Escalade",
"year": 2023,
"horsepower": 420,
"engine_cc": 6162,
"transmission": "Automatic"
},
{
"id": 8,
"make": "Chevrolet",
"model": "Camaro",
"year": 2018,
"horsepower": 455,
"engine_cc": 6162,
"transmission": "Manual"
},
{
"id": 9,
"make": "GMC",
"model": "Sierra",
"year": 2022,
"horsepower": 355,
"engine_cc": 5328,
"transmission": "Automatic"
},
{
"id": 10,
"make": "Chrysler",
"model": "300",
"year": 2019,
"horsepower": 292,
"engine_cc": 3604,
"transmission": "Automatic"
}
]
Each car is a flat record with a unique id and the fields make, model, year, horsepower, engine_cc, and transmission. That’s the entire data model your API will work with.
The application that serves this data is just as compact, as the following main.py file shows:
main.py
import json
from pathlib import Path
from fastapi import FastAPI, HTTPException
app = FastAPI()
cars: list[dict] = json.loads(Path("cars.json").read_text())
@app.get("/cars")
def list_cars() -> list[dict]:
"""Return a list of all cars."""
return cars
@app.get("/cars/{car_id}")
def get_car(car_id: int) -> dict:
"""Return a single car by its id, or raise 404 if it doesn't exist."""
for car in cars:
if car["id"] == car_id:
return car
raise HTTPException(status_code=404, detail="Car not found")
This app loads the cars data from cars.json and defines the two endpoints you saw earlier: list_cars() and get_car().
To run the API yourself, initialize the project, install the dependencies with uv, and start the development server:
$ uv init
$ uv add "fastapi[standard]"
$ uv run fastapi dev main.py
With the server running on http://127.0.0.1:8000, you can try both endpoints from another terminal. Start by listing every car with a GET request to /cars, piping the response through python -m json.tool to pretty-print it:
$ curl -s http://127.0.0.1:8000/cars | python -m json.tool
[
{
"id": 1,
"make": "Ford",
"model": "Mustang",
"year": 1969,
"horsepower": 290,
"engine_cc": 5752,
"transmission": "Manual"
},
...
]
The API returns the full contents of cars.json as a single JSON array, trimmed here to its first car. To fetch just one car, add its id to the path. For example, car 4 is the fully electric Tesla, with an engine_cc of 0:
$ curl -s http://127.0.0.1:8000/cars/4 | python -m json.tool
{
"id": 4,
"make": "Tesla",
"model": "Model S",
"year": 2022,
"horsepower": 670,
"engine_cc": 0,
"transmission": "Automatic"
}
In both cases, curl sends an HTTP GET request and prints the JSON the API returns. The /cars route returns every record in the dataset, while /cars/{car_id} reads the id from the URL and returns only the matching car. Ask for an id that isn’t there, such as /cars/999, and get_car() raises an HTTPException that FastAPI turns into a 404 Not Found response.
With the project in place, say that you want to grow the API with two more endpoints. Here’s the task you’ll hand to your agent. It’s a deliberately ordinary request, the kind you’d type without thinking twice:
Base prompt
The FastAPI app in main.py only supports listing cars and getting one car
by id. Add the following endpoints to the API:
- Create a new car
- Delete an existing car