Skip to content

Driving it from an agent

The SPA has no private channel: everything it shows rides plain JSON over HTTP, so an agent or a script can drive the same server headless. Start one and curl it:

Terminal window
npx @intentius/behold serve <chant-project-dir> # or preview / demo
curl -s http://localhost:4600/api | jq

GET /api is the front door. It lists the routes with a one-line description each, the server’s version, and a link to the full contract.

  1. observe. GET /api/graph returns { ir, svg, meta }. Every node in ir.nodes carries id, kind, lexicon, attrs, and sourceLoc. Drift status, when present, is attrs._status: good = managed, warn = foreign, accent = pending, neutral = unobserved, runtime = runtime child.
  2. focus. Narrow with query params: ?detail=0..3, ?components=1, ?logical=1, ?lens=blast:<id>&down=1, ?lens=lexicon:aws, plus the env / stack / tier / target axes the UI’s Scope tab exposes.
  3. go deeper. With an ?env=: /api/overlay is the live entity overlay, /api/diff slices per-node observed state / drift / field ownership, /api/reconcile summarizes the pending change set. /api/substrates reports substrate readiness, and /api/events (SSE) pushes changed / op / apply / pr so you re-pull only when something moved.
  4. inspect. A node’s sourceLoc.file is the typed source that declared it. To change the estate, edit there: chant is the source of truth, not behold. Provenance rides on the node too: attrs._release (the recorded deploy: run id, origin, commit, digest, actor, approver), attrs._carve (the Terraform address a carved entity came from), and on a Helm chart attrs._renderDrift.identity (whether the running release was deployed from this project’s render).

A directory that is not a chant project gets a structured {code: "no-project", error, remedy} from /api/graph. Every other precondition failure (lint, not-installed, tier, eval) takes the same shape, so an agent branches on code instead of parsing prose.

behold performs no cloud write of its own. The mutating endpoints trigger Ops the project committed: POST /api/apply?env=&component=, POST /api/ops/:name/run, POST /api/ops/:name/signal/:gate, POST /api/rollback?to=. All are guarded (one write at a time), gated where the Op declares a gate, and locked out entirely in preview and static modes. An environment .behold.json designates to a forge (executor) answers those with 409 executor-forge; its one deploy is POST /api/ci/dispatch?env=, through the operator’s gh, followed on the dial, with GET /api/ci/run the persisted record and POST /api/ci/readopt the re-follow after a restart. For build, lint, lifecycle diff and op status, prefer chant’s own MCP tools over shelling.

The canonical version of this guide ships inside the npm package and lives at AGENTS.md. Hand it to your agent verbatim.