Open query space
Open query is the power surface for agents that can write SQL. It sits beside the four assured operations — not under them.
Parent: Retrieval. Wire paths: API reference.
Three neutral choices
| Surface | Best for | Freshness model |
|---|---|---|
| SQL | Live joins, evidence composition, filters, graph helpers | Live spine views + nomination/traversal SRFs |
| Typed graph methods | Neighborhoods and bounded shortest paths | Same PostgreSQL repeatable-read snapshot |
| Assured ops | One-call typed envelopes for common intents | Envelope freshness block |
Discovery endpoint GET /query/space returns the bound two-layer headline, honesty warnings, worked examples, views, function signatures, SQL grammar, and tier limits.
HTTP entry points
| Method | Path | Contract |
|---|---|---|
POST | /query/sql | One sandboxed statement → QueryResult/v1 |
POST | /query/sql/explain | Plan without execution |
GET | /query/space | Full schema discovery payload |
GET | /query/space/search | Search checked-in manifest text |
GET | /query/saved | Saved-query registry metadata |
GET | /query/saved/{namespace}/{name} | One immutable version |
POST | /query/saved/{namespace}/{name}/run | Execute active saved SQL |
CLI and MCP expose the same operations; they do not invent a second dialect.
The two-layer rule (read this before writing SQL)
| Layer | Views (examples) | Meaning |
|---|---|---|
| Facts | facts_current, fact validity columns | What the system currently holds true |
| Claims / evidence | claims_live, fact_claim_evidence_live | Testimony and the bridge |
WRONG — using claim windows as current truth:
SELECT claim_id, claim_text, claim_valid_from, claim_valid_until
FROM claims_live
WHERE claim_valid_from <= $1::timestamptz
AND (claim_valid_until IS NULL
OR claim_valid_until >= $1::timestamptz);Claim validity is source-asserted testimony, not system belief.
RIGHT — start from adjudicated current facts, join testimony:
SELECT f.*, e.claim_id, e.stance, e.source_handle
FROM facts_current AS f
JOIN fact_claim_evidence_live AS e
USING (deployment_id, fact_kind, fact_id)
ORDER BY f.fact_kind, f.fact_id, e.stance, e.claim_id;Bound example patterns
Predicate vocabulary discovery
SELECT predicate, count(*) FROM facts_current GROUP BY 1 ORDER BY 2 DESC;Full audit trail
SELECT f.fact_kind, f.fact_id, f.predicate,
e.stance, e.source_handle,
c.claim_id, c.claim_text, c.asserted_at,
d.doc_id
FROM facts_current AS f
JOIN fact_claim_evidence_live AS e
USING (deployment_id, fact_kind, fact_id)
JOIN claims_live AS c
USING (deployment_id, claim_id)
JOIN documents_live AS d
ON d.deployment_id = c.deployment_id AND d.doc_id = c.doc_id
ORDER BY f.fact_id, e.stance;(Exact view/column names follow the deployment’s memory_v1 manifest — always re-check /query/space.)
Live graph traversal
Use memory_v1.graph_neighborhood, memory_v1.graph_path, or
memory_v1.graph_citation_path. Fixed shallow typed operations use SQL/PGQ;
the helpers provide bounded recursive traversal for deeper or shortest-tier
work. Returned identifiers are hydrated from evidence-rich authority views in
the same transaction, so there is no snapshot-confirmation phase.
The SQL sandbox hides each helper's internal terminal row after validating it.
Read aggregate truncation from QueryResult.truncated and
truncation_reason; read each helper's counters and effective budgets from
QueryResult.graph_invocations. Data rows may also project examined_edges
and returned_paths when those counters are useful in relational composition.
Semantic and lexical nomination in SQL
Allowlisted set-returning functions expose PostgreSQL-native P1 search so agents can:
- nominate claim/chunk ids by semantic similarity
- nominate by BM25/FTS
- join ranked candidates to live authority views in the same database snapshot
These are nomination helpers. Confirm against live facts/claims views before acting.
Saved queries
- Versioned registry rows under namespaces (e.g.
examples.*). - Seventeen former operation patterns live here as examples — not top-level tools.
- Running a saved query executes its immutable SQL at the active version.
List: GET /query/saved. Run: POST /query/saved/{namespace}/{name}/run.
Safety model
| Control | Behavior |
|---|---|
| Sandbox | Single statement; no arbitrary multi-statement scripts |
| Allowlist | Only published views/SRFs/helpers |
| Live graph helpers | Read-only, deployment-first, hard-clamped traversal |
| Limits | Tier caps on rows/time; disclosed as boundaries |
| Auth | Deployment perimeter on all endpoints when configured |
Writes never go through open query. The sole ordinary client write is ingest into E0.
When to prefer assured ops instead
Use fact_context / testimony_context / resolve_entity when you want:
- grain-typed envelopes
- automatic contradiction packaging
- standardized hydration depth
- less SQL surface area for a common intent
Use open query when you need joins, custom filters, graph patterns, or analytics the assured ops do not freeze.
Agent checklist
- Call
/query/spaceonce per deployment session (or when skill says manifest changed). - Decide fact vs evidence before writing filters.
- Prefer
facts_currentfor present tense. - Join
fact_claim_evidence_livefor why. - Inspect
QueryResult.graph_invocationsand aggregate truncation bounds. - Respect limit/boundary errors — re-plan, do not loop blindly.
Related
- Envelope for assured-op honesty
- Primitives for engine building blocks
- Mounts for filesystem-first orientation