Skip to main content
Laminar is an open-source, OpenTelemetry-native observability platform for AI agents. An LLM profile bundles a provider, the credentials for it, and the list of models you want to use into one workspace-level entry. Profiles are what the playground runs on, and on self-hosted deployments they are what Signals run on. Add a profile for a first-party provider (OpenAI, Anthropic, Google Gemini, Groq, Mistral, AWS Bedrock, Azure AI Foundry) or point one at any OpenAI-compatible gateway, including a model you host yourself.
LLM profiles settings page listing an OpenAI, Anthropic, and custom gateway profile with their models

Workspace settings: three LLM profiles, each with the models it exposes

Profiles are workspace-scoped: create one once and every project in the workspace can use it. Any workspace member can add, edit, and delete profiles.

Create a profile

1

Open LLM profiles

Go to Settings > LLM profiles, under Workspace settings, and click Profile.
2

Name it and pick a provider

The name is how the profile appears in the playground and Signal pickers, and it must be unique in the workspace. Pick the provider, then fill in the fields it asks for. See Providers below for what each one needs.
New LLM profile side sheet with name, provider, API key, and model list fields

The profile form: provider credentials on top, the model list below, Test connection on the left

3

List the models

Add every model you want this profile to offer, written exactly as the provider expects it (gpt-5-mini, claude-sonnet-4-5-20250929, anthropic.claude-sonnet-4-5-20250929-v1:0). Laminar does not fetch a model catalog: the list you type is the list the playground and Signal pickers show. One model minimum, 64 maximum per profile.
4

Test the connection

Test connection sends one small request per listed model with the credentials in the form, and reports the round trip per model. A model that the provider rejects (wrong name, no access, bad key) shows the provider’s own error, so you can fix it before saving.
5

Save

Click Create. The profile is immediately selectable in every project in the workspace.

Providers

One profile is one provider and one set of credentials. For OpenAI and Azure AI Foundry, also pick the API shape, which is the endpoint your deployments speak. A few notes on the less obvious ones:
  • API shape is not the same as the model. One Azure AI Foundry resource can serve all three shapes; pick the one the deployment you are calling speaks. Switching shape within a provider keeps the stored credentials, since the key is the same.
  • Bedrock takes long-form model ids, including the inference-profile prefix when you use one (us.anthropic.claude-sonnet-4-5-20250929-v1:0).
  • Custom speaks OpenAI Chat Completions only. Give it the API root; Laminar appends /chat/completions. Header names are stored with the profile, header values are stored as secrets. This is the option for vLLM, Ollama behind a proxy, LiteLLM, OpenRouter, an internal gateway, or any other OpenAI-compatible endpoint.

How credentials are stored

Every secret in a profile (API keys, AWS secret access keys, bearer tokens, custom header values) is encrypted at rest and write-only. Reads return a masked hint instead of the value: sk-***********kEA, or fully starred for a short value, plus the names of any custom headers. That is enough to tell which key a profile holds, and never enough to reuse it. Because secrets are write-only, editing a profile does not require retyping them. Leave a secret field blank and the stored value is kept; type a new value to rotate it. The same rule applies over the API: an omitted secret keeps what is stored.
On self-hosted deployments, profile secrets are encrypted with your own AEAD_SECRET_KEY, the same key that encrypts project API keys. See Self-hosting configuration.

Run the playground on a profile

The playground’s model picker is built from the workspace’s profiles: one submenu per profile, listing that profile’s models. Pick a profile and model, and the run uses that profile’s credentials.
Playground model dropdown showing LLM profiles with their models in submenus

The playground model picker: one submenu per profile, models listed as you entered them

A workspace with no profiles gets a No LLM profiles configured notice in place of the picker, with a link to settings. Open in playground on a traced LLM span binds the playground to a profile only when one of your profiles lists that span’s model verbatim; otherwise the rest of the span (messages, tools, parameters) is copied over and you pick the model. Deleting a profile, or removing a model from it, clears that selection on any playground that used it. The playground reopens with Select model and everything else intact.

Route Signals through a profile

Selecting a profile for a Signal is available on self-hosted deployments. On Laminar Cloud, Signals run on Laminar’s own model credentials and no profile is involved.
On a self-hosted deployment, each Signal runs on one profile and one of its models. The LLM section of the Signal form holds the pair:
Signal creation drawer showing the LLM profile and model selects

The Signal form's LLM section: profile on the left, one of its models on the right

  • New Signals must pick a profile and a model. If the workspace has exactly one profile, it is preselected with its first model. With no profiles at all, the picker reads No profiles yet and the Signal cannot be created until you add one.
  • Signals created before you added profiles keep running on the server’s LLM_PROVIDER environment configuration. The form flags them so you can move them onto a profile; there is no way back to environment credentials once a Signal points at a profile.
  • A bad profile fails the run, visibly. A revoked key, a model you lost access to, or a deleted profile fails the Signal run with the provider’s error and the profile name, so the Runs tab tells you what to fix instead of retrying forever.
Deleting a profile, or removing a model, is refused while a Signal uses it. Re-point or delete those Signals first. This is the opposite of the playground, where the same delete just clears the selection. Other AI features on a self-hosted deployment (chat with trace, SQL with AI) still use the server’s LLM_PROVIDER and LLM_API_KEY. Profiles do not replace those. See Self-hosting configuration.

Manage profiles from the CLI

lmnr-cli llm-profile is full CRUD over the same profiles the settings page edits, so you can script provisioning or hand the surface to a coding agent. It works on Laminar Cloud and on self-hosted deployments; only pinning a Signal to a profile is self-hosted only. The CLI authenticates as you and resolves the workspace from the linked project, so lmnr-cli login plus a linked directory (or --project-id <uuid>) is all you need. See CLI.
The ID column is what signal create --llm-profile-id takes. llm-profile get <profile-id> shows one profile in full, with secrets as masks:

Create a profile from the CLI

create takes the name as its argument, the provider in --provider, one --model per model, and the credential flags that provider needs:
--provider-base-url is the provider’s endpoint. --base-url is the Laminar API URL (the one you set for a self-hosted deployment). They are different flags.
Which credential flags a provider needs matches the Providers table: The auth type is inferred from the flags you pass: --access-key-id selects AWS keys, --token selects a bearer token, otherwise an API key. Nothing is validated locally, so the server’s own message is what you see:

Update and delete from the CLI

update is a partial patch: only the flags you pass change. Two rules to keep in mind, both server-side:
  • --model replaces the whole model list, it does not append.
  • Any config flag (--region, --provider-base-url, --resource-id, --api-version, --header) replaces the whole config object, so re-pass every config field the provider needs.
Secrets are the exception: omit them and the stored credentials are kept, pass one to rotate it.
An update with no flags is an error rather than a silent no-op, and a delete is refused while a Signal uses the profile (409). Every subcommand takes --json for machine-readable output on stdout:
The group is also aliased to llm-profiles, and every subcommand has examples in its help text:

Manage profiles over the API

Profiles are also full CRUD over HTTP, authenticated with a project API key from Settings > Project API keys. A project key manages the profiles of the workspace that project belongs to. Every field, status code, and the masked secrets object are in the API reference: list, create, get, update, and delete.
Self-hosting: replace the base URL with your app-server HTTP origin, including the port. For example, http://localhost:8000/v1/llm-profiles.
config carries the plaintext, provider-specific settings and secrets the credentials, split exactly as the form does it:
An OpenAI-compatible gateway keeps its header names in config and their values in secrets:
PATCH is a partial update: every field is optional, omitted secrets keep their stored values, and models replaces the whole list. Three things to watch:
  • Changing provider requires sending config with it (400 config is required when provider changes).
  • Sending any config replaces the whole object, so include every field the provider needs, not just the one you are changing.
  • Dropping a model a Signal runs on is refused with 409, same as deleting the profile itself.

Next steps

  • Playground - iterate on prompts, tools, and models on top of a profile.
  • Signals - extract structured outcomes and failures from your traces.
  • Self-hosting configuration - the environment-level LLM settings that the rest of the AI features use.
  • Custom model costs - price the models a custom or self-hosted profile calls.