Workbench
ontologiq workbench # http://127.0.0.1:4400
ontologiq workbench --open # and open the browser
One command, one page, no extra dependencies: the workbench is served by
the CLI itself, from the compiled ontology and your adapter connection.
It is the operational counterpart of ontologiq docs: where the
docs page describes the ontology for a reviewer, the workbench shows it
running — definitions next to live warehouse records, preconditions
evaluated on demand, proposals as they arrive.
Live on both axes. Records are queried from the warehouse on every
request, and the ontology itself follows the YAML while the workbench
runs: add an object, save, and the graph has it within seconds — its
records too, because reads are built from the compiled SELECT rather than
the materialized view, so run can come later. An edit that does not
validate never takes the page down: the last good ontology keeps serving
and the validation error appears as a banner until you fix it.
What you see
Overview. The entity graph — same deterministic layout as the docs page — with governed objects outlined. Click a node to browse it.
Objects. For each object: its properties, its states with the predicate that computes each one in priority order, its relations, its generated SQL — and beneath the definition, the live records, with computed state as a chip on every row and one-click filters per state. Click a row to open the record: every field, its relations one hop away, and the actions that apply to it.
Actions. Every governed action with its roles, precondition, approval rule and effect. Open one and you get a console: fill the identity and the parameters, pick a role to evaluate as, and dry run it. The same code path an agent’s dry run takes checks the role and evaluates the precondition against live data, then reports what would happen — record snapshot, whether approval would be required, what the effect would be. Nothing is proposed and nothing executes.
Proposals. The approval queue, live. Each pending proposal shows what was proposed, by which role, with which parameters, and when it expires — and next to it, the exact terminal command that decides it, ready to copy. Decided proposals stay visible as history with their outcomes.
Audit. The append-only trail: every denial, proposal, approval, precondition re-check and effect outcome, in order.
What you cannot do, and why
The workbench holds no write path. There is no propose button, no approve button, no route that fires an effect — the only POST it answers is the dry run, which changes nothing. This is not a missing feature; it is the security model applied to a new surface.
The product’s central guarantee is that an agent cannot complete a gated
action on its own, because approval lives in a process the model has no
way to address. An HTTP server on localhost is addressable — and an
agent already knows its proposal_id, because the propose response
returns it. If the workbench had an approve endpoint, one POST would
close the loop with no human anywhere. So it does not have one, and a
test pins that: every mutating route answers 405 with the reason.
Three more structural choices, each also pinned by a test:
- The socket binds
127.0.0.1, and there is no flag to widen it. Serving the workbench across a network is a different security posture — it needs authentication, which is the OIDC milestone on the roadmap, not a--hostflag. - A request whose
Hostheader is not local is refused. A malicious page on a domain that DNS-rebinds to127.0.0.1would otherwise be same-origin with the records API. - Records pass through the same query builders as the MCP tools:
properties marked
sensitiveare never selected, so their values never reach the browser — the workbench sees exactly what an agent would see.
The loop it enables
The workbench makes the decision informed; the terminal makes the decision:
- An agent (or a colleague with
ontologiq propose) proposes an action. The badge in the workbench ticks up. - You open the proposal: identity, parameters, proposer, expiry. You browse the record it targets and see its current state.
- You dry-run the action if you want the precondition checked this second, against live data.
- You copy the
ontologiq approvals approve …command the page offers, and run it in your terminal. The precondition is evaluated once more at execution — if the record moved while you deliberated, nothing executes.
When HTTP transport with OIDC lands, the identity of the person clicking becomes a verifiable fact rather than an assertion, and approval can move into the page. Until then the split stays physical — and the workbench is honest about it in its own header.