Skip to content

Playground & AI companion

At a glance

  • The MiniGraph Playground is a browser workbench (a WebSocket session at /ws/graph) for building, dry-running, and inspecting graphs interactively.
  • You drive it with a small command grammar; sessions can be shared for collaborative modeling; and the companion endpoint lets a script or an AI dispatch commands into a live session.
  • Dev-only. The Playground and companion endpoints are gated by app.env=dev and are not registered in production.

The command grammar

Everything you do in the Playground is a command typed into the console (multi-line where noted). The essentials:

Intent Command
Create a node create node <name> + with type <Type> + with properties + k=v lines
Update a node update node <name> + with type <Type> + with properties + k=v lines
Connect / disconnect connect <a> to <b> with <relation> · delete connection <a> and <b>
Delete a node delete node <name>
Instantiate (seed input) instantiate graph + optional type(value) -> input.body.<key> lines
Run / single node run · execute <node>
Inspect state inspect <key> (e.g. inspect output, inspect model.sum)
Describe describe graph · describe node <name> · describe skill <route>
List list nodes · list connections · seen
Persist export graph as <name> · import graph from <name>
Help help · help <topic>

A typical loop — build, seed, dry-run, inspect:

create node fetcher
with type Fetcher
with properties
skill=graph.api.fetcher
dictionary[]=person-name
input[]=input.body.person_id -> person_id
output[]=result.name -> output.body.name

connect root to fetcher with fetch
connect fetcher to end with done

instantiate graph
int(100) -> input.body.person_id

execute fetcher
inspect output

describe skill <route> (e.g. describe skill graph.api.fetcher) prints the authoritative, shipped help for each skill — the same content this Part documents.

Collaborative sessions

Each open Playground connection is a session with a public id like ws-178443-2. Sessions can be shared so several people model the same graph together:

session                       # show this session + its subscribers
session subscribe ws-178443-2 # join that primary session as an equal co-author
session unsubscribe           # detach, keeping your current graph
session reset                 # clear the primary session; subscribers keep their graphs

When you subscribe to a primary session, commands mirror both ways — every command except the session topology commands propagates to the primary and all subscribers alike, so all parties (human or AI) are equal co-authors of one shared model. (You can't subscribe to yourself or to a non-primary session; a primary session has nothing to unsubscribe.)

An AI agent asked to host a session should run the shipped session broker (scripts/playground-session-broker.mjs, in the starter-graph template and the minigraph-playground example) rather than hand-roll a WebSocket client — the session contract includes a keep-alive (ping every ~20 s) that hand-rolled clients typically miss, and a client without it dies silently at the idle timeout. See Hosting the session yourself.

The companion endpoint

The companion endpoint lets an HTTP client — a script, a test harness, or an AI agent — dispatch a Playground command into an already-open session. The command runs as if typed; the outcome comes back in the HTTP response, and every output line is also teed to that session's browser console so a watching human sees the same thing live.

POST /api/companion/{session-id}/sync
Content-Type: text/plain

<exactly ONE Playground command>

The response carries the command's outcome in-band:

{
  "ok": true,
  "id": "ws-123456-7",
  "command": "create node root ...",
  "output": ["> create node root ...", "node root created"],
  "result": [ ... structured data, e.g. a run's output.body ... ]
}

Null fields are omitted (error appears only on failure, result only when the command yields data). When ok is false, error carries the first failing line — read output for the full picture, fix, and re-issue. The complete contract, including the ok derivation and the rules an AI driver should follow, is in the AI agent guide.

Status codes: 200 executed (read ok/error in the body); 400 missing/empty/non-text body; 404 no active session for that id — operationally, a 404 means the session is gone (for example, the app was restarted): stop and obtain a fresh session id, because every command against a dead id will keep failing. To read the current model for a live session, GET /api/graph/session/{id}.

A minimal call:

SESSION_ID="ws-384729-17"
curl -sS -X POST "http://localhost:8300/api/companion/${SESSION_ID}/sync" \
  -H 'Content-Type: text/plain' \
  --data-binary $'create node root\nwith type Root\nwith properties\nskill=graph.math'

Retired: the original fire-and-forget POST /api/companion/{session-id} (which returned only {status:"accepted"} and streamed the real outcome to the console) was retired in 2026-09 — it hid errors from the caller and forced slower, sleep-padded drivers. The bare URL now answers 404; use /sync.

Under the hood, the endpoint (post.companion.command.sync) confirms the session is live, then dispatches to a singleton command handler so commands execute in order without races. Like the Playground itself, it is gated by @OptionalService("app.env=dev") — do not expose it beyond trusted dev environments (there is no auth).

Restarting the app ends every session — export first. The working graph lives in the session, not on disk: export graph as {name} before any restart (deploying a graph requires one), or the unexported work is lost. For a prototype or a demo the restart need not be a rebuild — see Rapid prototyping — deploy without a rebuild — and the shipped broker survives it: it reconnects, reports the new session id, and the agent re-imports the export before the humans re-subscribe.

Turning dev mode on in your own app

The Playground is not a separate application — it rides along in any Mercury app that depends on minigraph-playground-engine. Two things switch it on:

  1. app.env=dev in application.properties. Every Playground service is annotated @OptionalService("app.env=dev"), so without this line none of them register.
  2. The dev-mode rest.yaml entries — the companion endpoint, the live-model and describe-model reads, the two upload dialogs, and the state-machine inspector. A REST entry whose service is not registered is skipped with a warning at start-up, so the two settings belong together: app.env=dev without the routes gives you a WebSocket and no HTTP surface; the routes without app.env=dev give you a start-up log full of Skip [POST] /api/companion/{id}/sync - Service ... not available.
  3. The home page route — get.index.html at /index.html, which a request for / also reaches. The function follows the same switch: it serves the Playground web app when app.env=dev and a plain service page for any other value (or no app.env at all), so a production deployment never shows the Playground UI. The Playground page lives outside the static folder (template/playground.html in the engine jar); without this route, / falls through to the engine's static index.html, which is the same plain page in both modes.

All three ship pre-wired in templates/starter-graph — copy that directory and the Playground is live on first run. The distributed-cache example shows the same wiring inside an app that also serves ordinary Layer 1 and Layer 2 endpoints: dev mode is additive, so a real application can be co-authored in the Playground and still serve its production routes. Remove the single app.env=dev line to close the whole surface for production.

Depend on the graph engine alone. minigraph-playground-engine pulls in event-script-engine and platform-core transitively — one dependency, all three layers. Until 4.12.14, adding the other two by hand could also hide the Playground: its page was the engine jar's static classpath:/public/index.html, platform-core ships a placeholder welcome page at the same resource path, and whichever jar came first on the classpath won — every test, curl, and companion command still succeeded while the browser showed the placeholder. Since 4.12.15 the Playground page is served by get.index.html from template/playground.html, so the classpath order no longer decides what the browser shows: both jars' static index.html are plain pages.

User–AI collaboration

Put the two together and you get the seed of the framework's collaboration vision: a person watches the Playground in the browser while an AI companion builds the graph through the companion endpoint, one command per request, pausing for the human to confirm on the console between steps. The human steers and certifies; the AI drafts and refines; both work on the same live model.

This is collaboration over a model, not over code — which is exactly the point of treating a Knowledge Graph as the application. Today the AI is an external session driving the endpoint; maturing it into an integrated, pluggable companion is on the roadmap (see the maturity section).

See also