Skip to main content
Two endpoints close the loop between an agent and a user with the app open: POST /view-command moves the canvas, and GET /view-state reads it back. Commands travel to the app over Realtime. Drive the view from the conversation, not only on explicit commands. When the user wants to look at, focus on, or compare something, answer and move their canvas: selectIteration to surface a phase, zoomToNode or selectNode to put a node in front of them, setViewMode to switch between tree and matrix.

Send a command

success: true means enqueued, not applied. A connected client applies it within about two seconds.

Command types

An unknown type returns 400 { "error": "Invalid command", "validTypes": [...] }.

Unresolved targets

The API checks the target before enqueueing. A phase, node or goal that does not exist in the project returns HTTP 200 with success: false and a _meta._tip explaining why, so a typo never becomes a silent no-op:
selectIteration requires a non-empty iterationName and focusGoals a non-empty goalIds; sending null is refused the same way.

View-aware targeting

  • selectNode and zoomToNode auto-switch to matrix when the target is a job or task, the only view that renders them. Pass "autoSwitch": false in the command to stay in the current view.
  • Goals, needs and approaches are not auto-moved. Which view and expansion shows one best is your call: compose setViewMode, selectIteration, focusGoals, expandNode yourself. The _tip tells you the target’s type.

Read the view state

Before any client has connected, the response is the defaults: view_mode: "tree", empty lists, last_applied_command: null, command_seq: 0, clients_connected: false.

Confirming a command landed

  1. POST /view-command returns a commandId.
  2. Re-read GET /view-state and check last_applied_command.id === commandId (it equals command_seq). The id advances on every applied command, including a no-op, so this works even when the view did not visibly change.
  3. clients_connected: false means no live client (no heartbeat in the last 30 seconds). The command is queued but cannot apply until one connects, and last_applied_command will not advance.
Read the state first (what is the user already looking at?), act, then confirm.