Skip to main content
When you have multiple agents working on a research problem, they often need to share information — one task produces a result that another task uses as input. Qualia’s task-variable evidence system passes those values between tasks through the qualia package, which is available in every notebook kernel and in every script an agent runs.

How it works

The basic flow:
  1. Declare required variables on a task
  2. Assign values in a notebook cell (just use the variable name)
  3. Capture happens automatically when the cell runs
  4. Other agents read values in downstream tasks with qualia.get()

Reading captured evidence

In a downstream task’s notebook, read values captured by upstream tasks. The qualia namespace is already in scope — no import needed:
To recover a value scoped to one task (for example after a kernel reset, or in a fresh subagent), use the typed read:

Capturing variables

In a notebook, variables are captured from cells automatically:
  1. Define required variables when creating a task
  2. Run code that assigns values to those variable names
  3. Qualia captures the values when the cell executes
For example, if a task requires best_model and accuracy:
After this cell runs, both values are captured and available to downstream tasks. You can also be explicit, from the cell that produced the value:
The value fills the matching required variable on each active task in the chat. For an interesting value the task did not declare, record it as evidence without filling a slot:
Pass recall_priority ("low" by default, up to "high") when the value is something later agents should be shown rather than have to go looking for. See recall priority.
Captured variables become runtime-captured claims in the Knowledge System, creating a documented trail of data flow.

Capturing from a script

Scripts use the same package. There is no cell boundary, so there is no automatic capture — the script submits before it exits — and it imports the client itself. The qualia methods are async. Notebook cells can await them directly because IPython enables autoawait, but a script has to run them itself: top-level await is a SyntaxError outside a cell.
Use await when calling asynchronous capture methods; without it, the value is not captured.
R and Julia work the same way, with one difference worth knowing. Julia cannot read a calling function’s local variables by name, so add_evidence there is a macro:
A script claim points at the line of the script that produced the value, the way a notebook claim points at its cell. That line is re-checked whenever the claim is read, so editing the script past it marks the source as changed.

Saving a figure from a script

Use save_figure to save a chart from a script with its underlying values, so captured figures support data inspection.
A few things worth knowing:
  • It is a drop-in for the library’s own save. Extra arguments — dpi, bbox_inches, width — pass straight through, and the call returns the path it wrote.
  • Save to a path inside your workspace, and prefer SVG: it prints at any size and keeps its text as text.
  • The library’s own save still works, and the figure can still be captured — it just arrives as a picture with nothing behind it.
  • Plotly, Altair, and ggplot2 additionally produce a live chart, which is stored alongside the image and stays pannable and zoomable.
  • For Python Plotly in scripts, use fig.write_json("figures/name.plotly.json") and capture that file with capture_figure_file, naming the producing script. Embed the returned claim in a writeup with [[figure:C-123]] in its own paragraph.
  • Static Matplotlib and ggplot2 saves need no extra exporter. Altair image saves require vl-convert-python.

Evidence values

Record computed values from the notebook or script that produced them. This keeps the value’s precision and a link to its source.

When tasks use variable evidence

Most useful when:
  • Chaining experiments: One task trains a model, another evaluates it
  • Aggregating results: Multiple parallel tasks produce metrics, a final task compares them
  • Parameterized workflows: Pass configuration between stages
Example workflow:

Exporting notebooks

When you export a notebook for standalone use, Qualia replaces qualia.get() calls (and the R/Julia equivalents) with their actual values. The exported notebook runs without Qualia — all variable references are resolved to concrete data, so it works in other IDEs such as JupyterLab and VS Code.

Supported values

The system supports:
  • Python, R, and Julia, in notebooks and scripts
  • Primitive values: numbers, strings, booleans, and homogeneous lists of those. Dicts, DataFrames, and other complex objects are rejected — capture separate scalar variables instead
  • Shared task results: a captured value fills the matching required variable on each active task in the chat