Python API
Mount Lens in a notebook cell. Connect to that instance from a live agent kernel call with marimo_lens.agent.connect().
| Task | API |
|---|---|
| Add the notebook interface | Lens |
| Read selections, source, and images | Lens.context(), LensContext |
| Show agent work and return a result | start_activity(), stop_activity(), reveal() |
| Move addressed requests to History | resolve() |
| Connect an agent or capture current output | connect(), MountedLens |
| Release a Lens instance | close() |
The two caller roles are:
- Notebook authors construct
Lensand keep it mounted with the notebook. - Code-mode agents call
marimo_lens.agent.connect()and work through aMountedLenshandle.
The two surfaces share context, activity, reveal, and resolution behavior. The agent handle adds stable reconnection identity and current cell-output capture.
Source version
This reference follows the repository's main branch. PyPI follows tagged releases. Read Compatibility when the installed signatures differ.
Notebook-author API
The top-level package exports:
from marimo_lens import (
ActivityHandle,
CellReference,
Lens,
LensContext,
LensError,
LensReferences,
NotebookReference,
SelectionReference,
SelectionTargetReference,
__version__,
)__version__ comes from the installed marimo-lens distribution metadata.
Lens
Lens(*, dom_selector: str | None = None) -> LensCreates the Python widget and browser UI that own one Lens instance.
dom_selector: str | Noneadds configured DOM targets to the default notebook output targets. The string is stripped and accepts at most 1,024 UTF-16 code units.- Returns a renderable
Lensinstance. - Raises
TypeErrorfor a non-string selector. - Raises
ValueErrorfor an empty or oversized selector. - The browser reports invalid CSS syntax when the view mounts.
from marimo_lens import Lens
lens = Lens()
lensKeep the value mounted while people create selections and agents call its methods. Read Targets before configuring host DOM targets.
Lens.context
lens.context() -> LensContext
Returns detached selection references, lazy graph-context text, available selection-image bytes, and the captured selection-state revision.
context = lens.context()
selection = context.currentThe object does not update. Call context() again after notebook or Lens state changes. Existing contexts remain readable after lens.close().
Raises LensError(code="lens_closed") after the Lens closes.
Read the LensContext reference for every field and degradation rule.
Lens.start_activity
lens.start_activity(
target: str | SelectionReference,
*,
expected_revision: int | None = None,
duration_ms: int | None = None,
label: str | None = None,
message: str | None = None,
) -> ActivityHandleMarks one selection or cell as the current work location and returns the opaque owner accepted by stop_activity().
context = lens.context()
selection = context.current
if selection is not None:
activity = lens.start_activity(
selection,
expected_revision=context.revision,
label="Updating selected result",
message="Inspecting the target and its producing cells.",
)Pass a SelectionReference and its captured expected_revision to address the selected target. Pass a cell ID string for a notebook walkthrough. A cell address can omit expected_revision and must identify a current graph member.
duration_ms=None keeps activity visible until a matching stop, later attention, or teardown. A duration from 1 through 300,000 milliseconds clears it after that hold. label defaults to Working in the browser. Labels accept 40 UTF-16 code units and activity messages accept 240. Selection state does not change.
Raises LensError for a closed Lens, stale selection revision, missing selection, unavailable runtime, or missing cell. Invalid inputs raise TypeError or ValueError.
Lens.stop_activity
lens.stop_activity(activity) -> None
Stops activity when activity still owns the current presentation.
lens.stop_activity(activity)ActivityHandle is a string-backed, JSON-safe opaque value. A stale handle has no effect. A non-string value raises TypeError. An empty or oversized value raises ValueError. A closed Lens raises LensError(code="lens_closed").
Lens.reveal
lens.reveal(
target: str | SelectionReference,
*,
expected_revision: int | None = None,
duration_ms: int,
label: str | None = None,
message: str | None = None,
) -> NoneBrings one selection or cell into view for a required hold.
context = lens.context()
selection = context.current
if selection is not None:
lens.reveal(
selection,
expected_revision=context.revision,
duration_ms=8_000,
label="Updated result",
message="Verified the change and brought the selected target into view.",
)Target and revision rules match start_activity(). Reveal preserves selection state and keyboard focus. A later attention event replaces it. Wait for the hold before resolving when the resolution receipt should follow the revealed result.
duration_ms accepts 1 through 300,000 milliseconds. Labels accept 40 UTF-16 code units. Reveal messages accept 1,000. See Errors and limits for the complete validation contract.
Lens.resolve
lens.resolve(
selection_ids: str | Sequence[str],
*,
expected_revision: int,
summary: str | None = None,
) -> intMoves one or more Open selections into History and returns the next selection-state revision.
context = lens.context()
selection_ids = [item["id"] for item in context.references["selections"]]
if selection_ids:
revision = lens.resolve(
selection_ids,
expected_revision=context.revision,
summary="Updated the result and verified the affected cells.",
)Pass one ID string or a sequence of up to 64 unique strings. Lens validates the entire batch before changing state. The resolved selections share one resulting revision and optional summary of up to 240 UTF-16 code units. Their selection-image bytes are released.
The state transition commits before Lens sends its best-effort resolution receipt. A receipt delivery failure does not roll back History. Expected errors are lens_closed, revision_conflict, selection_not_found, and selection_context_limit.
Lens.close
lens.close() -> None
Closes the Lens instance, cancels pending cell-output capture, and releases Open selections, History entries, and Lens-owned selection images. Repeated calls have no effect.
Later public operations raise LensError(code="lens_closed").
Agent adapter
Import the adapter inside the live notebook kernel:
import marimo_lens.agent as lens_agentagent_plugin
agent_plugin() -> agent_plugins.Plugin
Returns the Agent Plugin resource bundle installed with the current marimo-lens distribution.
Raises agent_plugins.AgentPluginError when distribution metadata or the packaged plugin is unavailable. Reinstall the same marimo-lens version before retrying.
agent_skill
agent_skill() -> agent_plugins.Skill
Returns the packaged marimo-lens Agent Skill.
skill / "SKILL.md"gives the instruction path.skill.bodygives the Markdown instruction body.skill.filesgives the packaged resource inventory.
Raises agent_plugins.AgentPluginError when the plugin contains no Lens skill.
add_lens_cell
add_lens_cell(ctx) -> str
Returns the existing agent-managed Lens cell ID or queues one collapsed Lens cell and returns its new ID.
import marimo._code_mode as cm
import marimo_lens.agent as lens_agent
async with cm.get_context() as context:
cell_id = lens_agent.add_lens_cell(context)The code-mode context creates and runs a queued cell when its async context manager exits. Connect in a later kernel call after the browser renders Lens.
ctx must expose create_cell(), run_cell(), and cells.find(). Other objects raise TypeError. Several agent-managed Lens cells raise LensError(code="lens_ambiguous").
connect
connect(context=None, *, identity=None) -> MountedLens
Finds one live Lens and returns its agent-facing handle.
import marimo._code_mode as cm
import marimo_lens.agent as lens_agent
mounted = lens_agent.connect(cm.get_context())context adds Lens objects found in code-mode globals to browser-ready Lens registrations. identity selects the same Lens in a later kernel call.
Raises LensError(code="lens_unavailable") when no matching Lens exists. Raises LensError(code="lens_ambiguous") when several candidates exist and no identity selects one. A context without a globals mapping or a non-string identity raises TypeError. An empty identity raises ValueError.
MountedLens
MountedLens remains attached to one live Lens instance. It can address any selection owned by that instance.
| Member | Contract |
|---|---|
identity | Opaque string for reconnecting across kernel calls. |
context() | Delegates to Lens.context(). |
cell_image(cell_id, *, expected_revision) | Requests a fresh, unmarked cell-output PNG. |
start_activity(...) | Delegates to Lens.start_activity(). |
stop_activity(activity) | Delegates to Lens.stop_activity(). |
reveal(...) | Delegates to Lens.reveal(). |
resolve(...) | Delegates to Lens.resolve(). |
mounted.cell_image(cell_id, *, expected_revision) -> bytes | None
The first call starts browser capture and returns None. End that kernel call, reconnect to the same Lens, and repeat the same cell ID and revision. The completed call returns and consumes the PNG bytes.
context = mounted.context()
selection = context.current
if selection is not None and selection["cells"]:
cell_id = selection["cells"][0]["id"]
png = mounted.cell_image(
cell_id,
expected_revision=context.revision,
)One capture can be pending per Lens. Finish it before requesting another cell. A stale revision raises revision_conflict. A different cell while capture is pending raises capture_busy. A terminal result consumes the capture slot, so another call starts a new capture. Browser capture has a 15-second deadline and the Python request expires after 20 seconds. The operation requires a current graph member and a browser-ready Lens view. Read Context and evidence for the difference between a selection image and a cell-output image.
LensError
LensError extends RuntimeError and exposes:
code: str, a stable machine-readable failure code.revision: int | None, the current selection-state revision when available.
Read Errors and limits for every code, recovery action, argument rule, and bound. Read Connect an agent for the complete workflow.