Skip to main content

AI

The library is built so an agent can construct and drive diagrams through the same programmatic surface a human uses โ€” no separate AI API, no parallel data model. An LLM that can call addElement or setMode produces exactly the scene a click would.

The design intentโ€‹

A diagram is just a Scene โ€” a plain, serialisable data structure (see the scene model and Persistence). The editor engine is the single source of truth that mutates it. Because both are ordinary TypeScript values and functions, an agent operates the editor exactly like application code does: through EditorAPI and the underlying EditorInstance, or by building a Scene directly with @oh-just-another/scene operations.

Building a scene from codeโ€‹

The scene operations are pure functions returning { scene, patch }, so an agent can assemble a diagram with no editor mounted at all, then hand the result to the editor or serialise it.

import {
DEFAULT_LAYER_ID,
addElement,
emptyScene,
orderForTop,
type RectangleElement,
} from "@oh-just-another/scene";
import { elementId } from "@oh-just-another/types";
import { stringifyScene } from "@oh-just-another/serialization";

const box: RectangleElement = {
id: elementId("box-1"),
layerId: DEFAULT_LAYER_ID,
type: "rectangle",
position: { x: 40, y: 40 },
rotation: 0,
scale: { x: 1, y: 1 },
order: orderForTop([]),
style: { fill: "#e3f2fd" },
width: 160,
height: 80,
};

const { scene } = addElement(emptyScene(), box);
// chain further addElement / addLink calls on `scene`...
const json = stringifyScene(scene, 2);

Driving a live editorโ€‹

When the editor is mounted, the agent drives it through the same handle described on the Driver page โ€” set the mode, mutate the scene, change the selection, fit the viewport:

import type { Element } from "@oh-just-another/scene";
import type { EditorInstance } from "@oh-just-another/editor";

function agentStep(editor: EditorInstance, element: Element) {
editor.addElement(element, { select: true });
editor.zoomToFit();
}

MCP serverโ€‹

@oh-just-another/mcp packages this surface as an MCP (Model Context Protocol) server. An agent connected over stdio creates scenes, adds elements and links, queries a compact summary, and renders SVG/PNG โ€” no code integration needed:

{
"mcpServers": {
"oja": { "command": "npx", "args": ["-y", "@oh-just-another/mcp"] }
}
}

Tools: create_scene, load_scene, get_scene, add_elements, update_element, remove_elements, add_link, query_scene, export_svg, export_png, import_mermaid, get_scene_schema. Element input is validated against the serialization schema; missing base fields (id, layer, position, rotation/scale, order โ€” plus width/height for rectangle/ellipse/image) get defaults. See LLM Docs for the schema and prompt patterns.

What's possible todayโ€‹

  • Programmatic scene construction via @oh-just-another/scene factories and operations.
  • Driving a live editor via EditorAPI / EditorInstance.
  • MCP server (@oh-just-another/mcp) โ€” scene tools over stdio for any MCP client.
  • Import from text formats (Mermaid, dot, drawio) via @oh-just-another/importers โ€” a natural bridge for LLM-generated diagram source.
  • Serialise / deserialise scenes for round-tripping through a model, plus a JSON Schema of the wire format (sceneJsonSchema).

There is no built-in model client or prompt layer โ€” you wire your agent of choice to these surfaces. The point is that the surface already exists and is the real one, not an afterthought. See LLM Docs for pointing an agent at the API.