BBramaDocs

Brama onboarding: reaching first success

First success

Brama's first success is a real routed model response: one alias, its one route, and an answer the caller can read. This page walks the three paths that lead there and states the interfaces automation may depend on.

Safe local first success

Starting state

Use a clean shell. No Brama, Skarbiec, provider, or agent environment variables are required. The command below performs local hardware inspection only.

Run detection

git clone https://github.com/wisent-ai/brama.git brama
cd brama
cargo run --locked -- detect

Observe the result

Expected output has host-specific values and these stable labels:

GPU Type: ...
GPU Name: ...
VRAM: ... GB
RAM: ... GB
CPU Cores: ...
CUDA: ...
Metal: ...

The successful result is the detected resource report, not merely exit code zero.

Confirm the safe boundary

This path does not:

  • start the HTTP service;
  • read or create a Brama state directory;
  • redeem a capability;
  • list subscriptions;
  • contact a model or catalog provider;
  • incur model cost.

Stop and clean up

No background process is started. Remove the checkout to remove source and the target/ build cache. No product state or provider resource requires cleanup.

The canonical task is examples/getting-started/detect-local-resources.md.

Zero-state behavior

Running brama without a subcommand prints the product purpose, command list, and help supplied by Clap. It must not create state or contact external systems.

brama serve refuses to start when required generated configuration is absent. The first error names the missing configuration category; the operator then uses the packaged launcher rather than hand-authoring capability maps. A bare service startup is not the safe first-user path.

With an empty route registry document, no alias is declared, so every completion naming one is answered 404 with state and route in its details. Declare an alias with PUT /v1/admin/routes, whose body is exactly {"alias","primary"} and whose answer is {"ok":true,"routes":<document>}.

Authenticated loopback path

Provision this installation once, before its first start:

bin/provision-skarbiec-trust

That writes the signed policy, the workload registry, the trust root, the receipt command and the workload proof key into etc/brama-skarbiec. The release archive ships none of them, because the registry pins the absolute path and SHA-256 of the binary allowed to redeem a capability and a build machine cannot know either. Re-running it replaces this installation's identity, so it refuses without --force.

Use the packaged start-with-skarbiec launcher. It owns these steps:

  1. load the selected service environment file without overriding individual central policy values;
  2. materialize the authorized encrypted vault;
  3. import the scoped Brama recipient key into an owner-only runtime directory;
  4. verify this installation's Skarbiec trust, policy, and workload files are present, and refuse to start when any of them is missing;
  5. read each accepted client bearer from its dedicated item;
  6. load central Echo, legacy Content Platform, Oko, and Weles request-sign identities;
  7. derive provider and agent capability maps from live vault resources;
  8. start the owner-bound capability socket;
  9. exec brama serve --port <port>.

Confirm the aliases

Before spending quota, read what the gateway can serve:

brama aliases
curl -sS -H "Authorization: Bearer $BRAMA_TOKEN" http://127.0.0.1:8080/v1/aliases

brama aliases prints alias, state and route. Each GET /v1/aliases row carries alias, state, route, reason, required and authorized. One alias has one route, so one row describes the whole resolution: if that route cannot serve, the alias cannot serve, and the completion is answered 503 alias_unserviceable with details.state and details.route. Expect every alias you intend to call to read serving first.

The first call

Use loopback HTTP only from an authenticated local caller. A generic bearer-only GET /v1/models is the first non-billable machine workflow. Do not use /v1/chat/completions, /v1/messages, or /v1/responses until the intended provider, account, and cost are explicit: the three formats are one workflow and every one of them spends real quota, whether it answers in one piece or as a stream. Brama does not stop that attempt because of elapsed time. Completion, cancellation and failures follow the core request contract.

A routed answer from a serving alias is first success. A refusal from the route is the caller's result, and the repair belongs to the named dependency: see failures and reset.

Production path

Production uses the exact runtime published by the release workflow. The operator downloads the platform archive and checksum from GitHub Releases, verifies the digest, extracts it under an immutable versioned directory, and configures:

  • the host service account, immutable installation root, and service manager;
  • the local Brama control document containing client allowlists and aliases;
  • verifier-only consumers for dedicated client token items;
  • request-sign consumers for the exact central identities;
  • Brama's provider capability grants;
  • the trusted TLS terminator IP list;
  • journal backup and rollback retention.

Ingress, DNS, host registration, vault authorization, and consumer grants remain operator-owned prerequisites. The repository does not create them; the operator does, explicitly.

Where a host still runs an older registry file, run brama routes migrate as the registry owner before the first start; it commits the known-fields-only document with the same atomic replacement every other registry write uses and prints what it committed.

Machine onboarding contract

Automation must use stable machine interfaces:

  • brama version emits one JSON object with product/build identity;
  • GET /health emits one secret-free JSON object;
  • GET /v1/aliases emits one row per alias with its single route and state;
  • PUT /v1/admin/routes takes exactly {"alias","primary"} and DELETE /v1/admin/routes takes {"alias"}; both answer {"ok":true,"routes":<document>}, so a writer can assert the committed document without a second read;
  • protected HTTP endpoints use stable status and error codes from CORE.md;
  • non-health HTTP uses exactly one bearer authorization value;
  • agent-scoped operations additionally sign timestamp, agent ID, and exact body;
  • configuration is noninteractive and is rejected before serving on invalid input.

An unknown field in an admin route body is refused with the deserializer's own sentence, so automation gets a specific message rather than a guess. Automation must not parse decorative human log output.