Skip to content

Home

agent templateagent template

Pick a pattern, edit the prompt, ship it.

CI Docs Coverage Python 3.13 and 3.14 Pydantic AI v2 License

Examples · Which pattern should I use? · FAQ


Agent Template is a clean, opinionated starting point for building AI agents using Pydantic AI, with ready-to-go scaffolding for seventeen popular agent patterns: tool calling, retrieval, multi-agent workflows, human approval, durable execution and more. Run one script, pick a pattern, and you get the agent, its prompt, an offline test and an eval starter in your own project, as code you own. There is no framework to depend on.

Every pattern has been run against a real model: each comes with a recorded run you can read, live tests that check what the agent actually did and tests that cover every line of its code. The guardrails are on from the start (limits on requests, tokens and spend) and any model is one setting away.

Get started

# 1. Create your project: click "Use this template" on GitHub, or clone it
git clone https://github.com/tmtabor/agent-template.git my-agent && cd my-agent
uv sync --group dev
cp .env.example .env        # then add the API key for your model provider

# 2. Add an agent: pick a pattern from the menu
uv run python scripts/add_agent.py

# 3. Edit its prompt (agent/prompts/<name>.txt), then run the tests
uv run pytest

That gives you agent/agents/<name>.py, its prompt, a smoke test and an eval starter. Run add_agent.py again for each further agent; each can use a different pattern. The setup and commands below cover the rest, and Which pattern should I use? helps you choose.

What are you building?

From a first agent to a long-running multi-agent system, each of these is a pattern you add with one command. Each has working code, tests, and a recorded run against a real model.

Your first agent

One agent, one prompt, one typed output. Start from blank (empty) or single (a worked example).

uv run python scripts/add_agent.py single --name summarizer
from agent.agents.summarizer import run_agent

result = await run_agent("Hello, what can you do?")
result.output  # the validated output
result.usage  # tokens and requests for the whole run

Build this → single · blank

An agent that uses your tools

Give the model tools that call your systems, with errors it can recover from, or use the tools of an existing MCP server.

uv run python scripts/add_agent.py tool_calling --name releases
from agent.agents.releases import run_tool_agent

result = await run_tool_agent("What changed in Python 3.13 compared with 3.12?")

Build this → tool_calling · mcp_tools

Answers from your own documents

Documents are embedded and stored in a vector database (Chroma, running as a Docker service), so questions are matched by meaning and every cited source is checked against what was really retrieved.

uv run python scripts/add_agent.py rag --name support_docs
docker compose -f services/support_docs/docker-compose.yml up -d --wait   # the database
from agent.agents.support_docs import run_rag

result = await run_rag("How long can I send my hiking footwear back for my money?")
result.output.sources  # ['returns-policy']

Build this → rag

Structured data from text

Turn free text into a validated schema, with an output validator that sends a wrong answer back for correction.

uv run python scripts/add_agent.py extraction --name contacts
from agent.agents.contacts import run_extraction

result = await run_extraction(
    "Hi, it's Ada Lovelace from Analytical Engines Ltd. Reach me at ada@example.com."
)
result.output  # a validated Contact

Build this → extraction

Several agents working together

Six shapes, from the most predictable to the most flexible: a fixed pipeline, a router that picks a specialist, a parallel fan_out, an evaluator_optimizer loop, a planner_executor whose plan code checks, and a supervisor that decides as it goes. Which one?

uv run python scripts/add_agent.py router --name support
from agent.agents.support import run_router

result = await run_router("I was charged twice for my subscription this month.")
result.steps  # each agent run, in order

Build this → pipeline · router · fan_out · evaluator_optimizer · planner_executor · supervisor

Actions a person must approve

Pause a risky tool call until someone approves it, reject impossible requests before anyone is asked, or check input and output with guardrails.

uv run python scripts/add_agent.py human_in_the_loop --name refunds
from agent.agents.refunds import run_refunds

result = await run_refunds("Order A100 arrived with a broken sole. Please refund the full $84.50.")

Build this → human_in_the_loop · guardrails

Work that must not be lost

Run the agent as a Temporal workflow: a failing tool is retried, and a crashed worker is replaced, without repeating the model calls that already finished. Temporal runs as a Docker service.

uv run python scripts/add_agent.py temporal --name orders
docker compose -f services/orders/docker-compose.yml up -d --wait   # the Temporal server
from agent.agents.orders import run_order_desk

result = await run_order_desk(
    "I'd like to order 3 gizmos for Norway. Are they in stock, and what is the shipping?"
)

Build this → temporal

Exact answers over many lookups

Let the model write code that calls your tools in a loop and does the arithmetic, in a sandbox with hard limits, so one or two model requests do the work of dozens.

uv run python scripts/add_agent.py code_mode --name expenses
from agent.agents.expenses import run_expenses

result = await run_expenses("What is the total of Maya's travel expenses, in US dollars?")
result.output.amount_usd

Build this → code_mode

A conversation

Remember earlier turns, keep the context window bounded, and stream replies as they are generated.

uv run python scripts/add_agent.py conversation --name chat
from agent.agents.chat import run_chat

first = await run_chat("Hi! My name is Priya and I'm planning a trip to Lisbon.")
second = await run_chat("What's my name?", history=first.all_messages())

Build this → conversation

See all seventeen patterns, each with its source and a recorded run.

Why this template

It is opinionated on purpose. Four opinions are baked in, so you can tell whether they are yours:

  • Copy, don't depend. add_agent.py copies a pattern into your project. There is no library to import and nothing to upgrade in place; the code is yours to change.
  • Guardrails from the start. Every agent has limits on requests and tokens, an optional spend cap, and a response the provider blocks raises an error instead of coming back half finished. A misconfigured provider fails at import, not at the first request.
  • Observable by default. Runs are traced with no per-agent setup: to the console until you give it a Logfire token.
  • Any model, one config. AGENT_MODEL is the one setting. The patterns' live tests assert behavior that holds for any capable model, not one model's wording.

Stack

  • Python 3.13 and 3.14, uv
  • Pydantic AI v2 (agents, tools) + pydantic-evals (evals)
  • Logfire (observability)
  • pytest + pytest-asyncio

Next steps

  • Make it yours. Edit the prompt, replace the output schema, and add your tools: Customizing the prompt and Adding tools. Each pattern's README ends with how to adapt it.
  • Test it for real. Grow the eval fixtures for your task, and run uv run pytest -m eval with your key: Evals.
  • Set your limits. Tune USAGE_LIMITS and set AGENT_COST_LIMIT before real use: Usage limits.
  • See what it did. Add a Logfire token and every model call and tool call is traced: Observability.
  • Replace the stand-ins. The examples use invented data and demo services; swap in your own. The FAQ says what to check before production.
  • Join in. Report a problem or send a fix: Contributing.

Projects using agent-template

  • job-agent: a daily job-scanning agent. It fetches postings from several sources, filters and scores them against a candidate profile with an LLM, and emails a ranked digest. Runs on GitHub Actions.
  • content-agent: a multi-brand agent that generates social posts, blogs and newsletters, built with Pydantic AI, FastAPI/HTMX and a local Ollama model.
  • oss-notifier-agent: an LLM-triaged good-first-issue digest for GitHub repos, delivered by email. Runs on GitHub Actions, no server required.

Built something with it? Open a pull request to add it here.