How Note Creation Links to Sources and Insights in Open Notebook
In Open Notebook, note creation does not directly bind sources; instead, a note is attached to a notebook via an artifact edge, and downstream context builders traverse the notebook‑source‑insight graph to surface relevant material for LLM workflows.
Understanding how note creation links to sources and insights is essential for building effective retrieval workflows in Open Notebook. According to the lfnovo/open-notebook source code, the relationship is graph-based and indirect: a Note is persisted and optionally linked to a Notebook, which aggregates Source records and their SourceInsight children. When a user later queries or chats with the note, the ContextBuilder utility walks this relationship chain to assemble the full prompt context.
How Note Creation Works in Open Notebook
When a client POSTs a new note to /api/notes, the FastAPI handler defined in api/routers/notes.py instantiates a Note domain object from open_notebook/domain/notebook.py and stores it. The process splits into persistence, embedding, and optional notebook attachment.
Persisting and Embedding the Note
The handler awaits Note.save(), which writes the note record to SurrealDB and asynchronously fires an embed_note command so the note receives a vector embedding. In open_notebook/domain/notebook.py at lines 567‑580, Note.save() handles both persistence and embedding, ensuring the note is searchable before any notebook link is created.
Attaching a Note to a Notebook
If the JSON payload includes a notebook_id, the handler calls Note.add_to_notebook(). This method creates an artifact edge that links the note record to the specified notebook. As implemented in open_notebook/domain/notebook.py at lines 595‑600, this edge is the only structural bond between the note and the notebook.
A typical POST payload and handler flow looks like this:
{
"title": "My summary",
"content": "Lorem ipsum …",
"note_type": "human",
"notebook_id": "nb-12345"
}
# Simplified excerpt from api/routers/notes.py
new_note = Note(title=title, content=note_data.content, note_type=note_type)
command_id = await new_note.save() # persists + embeds
if note_data.notebook_id:
await new_note.add_to_notebook(note_data.notebook_id) # artifact edge
How Sources and Insights Connect to Notebooks
A Notebook acts as the aggregation layer between notes and raw material. It collects many Source records via a has edge queried through methods like Notebook.get_sources(). Each Source can own zero or more SourceInsight records, which are created and retrieved through Source-level methods in open_notebook/domain/notebook.py.
Adding and Retrieving Source Insights
To attach an insight to a source, the codebase uses Source.add_insight() at lines 459‑497 in open_notebook/domain/notebook.py. This method inserts a new source_insight record into SurrealDB and queues an embed_insight command for vectorization. Retrieval happens through Source.get_insights() at lines 392‑404, which returns all insight records tied to that source.
source = await Source.get(source_id)
insight_id = await source.add_insight(
insight_type="summary",
content="Key take‑aways from the PDF"
)
Traversing the Graph to Link Notes to Insights
Because a note is only directly tied to a notebook, the path to sources and insights is traversed at query time rather than at creation time. The graph follows this pattern:
note ──artifact──> notebook ──has──> source ──has──> source_insight
The ContextBuilder utility in open_notebook/utils/context_builder.py materializes this traversal. At lines 182‑190, it optionally pulls in insights using include_insights=True by default when assembling prompts for chat, ask, or transformation graphs. Therefore, note creation links to sources and insights through graph traversal, not explicit foreign keys.
builder = ContextBuilder(
source_ids=[source.id],
include_insights=True,
max_tokens=2000,
)
context = await builder.build()
# context now contains note text, source text, and any source_insight content.
Summary
Note.save()persists a note to SurrealDB and triggers anembed_notecommand inopen_notebook/domain/notebook.py.Note.add_to_notebook()creates anartifactedge linking the note to a notebook.- Notebooks aggregate sources via a
hasedge, and sources aggregate insights viaSource.add_insight()andSource.get_insights(). ContextBuildertraversesnote → notebook → source → source_insightat query time, withinclude_insights=Trueby default.- The relationship is indirect: note creation links to sources and insights through the notebook graph, not through direct source references in the note record.
Frequently Asked Questions
Does a note store direct references to its sources?
No. As implemented in lfnovo/open-notebook, a note does not store direct source identifiers. Instead, it links to a notebook via an artifact edge, and the notebook aggregates the sources. The ContextBuilder traverses this relationship when assembling context.
When are source insights pulled into a note’s context?
Insights are retrieved at query time by the ContextBuilder in open_notebook/utils/context_builder.py. When include_insights=True (the default), the builder walks the graph from note to notebook to source to source_insight and includes that content in the assembled prompt.
What happens if a note is created without a notebook_id?
If the POST payload to /api/notes omits notebook_id, the note is persisted and embedded but no artifact edge is created. Without that edge, standard graph traversals in ContextBuilder cannot discover related sources or insights for that note.
Which method is responsible for vectorizing a new insight?
Source.add_insight() in open_notebook/domain/notebook.py inserts the record and queues an embed_insight command. This ensures the insight is vectorized and available for semantic retrieval alongside the source and note content.
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 →