Skip to content

Embedded Go

Use PgQueryNarrative inside your own Go service: construct a narrative.Client directly, or mount its HTTP endpoints on your own router. Configuration matches the standalone server; see Configuration.

The Go module path is intentionally unchanged: github.com/pgquerynarrative/pgquerynarrative, even though the GitHub organization is pgquery-narrative. Import paths below are correct as written.

Library usage

import (
    "github.com/pgquerynarrative/pgquerynarrative/pkg/narrative"
)

cfg := narrative.LoadConfig()
client, err := narrative.NewClient(ctx, cfg)
if err != nil { /* ... */ }
defer client.Close()

result, err := client.RunQuery(ctx, "SELECT ... FROM demo.sales", 100)
report, err := client.GenerateReport(ctx, sql)
schema, err := client.GetSchema(ctx)

Example: examples/library-usage/basic.go.

Beyond the four methods above, the client also exposes ListSavedQueries, GetSavedQuery, SaveQuery, DeleteSavedQuery, GenerateReportFromSaved, RunQueryWithOptions, health/readiness (Ready, HealthReport), and typed service accessors (QueriesService, ReportsService, SchemaService, SuggestionsService, ConnectionsService, DashboardsService, SchedulesService, InvestigationsService, WorkspaceService) for the rest of the API surface.

HTTP middleware (Chi, Gin, Echo)

Package: pkg/narrative/middleware.

Framework Mount call
Chi narrativemw.MountChi(r, client, "/api")
Chi (with auth) narrativemw.MountChiSecured(r, client, "/api", sec)
Gin narrativemw.MountGin(r, client, "/api")
Echo narrativemw.MountEcho(e, client, "/api")

For auth and rate-limit parity with the standalone server, build a narrativemw.SecurityConfig using narrativemw.NewAuthenticator(...) and narrativemw.NewSessionManager(...) (the underlying auth types live under internal/ and can't be constructed directly outside this module), plus client.AuditStore() and your own rate limiter, then use MountChiSecured (Chi) or wrap individual handlers with WrapSecured (Gin, Echo; there is no secured mount helper for those two). Leaving Authenticator nil disables authentication entirely, so don't skip it.

For multi-tenant deployments, an API key or OIDC principal with no explicit org_id needs organization membership resolution, and CLI/MCP-issued keys need durable storage; both live behind the same internal/ boundary, so build them with narrativemw.NewMembershipStore(pool, autoJoinDefault) and narrativemw.NewManagedKeyStore(pool), then attach with authenticator.SetMembershipStore(...) / .SetManagedKeyStore(...) before building SecurityConfig. OIDC-based auth itself still isn't exposed to embedders (see above).

Mounted routes (with prefix /api; use "" to mount at root):

Method Path Description
POST /api/query/run Body: {"sql":"...", "limit": N}. Run read-only SQL
POST /api/report/generate Body: {"sql":"..."}. Generate a workbench narrative report (LLM, with a deterministic fallback)
GET /api/schema Allowed schemas, tables, columns
GET /api/suggestions/queries Query: intent, limit. Suggested SQL

Auth applies by prefix, not by mount call

AuthMiddleware only requires authentication for paths starting with /api/. If you mount at a prefix other than /api or "", MountChiSecured will still serve those routes without requiring auth. Choose /api (or "" with your own /api-rooted router) if you use the secured mount.

See also

Configuration · REST API · Releases and versioning: what's stable here