Source Chat vs Ask LangGraph Workflows in Open Notebook: Architecture and Implementation

Open Notebook implements two distinct LangGraph state-graph workflows—Source Chat for single-source contextual dialog and Ask for multi-search knowledge synthesis—each utilizing different state definitions, graph topologies, and model provisioning strategies.

Open Notebook is an open-source knowledge management platform that leverages LangGraph to orchestrate complex LLM interactions across your personal knowledge base. The repository defines specialized workflow patterns in open_notebook/graphs/source_chat.py and open_notebook/graphs/ask.py to handle fundamentally different query patterns: deep exploration of individual documents versus open-ended questions across the entire vector store. Understanding these LangGraph workflow differences is critical for developers extending the platform or debugging conversation flows.

Source Chat Workflow: Single-Source Contextual Conversation

The Source Chat workflow facilitates conversational exploration of a single source—such as a PDF, webpage, or video transcript—along with its extracted insights. This workflow builds a comprehensive full-text context from the source and injects it directly into the LLM prompt.

Graph Structure and Entry Point

The workflow compiles via source_chat_state.compile(...) to create a state graph with a single node named source_chat_agent. This node executes the call_model_with_source_context function to generate responses.

The execution flow is strictly linear:


START → source_chat_agent → END

Because the workflow only needs to generate a single contextualized response, it contains no conditional branching or sub-graphs.

State Management with SourceChatState

The workflow uses the SourceChatState TypedDict defined in open_notebook/graphs/source_chat.py:

  • messages: List of conversation history (AIMessage/SystemMessage objects)
  • source_id: The specific source being discussed
  • source and insights: The loaded source record and its derived insights
  • context: The formatted text up to 50k tokens injected into the prompt
  • context_indicators: Dictionary tracking which sources and insights were referenced
  • model_override: Optional model ID override for this specific conversation

Context Building Strategy

Unlike the Ask workflow, Source Chat utilizes the ContextBuilder class from open_notebook/utils/context_builder.py to assemble source content. The node pulls the source record and insights, then formats them using _format_source_context into a structured text block. This full context is rendered via the source_chat/system Jinja2 template and passed directly to the model, enabling precise citations to specific document sections.

Synchronous Model Provisioning

The source_chat_agent node calls provision_langchain_model synchronously within a new event loop using run_in_new_loop (see implementation in open_notebook/ai/provision.py). This design accommodates the synchronous context in which the graph often executes while supporting optional model_override parameters.

Ask Workflow: Multi-Step Knowledge Synthesis

The Ask workflow answers open-ended questions by orchestrating multiple vector searches, generating intermediate answers for each search result, and synthesizing a final comprehensive response.

Graph Structure and Entry Point

Compiling via agent_state.compile() builds a graph with three primary nodes:

  1. agent: Generates a search strategy by deciding which queries to execute
  2. provide_answer: Executes vector searches and generates answers for each search term
  3. write_final_answer: Synthesizes all sub-answers into the final response

State Management with ThreadState

The ThreadState defined in open_notebook/graphs/ask.py tracks multi-step progress:

  • question: The original user query
  • strategy: A list of Search objects (JSON-generated by the LLM) describing search terms
  • answers: Accumulated list of intermediate answers from each search
  • final_answer: The synthesized final response string

Conditional Execution and Sub-Graphs

Unlike the linear Source Chat flow, Ask implements conditional branching using the trigger_queries edge function. After the agent node generates a strategy, the graph evaluates trigger_queries to create separate sub-graph executions for each Search object in the strategy. Each sub-graph runs the provide_answer node independently, enabling parallel processing of multiple search results before the mandatory write_final_answer node finalizes the output.

Search-Based Context Retrieval

The Ask workflow does not use the ContextBuilder. Instead, it passes raw vector search results from SurrealDB directly to the LLM. The provide_answer node retrieves relevant chunks and renders them via the ask/query_process prompt template—a concise format containing the raw search hits and user instructions rather than a pre-built 50k token context.

Asynchronous Model Provisioning

The Ask workflow calls await provision_langchain_model asynchronously throughout, supporting different model configurations for each phase:

  • strategy_model: For generating the search strategy
  • answer_model: For processing individual search results
  • final_answer_model: For synthesizing the comprehensive response

Critical Architectural Differences

Graph Topology: Source Chat uses a linear single-node execution path, while Ask implements conditional branching with dynamic sub-graph creation via trigger_queries.

Context Strategy: Source Chat pre-materializes up to 50k tokens of source context using ContextBuilder and _format_source_context, whereas Ask retrieves raw vector search results from SurrealDB on-demand during sub-graph execution.

Execution Model: Source Chat provisions models synchronously using run_in_new_loop to bridge async/sync contexts, while Ask operates fully asynchronously with await provision_langchain_model.

State Complexity: SourceChatState tracks source-specific metadata and context indicators, while ThreadState manages a complex strategy-and-answer accumulation pattern across multiple LLM calls.

Error Handling Scope: Source Chat wraps the entire execution in a single try/except block using classify_error from open_notebook/utils/error_classifier.py, while Ask implements per-node error handling in call_model_with_messages, provide_answer, and write_final_answer.

Practical Code Examples

Invoking the Source Chat Graph

from open_notebook.graphs.source_chat import source_chat_graph
from langgraph.checkpoint.memory import MemorySaver

# Prepare initial state

state = {
    "messages": [],
    "source_id": "src_12345",
    "model_override": None,
}

# Execute the linear workflow

result = source_chat_graph.invoke(state)
print(result["messages"][-1].content)

Invoking the Ask Graph

from open_notebook.graphs.ask import graph

state = {
    "question": "What are the performance trade-offs of LangGraph?",
}

# Execute the multi-step workflow with conditional branches

answer = graph.invoke(state)
print(answer["final_answer"])

Summary

  • Source Chat workflows provide deep, contextual conversation about single sources using pre-built 50k token contexts and linear graph execution in open_notebook/graphs/source_chat.py.
  • Ask workflows answer broad questions through multi-step search strategies, conditional sub-graphs for each Search term, and asynchronous model provisioning defined in open_notebook/graphs/ask.py.
  • State definitions differ fundamentally: SourceChatState tracks source metadata while ThreadState manages search strategies and accumulated answers.
  • Execution models vary: Source Chat uses synchronous bridging via run_in_new_loop, while Ask leverages native async/await patterns with distinct model configurations for strategy, answer, and final synthesis phases.

Frequently Asked Questions

When should I use Source Chat instead of Ask?

Use Source Chat when you need to discuss specific content within a single document or source and its extracted insights, requiring deep contextual understanding of that specific material. Use Ask when you need to answer open-ended questions that require searching across multiple sources in your knowledge base, as it automatically generates search strategies and synthesizes results from the vector store.

How does the Ask workflow handle multiple concurrent searches?

The Ask workflow uses the trigger_queries edge condition to evaluate the strategy generated by the agent node. For each Search object in the strategy, it creates a separate sub-graph execution of the provide_answer node. Each sub-graph runs independently to perform its vector search and generate an intermediate answer, with all results accumulated in the ThreadState before write_final_answer synthesizes the final response.

Can Source Chat work without insights or handle multiple sources?

According to the source code in open_notebook/graphs/source_chat.py, the SourceChatState includes optional insights but requires a specific source_id. The ContextBuilder is designed to pull a single source record and its associated insights. The workflow does not support multi-source context building in its current implementation; for cross-source queries, use the Ask workflow instead.

What happens when model provisioning fails in these workflows?

Both workflows utilize classify_error from open_notebook/utils/error_classifier.py to normalize exceptions to specific OpenNotebookError subclasses. In Source Chat, the entire invocation is wrapped in a try/except block. In Ask, each node (agent, provide_answer, write_final_answer) implements its own error handling, allowing the graph to fail gracefully at specific steps and return meaningful error classifications to the API layer.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →