Ajolopy
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.
Install
pip install ajolopy # or: uv pip install ajolopy
Requires Python 3.14+. Optional extras documented under Install:
otel, mcp, redis, postgres, mongo, qdrant, pgvector.
Why Python 3.14+
- 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.
The killer demo
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 chunk
Run it:
ajolopy new acme-support
cd acme-support
uv sync
ajolopy dev
curl -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.
Why Ajolopy
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.
The 10 primitives
| 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+.
What's in the box (v0.1)
- 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
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
Where to go next
- 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.
Status
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/.
Contributing
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 next
File issues or open discussions at github.com/jcocano/Ajolopy.
License
MIT — see LICENSE.
The axolotl regenerates. So does Ajolopy.
Metadata
Release files for ajolopy 0.1.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ajolopy-0.1.8.tar.gz | 640.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ajolopy-0.1.8-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.1 MB
Release files / ajolopy-0.1.8.tar.gz
| Download URL | ajolopy-0.1.8.tar.gz |
|---|---|
| Size | 640.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4f39a2496ade603d658478be9b4def7acf5b206a698e7d98abc2ee8f8bfb1248
|
|
BLAKE2b-256 checksum How to use checksums |
a77fa6fb4b3c70b305114ae09ab5aa8dd12b2ac3a10652080a16bc3b9ed313cb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 19, 2026.
Transparency logRelease files / ajolopy-0.1.8-py3-none-any.whl
| Download URL | ajolopy-0.1.8-py3-none-any.whl |
|---|---|
| Size | 475.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3e2c7962ec09e89bdf8c47b7a059df1e289a2cfc7f1d2236d2241bb8a92d0ff5
|
|
BLAKE2b-256 checksum How to use checksums |
ff7b57d394fdbdf4c656ebdce4f555fec658ef899e141d80db9d080459160959
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 19, 2026.
Transparency log