The AI Engineering Stack: What I Use, and Why banner

The AI Engineering Stack: What I Use, and Why

Every tool in my AI engineering toolbox, what it actually is, and why it earned a spot — from Python and Postgres to LangGraph and Langfuse.

Aug 7, 2026

AI AI Engineering Python LLM Developer Tools RAG Agents

Share this post

Why a Stack Post

Every “learn AI engineering” list I find is either a wall of a hundred logos with no explanation, or a single opinionated blog post that assumes you already know why Postgres beat a dedicated vector database. Neither is useful when you’re actually deciding what to install today.

So here’s mine: every tool I reach for when building AI applications, what it is in one line, and why it earned the slot instead of the five alternatives next to it. Some of these I use daily and know deeply. Others I’m just aware of — enough to not be surprised by them in a job description or a migration doc. I’ve split those apart so you know which is which.

Languages & Core Engineering

This is the boring, load-bearing layer. Nothing here is AI-specific — it’s just good backend engineering, and skipping it is why so many AI prototypes never make it to production.

ToolWhat it isWhy it’s in the stack
PythonThe languageIndustry default for AI engineering; every major framework here is Python-first
SQL / PostgreSQLRelational database & query languageApp data, vectors, and full-text search all live in one boring, correct database
uvPython package & project managerReplaces pip/venv/poetry/pyenv with one fast tool; the current standard
ruffLinter + formatterOne instant tool, no config debates
pyrightStatic type checkerAI apps are schema-heavy; typing catches contract breaks before runtime
pytestTest frameworkStandard tests today, eval suites later — same tool carries both
PydanticData validation & serializationThe load-bearing library of the field: API contracts, LLM output schemas, tool signatures
FastAPIAsync web frameworkPydantic-native and streaming-friendly, so it serves everything I build
httpxAsync HTTP clientRaw provider API calls, SSE consumption, concurrent fan-out
DockerContainersLocal infra (Postgres, Langfuse) and the deployment artifact, same file
GitHub ActionsCI/CDRuns tests and eval regression gates on every change

Pydantic and FastAPI are the two I’d call non-negotiable. LLM outputs are untyped text pretending to be structured data — Pydantic is what turns “the model probably returned JSON” into “the model returned this exact shape or raised an error.” FastAPI just happens to be built around the same library, so the validation you write for your API is the same validation you write for the model.

Models & Model Access

This layer is where most people spend all their attention and it’s the one that churns fastest. My approach: go deep on one hosted API, stay aware of the rest, and treat “which model” as a swappable decision, not an architectural one.

ToolWhat it isWhy it’s in the stack
Anthropic APIHosted frontier models (Claude)The one I study in depth: streaming, tool use, prompt caching, batches
OpenAI APIHosted frontier modelsThe de facto wire-format standard most tooling speaks
OllamaLocal model runnerRun open-weight models (Llama/Qwen/DeepSeek families) on your own machine
OpenRouterModel aggregatorAware: many models behind one key
Microsoft FoundryMicrosoft’s unified AI platformEnterprise route to frontier models with quotas, content filters, private networking; my first-choice cloud
Amazon BedrockAWS managed model accessClaude and other models with AWS governance; Knowledge Bases, Guardrails
Vertex AIGCP’s AI platformAware: same concepts, third ecosystem

If you only take one thing from this section: learn one provider’s API properly before you learn five providers shallowly. Streaming, tool use, and prompt caching behave differently enough across providers that skimming all of them teaches you the lowest common denominator, not how any of them actually work.

Structured Outputs, RAG & Agents

This is the middle layer — where “call an LLM” turns into “build an application.” It’s also where I’ve made the most deliberate choices, usually after hand-rolling the naive version first and feeling the pain that the library solves.

ToolWhat it isWhy it’s in the stack
InstructorStructured-output libraryPydantic-validated LLM outputs with retries — adopted after hand-rolling the same loop
pgvectorVector extension for PostgresVectors + metadata + full-text search in one boring, correct database
sentence-transformersOpen-source embeddings & rerankersLocal embedding and cross-encoder reranking without API costs
Cohere RerankHosted rerankerThe biggest retrieval-quality jump per line of code
LangGraphAgent orchestration frameworkMy primary framework: durable state, human-in-the-loop, streaming
MCPModel Context ProtocolThe open standard for exposing tools to AI apps; worth building a server for
Pydantic AIType-safe agent frameworkAware: the lighter-weight alternative worth watching
Claude Agent SDKAgent harness SDKAware: the production harness behind Claude Code

Two picks here I’d defend hardest. First, pgvector over a dedicated vector database — unless you’re at a scale where that’s genuinely the bottleneck, running vectors next to your relational data means one fewer system to operate, back up, and reason about consistency for. Second, Cohere Rerank — of everything in a RAG pipeline, adding a reranking pass is the highest-leverage change you can make for the least code.

Evals, Observability & Production

The layer that separates a demo from something you’d trust with real traffic. This is also the section most tutorials skip entirely, which is exactly why things break in production and nobody can say why.

ToolWhat it isWhy it’s in the stack
promptfooEval & red-team CLIConfig-driven eval suites wired into CI; automated red-teaming
DeepEvalPytest-native eval libraryPrebuilt LLM/RAG metrics (faithfulness, relevancy) inside the pytest you already use
RagasRAG evaluation libraryAware: RAG-metric vocabulary; overlaps DeepEval
LangfuseLLM observability platformOpen-source tracing, cost tracking, datasets, feedback capture; self-hostable
LiteLLMLLM gateway/proxyOne choke point for budgets, rate limits, fallbacks, model routing
vLLMInference serverThe standard for self-hosting open-weight models on GPUs
Redis + arqQueue + async workerBackground jobs (ingestion, long agent runs) off the request path
Fly.io / RailwayContainer hostingSimple, cheap deploys for containerized apps
ModalPython-native serverless + GPUServerless GPUs for vLLM legs and spiky workloads
Azure AI SearchManaged retrieval serviceThe managed version of the RAG stack you built by hand
Azure Container AppsServerless containers on AzureMy primary cloud deploy target (Azure-first)

Langfuse is the one piece of this entire stack I’d call mandatory, not optional. Without tracing, “the agent gave a bad answer” is a mystery. With it, it’s a five-minute investigation: which prompt, which retrieved chunks, which tool call, which token cost. Evals tell you something is wrong in aggregate; tracing tells you exactly what happened in the one conversation your user is complaining about.

How I Actually Use This List

Not everything here gets equal attention. The pattern that’s worked for me:

  • Primary tools — Python, Postgres, Pydantic, FastAPI, the Anthropic API, LangGraph, Langfuse — I go deep on: real projects, not just tutorials.
  • “Aware” tools — OpenRouter, Vertex AI, Pydantic AI, Ragas — I read the docs, skim a comparison or two, and move on. The goal is recognizing them, not mastering them.
  • Everything gets revisited when the job actually calls for it. Reaching for vLLM before you’ve ever needed to self-host a model is optimizing for a problem you don’t have yet.

That’s the whole stack. If you’re building your own version of this list, the only rule that matters is: pick one thing per layer, go deep enough to feel its edges, and stay aware of the rest so nothing surprises you later.


Read Next