Railbase
GPTClaude

AI in Railbase

What the built-in AI engine is, where it runs, and the rules it follows.

Updated

Railbase has an AI Engine built into the core binary. It is not a plugin, not a separate service, and not a paid add-on: there is no AI licence, no token quota, and no AI line on your bill. What Railbase does not ship is a model — you bring the compute. Until you connect one, the AI features simply aren't there, and nothing else about your instance changes.

The engine is the part in between: it decides which model a call goes to, enforces your egress rules, redacts before anything leaves the process, and writes a redacted audit row for every generation. Plugins reach it through one platform binding ($app.ai) and never talk to a model themselves.

Bring your own model

You connect a model in the admin console under Settings → AI, on the LLM tab. There are exactly three kinds of provider.

Kind What it is Where the work happens
external.cloud A cloud provider reached with your own API key (BYOK) The provider's servers
local.endpoint An OpenAI-compatible server you already run Your machine (or LAN)
local.native A model file Railbase loads inside its own process Your machine

external.cloud — today the external provider is Anthropic; the field is fixed, and you supply your own API key plus an optional model name (left empty, claude-sonnet-5 is used). You pay the provider directly — Railbase never meters or bills the tokens.

local.endpoint — any server that speaks the OpenAI chat shape at /v1/chat/completions. You give it a base URL and (optionally) a model name; loopback and LAN addresses are allowed here, unlike the outbound client used for cloud providers. Railbase also probes the well-known local ports and shows what's live under Detected local endpoints, with a one-click Connect — Ollama on 11434, LM Studio on 1234, and on macOS an Apple Foundation Models bridge on 11435 that exposes the Mac's built-in on-device model through the same OpenAI-compatible shape. Nothing is auto-connected; detection only lists candidates.

local.native — Railbase itself is the runtime. The Local models panel installs two artifacts: a native inference library for your platform, and the weights. Each is streamed straight to disk and rejected unless its SHA-256 matches, and the model is loaded on first use inside the Railbase process, so no network is involved at inference time. The This host panel reads your actual CPUs, RAM, free disk and GPU and reports the largest model tier this machine can run. With nothing installed, local.native reports itself unavailable rather than failing calls hard — as it does on any platform other than macOS, the one its in-process runtime is verified on today.

Note

Not every backend can do everything. A chat model can generate; embeddings are a separate capability, and Railbase routes per capability instead of pretending one model does it all. Anthropic and Apple Foundation Models have no embeddings endpoint, and the current local.native slice ships no embedding weights — so $app.ai.embed reports no-embedding-backend on those. Document search and the assistants keep working regardless: with no embeddings backend the engine falls back to a built-in lexical index.

How keys are stored

Provider credentials live in a core-owned collection (_ai_providers) that only the engine reads. A plugin cannot reach them through its own secrets binding, and the key is never sent back to any client: the admin screens show only whether a key is set plus a last-four hint. There is no reveal and no in-place key edit: the connect form always adds an entry, so replacing a key means deleting the old one and connecting again. Each provider has a Test button that runs one real, minimal call so you can prove the key works before relying on it.

Everything is tenant-scoped

Providers, policies, the AI's own account, audit rows, usage counters and assistant conversations are all scoped to a tenant. An admin session has no tenant, so what an operator configures in Settings → AI is the site-level default; a tenant that has configured nothing of its own inherits it. A tenant that configures its own provider uses that instead.

The AI acts as itself, never as you

The AI does not borrow a user's identity. Each tenant gets exactly one AI agent account (_ai_agents), created lazily the first time that agent is used, and it is a first-class principal like a user or an admin. When the agent runs a declared plugin action, the call goes through the real request pipeline — same authentication, same licence check, same RBAC, same audit — under that principal. Consequences worth knowing:

  • It has no permissions by default. On the Agents tab you grant the agent roles, exactly as you would a person. A permission-gated action is refused until a granted role carries that permission.
  • Every AI action is attributable. Audit rows carry the actor type ai and the agent's id, so an AI-made change is never indistinguishable from a human-made one.
  • You can pause it. Disabling the agent stops all agent actions while keeping the account and its role grants intact.

What leaves your server, and when

Local backends never cross a trust boundary: a loopback endpoint or an in-process model receives exactly the text your plugin wrote. For an external.cloud provider, the engine applies a fail-closed gate before the call:

  • External model egress is a master switch on the Policies tab. Turn it off and no external call happens, even with a provider configured.
  • Sensitivity ceiling caps the data class allowed out — the default is normal. restricted never leaves, and anything unclassified is blocked rather than assumed safe.
  • Provider governance blocks a whole provider by name for a scope without deleting its configuration.
  • Autonomy overrides are tighten-only: you can demote a declared action toward confirmation, never lift a gate away.
  • A secret floor scrubs the prompt and system text on the way out: bearer tokens, vendor API-key shapes, JWTs, passwords inside URLs, and any key: value fragment whose key counts as a credential.

A plugin also declares its own AI needs in its bundle manifest. If it declares external_allowed: false, its calls are routed to local backends only — and on an external-only instance they are denied outright rather than quietly sent out.

Where you'll actually see it

The floating assistant — the round button in the bottom-right corner of every admin page — answers questions about Railbase and your installed plugins from indexed docs with citations (and says so when nothing matches rather than guessing). The product documentation embedded in the core is indexed for it automatically on first start, so it answers out of the box.

The admin AI consoleSettings → AI — is the operator surface: LLM, Policies, Usage (token counters, for observability — not billing), Tasks for async jobs, Agents, Docs, Memory, Peers, Delegations, Deliberations, Approvals for steps that paused for a human, and Audit with an XLSX export.

The site assistant — signed-in users get Assistant in the site navigation. It answers from the site-audience documentation of your installed apps, scoped to their tenant, with sources listed. Conversations belong to the individual user; another user's thread is simply not found.

Plugin capabilities — plugins call $app.ai for generation, structured JSON output, embeddings, document search and declared actions. Whatever provider you connected is what they use, under the policies you set. Nothing about a plugin's price or licence changes because it uses AI.

If you configure nothing

This is the default state, and it is a supported one. With no provider configured, every AI call returns no-provider-configured, the admin console shows the engine as unconfigured, and the site assistant answers with a plain "service unavailable". Records, plugins, jobs, auth and the rest of Railbase behave exactly as they always did. Connecting a provider is the opt-in; disconnecting it puts you back here.

Was this page helpful?Thanks for your feedback!