Skip to documentation

Conduit

Entity bindings & live data

A binding is the bridge between the layers: it declares that an entity (or every entity of a type) can be answered about with a specific domain component, and how the component's parameters get filled. Bindings make the graph live — and they make every live lookup explainable, because the binding is the human-authored reason a source was consulted.

Anatomy of a binding

Binding fields

entityId | entityTyperequiredstringExactly one of the two. entityId binds one specific entity; entityType (e.g. "Customer") binds every entity of that type at once.
queryIdrequiredstringThe domain component this binding resolves to.
labelrequiredstringHuman-readable purpose, e.g. "Live order backlog" — shown in the UI and to the model during discovery.
paramMapParamMapFor each query param, where its value comes from: entity_name, const, or model (see below).
enabledbooleanDisabled bindings are invisible to discovery.

Each entry in the param map is one of three sources:

  • { "source": "entity_name" }— the bound entity's display name. This is what makes type-level bindings powerful: one binding on the Customer type serves every customer entity, each substituting its own name.
  • { "source": "const", "value": … } — a fixed value baked in by the binding author (a window size, a status filter).
  • { "source": "model" }— supplied at call time by the calling model or API client, validated against the component's DataParamSpec before any SQL runs.
a type-level binding — every Customer entity becomes livejson
{
  "entityType": "Customer",
  "queryId": "01J… (customer-churn-risk)",
  "label": "Churn risk & account value",
  "paramMap": {
    "customer_name": { "source": "entity_name" }
  }
}

The kb_data agent tool

Agents and grounded chat consume bindings through kb_data, a read-only native tool with two operations:

  • discover — given an entity name (or nothing), returns the enabled bindings and domain components in scope: labels, component titles and descriptions, and the param specs still needing values. This is how the model learns what live questions this workspace can answer without ever seeing connection details.
  • lookup — executes a discovered binding or component with the remaining model-sourced params. Returns columns, rows (capped by the connector's maxRows, with a truncated flag), duration, and the dataCallId that anchors the citation.

Like every native tool, kb_data executes with injected workspace scope — the model never supplies workspaceId, and errors come back as structured { ok: false, error } data (a timeout or invalid-params is something the model can react to, not a crash). See Tools, MCP & HITL.

Read-only, no approval gate

kb_data is read-only by construction (single-statement SELECT/WITH, enforced twice), so it does not require HITL approval the way side-effecting MCP tools do. Governance lives in the layer itself: named queries, row/time caps, and an append-only provenance trail for every call — including failed ones.

Dual citations in answers

Answers that touch the data layer cite both layers. Document chunks register as [Sn] sources exactly as in grounded chat; each executed lookup registers a [Dn] citation backed by its persisted data_calls row — component slug, params used, row count, duration, status. In the UI a [Dn] chip expands to the call details; over the structured query API each dataCalls entry carries the connector, query title, row count, and timestamp, plus the dataCallId that anchors it to the persisted provenance row.

one answer, two provenance trailstext
Acme Corp is an enterprise account in EMEA worth $410k/yr with churn
risk "high" [D1]; the Q2 QBR notes flag renewal concerns over support
latency [S1] [S2].

[S1] meetings/acme-qbr-2026-q2.md · chunk 1
[S2] accounts/acme-corp.md · chunk 4
[D1] customer-churn-risk(customer_name="Acme Corp") on ops-postgres · 1 row · 38ms

The entity Live data panel

Every bound entity's detail page gains a Live data panel:

  • the bindings that apply to it — direct entityId bindings and inherited entityType bindings — each with its label and target component;
  • a run-now action that executes a binding and renders the rows inline (writing a provenance row like any other call);
  • recent data calls for the entity, so "what did we ask the ops database about this system, and when" has a first-class answer.

Binding management (create, edit, enable/disable) is owner/admin-gated, from the entity page and the Data page.

External consumers

Bindings power more than the UI: MCP clients get kb_data_discover / kb_data_lookup from the eli.ai MCP server, and third-party systems get dual-cited structured answers from POST /api/v1/query.