# How LangGraph Workflows Operate in Open Notebook's chat.py, ask.py, source.py, and transformation.py

> Explore how LangGraph workflows operate within Open Notebooks chat.py, ask.py, source.py, and transformation.py. Discover typed state, async nodes, and SQL checkpointing.

- Repository: [Luis Novo/open-notebook](https://github.com/lfnovo/open-notebook)
- Tags: internals
- Published: 2026-06-06

---

**Open Notebook implements its AI-powered features using LangGraph state machines that follow a consistent pattern of typed state definitions, asynchronous node functions, and SQL-backed checkpointing across all four workflow modules.**

Open Notebook (`lfnovo/open-notebook`) leverages LangGraph to orchestrate complex LLM interactions through modular workflow graphs. Understanding how these state machines operate internally reveals why the application maintains reliable conversation context and deterministic execution paths across its chat, questioning, source management, and transformation features.

## LangGraph Architecture Pattern

All four workflow modules follow an identical architectural foundation built on four pillars:

1. **Typed state definition** – A `TypedDict` (or Pydantic model) that describes immutable data passed between graph nodes
2. **Node functions** – Asynchronous callables that receive current state, invoke LLMs via `provision_langchain_model`, and return partial state updates
3. **Edge wiring** – `StateGraph` objects that connect `START` → node(s) → conditional edges → `END`
4. **Checkpointing** – Compiled graphs persisted with `SqliteSaver` to maintain state across interruptions (implemented in [`chat.py`](https://github.com/lfnovo/open-notebook/blob/main/chat.py) and available to others)

## chat.py: Single-Turn Conversation Flow

The [`chat.py`](https://github.com/lfnovo/open-notebook/blob/main/chat.py) module implements the simplest workflow, handling direct message exchanges without complex multi-step reasoning.

### State Definition

The workflow defines `ThreadState` in [`open_notebook/graphs/chat.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/graphs/chat.py) (lines 22-28) to track conversation context:

```python
class ThreadState(TypedDict):
    messages: List[BaseMessage]
    notebook: Notebook
    context: Optional[str]
    model_id: Optional[str]

```

This schema enables the graph to persist conversation history, maintain references to the active notebook, and support model overrides per thread.

### Node Implementation: `call_model_with_messages`

The core node function operates through a specific execution sequence:

1. **System Prompt Rendering** – Loads the `chat/system` template to establish AI behavior
2. **Message Construction** – Builds a payload combining `SystemMessage` with previous chat history
3. **Model Resolution** – Determines the model ID from LangGraph config or per-chat overrides
4. **Async Invocation** – Calls `provision_langchain_model` inside a dedicated event loop (handling cases where a loop already exists)
5. **Output Processing** – Invokes the model, extracts raw text, and removes artifact markers

### Checkpointing Implementation

Unlike the other workflow modules, [`chat.py`](https://github.com/lfnovo/open-notebook/blob/main/chat.py) specifically configures persistence:

```python

# From the source compilation

graph.compile(checkpointer=SqliteSaver())

```

This enables the chat workflow to resume interrupted conversations and maintain state across API restarts.

## ask.py, source.py, and transformation.py: Specialized Workflows

While [`chat.py`](https://github.com/lfnovo/open-notebook/blob/main/chat.py) handles conversational state, the remaining three modules implement domain-specific state machines following the identical LangGraph pattern:

- **ask.py** – Manages question-answering workflows with retrieval-augmented generation state
- **source.py** – Orchestrates document ingestion and source material processing
- **transformation.py** – Handles content conversion and restructuring operations

Each module defines custom `TypedDict` schemas appropriate to their domain (e.g., source documents for [`source.py`](https://github.com/lfnovo/open-notebook/blob/main/source.py), transformation parameters for [`transformation.py`](https://github.com/lfnovo/open-notebook/blob/main/transformation.py)), but all use `provision_langchain_model` for LLM invocation and `StateGraph` for execution flow.

## Common Implementation Details

### LLM Provisioning Pattern

All four modules utilize the centralized `provision_langchain_model` utility to instantiate language models. This ensures consistent configuration handling across the application:

- Model ID resolution from state or default configuration
- Async-safe invocation handling
- Output parsing and error recovery

### Graph Construction Standards

The workflows follow LangGraph's declarative construction pattern:

```python
from langgraph.graph import StateGraph, START, END

workflow = StateGraph(ThreadState)
workflow.add_node("process", node_function)
workflow.add_edge(START, "process")
workflow.add_edge("process", END)
graph = workflow.compile()

```

### Conditional Edge Routing

Complex workflows (particularly in [`ask.py`](https://github.com/lfnovo/open-notebook/blob/main/ask.py) and [`transformation.py`](https://github.com/lfnovo/open-notebook/blob/main/transformation.py)) implement conditional edges that route execution based on state content, enabling loops for multi-step reasoning or fallback paths for error handling.

## Summary

- **Consistent Architecture** – All four modules ([`chat.py`](https://github.com/lfnovo/open-notebook/blob/main/chat.py), [`ask.py`](https://github.com/lfnovo/open-notebook/blob/main/ask.py), [`source.py`](https://github.com/lfnovo/open-notebook/blob/main/source.py), [`transformation.py`](https://github.com/lfnovo/open-notebook/blob/main/transformation.py)) implement the same LangGraph pattern: typed state, node functions, graph wiring, and optional checkpointing.
- **State Isolation** – Each workflow maintains its own `TypedDict` schema in `open_notebook/graphs/`, ensuring type safety across notebook contexts, source materials, and transformations.
- **Centralized LLM Management** – The `provision_langchain_model` function standardizes model instantiation across all graph nodes.
- **Persistence Strategy** – Only [`chat.py`](https://github.com/lfnovo/open-notebook/blob/main/chat.py) currently implements `SqliteSaver` checkpointing, while other workflows operate as stateless transformations or maintain persistence at the application layer.

## Frequently Asked Questions

### How does Open Notebook maintain conversation state across API calls?

The [`chat.py`](https://github.com/lfnovo/open-notebook/blob/main/chat.py) workflow compiles its LangGraph with a `SqliteSaver` checkpointer, which persists the `ThreadState` to SQLite. This allows the graph to resume from exact execution points after interruptions, maintaining `messages` history and notebook context between calls.

### Why use LangGraph instead of direct LangChain calls?

According to the source implementation, LangGraph provides deterministic state machines required for reliable multi-step AI operations. The graph structure in [`ask.py`](https://github.com/lfnovo/open-notebook/blob/main/ask.py) and [`transformation.py`](https://github.com/lfnovo/open-notebook/blob/main/transformation.py) enables conditional routing and loops impossible with simple LangChain chains, while [`chat.py`](https://github.com/lfnovo/open-notebook/blob/main/chat.py) benefits from built-in checkpointing that pure LangChain lacks.

### How do the workflows handle asynchronous LLM execution?

All node functions wrap `provision_langchain_model` calls in dedicated event loop handling (specifically noted in the [`chat.py`](https://github.com/lfnovo/open-notebook/blob/main/chat.py) implementation). This pattern manages cases where nodes execute within existing async contexts, preventing event loop conflicts when invoking models.

### What distinguishes the four workflow files from each other?

While architecturally identical, each serves distinct domains: [`chat.py`](https://github.com/lfnovo/open-notebook/blob/main/chat.py) manages conversational `ThreadState` with checkpointing; [`ask.py`](https://github.com/lfnovo/open-notebook/blob/main/ask.py) handles question-answering with retrieval states; [`source.py`](https://github.com/lfnovo/open-notebook/blob/main/source.py) processes document ingestion; and [`transformation.py`](https://github.com/lfnovo/open-notebook/blob/main/transformation.py) executes content restructuring. They share the `StateGraph` pattern but implement domain-specific node logic and state schemas.