My AI Engineering Journey: Understanding LangChain and Building Agentic AI
Building Smart Finance AI an Agentic Multi-agent financial orchestration Application illuminated curiosity in my AI engineering education. The path from foundational concepts to production-grade agentic applications becoming well documented, and existing resources are providing the architectural depth necessary for building systems that actually work.
As a lifelong learner and engineer, I continued to create this repository to while learning about AI, not just for myself, albeit for those passionate about building real AI applications. I as always emphasize I read the documentation. This was no different. This is the learning path I needed, distilled into 12 initial progressive tutorials then a total of 42 that take you from basic agent concepts to sophisticated multi-agent architectures.
Amazing AI Engineering Resources: LangChain
With LangChain learning resources there was a great deal of incredible documentation. These prioritized building foundational understanding, and extracting the conceptual patterns beneath the wonderful technical detail.
I began quickly, the documentation was comprehensive and architecturally rigorous, and well written, they were valuable. They're excellent first steps, in completing my journeys.
The connective tissue - resources that met me where introductory tutorials that I learned from and walked me through systematically toward production-ready implementations. This translated to concepts, architectural decisions, development attention.
My post-baccalaureate coursework in AI technology and systems provided theoretical grounding in LangGraph, RAG, CAG architectures, and hybrid systems. However, translating that foundation into production-ready code required synthesizing disparate patterns into coherent implementation strategies. This repository emerged from that synthesis process and from my genuine love of engineering and continuous learning.
What I Continued to Built: A Complete Learning Architecture
This isn't a code snippet collection. It's a structured learning path from foundational agent concepts to sophisticated multi-agent orchestration, where each tutorial builds systematically on established patterns.
Design Principles
This Repository Adheres To Three Principles:
Executable Completeness: Every tutorial runs without modification. No dependency gaps, no implementation exercises, no ambiguous instructions.
Architectural Rationale: Documentation explains not merely what the code accomplishes, but why particular patterns were selected over alternatives; the decision criteria that matter in production contexts.
Progressive Complexity: Each tutorial assumes mastery of preceding concepts, creating a deliberate pedagogical arc from basic agent instantiation to complex multi-agent coordination.
The Learning Path: From Foundations to Production
Phase I: Core Foundations (Tutorials 0-6)
The journey begins with essential concepts, but extends beyond basic functionality to address production concerns:
Tutorial 0 - Quickstart: Agent instantiation with tool integration and memory persistence. First exposure to the patterns that recur throughout the repository.
Tutorial 1 - Agents: Dynamic model selection, middleware injection, graceful error handling. The distinction between basic agents and production-ready agents becomes clear here.
Tutorial 2 - Models: Invocation methods, tool calling semantics, structured output generation. Understanding how to communicate with language models effectively.
Tutorial 3 - Messages: Conversation management, message type semantics, multimodal content handling. The data structures that enable sophisticated interactions.
Tutorial 4 - Tools: Tool creation with runtime context access. How to design tools that agents can actually use effectively.
Tutorial 5 - Memory: Short-term memory patterns, state management, conversation summarization. The architecture that enables agents to maintain context.
Tutorial 6 - LangSmith: Distributed tracing, debugging infrastructure, production monitoring. The observability layer that transforms development from guesswork into systematic refinement.
# Not just "here's an agent"—demonstrating architectural thinking
agent = create_agent(
model=ChatOpenAI(model="gpt-4o-mini"),
tools=[get_weather, search_web],
memory=MemorySaver(), # State persistence—the foundation of memory
middleware=[error_handler, logger] # Production concerns from day one
)
Phase II: Retrieval-Augmented Generation (Tutorials 7-10)
This sequence demonstrates architectural evolution through a carefully structured progression:
Tutorial 7: Document Loaders - Building the Knowledge Base
Foundation Work: PDF processing, text chunking strategies, embedding generation, ChromaDB storage. The infrastructure that enables retrieval.
# RecursiveCharacterTextSplitter: balancing context preservation with retrieval precision
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, # Large enough for context
chunk_overlap=200 # Overlap preserves semantic continuity
)
The tutorial addresses chunk size trade-offs explicitly: too small loses context, too large reduces precision. The sweet spot (800-1200 characters) emerges from production experience, not arbitrary selection.
Tutorial 8: Retrieval - Querying Strategies
Beyond basic similarity search to explore the retrieval strategy spectrum:
- Similarity Search: Baseline relevance-based retrieval
- Maximum Marginal Relevance (MMR): Balancing relevance with diversity to avoid redundant results
- Score Thresholds: Quality control through similarity filtering
- Metadata Filtering: Targeted search within document subsets
Each strategy serves specific use cases. The tutorial provides decision criteria, not just implementation options.
Tutorial 9: Two-Step RAG - Fixed Pipeline Architecture
Deterministic retrieval-then-generation pattern:
@tool
def search_knowledge_base(query: str) -> str:
"""Search the knowledge base for relevant information."""
docs = vectorstore.similarity_search(query, k=3)
return "\n\n".join(doc.page_content for doc in docs)
agent = create_agent(
model="openai:gpt-4o-mini",
tools=[search_knowledge_base],
system_prompt="Use search_knowledge_base to find information before answering.",
name="rag_agent"
)
Characteristics:
- Predictable execution path
- Consistent latency
- Suitable for document-focused Q&A where context is always required
Tutorial 10: Agentic RAG - Autonomous Retrieval Decisions
Agent-Controlled Retrieval Strategy:
agent = create_agent(
model="openai:gpt-4o-mini",
tools=[search_documents],
system_prompt=(
"Use search_documents when you need specific document information. "
"If you can answer from general knowledge, do so."
),
name="agentic_rag"
)
The Critical Distinction: System Prompt Language. "Use tool when needed" versus "Use tool always" fundamentally alters agent behavior.
Phase III: Multi-Agent Orchestration (Tutorial 11)
The Supervisor Pattern Represents Architectural Sophistication:
# Specialized sub-agents
calendar_agent = create_agent(
model="openai:gpt-4o-mini",
tools=[], # Production: calendar API tools
system_prompt="You are a calendar specialist. Handle scheduling tasks."
)
email_agent = create_agent(
model="openai:gpt-4o-mini",
tools=[], # Production: email API tools
system_prompt="You are an email specialist. Handle email tasks."
)
# Supervisor coordinates sub-agents
@tool
def schedule_event(request: str) -> str:
"""Schedule calendar events using natural language."""
result = calendar_agent.invoke({"messages": [{"role": "user", "content": request}]})
return result["messages"][-1].content
supervisor = create_agent(
model="openai:gpt-4o-mini",
tools=[schedule_event, manage_email, research_topic],
system_prompt="You are a coordinator. Use specialized agents based on requests."
)
This architecture was implemented in my SmartFinance AI applications which provides modularity, testability, and horizontal scalability. Each sub-agent maintains focused expertise within clear domain boundaries.
When To Use Multi-Agent Systems:
- Multiple distinct domains requiring specialized knowledge
- Each domain has complex logic or dedicated tools
- Need centralized coordination without direct user interaction per agent
- System complexity justifies architectural overhead
Advanced Implementation: Context-Augmented Generation (CAG)
In addition to Retrieval Augmented Generation (RAG), this repository explores sophisticated context management through three architectural layers:
Layer 1: Model Context (Tutorial 12)
Transient modifications to model invocations which changes that affect single calls without persisting to state:
@wrap_model_call
def smart_model_selection(
request: ModelRequest,
handler: Callable[[ModelRequest], ModelResponse]
) -> ModelResponse:
"""Route to appropriate model based on query complexity."""
latest_message = request.messages[-1]["content"]
# Complexity heuristic
is_complex = (
len(latest_message) > 200 or
any(word in latest_message.lower()
for word in ["analyze", "compare", "explain in detail"])
)
model = "openai:gpt-4o" if is_complex else "openai:gpt-4o-mini"
request = request.override(model=model)
return handler(request)
Use Cases: Dynamic system prompts, conditional tool availability, model routing based on complexity, adaptive output schemas.
Layer 2: Tool Context (Tutorial 13)
Controlling what tools access (reads) and produce (writes):
@tool
def authenticate_user(
username: str,
password: str,
runtime: ToolRuntime
) -> Command:
"""Authenticate user and update session state."""
if password == "correct":
return Command(
update={
"authenticated": True,
"username": username,
"login_time": datetime.now().isoformat()
},
result="Authentication successful."
)
return Command(
update={"authenticated": False},
result="Authentication failed."
)
Three data sources:
- State: Current conversation session data
- Store: Cross-conversation persistent data (user preferences, history)
- Runtime Context: Static configuration (API keys, permissions)
The tool writes are persistent, they modify state permanently, unlike transient model context changes.
Layer 3: Life-cycle Context (Tutorial 14)
Intercepting the agent loop between core steps for cross-cutting concerns:
@before_model
def enforce_token_budget(state: dict) -> dict:
"""Prevent expensive calls exceeding budget."""
tokens_used = state.get("tokens_used", 0)
max_tokens = state.get("token_budget", 10000)
if tokens_used >= max_tokens:
state["messages"].append({
"role": "assistant",
"content": "Token budget exceeded. Please start a new conversation."
})
raise GraphInterrupt("Token budget exceeded", state=state)
return state
Hook types:
-
before_model: Input validation, content moderation, budget enforcement -
after_model: Response formatting, logging, metrics tracking -
before_tools: Authorization, validation -
after_tools: Error handling, result validation
The Life-cycle hooks enable automatic message summarization, content filtering, comprehensive monitoring. The cross-cutting concerns that distinguish production systems from prototypes.
Architecture:
(LangChain Docs) |
Understanding Context & Retrieval Patterns in LangChain
When building LLM applications, there are different ways to provide information (“context”) to the model. In LangChain, these patterns range from simple prompt-based context to fully agent-driven retrieval systems. Understanding when to use each approach is more important than memorizing definitions.
CAG (Static Context Injection): Context Without Retrieval
In the simplest setups, the model already has everything it needs. CAG refers to providing this information directly to the model through prompts, predefined documents, or memory - without performing any dynamic search.
This approach works best when the knowledge domain is small, stable, and well-curated, such as application rules, policies, or product documentation. Responses are fast and predictable, though updating or scaling the knowledge requires manual changes.
In Practice: This is often just a well-designed prompt or chain with static context.
from langchain.prompts import PromptTemplate
from langchain.chat_models import ChatOpenAI
# Static context provided directly to the model
static_context = """
You are an expert travel guide.
Provide helpful recommendations for tourists in Paris.
"""
prompt = PromptTemplate(
input_variables=["question"],
template=static_context + "\nQuestion: {question}\nAnswer:"
)
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
question = "What are the best hidden cafes to visit?"
answer = llm(prompt.format(question=question))
print(answer)
Two-Step RAG: Fixed Retrieval Pipeline
Two-Step RAG introduces dynamic retrieval. Before generating a response, the system always retrieves relevant documents (e.g., from a vector database) and passes them to the model.
This fixed sequence - retrieve, then generate - makes the system easy to understand and debug. However, retrieval is performed for every query, even when it may not be strictly needed, which can be inefficient for simple or mixed questions.
In Practice: This is most common starting point for RAG systems in LangChain.
from langchain.chains import RetrievalQA
from langchain.vectorstores import Chroma
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.chat_models import ChatOpenAI
# Sample documents
documents = [
"Paris has hidden cafes in Le Marais and Montmartre...",
"The Louvre and Musée d'Orsay are must-see museums."
]
# Create embeddings
embeddings = OpenAIEmbeddings()
# Initialize ChromaDB vector store (matches your repo)
vectorstore = Chroma.from_texts(documents, embedding=embeddings)
# Create retriever
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
# Create RetrievalQA chain
qa_chain = RetrievalQA.from_chain_type(
llm=ChatOpenAI(model_name="gpt-3.5-turbo"),
retriever=retriever,
return_source_documents=True
)
question = "Where can I find hidden cafes in Paris?"
result = qa_chain.run(question)
print(result)
Agentic RAG: Conditional Retrieval and Planning
Agentic RAG adds an agent layer that allows the system to decide whether retrieval is needed and how to perform it. The agent can reason about the query, choose tools, and orchestrate multi-step actions. The agent also reasons about the user’s request and chooses which tools to use - including retrieval.
This enables more advanced workflows, such as multi-step reasoning, tool use, and adaptive responses.
In Practice: This pattern is used when queries are complex, ambiguous, or require reasoning across multiple sources.
from langchain.agents import initialize_agent, Tool
from langchain.chat_models import ChatOpenAI
from langchain.vectorstores import Chroma
from langchain.embeddings.openai import OpenAIEmbeddings
# Sample documents
documents = ["Paris cafes guide...", "Hidden spots in Montmartre..."]
# Create embeddings
embeddings = OpenAIEmbeddings()
# Initialize Chroma vector store
vectorstore = Chroma.from_texts(documents, embedding=embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
# Define a retriever tool
def search_docs(query: str):
return retriever.get_relevant_documents(query)
tools = [
Tool(
name="DocumentRetriever",
func=search_docs,
description="Fetch relevant documents for user questions"
)
]
# Initialize agent (agent decides if retrieval is needed)
agent = initialize_agent(
tools=tools,
llm=ChatOpenAI(model_name="gpt-3.5-turbo"),
agent="zero-shot-react-description",
verbose=True
)
question = "Compare hidden cafes in Montmartre with Le Marais and recommend a day itinerary."
answer = agent.run(question)
print(answer)
How These Patterns Relate in LangChain
- CAG focuses on how context is provided
- RAG focuses on how context is retrieved
- Agents focus on how decisions are made
LangChain supports all three patterns, allowing developers to start simple and progressively add complexity as needed. I liked that.
Important Note for Learners As I Learned Myself
CAG is used here as a descriptive term for static context injection. LangChain does not currently define CAG as a formal RAG architecture, but fully supports this pattern through prompt templates, memory, and chains.
A Simple Way to Think About It
- Start with CAG when your knowledge is small and stable
- Move to 2-Step RAG when you need dynamic knowledge retrieval
- Use Agentic RAG when the system must reason, plan, or choose actions
At times, the best architecture is the simplest one that solves the problem.
Why This Progression in Development in AI Matters
What I learned is that LangChain is designed to support growth: you can begin with basic prompt-based systems and gradually evolve toward agent-driven architectures as your application’s needs increase.
CAG optimizes how context is supplied, RAG optimizes how context is retrieved, and agents optimize how decisions are made.
- CAG → Prompt templates, memory, static documents, system context
- 2-Step RAG → Chains + retrievers
- Agentic RAG → Agents or LangGraph with retrievers as tools
Personal Developers Note
I included CAG (Context-Augmented Generation) in this discussion because it is not usually highlighted, I learned about CAG - I feel it is an important part of LLM system design. By injecting context directly into prompts or memory, it offers simplicity, minimal latency, and predictable behavior. Showing CAG alongside 2-Step and Agentic RAG helps learners see the full spectrum of context strategies, from basic setups to complex agent-driven reasoning.
Agentic AI Implementation: My Application Smart Finance AI
These patterns aren't theoretical. Every implementation emerged from building Smart Finance AI, an Agentic AI/Multi-Agent Financial System providing:
- Portfolio Management: State tracking and real-time position monitoring
- Market Analysis: Sentiment processing and trend identification
- Financial Planning: Goal orchestration and strategy optimization
- LangGraph Coordination: Multi-agent workflows with sophisticated state management
This repository represents the technology and curriculum I successfully learned and completed and required when beginning this implementation. Each pattern addresses production challenges encountered during development, the lessons learned from building systems that actually run in production.
MY Final Thoughts Regarding LangChain - I Mean Why not LangChain Its Great!
I love engineering. I love learning. This repository exists at the intersection of both.
As a lifelong learner, I required resources that went beyond surface-level tutorials albeit remained accessible enough to build understanding systematically. The process of creating Agentic AI Application taught me that the path from learning AI concepts to implementing production systems requires more than the surface level - it requires a coherent sophisticated learning architecture.
This repository assisted me in learning, developing, creating, and building Agentic AI applications. If you're on a similar journey, passionate about engineering, committed to continuous learning, eager to build real systems - I hope it helps you as well.
Every tutorial reflects production experience. Every pattern addresses real challenges. Every architectural decision is explained with the criteria that matter when your code requirement to work reliably.
Who This Serves
This resource is for everyone - especially developers who:
- Possess Python proficiency and need to learn LangChain
- Have implemented basic LLM applications and seek production-grade patterns
- Require understanding of RAG and CAG architectures beyond marketing materials
- Require understanding of Agentic AI systems
- Are building production AI systems
- Are preparing for AI engineering roles requiring architectural competency
- Share a passion for continuous learning and engineering excellence
- Enjoy learning and development
Getting Started
git clone https://github.com/eriperspective/langchain.git
cd langchain
pip install langchain langchain-openai langchain-community langgraph pypdf langsmith
export OPENAI_API_KEY="your-api-key-here"
python 0-quickstart/quickstart_demo.py
Recommended Learning Path:
- Work through tutorials 0-6 sequentially to establish foundational patterns
- Complete tutorial 6 to establish debugging infrastructure
- Progress through RAG sequence (7-10) to understand retrieval architectures
- Study tutorial 11 for multi-agent coordination patterns
- Explore advanced topics (12-41) based on specific implementation needs added for deeper learning
Technology Stack
- LangChain v1.0+: Current patterns, no deprecated implementations
- LangGraph: Complex agent workflow orchestration
- OpenAI GPT-4o-mini: Sufficient capability, cost-optimized for learning
- ChromaDB: Vector database for RAG implementations
- LangSmith: Distributed tracing and debugging infrastructure
Key Repository Features
Production-Quality Code:
- Comprehensive error handling and validation
- Clear progress indicators and visual feedback
- Both automated testing and interactive modes
- Prerequisite checking and dependency verification
Architectural Emphasis:
- Explicit trade-off analysis (when to use which pattern)
- Decision criteria for architectural selection
- Production patterns from real system implementation
- Focus on why, not just how
Progressive Complexity:
- Each tutorial builds on established foundations
- Clear prerequisites and learning dependencies
- Concepts introduced when needed, not prematurely
- Natural progression from simple to sophisticated
Acknowledgments
Professor Charles Jesture at Revature who taught me Langchian and AZ Next at Arizona State University with Rob Buelow provided the theoretical foundation through post-baccalaureate coursework that enabled this amazing work. The transition from conceptual understanding to production implementation is substantial, and rigorous educational grounding proved essential.
The Future is Now & I Am Thoroughly Excited
I'll continue expanding this repository as production systems evolve. Upcoming may additions include:
- Advanced error recovery patterns and circuit breaker implementations
- Streaming response architectures for improved user experience
- Cost optimization strategies for production-scale deployment
- Additional integration examples from production systems
For developers building with these patterns, I welcome dialogue. Engineering is fundamentally collaborative, and continuous learning happens through shared experience which I enjoy.
Repository: github.com/eriperspective/langchain
This post is part of My AI engineering Journey.
Follow along for more AI Engineering Building with Eri!
What architectural challenges are you encountering in AI system development? What patterns would help you build better systems? Let's learn together.



Top comments (0)