What the platform is, and what it needs from your environment.
What the platform is
Brain-Stem is a set of services that share one database. The database stores the operational data, and it also stores the configuration, the workflow definitions, the decision rules and the audit history.
You can change much of the platform's behaviour by editing that data, without deploying a release. New capability still requires a release, and an edited rule takes effect after the running service reloads its cache.
Five consumers (Web and API, Agent tool surface,
Model dispatch, Background work and Logs and traces)
each read their configuration from, and write their audit record to, one store.
One control planemanaged tables · callable SQL functions · one schema
Most of it is data, not code. Changing it is usually a write, though new capability still
takes a release. The store holds:
Workflow definitions: steps, edges, dependencies
Decision rules and thresholds: matched by shape, bands per ontology
Service and model routing: a healthy instance, by capability and cost
Secrets: provider keys encrypted at rest
A history table: beside every managed table; soft delete only, and every change keeps its author, its timestamp and its prior value
Services read their configuration from, and write their audit record to, one control plane
Every managed table follows the same pattern:
Ownership. Each row records the company that owns it.
Audit fields. Each row records who created it and who last changed it.
History. Each table has a history table that stores every version of every row.
Soft deletes. Deleting a row marks it as deleted. The row stays in the table.
How work arrives
Work reaches the platform in three ways. All three are handled by the same implementation; there is no second or third implementation behind them.
1 · External signals and systemsREST APIs · the event API · runtime schema discovery · device telemetry over MQTT · documents and codebases, ingested
The human gate (quality, risk, governance) covers these two lanes only. A person decides before work proceeds, where the gate says so.
2 · Agent conversationsany MCP client connecting to your deployment's brain-stem-mcp
3 · User interfacesweb frontends and dashboards, served by the platform over the event API
All three are handled by one platform, one implementation: events, workflows, the
decision loop: deterministic first, probabilistic second, human last, recorded either way.
Out: model providers, or in-network, on by default · signed webhooks to URLs you
own · push notifications (FCM) · cloud APIs, only if configured.
Alerts and logs are outputs of the platform, not inputs, so they are not counted as a way in.
Three input channels converging on one platform, with the human gate across the two human-facing lanes
Events. External systems and signals arrive as events.
Agents. Your own agents connect through a Model Context Protocol (MCP) server. The server exposes the platform's capabilities to them as tools.
People. They work through the user interfaces.
Work from the two human-facing channels passes through a gate. The gate checks quality, risk and governance before the work proceeds.
How a decision gets made
Deterministic first, probabilistic second, human last.
1Deterministic firstAn event arrives. Known shape, matching rule? Shapes and rules are matched by hash.yes → apply the workflow, no model callno → step 2
2Probabilistic secondModel reasoning, constrained by your policy, then a quality gate.approve → proceedreview → try againreject → step 3
3Human lastThe human queue: an operator decides.
Promote to a learned rule, approved by a second person. That is how the system
learns, and what gives step one more to match on next time.
This is the order the code actually runs in, not a statement of philosophy. Rules are evaluated
first; where a model runs, a rule decided to call it and a rule bounds it.
Deterministic first, probabilistic second, human last, with promoted rules looping back to the top
Patterns first. When work matches a known pattern, the platform applies the matching workflow.
Rules second. When no pattern matches, the platform evaluates its rules. Probes are dispatched by rules.
Models third. When the rules cannot decide either, a model reasons about the work within the policy it has been given.
People last. Work that clears its threshold proceeds. Work in the review band is retried or handed to a person. Work that matches nothing waits for a person.
When a person resolves a case that the platform could not, that resolution can be promoted into a learned rule. The next time the same situation occurs, the platform handles it deterministically. Promoting a rule requires a second approver.
What it records
One traced request. A request arrives and a trace_id is minted;
every log line and every error carries it from that point on. Along the way a step runs, a model is
called where a rule dispatches one, a person decides only if the gate sends it there, and rows are
written to managed tables.
What it leaves behind, all reachable from that one identifier:
Log lines, by trace: trace_id plus span_id on every line, shipped into the database.
Step snapshot: workflow_step_executions, with the output written to workflow state.
Prompt and response: persisted per trace and span as artefacts, with the cost in llm_usage_stats.
Decision event: decision_events, kind hitl_resolved, so the person's decision is recorded inside the trail, not beside it.
History rows: a platform_history row per change, carrying the author, the timestamp and the prior value. Soft delete only.
So "what happened, and why" is a query against one identifier, not a reconstruction.
What one traced request leaves behind, and how you ask for it
Each request produces a connected record:
Log lines that carry the request's trace id.
A snapshot at each step.
The prompt and the response for every model call.
A decision event at every point where a person was asked.
A history row for every write the request made.
The same identifier runs through all of them. When you need to know what happened and why, you query the record instead of reconstructing it.
Where model calls go
1A model call is madeChat, embedding or rerank, from any service, through brain-stem-llm.
2The registry resolves itservice_models × service_instances: a healthy instance for the capability, chosen by cost.
3Self-hosted, firstvLLM, in your network: no credential, and no prompt egress.healthy → response to the callernone healthy → step 4
4A cloud provider, only if none is healthyActive by flag, with the key resolved by name from secrets and decrypted at the point of use, so swapping a provider key is one row.
A failing instance is paused by setting available_after per
capability. The window expires by itself and the instance returns to rotation, with no operator
action.
Every call is recorded: llm_usage_stats carries the provider, the model, the cost and the trace_id.
Production without a GPU runs cloud-only, through this same path. Nothing about the route changes; only which step succeeds.
The mix is a routing decision you own: which models are self-hosted and which providers are active are rows in the registry, and the spend is queryable per call.
One model call resolved by the registry, preferring self-hosted, failing over, and recorded
The platform stores the destination of each model call in its registry. For each call, it selects a model by capability and cost:
Self-hosted first. The platform prefers a self-hosted model where one is available.
Failover. If a provider is unhealthy, the platform sends the call to another provider.
Recovery. A failing instance is paused until it recovers.
The platform looks up provider keys by name when it makes the call. It records every call together with its cost.
Because the destination is a database row, you can change it. Point it at a model you run yourself when your prompts must not leave your network.
What stays in your environment
The platform stores everything in the database, on the host you choose: the control plane, your own content, and the logs. Data at rest stays on that host, and document conversion runs there too.
There is no telemetry, analytics, crash reporting or phone-home of any kind. The services do not report usage or errors to any vendor, and they do not call home to us.
Inside the customer's network.nginx terminates TLS and routes
requests, in front of:
Platform API: REST and events
Agent tool surface: the MCP server
Web and account API: REST
Model gateway: routes every model call
Background workers: no listening port
Log shipper: logs into the database
One database: control plane, data, logs and history in one instance; vector search required
An optional in-network model host: which removes prompt egress entirely. A GPU is a choice, not a requirement.
On the host: document conversion, and a secrets master key supplied from the environment.
Reached by default: your chosen LLM provider (prompt content leaves, unless the
in-network option is taken, and the destination is a registry row, so it is substitutable).
Off unless explicitly configured: other model providers (Groq, Together AI,
DeepSeek, OpenRouter, Anthropic, OpenAI, Google) · Google Sheets, Drive, FCM push and Gemini · AWS
S3 and Secrets Manager · data sources and brokers (OpenStreetMap, Crawl4AI, an MQTT broker,
external MCP servers) · signed callbacks to webhook URLs you register (HMAC-SHA256).
No telemetry, analytics, crash reporting or phone-home of any kind. Nothing else crosses
the line.
Services bind all interfaces, so inside your network they are reachable from the LAN unless you
firewall them. Some outbound paths leave via spawned CLI subprocesses, not HTTP, so enforce the
egress allow-list at the host or network layer, not in a proxy.
What runs inside the customer's network, and what crosses the boundary
In the default configuration, one kind of data leaves your network: prompts, and the context sent with them, go to the registered model provider.
To keep prompts inside your network, point the registry at a model you host yourself.
Every other outbound path is off until you configure it. Each path needs a configuration row and a credential before it does anything: spreadsheet and drive integrations, push notifications, object storage, map tiles, a message broker, external MCP servers, and any webhook URL you register. If you configure none of them, nothing else leaves.
Enforce the egress allow-list at the host or network layer. A proxy configuration is not enough, because some paths leave through spawned command-line subprocesses and never appear in an HTTP-level audit.
Running it in your own environment
Local and sovereign deployment is available where you require it, and how it is delivered is scoped per engagement.
That commits us to everything above: your data stays in your database, document conversion runs on your host, the model path can be made fully in-network, and nothing phones home. What gets scoped with you is the delivery, against your environment.
Check the rest of it in a working session
Book a briefing to walk through your environment, or take the assessment to see where you stand first.