You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(agentic-server): make canonical package the OpenAI-compatible gateway
Consolidate the two divergent agentic-server implementations into one
source of truth. The published agentic-server becomes the stateless
OpenAI-compatible gateway (ported from constructive-db) with backend-
agnostic metering via an injected InferenceSink — it no longer imports
any concrete telemetry/billing backend.
The legacy stateful threads router (createAgenticRouter, express-context
auth) is relocated into graphql/server as server-internal code so the
deployed /v1/threads and /v1/embed surface is preserved unchanged.
- agentic-server: gateway router/providers/transforms/server + types;
exports createAgenticServer, createRouter, InferenceSink/InferenceEntry
- graphql/server: local src/agentic threads router; server mounts it
- deps: drop agentic-server dep from graphql/server, add the threads
router's deps (@agentic-kit/ollama, llm-env); gateway keeps only logger
Standalone Express LLM service — agent threads, chat streaming, billing metering, and inference logging via `@constructive-io/express-context`.
15
+
Standalone, OpenAI-compatible LLM gateway — a stateless multi-provider proxy with pluggable inference metering.
16
16
17
17
## Overview
18
18
19
-
`agentic-server` is the Express-only equivalent of what `graphile-llm` does inside PostGraphile. It provides the same capabilities (agent threads, chat, embeddings, billing, inference logging) but as a standalone Express router that uses `@constructive-io/express-context` for tenant-scoped database access.
19
+
`agentic-server` is a small Express app that accepts OpenAI-compatible requests, routes them to a configured LLM provider (OpenAI, Anthropic, or Ollama), normalizes the response back to the OpenAI shape, and records usage through an injected sink. It is **backend-agnostic**: the gateway never imports a concrete telemetry/billing implementation — callers inject an `InferenceSink`, so the same gateway can meter to `compute_log`, a billing service, or nothing at all.
-**RLS enforcement**: All database operations run within tenant-scoped RLS transactions
43
+
| POST |`/v1/chat/completions`| OpenAI-compatible chat completion (multi-provider) |
44
+
| POST |`/v1/embeddings`| OpenAI-compatible embeddings (multi-provider) |
45
+
| POST |`/v1/usage`| Submit an external usage report to the metering sink |
46
+
| GET |`/v1/providers`| List configured providers |
47
+
| GET |`/healthz`| Health check |
48
+
49
+
## Identity & tenancy
50
+
51
+
Requests carry tenant identity via headers: `X-Database-Id` (**required** — requests without it are rejected `400`), `X-Entity-Id`, and `X-Actor-Id`. Routing to a specific provider can be forced with `X-LLM-Provider`.
52
+
53
+
`isPublic` controls trust: when `false` (default) the server sits on a private network and trusts these headers directly; when `true` the identity headers are stripped from incoming requests (external clients cannot set tenant context), so such requests fail loud rather than being mis-attributed.
54
+
55
+
## Metering
56
+
57
+
Metering is injected, not built in:
58
+
59
+
```typescript
60
+
interfaceInferenceSink {
61
+
logInference(entry:InferenceEntry):void; // fire-and-forget; must not throw
62
+
}
63
+
```
64
+
65
+
The gateway calls `logInference` after each chat/embedding (and for `/v1/usage` reports). Consumers own the concrete implementation — e.g. `constructive-db` injects a `compute_log`-backed sink built on its `ModuleLoader`.
71
66
72
67
## Architecture
73
68
74
69
```
75
-
Cloud Function → POST /v1/threads/:id/messages → agentic-server
76
-
│
77
-
┌───────────────────┼───────────────────┐
78
-
│ │ │
79
-
express-context OllamaAdapter Billing
80
-
(tenant DB context) (LLM provider) (quota + usage)
70
+
Client → POST /v1/chat/completions → agentic-server
The cloud function doesn't need to know about databases, billing, or LLM providers. It just POSTs `{ messages, model }` and gets back a streamed response.
0 commit comments