C# notebooks
A C# notebook runs cells in the Shell scope and keeps what they declare. This page shows how cells share state, how to query the graph, how to stop a cell, and how to chart a result. For what a notebook is and what it can reach, see the overview.
Open Shell, select New tab, and choose Notebook (C#).
Cells share variables, methods and types
Each cell continues the one before it, the way a C# script continues in an interactive session. A variable, method or type declared in one cell is available in every cell after it.
// Cell 1
var threshold = 5;
int Twice(int x) => x * 2;
record Point(int X, int Y);
// Cell 2
Twice(threshold)
10
// Cell 3
new Point(3, 4).X + threshold
8
The last expression of a cell is its value. A cell that ends in a statement, such as a declaration, shows nothing.
The helper classes of the workspace (N, E, Endpoints, AI_Tools, Agents, PromptTemplates, Indexes, and the schema helpers) are added once, before the first cell, so every cell can use them. See auto-generated helpers.
What is in scope
Every member of the shell scope is available by name: Q(), Query(), Graph, CurrentUser, ChatAI, CancellationToken and the others. The namespace Mosaik.GraphDB.Plotting is imported as well, which brings in Plot, Chart and the ToRows() extension for queries. They are described in charts and tables and in the C# reference.
Query the graph
Return a query to see its results in the viewer the Shell's Results pane uses:
Q().StartAt("Ticket").Where(n => n.GetString("Status") == "Open").Emit("N")
A query is not run until something reads it. To work with the nodes in code, read them and keep the result:
// Cell 1
var open = Q().StartAt("Ticket").Where(n => n.GetString("Status") == "Open").AsEnumerable().ToList();
open.Count
// Cell 2
open.GroupBy(t => t.GetString("Priority")).Select(g => new { Priority = g.Key, Tickets = g.Count() })
A cell that returns an anonymous object, a list or a record shows it as JSON, with its text form beside it.
To get rows you can chart or hand to other code, use ToRows(), which is described below.
Turn a query into rows
ToRows() turns a query, or a list of nodes, into one dictionary per node:
var rows = Q().StartAt("Ticket").ToRows("Status", "Priority");
rows[0]
{ "Status": "Open", "Priority": "High" }
Without arguments it returns UID, Type and every field of the nodes. Naming fields returns only those, in that order. A node that lacks a field has null for it, so every row has every column. Fields hidden by the schema are not included, and node types that never leave the server, such as secrets, are dropped. A query of more than 100,000 nodes fails with a message to narrow it first.
Stop a running cell
Select Stop, or the stop button on the cell, while a cell runs. This cancels the CancellationToken of the scope. Code that watches the token stops: queries, endpoint and tool calls started through the scope, Task.Delay(…, CancellationToken) and ThrowIfCancellationRequested().
await Task.Delay(60000, CancellationToken);
"finished"
The cell was interrupted.
The notebook keeps its variables. Each cell gets a token of its own, so the next cell starts with a fresh one.
Code that does not watch the token cannot be stopped from the notebook. A while (true) { } loop runs until it ends, so pass CancellationToken to long calls and check IsCancellationRequested in loops:
foreach (var batch in batches)
{
ThrowIfCancellationRequested();
Process(batch);
}
Errors
A cell that does not compile shows each error with its position, and the notebook carries on:
(1,9): error CS1525: Invalid expression term ';'
The position is the line and column in that cell. An exception thrown by a cell shows its stack trace. Variables the cell declared before it threw are kept.
Chart a result
Plot builds a chart from rows. End a cell with one to draw it:
var tickets = Q().StartAt("Ticket").ToRows("Status", "Priority");
Plot.Bar(tickets, x: "Status", y: "Priority", title: "Tickets by status")
The next page covers every chart type, both languages and how a model-written spec draws here as well: charts and tables.
Sandbox
With the Sandbox toggle on when you open the notebook, cells run in the sandboxed shell scope: the graph is read-only and queries cannot start transactions. Changing the toggle later does not affect a notebook that is already open; open a new one.
Differences from a Shell script
| Script (C#) | Notebook (C#) | |
|---|---|---|
| State between runs | None. | Variables, methods and types are kept. |
| Result | The value the script returns. | The value of each cell's last expression. |
| Compile errors | Shown in the editor as you type. | Shown when the cell runs. |
| Stop | Not available. | Cancels the cell's CancellationToken. |
| Charts | Not drawn. | Drawn. |