Vol. 03 · Application Engineering

The LLM Framework Ecosystem

Key abstractions, architectural patterns, pitfalls and selection criteria for the main frameworks of the LLM ecosystem. Each one is disassembled atomically.

Retrieval answer

Key abstractions, architectural patterns, pitfalls and selection criteria for the main frameworks of the LLM ecosystem. Each one is disassembled atomically. LangChain is an abstraction layer on top of the LLM API. His philosophy: everything is a component, components are connected through pipes into chains (LCEL). This New Runtime record is an evidence-linked retrieval unit.

01

LangChain — Orchestration Foundation

3 cards
01orchestrationLangChain - key abstractions1 visual1 source note

LangChain is an abstraction layer on top of the LLM API. His philosophy: everything is a component, components are connected through pipes into chains (LCEL). The main value is not in the “magic”, but in uniform interfaces for 100+ providers and tools.

Source-complete notesWhen to buy LangChain

When to buy LangChain

  • rapid prototype RAG
  • need integration with 50+ providers
  • the team already knows LangChain
  • complex stateful agent → LangGraph
  • production without overhead → pure SDK
02orchestrationLCEL — LangChain Expression Language1 source note

A modern way to assemble chains is through the | operator. Provides streaming, batching, tracing and async out of the box for any chain. Replaces the old Chain classes.

Source-complete notesLCEL Syntax
LCEL Syntaxtypescript
# Simple RAG chain
chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt_template
    | chat_model
    | StrOutputParser()
)

# Everything works automatically:
chain.invoke(query) # synchronously
chain.stream(query) # token streaming
chain.batch([q1, q2, q3]) # in parallel
await chain.ainvoke(query) #async
03pitfallsLangChain - pitfalls1 source note

LangChain is often criticized for its abstractions that hide what's going on under the hood - and this is what causes most problems in production.

Source-complete notesCommon problems
Common problemstext
✗ Magic prompts
  Default prompts inside Chain classes
  → unpredictable, impossible to control

✗ Hidden LLM challenges
  RetrievalQA does extra. calls unnoticed
  → unexpected costs, hidden latency

✗ Versioning
  Frequent breaking changes between minor versions
  → pin version, test updates carefully

✓ Solution: LCEL + explicit prompts + tracing everything
02

LangGraph — Stateful Agent Graphs

4 cards
04graph / stateLangGraph - philosophy and abstractions1 visual1 source note

LangGraph is a way to describe agents as state machines with explicit state. Not chains, but a graph: nodes are actions/LLM calls, edges are transitions between states. This gives something that LangChain does not: loops, branches, human-in-the-loop, persistent state.

Visual model · Process flowFollow the sequence behind LangGraph - philosophy and abstractions and locate where work or state changes.
Complete view · 3 layers
Source-complete notesWhen to take LangGraph instead of LangChain

When to take LangGraph instead of LangChain

  • agent with loops and branching
  • need human-in-the-loop (pause, confirmation)
  • persistent state between sessions
  • multi-agent with clear orchestration
05graph / stateState + Reducer is the heart of LangGraph1 source note

Each node reads and writes to a common State. Reducer determines how the state is updated when there is a conflict (append vs replace). This makes the graph reproducible and debuggable.

Source-complete notesExample State
Example Statesql
from typing import Annotated
from langgraph.graph import add_messages

class AgentState(TypedDict):
    messages: Annotated[list, add_messages]
    # add_messages = reducer: append, not replace
    retrieved_docs: list[str]
    iteration_count: int
    final_answer: str | None

# each node receives state and returns patch:
def agent_node(state: AgentState) -> dict:
    response = llm.invoke(state["messages"])
    return {"messages": [response]}
06graph / stateConditional Edges - flow control1 source note

Edges can be conditional: a function looks at the state and decides which node to go to next. This allows you to build complex logic without imperative code inside nodes.

Source-complete notesBranching example
Branching examplepython
def should_continue(state) -> str:
    last_msg = state["messages"][-1]
    if last_msg.tool_calls:
        return "tools" # → tools node
    elif state["iteration_count"] > 5:
        return "force_end" # → force stop
    else:
        return "end" # → final response

graph.add_conditional_edges("agent", should_continue,
    {"tools": "tools", "end": END, "force_end": END})
07graph / stateCheckpointing - persistence and HITL1 source note

LangGraph can save state after each step in the database (Postgres, SQLite, Redis). This gives: continuation after a failure, human-in-the-loop (pause → wait for confirmation → continue), time travel (rollback to the previous state).

Source-complete notesHuman-in-the-loop pattern
Human-in-the-loop patternpython
checkpointer = PostgresSaver(conn)
graph = graph.compile(
    checkpointer=checkpointer,
    interrupt_before=["dangerous_action"] ← pause here
)

# 1. Run before interrupt
graph.invoke(input, config={"thread_id": "t1"})
# 2. Show the person a pending action
state = graph.get_state(config)
# 3. The person approves → continue
graph.invoke(None, config) # resume
03

LlamaIndex — RAG & Data Layer

3 cards
08rag frameworkLlamaIndex - philosophy and abstractions1 visual1 source note

LlamaIndex is focused on one thing: connecting LLM with your data. While LangChain is a general-purpose orchestration tool, LlamaIndex is a specialized data layer. The main primitive is Index and QueryEngine.

Visual model · Process flowFollow the sequence behind LlamaIndex - philosophy and abstractions and locate where work or state changes.
Complete view · 2 layers
Source-complete notesWhen LlamaIndex beats LangChain

When LlamaIndex beats LangChain

  • complex RAG logic (parent-doc, multi-hop)
  • many data sources (PDF, Notion, SQL, ...)
  • need advanced indexes (KG, Summary)
  • orchestration is more difficult → LangGraph is better
09rag frameworkTypes of indexes - not just vectors1 source note

LlamaIndex offers several types of indexes for different tasks. The choice of index is an architectural decision that affects the quality of answers more than the choice of model.

Source-complete notesTypes of Indexes
Types of Indexestext
VectorStoreIndex standard RAG for embeddings
SummaryIndex summarization of the entire corpus sequentially
KeywordTableIndex keyword extraction → keyword search
KnowledgeGraph entity graph → search by relationships
DocumentSummary summary per doc → document selection → details
TreeIndex hierarchical tree of summations

Multi-Index: different indexes for different types of questions
10rag frameworkIngestionPipeline - correct indexing1 source note

Document processing pipeline before indexing: transformations, splitters, metadata, deduplication. With caching - re-indexing skips already processed documents.

Source-complete notesExample
Exampletext
pipeline = IngestionPipeline(
    transformations=[
        SentenceSplitter(chunk_size=512, overlap=64),
        TitleExtractor(), # LLM metadata
        QuestionsAnsweredExtractor(), # hypothetical questions
        OpenAIEmbedding(),
    ],
    vector_store=chroma_store,
    cache=IngestionCache(), # do not reindex old
)
04

Multi-Agent Frameworks — CrewAI · AutoGen · Agno

4 cards
11multi-agentCrewAI - roles, tasks, teams1 visual1 source note

CrewAI models multi-agent systems as a team with roles. Each agent is a role + a set of tools + a goal. Tasks are assigned to agents and executed sequentially or in parallel. Very readable declarative API - good for business processes where roles are obvious.

Visual model · Process flowFollow the sequence behind CrewAI - roles, tasks, teams and locate where work or state changes.
Complete view · 4 layers
Source-complete notesWhen CrewAI

When CrewAI

  • business processes with clear roles
  • quick start of a multi-agent prototype
  • complex graph → LangGraph more precise
  • hidden prompts inside the framework
12multi-agentAutoGen — conversational multi-agent1 source note

AutoGen (Microsoft) is based on the idea of interlocutor agents: agents exchange messages with each other, like in a chat. GroupChat allows multiple agents to discuss a task until consensus.

Source-complete notesKey primitives
Key primitivestext
ConversableAgent base agent with LLM + human_input_mode
AssistantAgent LLM agent without human input
UserProxyAgent executes code, optionally requests a person
GroupChat multiple agents + next selection manager
GroupChatManager LLM decides who speaks next

Pattern: Coder + Reviewer + Executor
Coder writes → Reviewer criticizes → Executor launches
13multi-agentAgno (ex-Phidata) - lightweight agents2 source notes

Agno is a minimalistic framework for agents: minimum abstractions, maximum control. Agent = LLM + tools + storage. No magic. Easy to read and easy to debug. Built-in support for memory and knowledge bases.

Source-complete notesMinimal example · Applicable
Minimal exampletext
agent = Agent(
    model=Claude(id="claude-sonnet-4"),
    tools=[DuckDuckGoSearch(), PythonTool()],
    memory=AgentMemory(db=SqliteMemoryDb()),
    knowledge=PDFKnowledgeBase(path="docs/"),
    instructions=["Answer in Russian", "Use numbers"],
    show_tool_calls=True,
    markdown=True,
)
agent.print_response("WB 2025 Market Analysis")

Applicable

  • transparent simple agents
  • quick start without learning the framework
14comparisonComparison of multi-agent frameworks1 source note

The choice between frameworks is determined not by “which is more powerful”, but by “which abstractions coincide with your task.”

Source-complete notestable
CriterionCrewAIAutoGenLangGraphAgno
AbstractionRoles / tasksAgent chatGraph / stateAgent + tools
ControlMediumMediumHighHigh
Learning curveLowMediumHighLow
LoopsNoPartialYesNo
Production readinessUse carefullyUse carefullyYesYes, with caveats
05

Eval Frameworks — RAGAS · ARES · DeepEval · Braintrust

4 cards
15evalsRAGAS - standard for RAG eval1 visual1 source note

RAGAS is a specialized eval framework for RAG systems. Uniqueness: reference-free metrics - you don’t need a dataset with GT answers for most metrics. Assessment via LLM judge with atomic approvals.

Visual model · Formula mapConnect the quantities and operations that determine RAGAS - standard for RAG eval.
Source-complete notesApplicable

Applicable

  • RAG assessment without GT dataset
  • diagnostics: retrieval vs generation problem
  • expensive for LLM-judge on large datasets
16evalsDeepEval - pytest for LLM1 source note

DeepEval integrates into pytest and allows you to write eval tests as unit tests. Large library of ready-made metrics + support for custom ones. Fits well into CI/CD.

Source-complete notesSyntax
Syntaxpython
@pytest.mark.parametrize("case", test_cases)
def test_rag_quality(case):
    actual_output = rag_pipeline(case.input)

    assert_test(
        test_case=LLMTestCase(
            input=case.input,
            actual_output=actual_output,
            retrieval_context=case.context
        ),
        metrics=[
            FaithfulnessMetric(threshold=0.8),
            AnswerRelevancyMetric(threshold=0.7),
            HallucinationMetric(threshold=0.1),
        ]
    )
17evalsBraintrust - eval as a product1 source note

Braintrust is a platform for eval with UI: launching experiments, comparing prompt versions, history of runs, drill-down on cases. Like Weights & Biases, but for LLM pipelines. The SDK works without a platform.

Source-complete notesExperiment concept
Experiment concepttypescript
Eval(
    name="RAG pipeline v2 vs v3",
    data=dataset, # list {input, expected}
    task=rag_pipeline, # functionoutput
    scores=[ # metrics
        Faithfulness,
        AnswerRelevancy,
        NumTokens, # cost tracking
        Latency
    ],
    experiment_name="v3-with-rerank"
)
18evalsARES - autonomous eval system2 source notes

ARES (Stanford) is a system that trains small LM classifiers for evaluation instead of expensive LLM judges. You need a small number of human tags for training - further quickly and cheaply at any volume.

Source-complete notesPrinciple · Applicable
Principletext
# One-time use:
human_labels = 150 labeled examples
synthetic_data = LLM.generate_training_data(docs)
classifier = finetune(small_lm, human_labels + synthetic)

# Next - cheap and fast:
scores = classifier.score(10_000_examples)
# vs LLM-judge: 100x cheaper, comparable quality

Applicable

  • large volumes of assessment
  • eval cost reduction
06

Observability — Langfuse · Phoenix Arize · Helicone

4 cards
19observabilityLangfuse — open-source LLM observability1 visual1 source note

Langfuse is the most complete open-source tool: traces, eval, datasets, prompt management, cost tracking - in one place. Self-hosted via Docker. Integration via SDK or OpenTelemetry.

Visual model · Annotated exampleInspect the concrete example behind Langfuse — open-source LLM observability, one layer at a time.
Complete view · 3 layers
Source-complete notesStrengths

Strengths

  • self-hosted, GDPR-compliant
  • prompt management + tracing in one
  • integration with LangChain/LlamaIndex out of the box
  • UI is slower than Arize at high volumes
20observabilityPhoenix Arize - ML observability for LLM1 source note

Arize Phoenix - from ML observability to LLM. Strengths: visualization of embeddings, drift detection at the vector space level, UMAP query projections. The best choice if you need to analyze retrieval quality visually.

Source-complete notesUnique features vs Langfuse
Unique features vs Langfusesql
Embedding visualization
  UMAP/TSNE projections: see query clusters
  → find anomalies and OOD queries visually

Retrieval analysis
  scatter plot: query embeddings vs doc embeddings
  → see where retrieval misses

Drift detection
  comparison of distributions between periods
  → automatically finds data drift

OpenInference
  open tracing standard LLM (like OTEL)
21observabilityHelicone — gateway + observability2 source notes

Helicone works as a proxy gateway between your code and the LLM API. Zero-instrumentation: you change one URL, you get all the metrics. Built-in caching, rate limiting, cost alerts.

Source-complete notesConnection in 1 line · Applicable
Connection in 1 linetext
client = OpenAI(
    base_url="https://oai.helicone.ai/v1",
    # ← instead of api.openai.com
    default_headers={
        "Helicone-Auth": f"Bearer {HELICONE_KEY}",
        "Helicone-Cache-Enabled": "true", # cache
        "Helicone-User-Id": user_id, # per-user
    }
)

Applicable

  • no time for instrumentation
  • need cache + rate limit immediately
  • less flexibility than Langfuse
22observabilityOpenTelemetry for LLM - tracing standard1 source note

OpenInference (Arize) and OpenLLMetry (Traceloop) extend OpenTelemetry to be LLM-specific. The span attributes are standardized: input/output, model, tokens. Allows you to send traces to any OTEL-compatible backend.

Source-complete notesStandard attributes OTEL LLM span
Standard attributes OTEL LLM spantext
gen_ai.system = "anthropic"
gen_ai.request.model = "claude-sonnet-4"
gen_ai.usage.input_tokens = 1240
gen_ai.usage.output_tokens = 312
gen_ai.prompt = [messages]
gen_ai.completion = [response]
# → goes to Langfuse / Jaeger / Grafana Tempo
07

DSPy — Prompt Optimization as Code

3 cards
23prompt optimizationDSPy — philosophy: program, don't prompt1 visual1 source note

DSPy reverses the approach: instead of writing prompts manually, you describe the task signature (inputs → outputs) and quality metrics, and the optimizer itself finds the best prompts, few-shot examples and call chains. This is a compiler for LLM programs.

Visual model · Formula mapConnect the quantities and operations that determine DSPy — philosophy: program, don't prompt.
Source-complete notesWhen DSPy beats manual prompting

When DSPy beats manual prompting

  • the base model changes frequently
  • there is a dataset with a metric - the prompt can be optimized
  • multi-hop tasks with multiple LLM calls
  • no dataset → DSPy will not help
  • high entry threshold
24prompt optimizationDSPy Modules - building blocks1 source note

DSPy modules are typed LLM call patterns. Each module is independently optimized and can be combined into programs.

Source-complete notesMain modules
Main modulestext
dspy.Predict
  direct call by signature, without CoT

dspy.ChainOfThought
  adds a reasoning field → response
  # prompt with CoT is generated automatically

dspy.ReAct
  agent with tools based on the ReAct pattern

dspy.Retrieve
  search in the connected knowledge base

dspy.MultiChainComparison
  several reasoning paths → the best
25prompt optimizationTextGrad & OPRO - DSPy alternatives1 source note

TextGrad (Stanford) - "gradient descent" for text: LLM calculates the "gradient" (critique) and updates the prompt. OPRO (Google) - LLM as an optimizer: generates prompt candidates, evaluates, improves iteratively.

Source-complete notesTextGrad idea
TextGrad ideatext
loss = metric(output, gt) # "how bad"
gradient = LLM( # "why is it bad"
    f"Output: {output}
Loss: {loss}
What's wrong with the prompt?"
)
new_prompt = LLM( # "fix"
    f"Old prompt: {prompt}
Gradient: {gradient}
Improved prompt:"
)
08

Navigating the ecosystem - when to take what

3 cards
26navigationDecision Tree - choosing a framework1 visual

Ask yourself these questions before choosing a framework. A wrong choice at the beginning costs correspondence later.

Visual model · ComparisonContrast the alternatives in Decision Tree - choosing a framework under the same frame.
Complete view · 3 layers
27pitfallsAntipattern - a framework for the sake of a framework1 source note

The most common mistake: they take LangChain/LlamaIndex “because everyone uses it” - and get an abstraction layer that hides bugs, slows down debugging and creates a dependence on other people’s breaking changes.

Source-complete notesWhen a framework is not needed
When a framework is not neededtext
✗ One or two LLM challenges
  → direct SDK (anthropic, openai) is better

✗ The team does not know the framework
  → time to study > time to write yourself

✗ Specific logic in every step
  → abstractions get in the way, you write workarounds

✓ The framework is justified when:
  → 10+ integrations are needed (providers, vector databases)
  → complex stateful graph (LangGraph)
  → the team already knows him
28recommendationsStack for 2025 - what really works1 source note

Community opinion based on the results of production experience: which combinations give the least number of problems with the greatest flexibility.

Source-complete notesRecommended Stacks
Recommended Stackstext
Minimalistic (small team):
  SDK + Instructor + Langfuse

RAG product:
  LlamaIndex + LangGraph (agent) + RAGAS + Langfuse

Multi-agent enterprise:
  LangGraph + LangChain tools + Braintrust + Arize

Research/Experiments:
  DSPy + Langfuse + DeepEval

Main principle:
  start with the minimum → add frameworks
  only when the pain without them is obvious

No dead end

Keep moving through the map.

Continue in sequence, switch to a related guide, or return to the seven-track learning map.

Discovery graph / next reads

Continue through New Runtime

Open the graph
  1. 01learning trackApplication EngineeringOpen the complete learning track.
  2. 02related materialThe Python Utility Stack for LLM PipelinesContinue with another guide in this learning track.
  3. 03related materialProduction LangChain + LangGraph: Code Structure & RuntimeContinue with another guide in this learning track.
  4. 04related materialMini-Repository: FastAPI + LangGraph + LangChain as a ServiceContinue with another guide in this learning track.
  5. 05related materialStarter Kit: FastAPI + LangGraph + LangChain by FileContinue with another guide in this learning track.

These links are also published in this page’s JSON twin and as typed edges in DiscoveryGraph v1.

Who read this page?Machine requests, hidden until opened

Loading the privacy-safe route aggregate…

Open the JSON contract