An agent inside the tenancy model,not beside it
The assistant is not a wrapper that reads your screen. It calls the same API you do, as a principal the database recognises, under the same row-level policies — so there is no question of what it can reach, and no second permission model to keep in step with the first.
Four properties, each of which is a design decision rather than a setting
It plans before it acts
propose_analysis_planAsked for something consequential, the agent proposes a plan and stops. You see the analysis it intends to run and the layers it intends to touch, and it waits. An agent that runs first and reports afterwards is one you have to supervise; one that proposes is one you can direct.
Every tool call is visible
live traceThe transcript shows each tool call with its arguments and its result as it happens — including the calls that returned an error. A tool that failed and was retried is part of the record, because a trace that only shows the successful path is a summary, not a trace.
It answers with the catalogue's own objects
dataset and quality cardsWhen the agent talks about a dataset it renders the dataset's card: the profile, the CRS reading, the findings. You are looking at the platform's own view of the record, not at the agent's paraphrase of it.
Its reach is a database fact
record-scoped principalThe agent signs in as a principal like any other. A query it should not be able to answer returns nothing, for the same reason it would for a person: the policy did not produce the rows. There is no agent-specific allowlist to get wrong.
An agent auditing the catalogue, mirrored live
An external agent is asked which datasets the platform will refuse to draw. It searches the catalogue, reads two profiles, and explains the difference between a dataset with no inferable CRS and one whose publisher simply declared the wrong code. Its conversation appears in the assistant panel as it works.
An outside agent's work, inside the app
An AI agent doing real work for your team usually does it somewhere your team cannot see: a terminal, an IDE, a CI job. What arrives is a screenshot in a chat channel — not reviewable, not searchable, not addressable. A mirror session makes that work a first-class conversation in DjiniousMap, rendered by the same transcript the app's own assistant uses.
- The external agent opens a session and pushes its transcript in; there is no LLM attached on this side
- It renders with the same blocks a native run produces — reasoning, tool calls with their arguments and results, the answer
- The panel badges it and withholds the composer, because a mirror session has no run to start
- It is a session like any other: tenant-scoped, in the append-only log, replayable, exportable
- Open a session
- POST /v1/ai/agents with kind: 'mirror'
- Push a batch
- POST /v1/ai/agents/:id/mirror — up to 256 events, 1 MB
- Event kinds
- The same closed set a native run appends, so an external agent cannot produce a turn the client has no case for
- Ordering
- The server allocates the sequence numbers, under a per-session lock, so a flush is never interleaved
- Driving it
- scripts/mirror-agent.ts reads NDJSON on stdin and batches it
An MCP server, with tokens scoped per agent
Agents outside the app — a coding assistant, a scheduled analyst, your own tooling — reach the platform through a Model Context Protocol server. Tokens are minted per agent and carry their own scopes, so granting one agent the ability to run an analysis does not grant it to every agent you have ever issued a token to.
- Per-token scopes, minted and revoked from the settings page
- The same tool surface the in-app assistant uses, including catalogue search and analysis
- Revoking one token leaves every other agent's session untouched


A conversational embed for people who will never open the app
A published map can be embedded with a chat panel beside it, scoped to that map's data by the share token. A reader asks a question in words and gets an answer drawn from the layers on the map — without an account, and without reach beyond what the token already made public.
The embed's reach is the share token's reach. It is a principal inside the tenancy model, not an exception carved out of it — so a question the token could not answer through the API cannot be answered by asking it in words instead.
Watch an agent work your catalogue
The most useful demo is the one where you ask the agent something we did not prepare for. Bring a question about your own data.