Skip to main content

The Python framework for building AI-native applications in production.

Project description

Ajolopy

The Python framework for building AI-native applications in production.

PyPI Python CI Docs License: MIT

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 annotations is 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 @Injectable providers via real annotation objects; PEP 649 makes that cheap and correct.
  • Modern stdlibasyncio.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:

  1. Env varsajolopy dev refuses to boot with missing required variables. No more 2 a.m. discovery in staging.
  2. Cost — every span carries gen_ai.cost_usd. Sum by user / tenant / agent in one SQL query against your trace backend.
  3. Evals as a CI gateajolopy eval --ci blocks the PR when a metric regresses. The model upgrade that quietly broke safety is visible before a customer reports it.
  4. SSE streaming with backpressure@Stream handles disconnects, heartbeats, and cancellation. Not 30 lines of Starlette glue.
  5. Cross-provider fallbackfallback="claude-haiku-4-5" cuts in when Anthropic returns a retriable error. Switching providers is a kwarg, not a rewrite.
  6. Diagnosticsajolopy doctor runs twelve health checks: Python version, env vars, deps, provider connectivity, etc. Lighthouse for AI apps.
  7. Project layoutajolopy new scaffolds 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> — generates fly.toml, railway.json, render.yaml, vercel.json (with warnings), or a universal Dockerfile.prod for k8s / VPS / ECS.
  • Memory — five chat-history backends behind one Memory ABC: in-memory, Redis, Postgres, Mongo, SQLite.
  • RAGRetriever ABC with Qdrant and pgvector backends.
  • MCP@MCP to consume external Model Context Protocol servers, @MCPServer to publish your own @Tool methods as one.
  • Observability — OpenTelemetry on by default; five recipes for Langfuse, Sentry, Grafana, Honeycomb, and Datadog.
  • Eval framework@Eval + @Metric with built-in metrics (exact_match, json_match, llm_judge, contains, intent_match, tool_called) and regression detection.
  • CLInew, dev, doctor, env:show/validate/diff, generate, eval, deploy.

Examples

  • examples/support-agent/ — runnable companion to the 3-step killer demo tutorial. Fork it, set ANTHROPIC_API_KEY, run uv sync && ajolopy dev, and watch every primitive from @Agent through @Workflow and @MCP answer real HTTP requests.
  • examples/web-research/ — the canonical "wire an external HTTP API as a @Tool" reference. A Researcher agent 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-built Dockerfile.prod + fly.toml.
  • examples/oncall-agent/ — focused demo of the @MCP primitive against a real external server. Spawns the canonical @modelcontextprotocol/server-github over stdio so the on-call agent can search issues, PRs, and commits while triaging incidents. Pairs a local @Tool with the MCP tools to show how Ajolopy resolves name collisions in favour of local code.
  • examples/local-ollama/ — the same @Agent + @Tool + @Stream shape 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 answers POST /chat entirely on your laptop.
  • examples/memory-assistant/ — persistent task tracker showing @Agent(memory="redis://...") end-to-end. A Memory escape-hatch wrapper partitions chat history by a request-scoped session_id, so two users hitting the same /chat endpoint see independent transcripts in Redis. Ships with a docker-compose.yml (app + Redis) and a 5-row eval suite whose memory_isolation metric catches cross-session leaks.
  • dogfood/docsbot/ — Ajolopy's own docs bot, the first dogfood app. Answers questions about the framework using an in-memory Retriever subclass over the project's own docs/ tree. Exercises @Agent + @Tool + @Stream + @Eval end-to-end and ships pre-generated Dockerfile.prod + fly.toml so it can be deployed in one fly deploy.
  • examples/contextual-rag/ — production-grade RAG agent with contextual chunking, hybrid retrieval, and citation-enforcing evals over a synthetic handbook. Builds on dogfood/docsbot with 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 / PgvectorRetriever for real embeddings.

Where to go next

  • Quickstart — five minutes from pip install to 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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ajolopy-0.1.3.tar.gz (615.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ajolopy-0.1.3-py3-none-any.whl (462.1 kB view details)

Uploaded Python 3

File details

Details for the file ajolopy-0.1.3.tar.gz.

File metadata

  • Download URL: ajolopy-0.1.3.tar.gz
  • Upload date:
  • Size: 615.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for ajolopy-0.1.3.tar.gz
Algorithm Hash digest
SHA256 2cc278285a89ac788e2df0378979b522c0f5179bb4189cb95179b904a60f8aea
MD5 5a0e3717c2802c78aaeb9c3c2e116942
BLAKE2b-256 2fbcb066e8baadbdaaeea1853fc41167687b00be1560da1dfdabf5b6a2215415

See more details on using hashes here.

Provenance

The following attestation bundles were made for ajolopy-0.1.3.tar.gz:

Publisher: release.yml on jcocano/Ajolopy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ajolopy-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: ajolopy-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 462.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for ajolopy-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 fbe0614c3c65aa56c800d52f571946f18e459280c955288fc46408950de0fb93
MD5 1a37e9d374298000e78683938cb2a880
BLAKE2b-256 5113732432e62e4db391be42f396c97cbfec1ef74dd69783a7613a31f40a3fe0

See more details on using hashes here.

Provenance

The following attestation bundles were made for ajolopy-0.1.3-py3-none-any.whl:

Publisher: release.yml on jcocano/Ajolopy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page