https://github.com/nevin100/langgraph-revision
This repository serves as an educational resource for understanding LangGraph, a framework for building stateful multi-actor applications with language models.
https://github.com/nevin100/langgraph-revision
agent groq-api langchain langgraph python rag sqlite uv
Last synced: about 1 month ago
JSON representation
This repository serves as an educational resource for understanding LangGraph, a framework for building stateful multi-actor applications with language models.
- Host: GitHub
- URL: https://github.com/nevin100/langgraph-revision
- Owner: Nevin100
- Created: 2026-05-18T07:09:40.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-05-23T06:57:02.000Z (about 1 month ago)
- Last Synced: 2026-05-23T08:29:56.726Z (about 1 month ago)
- Topics: agent, groq-api, langchain, langgraph, python, rag, sqlite, uv
- Language: Jupyter Notebook
- Homepage:
- Size: 190 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# LangGraph Workflow Patterns & Advanced Topics
A comprehensive learning repository demonstrating LangGraph's core workflow patterns and advanced features for building AI-powered applications with LLM agents.
---
## Table of Contents
1. [Project Overview](#project-overview)
2. [Getting Started](#getting-started)
3. [Project Structure](#project-structure)
4. [Core Workflow Patterns](#core-workflow-patterns)
5. [Key Concepts & Implementations](#key-concepts--implementations)
6. [Advanced Topics](#advanced-topics)
7. [Common Issues & Solutions](#common-issues--solutions)
8. [Dependencies](#dependencies)
9. [Contributing & Future Work](#contributing--future-work)
---
## Project Overview
This repository is a **comprehensive LangGraph learning and reference repository** demonstrating production-ready implementations of:
- **Core workflow patterns** (Sequential, Parallel, Conditional)
- **Advanced features** (Persistence, Streaming, Memory Systems, Tools, RAG, HITL)
- **11 complete implementations** with working code, not just concepts
All code uses **LLaMA-3.3-70b-versatile** model via Groq API, Python 3.12+, and production-grade LangGraph patterns.
### ✅ What's Implemented (11 Complete Modules)
**Fundamental Patterns:**
1. Sequential Workflows - Linear task execution
2. Parallel Workflows - Concurrent independent tasks
3. Conditional Workflows - Dynamic routing based on logic
**Production Features:**
4. Persistence - SQLite checkpointing & state resumption
5. Streaming - Real-time token streaming with async execution
6. Chat Memory (SQLite) - Persistent conversation history
7. Short-Term Memory - Thread-specific isolated sessions
8. Long-Term Memory - Global cross-session user profiles
9. Human-in-the-Loop - Workflow interrupts for human decisions
10. Tool Binding - LLM-driven autonomous tool selection
11. RAG - Retrieval-Augmented Generation with semantic search
**Target Audience:** LangGraph learners, AI engineers, teams building production chatbots, multi-step AI workflows, and agent systems.
---
## Getting Started
### Prerequisites
- Python 3.12 or higher
- Groq API key (for LLM features)
- Git
### Installation
1. **Clone the repository:**
```bash
git clone
cd langgraph-revision
```
2. **Create virtual environment (if not already done):**
```bash
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
```
3. **Install dependencies:**
```bash
pip install -r requirements.txt
```
4. **Set up environment variables:**
```bash
cp .env.example .env # Create .env file if needed
# Add your GROQ_API_KEY to .env
export GROQ_API_KEY="your-api-key-here"
```
5. **Run notebooks:**
```bash
jupyter notebook
```
---
## Project Structure
```
langgraph-revision/
├── 1)Sequential_Workflow/ ✅ COMPLETE
│ ├── workflow.ipynb # BMI calculator (simple pattern)
│ └── llmworkflow.ipynb # Q&A system with LLM
│
├── 2)Parallel_Workflow/ ✅ COMPLETE
│ ├── simple_workflow.ipynb # String processing in parallel
│ └── llm_workflow.ipynb # 3 parallel LLM tasks + aggregation
│
├── 3)Conditional_Workflows/ ✅ COMPLETE
│ ├── simple_workflow.ipynb # Quadratic solver (discriminant-based)
│ └── llm_workflow.ipynb # LLM-powered question classifier
│
├── 4)Persistence/ ✅ COMPLETE
│ └── workflow.ipynb # Joke workflow with checkpointing
│
├── 5)Streaming/ ✅ COMPLETE
│ ├── graph.py # Graph with async streaming support
│ └── run.py # Async main with token streaming
│
├── 6)Sqllite_Integration/ ✅ COMPLETE
│ ├── code.py # Chat with SQLite persistence
│ └── chat_memory.db # Database (auto-created)
│
├── 7)Short_Term_Memory/ ✅ COMPLETE
│ └── code.py # Thread-scoped conversation memory
│
├── 8)Long_Term_Memory/ ✅ COMPLETE
│ └── code.py # Global user profiles (InMemoryStore)
│
├── 9)HITL_Concept/ ✅ COMPLETE
│ └── code.py # Human-in-the-Loop with interrupts
│
├── 10)Tools/ ✅ COMPLETE
│ └── code.py # LLM with tool binding + execution
│
├── 11)RAG/ ✅ COMPLETE
│ └── code.py # RAG system with vector search
│
├── main.py # Entry point
├── requirements.txt # Dependencies
├── pyproject.toml # Project metadata
└── README.md # This file
```
---
## Core Workflow Patterns
### 1. Sequential Workflows
**Concept:** Tasks execute one after another in a strict order. Output of one task becomes input to the next.
**Characteristics:**
- Linear execution path
- Each node waits for previous node to complete
- State flows sequentially through nodes
**Real-world Use Cases:**
- Document processing pipelines
- Data transformation chains
- Step-by-step problem solving
**Key Files:**
- `1)Sequential_Workflow/workflow.ipynb` - Simple example with static data
- `1)Sequential_Workflow/llmworkflow.ipynb` - LLM integration for multi-step reasoning
**Example Flow:**
```
Input → Node1 → Node2 → Node3 → Output
```
---
### 2. Parallel Workflows
**Concept:** Multiple independent tasks execute simultaneously. Results are aggregated when all tasks complete.
**Characteristics:**
- Concurrent execution of multiple nodes
- Requires `Annotated` types for state fields receiving parallel updates
- Better performance for independent tasks
- Reduces total execution time
**Real-world Use Cases:**
- Multi-perspective analysis (summarize, extract key points, suggest actions simultaneously)
- Parallel data enrichment
- Independent calculations that need aggregation
**Key Files:**
- `2)Parallel_Workflow/simple_workflow.ipynb` - Basic parallel execution
- `2)Parallel_Workflow/llm_workflow.ipynb` - LLM tasks running in parallel
**Important:** Using `Annotated[type, ""]` prevents `InvalidUpdateError` when parallel nodes update the same state field.
**Example Flow:**
```
┌─→ Node1 ─┐
Input →┼─→ Node2 ─┼→ Aggregator → Output
└─→ Node3 ─┘
```
---
### 3. Conditional Workflows
**Concept:** Workflow path is determined dynamically based on routing logic. Different branches execute based on conditions.
**Characteristics:**
- Decision-based routing
- Router node returns destination node name (as string)
- Enables dynamic behavior based on input analysis
- Efficient filtering of tasks
**Real-world Use Cases:**
- Intent-based routing (customer support, question classification)
- Specialized processing pipelines (math vs. general questions)
- Dynamic task selection based on input type
**Key Files:**
- `3)Conditional_Workflows/simple_workflow.ipynb` - Quadratic equation solver with conditional branches
- `3)Conditional_Workflows/llm_workflow.ipynb` - LLM-based question classifier and responder
**Example Flow:**
```
Input → Router → Decision: "math" or "general"?
↓ ↓
Math Node General Node
↓ ↓
Output Output
```
---
## Key Concepts & Implementations
### State Management
**TypedDict Definition:**
```python
class WorkflowState(TypedDict):
question: str
category: str
answer: str
```
States define all data flowing through the workflow. LangGraph maintains state consistency across nodes.
### Node Functions
Nodes are functions that process state and return updated state:
```python
def math_node(state: WorkflowState) -> WorkflowState:
"""Process math questions"""
response = llm.invoke(prompt)
state['answer'] = response.content # Extract content, not entire object
return state
```
**Important:** Always extract `.content` from LLM responses, not the entire message object.
### Graph Construction
LangGraph uses a builder pattern to construct workflows:
```python
builder = StateGraph(WorkflowState)
builder.add_node("input_node", input_node)
builder.add_edge(START, "input_node")
builder.add_conditional_edges("input_node", router_function)
workflow = builder.compile()
```
### Router Functions
Router functions determine which node to execute next:
```python
def llm_router(state: WorkflowState) -> Literal['math_node', 'general_node']:
"""Classify and route to appropriate node"""
response = llm.invoke(prompt)
category = response.content.strip().lower()
state["category"] = category
return category + "_node" # Return node name as STRING
```
**Critical:** Router must return node name as string, not execute the node.
### Handling Parallel Updates with Annotated
When parallel nodes update the same state field:
```python
from typing import Annotated
class WorkflowState(TypedDict):
summary: Annotated[str, ""] # Metadata tells LangGraph how to merge
key_points: Annotated[str, ""]
action_items: Annotated[str, ""]
```
The `Annotated` metadata allows safe concurrent updates. Without this, `InvalidUpdateError` occurs.
---
## Advanced Topics
### 1. Persistence & State Management
**Definition:** Saving workflow state to allow resumption after interruptions, enabling audit trails and multi-session continuity.
**Use Cases:**
- Long-running workflows that might fail mid-execution
- Audit trails and compliance requirements
- Workflow history and debugging
- Multi-turn conversations with context preservation
**Implementation in Project:**
- **Location:** `4)Persistence/workflow.ipynb`
- **Technology:** SQLite Checkpointer
- **Key Concept:** State is saved at each step, allowing workflow to resume from exactly where it paused
**Implementation Approach:**
```python
from langgraph.checkpoint.sqlite import SqliteSaver
conn = sqlite3.connect("workflow.db", check_same_thread=False)
checkpointer = SqliteSaver(conn)
graph = builder.compile(checkpointer=checkpointer)
# Resume workflow with thread_id
result = graph.invoke(
initial_state,
config={"configurable": {"thread_id": "user-123"}}
)
```
**Persistence Strategies:**
- **In-Memory:** Fast but lost on restart
- **SQLite:** Good for development and testing (used in this project)
- **PostgreSQL:** Scalable for production
- **Custom Storage:** Cloud databases, etc.
---
### 2. Streaming in LangGraph
**Definition:** Real-time output streaming as workflow executes, instead of waiting for completion.
**Use Cases:**
- Large LLM outputs (show tokens as they generate)
- User experience improvement (no waiting for full response)
- Progressive results display
- Real-time monitoring and debugging
**Implementation in Project:**
- **Location:** `5)Streaming/` (graph.py, run.py)
- **Key Feature:** Async streaming with `astream()` method
- **Pattern:** Token-by-token output as LLM generates responses
**Implementation Approach:**
```python
async def main():
input_state = {"messages": [{"role": "user", "content": "Your question"}]}
print("Streaming tokens:\n")
async for chunk in graph.astream(input_state, stream_mode="messages"):
token = chunk[0].content
if token:
print(token, end="", flush=True)
asyncio.run(main())
```
**Stream Modes:**
- `stream_mode="messages"` - Stream individual tokens/messages
- `stream_mode="updates"` - Stream node updates
- `stream_mode="values"` - Stream complete state snapshots
**Benefits:**
- Better user experience
- Earlier error detection
- Real-time debugging and monitoring
---
### 3. Memory Systems in LangGraph
#### Short-Term Memory
**Definition:** Conversation context within current session only. Memory is thread-specific using `thread_id`.
**Implementation in Project:**
- **Location:** `7)Short_Term_Memory/code.py`
- **Pattern:** Messages stored per thread, accessible only within that thread session
- **Persistence:** SQLite database (`short_term.db`)
**Key Concept:**
```python
# Different thread_id = different conversation = no shared memory
config = {"configurable": {"thread_id": "thread-123"}}
# Only messages within this thread are remembered
for chunk, metadata in graph.stream({"messages": messages}, config=config):
# Process streaming output
```
**Use Cases:**
- Multi-turn conversations
- Context-aware responses within single session
- Temporary working memory
- User-specific conversation history
#### Long-Term Memory
**Definition:** Persistent storage of knowledge/information across sessions and conversations.
**Implementation in Project:**
- **Location:** `8)Long_Term_Memory/code.py`
- **Approaches:**
1. **Vector Database (RAG):** Store embeddings of important facts for semantic search
2. **Knowledge Base:** Structured information storage
3. **User Profiles:** Preferences and history across sessions
4. **Learned Patterns:** Insights from past interactions
**Use Cases:**
- User preferences across multiple sessions
- Learned patterns from past interactions
- Domain-specific knowledge base
- Multi-session conversation continuity with context
---
### 4. SQLite Integration
**Definition:** Persistent storage layer using SQLite for checkpointing and state management.
**Implementation in Project:**
- **Location:** `6)Sqllite_Integration/code.py`
- **File:** `chat_memory.db` (SQLite database)
- **Pattern:** Multi-threaded safe SQLite connection with `check_same_thread=False`
**Implementation Pattern:**
```python
from langgraph.checkpoint.sqlite import SqliteSaver
# Multi-thread safe connection
conn = sqlite3.connect("chat_memory.db", check_same_thread=False)
checkpointer = SqliteSaver(conn)
graph = builder.compile(checkpointer=checkpointer)
# Use thread_id to manage conversation sessions
config = {"configurable": {"thread_id": thread_id}}
```
**Real-World Use:**
- Persistent chat history
- Session management
- Conversation recovery after interruptions
- Multi-user conversation tracking
---
### 5. Human-in-the-Loop (HITL)
**Definition:** Workflows that pause mid-execution to wait for human input/approval before proceeding.
**Implementation in Project:**
- **Location:** `9)HITL_Concept/code.py`
- **Key Mechanism:** `interrupt()` and `Command(resume=value)` pattern
- **Requirement:** Checkpointer is mandatory (state must be saved during pause)
**How It Works:**
1. Workflow executes normally until it hits `interrupt()`
2. Entire state is saved to checkpointer
3. Workflow pauses and waits for human decision
4. Human reviews output and provides feedback
5. `Command(resume=value)` resumes workflow from exact pause point
6. Workflow continues execution with human's decision incorporated
**Implementation Approach:**
```python
def human_review(state: MessagesState):
draft = state["messages"][-1].content
print(f"[Node] Draft is ready:\n{draft}\n")
# Pause and wait for human decision
decision = interrupt({
"question": "should we forward the mail?",
"draft": draft
})
if decision == "approve":
return {"messages": [AIMessage(content="Email approved and sent!")]}
else:
return {"messages": [AIMessage(content=f"Email cancelled. Feedback: {decision}")]}
# Add node to graph
builder.add_node("human_review", human_review)
```
**Use Cases:**
- Approval workflows (high-stakes decisions need human review)
- Interactive debugging and refinement
- User confirmation for critical actions
- Feedback collection and incorporation
**Critical Considerations:**
- **Checkpointer is Mandatory:** Without persistence, state cannot be saved during pause
- **State Preservation:** Entire workflow state is maintained during interruption
- **Resume Mechanism:** `Command(resume=value)` tells workflow where to continue and what to do next
---
### 6. Tool Binding & Autonomous Tool Use
**Definition:** Enable LLMs to autonomously decide when to use external tools and execute them automatically.
**Implementation in Project:**
- **Location:** `10)Tools/code.py`
- **Pattern:** LLM with `bind_tools()` + ToolNode for automatic execution
- **Pre-built Tools:** Weather, Calculator, Joke (demo tools)
**Implementation Approach:**
```python
@tool
def get_weather(city: str) -> str:
"""Get the current weather of a city."""
# Tool docstring is critical - LLM reads this to decide when to use
@tool
def calculator(expression: str) -> str:
"""Evaluate mathematical expressions."""
return str(eval(expression))
llm_with_tools = llm.bind_tools([get_weather, calculator, get_joke])
# Graph routing
from langgraph.prebuilt import ToolNode
from langgraph.prebuilt.chat_agent_executor import tools_condition
builder.add_node("tools", ToolNode(tools))
builder.add_conditional_edges("chatbot", tools_condition)
builder.add_edge("tools", "chatbot") # Loop back for final response
```
**Key Features:**
- Tool docstrings are LLM's interface
- Automatic tool selection based on context
- Tool execution happens automatically
- Loop pattern allows multiple tool calls before final response
- Zero manual tool invocation needed
**Use Cases:**
- Chatbots that need external data (weather, stocks, APIs)
- Calculation-intensive workflows
- Information retrieval tasks
- External system integration
---
### 7. Retrieval Augmented Generation (RAG)
**Definition:** Ground LLM responses in custom knowledge base instead of LLM training data - prevents hallucinations.
**Implementation in Project:**
- **Location:** `11)RAG/code.py`
- **Architecture:** Vector search → Retrieve → Generate pattern
- **Vector DB:** Chroma (in-memory)
- **Embeddings:** HuggingFace (all-MiniLM-L6-v2)
- **Knowledge Base:** 6 LangGraph documentation samples
**Implementation Approach:**
```python
from langchain_community.vectorstores import Chroma
from langchain_huggingface import HuggingFaceEmbeddings
# Create embeddings and vector store
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
docs = [Document(page_content=text) for text in knowledge_base]
vector_store = Chroma.from_documents(docs, embeddings)
# Retrieve node - semantic search
def retrieve(state):
docs = vector_store.similarity_search(state["question"], k=2)
return {"context": docs}
# Generate node - answer based on retrieved context
def generate(state):
context_text = "\n".join([doc.page_content for doc in state["context"]])
prompt = f"Using this context:\n{context_text}\n\nAnswer: {state['question']}"
response = llm.invoke(prompt)
return {"answer": response.content}
```
**Graph Flow:**
```
User Query → Retrieve Node (Vector Search) → Retrieved Docs
↓
→ Generate Node (LLM with Context)
↓
→ Final Answer (Grounded in knowledge base)
```
**Key Features:**
- Vector semantic search for relevance
- Context-grounded answers (no hallucinations)
- Easy to add/update knowledge without retraining
- Transparent source citations possible
- Temperature=0 for consistency
**Use Cases:**
- Customer support bots (company knowledge base)
- Document Q&A systems
- Internal knowledge bases
- FAQ systems
- Domain-specific chatbots
---
## Common Issues & Solutions
### Issue 1: InvalidUpdateError - "unhashable type: 'dict'"
**Symptom:**
```
TypeError: unhashable type: 'dict'
At key 'summary': Can receive only one value per step
```
**Cause:** Multiple parallel nodes updating same state field without `Annotated` type.
**Solution:**
```python
# ❌ Wrong:
class WorkflowState(TypedDict):
summary: str
# ✅ Correct:
class WorkflowState(TypedDict):
summary: Annotated[str, ""]
```
---
### Issue 2: Router Returning Node Object Instead of String
**Symptom:**
```
TypeError: unhashable type: 'dict'
```
**Cause:** Router function executes node and returns dict instead of returning node name.
**Solution:**
```python
# ❌ Wrong:
def router(state):
if condition:
return node_function(state) # Returns dict
# ✅ Correct:
def router(state):
if condition:
return "node_name" # Return string node name
```
---
### Issue 3: LLM Response Appears as Object
**Symptom:**
```
Output:
```
**Cause:** Not extracting `.content` from LLM response.
**Solution:**
```python
# ❌ Wrong:
state['answer'] = response
# ✅ Correct:
state['answer'] = response.content
```
---
### Issue 4: Missing Environment Variables
**Symptom:**
```
AuthenticationError: Groq API key not found
```
**Solution:**
```bash
# Add to .env file or environment:
export GROQ_API_KEY="your-actual-api-key"
# Or in Python:
from dotenv import load_dotenv
load_dotenv()
```
---
## Dependencies
### Core Dependencies
| Package | Version | Purpose |
|---------|---------|---------|
| **langgraph** | >=1.2.0 | Workflow orchestration framework |
| **langchain** | >=1.3.1 | LLM integration and tools |
| **langchain-groq** | >=1.1.2 | Groq LLM API integration |
| **langchain-community** | Latest | Vector stores (Chroma), retriever integration |
| **langchain-huggingface** | Latest | HuggingFace embeddings (all-MiniLM-L6-v2) |
| **python-dotenv** | >=1.2.2 | Environment variable management |
| **ipython** | >=9.13.0 | Interactive notebook environment |
| **chroma** | Latest | Vector database for RAG |
### Installation via Requirements
```bash
pip install -r requirements.txt
```
### Installation via Pyproject.toml
```bash
pip install -e .
```
---
## Code Examples & Patterns
### Example 1: Running a Simple Sequential Workflow
```python
from typing import TypedDict
from langgraph.graph import START, END, StateGraph
class SimpleState(TypedDict):
text: str
processed: str
def step1(state: SimpleState) -> SimpleState:
state['processed'] = state['text'].upper()
return state
def step2(state: SimpleState) -> SimpleState:
state['processed'] += "!"
return state
builder = StateGraph(SimpleState)
builder.add_node("step1", step1)
builder.add_node("step2", step2)
builder.add_edge(START, "step1")
builder.add_edge("step1", "step2")
builder.add_edge("step2", END)
workflow = builder.compile()
result = workflow.invoke({"text": "hello", "processed": ""})
```
---
### Example 2: Parallel Workflows with Aggregation
```python
from typing import Annotated
from operator import add
class ParallelState(TypedDict):
query: str
results: Annotated[list, add] # Accumulates results
def search1(state: ParallelState) -> ParallelState:
return {"results": ["Result from source 1"]}
def search2(state: ParallelState) -> ParallelState:
return {"results": ["Result from source 2"]}
builder = StateGraph(ParallelState)
builder.add_node("search1", search1)
builder.add_node("search2", search2)
builder.add_edge(START, ["search1", "search2"]) # Parallel
builder.add_edge(["search1", "search2"], END)
workflow = builder.compile()
result = workflow.invoke({"query": "test", "results": []})
```
---
### Example 3: LLM-Powered Conditional Router
```python
from langchain_groq import ChatGroq
from typing import Literal
llm = ChatGroq(model="llama-3.3-70b-versatile", temperature=0.2)
def classify_query(state) -> Literal['math_path', 'general_path']:
prompt = f"Is this a math question? Reply only: 'math' or 'general'. Query: {state['query']}"
response = llm.invoke(prompt)
category = response.content.strip().lower()
return "math_path" if category == "math" else "general_path"
# Add to graph
builder.add_conditional_edges("classifier", classify_query)
```
---
## Learning Path
### Beginner (Weeks 1-2)
1. Understand graph concepts (nodes, edges, states)
2. Run simple sequential workflow examples (`1)Sequential_Workflow/workflow.ipynb`)
3. Explore parallel workflows (`2)Parallel_Workflow/simple_workflow.ipynb`)
4. Modify examples to understand state flow
### Intermediate (Weeks 3-4)
1. Implement conditional routing logic (`3)Conditional_Workflows/simple_workflow.ipynb`)
2. Debug `Annotated` type issues for parallel nodes
3. Integrate with LLM APIs (`1)Sequential_Workflow/llmworkflow.ipynb`)
4. Understand state management and `MessagesState`
5. Run LLM-based conditional routers (`3)Conditional_Workflows/llm_workflow.ipynb`)
### Advanced (Weeks 5-8)
1. **State Persistence:** Explore `4)Persistence/workflow.ipynb` - SQLite checkpointing & time travel
2. **Real-time Streaming:** Study `5)Streaming/` - Async token streaming from LLMs
3. **Chat Memory:** Build with `6)Sqllite_Integration/code.py` - Persistent conversations
4. **Short-Term Memory:** Implement `7)Short_Term_Memory/code.py` - Thread-specific memory
5. **Long-Term Memory:** Design `8)Long_Term_Memory/code.py` - Global user profiles
### Expert (Weeks 9+)
1. **Human-in-the-Loop:** `9)HITL_Concept/code.py` - Workflow interrupts for human decisions
2. **Tool Binding:** `10)Tools/code.py` - LLM-driven autonomous tool use
3. **RAG Systems:** `11)RAG/code.py` - Vector search + grounded generation
4. Production deployment patterns with persistence
5. Multi-agent workflows and communication
6. Custom memory backends (PostgreSQL, Vector DBs)
7. Advanced streaming strategies
8. Performance optimization and scaling
---
## Next Steps & Future Development
### Implemented Features ✅ (11 Complete Modules)
**All features listed below are FULLY IMPLEMENTED with working code:**
1. ✅ **Sequential Workflows** - Linear task execution with state flow
2. ✅ **Parallel Workflows** - Concurrent independent tasks with aggregation
3. ✅ **Conditional Workflows** - Dynamic routing based on logic
4. ✅ **Persistence & State Management** - SQLite checkpointing with resumption
5. ✅ **Real-time Streaming** - Async token streaming from LLMs
6. ✅ **Chat with SQLite Memory** - Persistent conversation history
7. ✅ **Short-Term Memory** - Thread-scoped isolated sessions
8. ✅ **Long-Term Memory** - Global cross-session user profiles
9. ✅ **Human-in-the-Loop** - Workflow interrupts with state preservation
10. ✅ **Tool Binding** - LLM-driven autonomous tool selection & execution
11. ✅ **Retrieval Augmented Generation** - Vector search + grounded answers
### Potential Future Enhancements
1. **Multi-Agent Workflows**
- Agent-to-agent communication patterns
- Shared workspace and tool usage
- Consensus mechanisms between agents
2. **Advanced Memory Systems**
- Vector database integration (Pinecone, Weaviate, Milvus)
- Semantic similarity-based memory retrieval
- Hybrid memory (short + long term combined)
3. **Production Deployment**
- Docker containerization examples
- Kubernetes orchestration
- Load balancing strategies
- API deployment patterns
4. **Monitoring & Observability**
- LangSmith integration with custom metrics
- Performance optimization guide
- Error tracking and alerting
- Cost analysis per workflow
5. **Advanced LLM Patterns**
- Function calling with complex schemas
- Structured output parsing
- Multi-model workflows
- Fallback strategies
### Contributing
To contribute examples or improvements:
1. Fork the repository
2. Create feature branch: `git checkout -b feature/your-feature`
3. Add well-documented examples
4. Test thoroughly
5. Submit pull request with documentation
---
## References & Resources
### Official Documentation
- [LangGraph Documentation](https://python.langchain.com/docs/langgraph)
- [LangChain Documentation](https://python.langchain.com/docs)
- [Groq API Documentation](https://groq.com/docs)
### Key Concepts
- [State Graphs in LangGraph](https://python.langchain.com/docs/langgraph/concepts/low_level_conceptual_guide)
- [Routing and Conditional Edges](https://python.langchain.com/docs/langgraph/how-tos/define-nodes-edges)
- [Persistence and Checkpointing](https://python.langchain.com/docs/langgraph/concepts/persistence)
### Related Tools
- [LangSmith - Debugging & Monitoring](https://smith.langchain.com/)
- [LangChain Templates](https://templates.langchain.com/)
- [LangGraph Hub](https://langchain-ai.github.io/langgraph/reference/library/)
---
## Troubleshooting Guide
### Quick Fixes
| Problem | Quick Fix |
|---------|-----------|
| `ModuleNotFoundError: No module named 'langgraph'` | Run `pip install -r requirements.txt` |
| `AuthenticationError` with LLM | Check `GROQ_API_KEY` environment variable |
| Workflow runs but produces no output | Check node return statements are updating state |
| Parallel execution fails with state error | Use `Annotated` for concurrent state updates |
| Router function not working | Ensure router returns string (node name), not object |
---
## FAQ
**Q: What's the difference between parallel and sequential workflows?**
A: Sequential executes nodes one-by-one; parallel executes independent nodes simultaneously, reducing total time.
**Q: When should I use conditional edges?**
A: When different paths should execute based on runtime conditions or input classification.
**Q: How do I persist workflow state?**
A: Use LangGraph's checkpointer (SQLite, PostgreSQL, etc.) to save state at each step.
**Q: Can I use LangGraph without LLMs?**
A: Yes, LangGraph works with any Python functions, though LLM integration is powerful.
**Q: What's the purpose of `Annotated` in state definitions?**
A: It tells LangGraph how to merge values when multiple nodes update the same field concurrently.
---
## License
This project is provided as an educational resource.
---
## Contact & Support
For questions or issues:
- Check the troubleshooting section
- Review example notebooks
- Consult official LangGraph documentation
---
**Last Updated:** May 2026
**Repository Version:** 0.1.0