# Chat vs Ask Workflows in Open Notebook: Architecture and Implementation Guide

> Explore chat vs ask workflows in Open Notebook. Understand the architecture and implementation for persistent conversations and temporary search strategies. Learn how to leverage these distinct approaches.

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

---

**The chat workflow maintains persistent, session-based conversations within a notebook using a simple single-node LangGraph, while the ask workflow executes a multi-step, temporary search strategy across the entire knowledge base without checkpointing.**

Open Notebook is an open-source knowledge management system that provides two distinct LangGraph-driven workflows for AI interaction. Understanding the differences between chat and ask workflows in Open Notebook is essential for developers building conversational interfaces versus targeted research queries.

## Architectural Design and Purpose

### Chat Workflow

The **chat workflow** is designed for interactive, session-based conversations that live inside a specific notebook. It maintains conversational state across multiple turns, allowing users to reference previous messages and build context incrementally. This workflow is ideal when users need to iteratively explore ideas, summarize content, or engage in back-and-forth dialogue with their knowledge base.

### Ask Workflow

The **ask workflow** provides a one-shot "question-answer" capability over the entire knowledge base using a generated search strategy. Rather than maintaining conversation history, it executes a temporary, multi-step reasoning process that searches across all sources and synthesizes a final answer. This workflow suits factual research queries where the user needs a comprehensive answer drawn from multiple documents without ongoing conversation.

## LangGraph Implementation Details

### Chat Graph Topology

In [`open_notebook/graphs/chat.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/graphs/chat.py) (lines 22-99), the chat workflow defines a simple `StateGraph` containing a single *agent* node. This node receives the complete message list from the `ThreadState`, processes it through the language model, and returns a new AI message to append to the conversation.

The graph uses a straightforward linear flow: input → agent → output. According to the source code, the `ThreadState` class (lines 22-27) holds `messages`, an optional `notebook` reference, `context` data, and a possible `model_override` parameter.

### Ask Graph Topology

In contrast, [`open_notebook/graphs/ask.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/graphs/ask.py) (lines 20-156) implements a multi-node `StateGraph` with conditional edges that orchestrate a three-stage pipeline:

1. **agent** – Creates a JSON **strategy** outlining search terms and approaches
2. **provide_answer** – Executes vector/text searches for each term in the strategy and generates intermediate answers
3. **write_final_answer** – Combines intermediate answers into a coherent final response

The `ThreadState` for this workflow (lines 44-49) tracks `question`, the generated `strategy`, a list of `answers`, and the final answer string.

## State Management and Persistence

### Chat State and Checkpoints

The chat workflow persists conversation state using LangGraph's checkpointing system. As implemented in [`open_notebook/graphs/chat.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/graphs/chat.py) (lines 88-99), checkpoints are stored in a SQLite file defined by `LANGGRAPH_CHECKPOINT_FILE`, enabling conversation recovery and resumption across sessions.

### Ask State Structure

The ask workflow maintains no persistence. As noted in [`open_notebook/graphs/ask.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/graphs/ask.py), the graph runs to completion within a single request, and the `ThreadState` exists only transiently during execution. This stateless design reflects the workflow's one-shot nature.

## Model Configuration and Prompting

### Chat Model Provisioning

The chat workflow uses `provision_langchain_model(..., "chat")` as shown in [`open_notebook/graphs/chat.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/graphs/chat.py) (lines 30-38). It respects an optional *model_override* supplied by the session or request, allowing dynamic model selection per conversation. The system utilizes a single prompt template: `chat/system`.

### Ask Multi-Model Pipeline

The ask workflow requires three separate model configurations passed via `RunnableConfig`, as defined in [`api/routers/search.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/search.py) (lines 61-78):

- **strategy_model** – Generates the search strategy
- **answer_model** – Processes individual search queries
- **final_answer_model** – Synthesizes the final response

According to [`open_notebook/graphs/ask.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/graphs/ask.py) (lines 53-63), this workflow uses three distinct prompt templates: `ask/entry` for strategy generation, `ask/query_process` for per-search processing, and `ask/final_answer` for synthesis.

## API Integration and Usage

### Chat Endpoints

The chat workflow exposes endpoints in [`api/routers/chat.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/chat.py) (lines 30-34):

- **`/chat/execute`** – Adds a user message, runs the graph, and returns the updated message list
- **`/chat/context`** – Builds a context payload from notebook sources

### Ask Endpoints

The ask workflow surfaces through [`api/routers/search.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/search.py) (lines 13-23):

- **`/search/ask`** – Streaming SSE endpoint for real-time answer generation
- **`/search/ask/simple`** – Non-streaming endpoint returning the complete answer

### Code Examples

**Chat workflow implementation:**

```python
import httpx

BASE = "http://localhost:5055"

# Create a chat session for notebook "nb123"

resp = httpx.post(
    f"{BASE}/chat/sessions",
    json={"notebook_id": "nb123", "title": "Research chat"},
)
session_id = resp.json()["id"]

# Build context from notebook sources

ctx_resp = httpx.post(
    f"{BASE}/chat/context",
    json={"notebook_id": "nb123", "context_config": {}},
)
context = ctx_resp.json()["context"]

# Execute chat

chat_resp = httpx.post(
    f"{BASE}/chat/execute",
    json={
        "session_id": session_id,
        "message": "Explain the difference between supervised and unsupervised learning.",
        "context": context,
    },
)
print(chat_resp.json()["messages"][-1]["content"])

```

*Relevant server code*: The request hits `execute_chat` in [`api/routers/chat.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/chat.py), which builds the LangGraph state and invokes `chat_graph` defined in [`open_notebook/graphs/chat.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/graphs/chat.py).

**Ask workflow implementation:**

```python
import httpx

BASE = "http://localhost:5055"

ask_payload = {
    "question": "What are the health benefits of a Mediterranean diet?",
    "strategy_model": "openai-gpt-4o-mini",
    "answer_model": "openai-gpt-4o-mini",
    "final_answer_model": "openai-gpt-4o-mini",
}
resp = httpx.post(f"{BASE}/search/ask/simple", json=ask_payload)
print(resp.json()["answer"])

```

*Relevant server code*: `ask_knowledge_base_simple` in [`api/routers/search.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/search.py) streams the `ask_graph` (defined in [`open_notebook/graphs/ask.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/graphs/ask.py)) and extracts the final answer from the `write_final_answer` node.

## Embedding Requirements

The chat workflow treats embeddings as optional, since context can be supplied directly by the client. However, the ask workflow mandates embedding configuration. As implemented in [`api/routers/search.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/search.py) (lines 38-45), the ask graph validates that an embedding model is configured before executing any search operations.

## Summary

- **Chat workflow** uses a simple single-node LangGraph in [`open_notebook/graphs/chat.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/graphs/chat.py) with SQLite checkpointing for persistent conversations
- **Ask workflow** implements a three-node pipeline in [`open_notebook/graphs/ask.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/graphs/ask.py) (strategy → answer → final) without persistence
- **Chat endpoints** (`/chat/execute`) maintain session state, while **ask endpoints** (`/search/ask`) execute stateless, one-shot queries
- **Ask requires** three distinct model configurations and mandatory embeddings, whereas **chat uses** a single model with optional embeddings
- **Chat** suits iterative notebook-based conversations, while **ask** handles comprehensive knowledge base queries requiring synthesized answers

## Frequently Asked Questions

### When should I use the chat workflow versus the ask workflow?

Use the **chat workflow** when building interactive, multi-turn conversations within a specific notebook where context accumulates over time. Use the **ask workflow** when you need a single, comprehensive answer synthesized from across your entire knowledge base without maintaining conversation history.

### Does the ask workflow support conversation history?

No. The ask workflow is designed as a stateless, one-shot operation. As implemented in [`open_notebook/graphs/ask.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/graphs/ask.py), it does not use LangGraph checkpointing and cannot access previous interactions. Each question is treated as an independent query against the knowledge base.

### What embedding requirements exist for each workflow?

The **chat workflow** operates without mandatory embeddings, as context can be provided directly by the client via the `/chat/context` endpoint. The **ask workflow** requires configured embeddings, with [`api/routers/search.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/search.py) (lines 38-45) explicitly validating that an embedding model is available before executing the search strategy.

### How do I configure different models for the ask workflow steps?

Pass three distinct model identifiers via the `RunnableConfig` when invoking the ask graph. According to [`api/routers/search.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/search.py) (lines 61-78), you must specify `strategy_model` for the initial planning phase, `answer_model` for processing individual search results, and `final_answer_model` for the synthesis phase.