Open Notebook LangGraph Workflows: Source Chat vs Ask Explained
Open Notebook implements two distinct LangGraph state-graph workflows—Source Chat for single-source conversation and Ask for multi-step vector search research—each using different state schemas, node architectures, and context-building strategies.
Open Notebook leverages LangGraph to orchestrate complex LLM interactions through specialized workflows defined in open_notebook/graphs/source_chat.py and open_notebook/graphs/ask.py. While both workflows generate AI responses, they serve fundamentally different user intents: conversing with a specific document versus conducting open-ended research across your entire knowledge base.
Core Purpose and Interaction Models
Source Chat: Conversational Source Exploration
The Source Chat workflow enables users to explore a single source—such as a PDF, webpage, or video—through natural conversation. It builds a comprehensive context from the source content and its derived insights, then injects this into a chat prompt to generate responses that reference specific source material. This workflow is optimized for deep dives into individual documents where maintaining the full context of the source is critical.
Ask: Multi-Step Research and Synthesis
The Ask workflow answers open-ended questions by searching across the entire vector store. Rather than focusing on one document, it executes a strategy that may involve multiple vector searches, processes each result set through sub-graphs, and synthesizes findings into a final comprehensive answer. This approach supports complex research queries that require aggregating information from multiple sources.
State Schemas and Graph Architecture
SourceChatState vs ThreadState
Each workflow maintains distinct state definitions reflecting their operational requirements:
SourceChatState (defined in open_notebook/graphs/source_chat.py) tracks:
messages: Conversation historysource_id: Target document identifiersourceandinsights: The loaded source and its extracted insightscontext: Generated full-text context (up to 50,000 tokens)model_override: Optional alternative model selectioncontext_indicators: Dictionary tracking which sources and insights were referenced
ThreadState (defined in open_notebook/graphs/ask.py) tracks:
question: The original user querystrategy: A list ofSearchobjects generated by the LLManswers: Accumulated responses from each search executionfinal_answer: The synthesized result
Node Structure and Topology
The Source Chat graph compiles to a linear pipeline: START → source_chat_agent → END. The single node source_chat_agent calls call_model_with_source_context to build context and generate a response.
The Ask graph compiles to a three-node structure with conditional branching:
agent: Creates a search strategy via thestrategy_modelprovide_answer: Executes vector searches and generates intermediate answers (may run multiple times viatrigger_queries)write_final_answer: Synthesizes all sub-answers using thefinal_answer_model
Context Building and Retrieval Strategies
Full-Text Context Assembly
Source Chat relies on ContextBuilder (from open_notebook/utils/context_builder.py) to pull the source record, associated insights, and metadata. The _format_source_context method formats this into a rich prompt context that can consume up to 50k tokens, providing the LLM with comprehensive source material via the source_chat/system prompt template.
Vector Search Results
Ask bypasses explicit context building in favor of dynamic retrieval. The provide_answer node executes vector_search queries against SurrealDB for each term in the strategy. The raw search results serve as the context, fed directly to the ask/query_process prompt alongside user instructions. This approach prioritizes relevance over completeness.
Model Provisioning and Execution
Synchronous vs Asynchronous Provisioning
Source Chat invokes provision_langchain_model synchronously within a new event loop using run_in_new_loop, because the graph operates in a synchronous context. It supports an optional model_override parameter for flexible model selection.
Ask uses asynchronous provisioning with await provision_langchain_model throughout its async graph. It employs three distinct configurable model IDs: strategy_model for planning, answer_model for processing search results, and final_answer_model for synthesis.
Error Handling Patterns
Both workflows utilize classify_error from open_notebook/utils/error_classifier.py to normalize exceptions into OpenNotebookError subclasses. Source Chat wraps the entire call in a single try/except block, while Ask implements granular error handling within each node (call_model_with_messages, provide_answer, write_final_answer).
Implementation Examples
Invoking Source Chat
from open_notebook.graphs.source_chat import source_chat_graph
state = {
"messages": [],
"source_id": "src_12345",
"model_override": None,
}
result = source_chat_graph.invoke(state)
print(result["messages"][-1].content)
Invoking Ask
from open_notebook.graphs.ask import graph
state = {
"question": "What are the performance trade-offs of LangGraph?",
}
answer = graph.invoke(state)
print(answer["final_answer"])
Summary
- Source Chat provides a linear, single-source conversation workflow using
SourceChatStateand full-text context building viaContextBuilder. - Ask implements a multi-step research workflow using
ThreadState, conditional branching viatrigger_queries, and vector search aggregation. - Model provisioning differs significantly: Source Chat uses synchronous calls with optional overrides, while Ask uses async provisioning with role-specific models (strategy, answer, final).
- Context strategies contrast sharply: Source Chat builds comprehensive source context (up to 50k tokens), while Ask relies on dynamic vector search results.
- Both workflows share the
classify_errorutility for consistent error handling but implement it at different granularities.
Frequently Asked Questions
What is the primary difference between Source Chat and Ask workflows?
Source Chat is designed for exploring a single document through conversation, building rich context from that specific source and its insights. Ask is designed for research questions that require searching across multiple sources, implementing a strategy-planning phase and aggregating results from multiple vector searches before synthesizing a final answer.
How does the state management differ between these LangGraph workflows?
Source Chat uses SourceChatState which tracks a specific source_id, conversation messages, and pre-built context strings. Ask uses ThreadState which tracks a question, a generated strategy of search terms, accumulated answers from each search execution, and a final answer string.
Can I use different AI models for different stages of the Ask workflow?
Yes. The Ask workflow in open_notebook/graphs/ask.py supports three distinct model configurations: strategy_model for generating the search plan, answer_model for processing individual search results, and final_answer_model for synthesizing the comprehensive response.
Why does Source Chat use synchronous model provisioning while Ask uses async?
Source Chat runs in a synchronous context and therefore calls provision_langchain_model within a new event loop using run_in_new_loop. The Ask workflow is implemented as an async graph, allowing it to use await provision_langchain_model directly, which is more efficient for I/O-bound operations like multiple parallel vector searches.
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 →