Architectural Differences Between Chat, Ask, and Transformation LangGraph Workflows in Open Notebook
Open Notebook implements three distinct LangGraph workflows—Chat, Ask, and Transformation—that differ fundamentally in state management, graph topology, and execution patterns, with Chat using persistent SQLite checkpointing for conversations, Ask generating dynamic multi-step research graphs, and Transformation executing single-step content rewrites.
Open Notebook is an open-source knowledge management system that leverages LangGraph to orchestrate LLM interactions through specialized agentic workflows. While all three workflows utilize LangGraph's StateGraph abstraction, they diverge significantly in their state shapes, node architectures, and runtime characteristics. Understanding these architectural differences is essential for developers extending the platform or integrating with its API.
State Management and Graph Topology
The three workflows define distinct state schemas that reflect their specific operational requirements.
Chat Workflow uses ThreadState (defined in open_notebook/graphs/chat.py) to maintain message history, notebook context, and conversation metadata. This state persists across interactions, enabling multi-turn conversations with contextual grounding.
Ask Workflow also uses ThreadState (defined in open_notebook/graphs/ask.py) but extends it with a subsidiary SubGraphState for each search operation. The state tracks the original question, a generated search strategy, intermediate answers, and the final synthesized response. This structure supports the workflow's dynamic expansion pattern.
Transformation Workflow employs a simpler TransformationState (defined in open_notebook/graphs/transformation.py) containing only the input text, source reference, transformation definition, and output field. This minimal state reflects the single-step nature of content rewriting operations.
Node Structure and Execution Flow
Each workflow implements a distinct graph topology optimized for its specific use case.
Chat implements a linear pipeline: START → agent → END. The single agent node calls the LLM with accumulated messages and returns the response. There are no conditional branches or dynamic node creation.
Ask implements a sophisticated conditional graph. The flow begins with an agent node that generates a JSON-encoded search strategy. Based on this strategy, the graph dynamically creates multiple provide_answer nodes (one per search term) that execute vector searches in parallel. Finally, a write_final_answer node synthesizes the aggregated results before reaching END. The edge definitions in lines 50-53 of ask.py handle this conditional routing.
Transformation uses the simplest topology: START → agent → END. The single agent node applies the transformation prompt to the input text and optionally stores the result back to the source via source.add_insight.
Model Provisioning and Async Handling
The workflows differ significantly in how they handle asynchronous execution and model provisioning.
Chat Workflow requires special handling because it may be invoked from synchronous FastAPI routes. According to lines 38-73 of open_notebook/graphs/chat.py, the workflow wraps provision_langchain_model inside a synchronous wrapper that spins a new event loop when called from a sync context. This hybrid approach ensures compatibility with the chat endpoint while maintaining async capabilities within the graph.
Ask Workflow operates entirely asynchronously. Each node independently provisions its own model instance via provision_langchain_model without special loop handling. The strategy generation, vector search execution, and final answer synthesis all run as async operations.
Transformation Workflow also runs fully async, with the single node provisioning its model and executing the transformation in one atomic operation.
Persistence and Checkpointing
Only the Chat workflow implements persistent state management.
Chat utilizes LangGraph's SqliteSaver (configured in open_notebook/config.py) to persist conversation state. This enables long-running conversations to resume across requests and provides durability for the chat interface.
Ask operates without checkpointing. The entire multi-step research flow executes within a single request/response cycle, and intermediate states exist only in memory during graph execution.
Transformation functions as a fire-and-forget operation with no checkpointing, appropriate for one-off content processing tasks.
Data Access Patterns
Each workflow interacts with the domain model differently based on its informational requirements.
Chat may attach a Notebook object to the state to enrich context with existing knowledge. This allows the LLM to reference previously curated content during conversations.
Ask bypasses the notebook abstraction and calls the vector store directly via vector_search (see lines 98-104 of ask.py). This direct access enables semantic search across the knowledge base to gather relevant context for the research task.
Transformation directly accesses Source records and optionally persists insights back to the source using source.add_insight, creating a tight integration between the transformation output and the knowledge repository.
Error Handling Strategy
All three workflows share a common error classification system using OpenNotebookError with the classify_error helper to convert exceptions into user-friendly messages. However, each implements workflow-specific wrapping:
- Chat handles errors at the graph level with conversational context preservation.
- Ask re-wraps errors at each sub-node to preserve the specific stage (strategy generation, search, or synthesis) where failures occur.
- Transformation additionally catches validation errors on the source object during the persistence phase.
Practical Implementation Examples
Chat Workflow
import httpx
payload = {
"messages": [{"role": "user", "content": "Explain quantum entanglement"}],
"model_override": "gpt-4o"
}
response = httpx.post("http://localhost:5055/chat", json=payload)
print(response.json()["messages"][-1]["content"])
The FastAPI endpoint creates a ThreadState and runs the graph defined in open_notebook/graphs/chat.py, persisting the conversation to SQLite.
Ask Workflow
import httpx
payload = {"question": "What are the health benefits of a Mediterranean diet?"}
resp = httpx.post("http://localhost:5055/ask", json=payload)
print(resp.json()["final_answer"])
The LLM first creates a JSON strategy containing Search objects, the system executes vector searches for each term, then the final synthesis node produces the aggregated answer.
Transformation Workflow
import httpx
payload = {
"input_text": "The quick brown fox jumps over the lazy dog.",
"transformation": {
"title": "Summarize",
"prompt": "Summarize the following text in one sentence."
}
}
resp = httpx.post("http://localhost:5055/transform", json=payload)
print(resp.json()["output"])
The workflow in open_notebook/graphs/transformation.py sends the text together with the custom prompt to the LLM and returns the cleaned output.
Summary
- Chat provides a linear dialog graph with persistent SQLite checkpointing, requiring sync-to-async adapter code for FastAPI compatibility.
- Ask implements a dynamic multi-stage research pipeline that generates search strategies, executes parallel vector searches, and synthesizes final answers without persistence.
- Transformation offers a single-step content rewrite operation with optional source persistence, using the simplest state management of the three.
- All workflows share common utilities including
provision_langchain_modelandOpenNotebookError, but differ in their graph topology, async handling, and checkpointing strategies.
Frequently Asked Questions
Which workflow maintains conversation history across sessions?
Only the Chat workflow persists state using LangGraph's SqliteSaver (as configured in open_notebook/config.py), enabling long-running conversations to resume across API calls. The Ask and Transformation workflows operate as stateless, single-request operations.
How does the Ask workflow handle complex multi-part research questions?
The Ask workflow utilizes dynamic node generation. After the initial agent node generates a JSON search strategy, the graph conditionally creates multiple provide_answer nodes (one per search term) based on the strategy content. These nodes execute vector searches in parallel before the final synthesis step, as implemented in lines 50-53 of open_notebook/graphs/ask.py.
Why does the Chat workflow require special synchronous handling while Ask does not?
The Chat workflow includes a synchronous wrapper around provision_langchain_model (lines 38-73 of open_notebook/graphs/chat.py) because it may be invoked from non-async FastAPI routes. This wrapper spins a new event loop when called from synchronous contexts. The Ask workflow assumes fully async execution throughout its pipeline, eliminating the need for this adapter pattern.
When should I use the Transformation workflow instead of the Chat workflow?
Use the Transformation workflow when you need a one-off content rewrite (summarization, extraction, or restructuring) that optionally persists back to a specific source. Use the Chat workflow for interactive, multi-turn conversations where maintaining message history and conversational context is essential. Transformation is atomic and fire-and-forget; Chat is conversational and persistent.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →