The Python framework for building AI-native applications in production.
Documentation · Quickstart · Tutorial · Reference · Recipes
What Rails was for database-backed web apps and what NestJS is for enterprise Node services: the default choice when what you're building has LLMs, agents, tools, prompts, evals, streaming, and MCP as core ingredients — not as an addon.
Ajolopy does not compete with FastAPI or LangChain. It competes for the complete AI-native application framework category, which was empty in Python before v0.1.
pip install ajolopy # or: uv pip install ajolopyRequires Python 3.14+. Optional extras documented under Install:
otel, mcp, redis, postgres, mongo, qdrant, pgvector.
- PEP 649 — deferred evaluation of annotations is native, so
from __future__ import annotationsis forbidden in this codebase (it would hide real typing errors at runtime). - Pyright strict pays off — runtime introspection of type hints
(
inspect.get_annotations) works without the lazy-eval workarounds older Pythons need. - DI by type-hints — Ajolopy resolves
@Injectableproviders via real annotation objects; PEP 649 makes that cheap and correct. - Modern stdlib —
asyncio.TaskGroup, structural pattern matching, and the new error-message machinery are assumed everywhere.
Twelve real lines (plus imports). Each token has a job — see the Step 1 tutorial for the line-by-line breakdown.
from typing import Annotated
from pydantic import BaseModel
from ajolopy import Agent, Stream, Tool
from ajolopy.http import Body
class ChatRequest(BaseModel):
message: str
@Agent(
model="claude-opus-4-7",
system="You are Acme Support. Be concise, friendly, and accurate.",
fallback="claude-haiku-4-5",
)
class Support:
@Tool
async def lookup_order(self, order_id: str) -> dict[str, str]:
"""Look up an order's current state by id."""
return {"order_id": order_id, "status": "in_transit", "eta": "tomorrow"}
@Stream("/chat")
async def respond(self, body: Annotated[ChatRequest, Body()]):
async for chunk in self.stream(body.message):
yield chunkRun it:
ajolopy new acme-support
cd acme-support
uv sync
ajolopy devcurl -N -X POST http://127.0.0.1:8000/chat \
-H "Content-Type: application/json" \
-d '{"message": "Where is order 4392? Use the tool."}'Token-by-token streaming response, function-calling loop, env-var
validation at boot, fallback to claude-haiku-4-5 on retriable
failure, OpenTelemetry spans for free. Twelve lines.
The framework targets the seven production pains the wedge AI Engineer hits in week one:
- Env vars —
ajolopy devrefuses to boot with missing required variables. No more 2 a.m. discovery in staging. - Cost — every span carries
gen_ai.cost_usd. Sum by user / tenant / agent in one SQL query against your trace backend. - Evals as a CI gate —
ajolopy eval --ciblocks the PR when a metric regresses. The model upgrade that quietly broke safety is visible before a customer reports it. - SSE streaming with backpressure —
@Streamhandles disconnects, heartbeats, and cancellation. Not 30 lines of Starlette glue. - Cross-provider fallback —
fallback="claude-haiku-4-5"cuts in when Anthropic returns a retriable error. Switching providers is a kwarg, not a rewrite. - Diagnostics —
ajolopy doctorruns twelve health checks: Python version, env vars, deps, provider connectivity, etc. Lighthouse for AI apps. - Project layout —
ajolopy newscaffolds a NestJS-style module tree. Any senior backend dev reads it on first sight.
Read the long form for the full framing.
| AI (7) | Framework (3) |
|---|---|
@Agent, @Tool, @Stream, @Eval, @Metric, @Workflow, @MCP |
@Module, @Injectable, @Controller |
Every primitive ships with a magical default (covers the 90% case with zero ceremony) and an escape hatch (subclass or override) for the 10% that needs full control. The surface is locked at ten — anything that would require an eleventh decorator goes to v0.2+.
- Multi-provider LLM — Anthropic, OpenAI, Gemini, and a universal
OpenAI-compatible client that covers Ollama / Together / Groq /
Mistral / DeepSeek / OpenRouter, plus any other OpenAI-compatible
endpoint via the
base_urls=constructor escape hatch. ajolopy deploy <target>— generatesfly.toml,railway.json,render.yaml,vercel.json(with warnings), or a universalDockerfile.prodfor k8s / VPS / ECS.- Memory — five chat-history backends behind one
MemoryABC: in-memory, Redis, Postgres, Mongo, SQLite. - RAG —
RetrieverABC with Qdrant and pgvector backends. - MCP —
@MCPto consume external Model Context Protocol servers,@MCPServerto publish your own@Toolmethods as one. - Observability — OpenTelemetry on by default; five recipes for Langfuse, Sentry, Grafana, Honeycomb, and Datadog.
- Eval framework —
@Eval+@Metricwith built-in metrics (exact_match,json_match,llm_judge,contains,intent_match,tool_called) and regression detection. - CLI —
new,dev,doctor,env:show/validate/diff,generate,eval,deploy.
examples/support-agent/— runnable companion to the 3-step killer demo tutorial. Fork it, setANTHROPIC_API_KEY, runuv sync && ajolopy dev, and watch every primitive from@Agentthrough@Workflowand@MCPanswer real HTTP requests.examples/web-research/— the canonical "wire an external HTTP API as a@Tool" reference. AResearcheragent that calls the Tavily search API through one@Tool, composes a Markdown-cited answer through a second pure-Python@Tool, and streams the result over SSE. Ships with@Eval+ LLM-judge regression suite and pre-builtDockerfile.prod+fly.toml.examples/oncall-agent/— focused demo of the@MCPprimitive against a real external server. Spawns the canonicalgithub-mcp-serverover stdio so the on-call agent can search issues, PRs, and commits while triaging incidents. Pairs a local@Toolwith the MCP tools to show how Ajolopy resolves name collisions in favour of local code.examples/local-ollama/— the same@Agent+@Tool+@Streamshape running on a local Ollama server through Ajolopy's universal OpenAI-compatible provider. No API key required — install Ollama,ollama pull llama3.3,uv sync && ajolopy dev, and the streaming code reviewer answersPOST /chatentirely on your laptop.examples/memory-assistant/— persistent task tracker showing@Agent(memory="redis://...")end-to-end. AMemoryescape-hatch wrapper partitions chat history by a request-scopedsession_id, so two users hitting the same/chatendpoint see independent transcripts in Redis. Ships with adocker-compose.yml(app + Redis) and a 5-row eval suite whosememory_isolationmetric catches cross-session leaks.dogfood/docsbot/— Ajolopy's own docs bot, the first dogfood app. Live at https://ajolopy-docsbot.fly.dev. Answers questions about the framework using an in-memoryRetrieversubclass over the project's owndocs/tree. Exercises@Agent+@Tool+@Stream+@Eval+ cross-provider fallback end-to-end and ships pre-generatedDockerfile.prod+fly.tomlso it can be deployed in onefly deploy.examples/contextual-rag/— production-grade RAG agent with contextual chunking, hybrid retrieval, and citation-enforcing evals over a synthetic handbook. Builds ondogfood/docsbotwith header-based chunks, a 0.4 keyword- 0.6 semantic-hash hybrid scorer, and three eval metrics (one
LLM-as-judge, two deterministic) that fail when citations are
missing or point at the wrong section. Documents the upgrade path to
QdrantRetriever/PgvectorRetrieverfor real embeddings.
- 0.6 semantic-hash hybrid scorer, and three eval metrics (one
LLM-as-judge, two deterministic) that fail when citations are
missing or point at the wrong section. Documents the upgrade path to
- Quickstart —
five minutes from
pip installto a streaming agent. - Tutorial — the three-step killer demo arc (hello → evals → multi-agent + MCP) in ~55 lines.
- Reference — one page per primitive with every kwarg and the escape hatch.
- Observability recipes — Langfuse / Sentry / Grafana / Honeycomb / Datadog wired in via the standard OTel exporter.
v0.1 — first public release. APIs are stable for the 10 primitives; expect additive changes in v0.1.x. Pin exact versions if you depend on the framework today.
The roadmap and current work are tracked in
board.json, validated against
.board-schema.json. Prose specs live in
specs/.
Work is tracked on a PM-style board.
AGENTS.md documents the claim / branch / transition
protocol for both human and AI contributors. The
contributor release guide
covers how to cut a new version.
uv run python tools/board.py list # see what's open
uv run python tools/board.py next # see what to pick up nextFile issues or open discussions at github.com/jcocano/Ajolopy.
MIT — see LICENSE.
The axolotl regenerates. So does Ajolopy.