AI agent guide — building graphs via the companion endpoint
At a glance
- Read this if you are an AI agent asked to build or modify a MiniGraph. It is the single context you need — you should not need to read the engine source.
- Generate from rules, not guesses. The command grammar and its machine-readable form
minigraph-commands.jsonare the source of truth. Validate every command against them before sending.- Two endpoints, two jobs — see below. Both are dev-only (
app.env=dev), no auth.
Which endpoint?
| Goal | Endpoint | Notes |
|---|---|---|
| Execute a deployed graph | POST /api/graph/{graph-id} |
Send the request body; get the response. No session. |
| Build/edit a graph in a live session | POST /api/companion/{session-id} |
Dispatch Playground commands into an open browser session. |
| Read the live model | GET /api/graph/session/{session-id} |
Returns the current graph as JSON. |
This guide is about the companion flow — co-authoring a graph with a human watching the Playground.
The companion contract
1. A human opens the Playground: ws://{host}/ws/graph
2. The first WebSocket frame carries the session id, format ws-<6 digits>-<counter>
(e.g. ws-384729-17). Get this id from the human.
3. For each command: POST /api/companion/{session-id} with Content-Type: text/plain
and exactly ONE command in the body.
4. The HTTP response is just an acknowledgement (HTTP 200 = dispatched).
The real output — including syntax errors — streams to the WebSocket console, NOT the
HTTP response. Ask the human to confirm on the console between steps.
5. Read state with GET /api/graph/session/{session-id}.
Status codes: 200 dispatched (a syntax error still returns 200 — its text appears on the WS);
400 missing/empty/non-text body; 404 no active session for that id.
Rules of engagement: one command per POST (multi-line commands are fine — see the grammar); the session must already be open (you do not create it); single operator — don't POST while a human is typing in the same instant; never expose this beyond a trusted dev host.
Generate deterministically
- Use the grammar as source of truth —
command-reference.mdfor the rules,minigraph-commands.jsonto look up a command's exact syntax, params, and allowed values. Do not infer syntax from a single example. - Validate before sending — check each command against this list (the engine's invariants):
Pre-send checklist - [ ] The root node is named
root; the end node is namedend. - [ ] Node names and types are lowercase + hyphen only. - [ ] Each node has 0 or 1 skill (skill={route}); the skill's required properties are present (see the skill→property matrix). - [ ] Every node in the traversal path connects to ≥1 node (orexportfails). Config nodes (Dictionary/Provider) are referenced by name (dictionary[]=,provider=) and need no connections. - [ ] Multi-line commands (create/update/instantiate) are sent as one block; multi-line values use'''…'''. - [ ]instantiate graphprecedesrun/execute/inspect. - [ ] Exactly one command per POST.
Canonical build recipe
A reliable order for building a graph:
- Plan the nodes and the connections (root → … → end) before issuing commands.
- Create nodes:
create node root(typeRoot), the active/skill nodes, andcreate node end(typeEnd, usually withgraph.data.mapperto shapeoutput.body). - Connect them so traversal flows root → end, with no orphans.
- Instantiate with mock input:
instantiate graph+{constant} -> input.body.{key}lines. - Run and inspect:
run(orexecute {node}), theninspect {output.body}; iterate. - Export & deploy:
export graph as {name}, deploy the JSON, then callPOST /api/graph/{name}.
Worked example
Building the hello-world graph via the companion endpoint, one command per request:
SID="ws-384729-17" # from the WebSocket welcome frame
curl -sS -X POST "http://{host}/api/companion/${SID}" -H 'Content-Type: text/plain' \
--data-binary $'create node root\nwith type Root\nwith properties\npurpose=demo'
curl -sS -X POST "http://{host}/api/companion/${SID}" -H 'Content-Type: text/plain' \
--data-binary $'create node end\nwith type End\nwith properties\nskill=graph.data.mapper\nmapping[]=text(hello world) -> output.body'
curl -sS -X POST "http://{host}/api/companion/${SID}" -H 'Content-Type: text/plain' \
--data-binary 'connect root to end with done'
curl -sS -X POST "http://{host}/api/companion/${SID}" -H 'Content-Type: text/plain' \
--data-binary 'instantiate graph'
curl -sS -X POST "http://{host}/api/companion/${SID}" -H 'Content-Type: text/plain' \
--data-binary 'run'
curl -sS "http://{host}/api/graph/session/${SID}" # read the resulting model
Each run/result appears on the human's WebSocket console — pause there for confirmation before
continuing, so a mistake doesn't cascade.
See also
- MiniGraph command grammar +
minigraph-commands.json— the source of truth. - Playground & AI companion — the human-facing view of the same surface.
- Built-in skills reference — per-skill properties and examples.