> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.ellaworx.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.ellaworx.ai/_mcp/server.

# Environment Setup

This guide walks you through setting up the core building blocks of Ellaworx: a prompt registry, an environment, and optionally a fleet and LLM provider. By the end you'll have a working foundation for versioning and deploying prompts.

## Set up a Prompt Registry

A registry is where your versioned prompt artifacts live — think of it as a package repository scoped to your organization.

> **Note**
>
> Registries, environments, and secrets are managed by organization owners and admins. Other members don't see these pages in the sidebar.

#### Navigate to Registries

From your organization dashboard, click **Registries** in the sidebar (under **Assets**).

![Navigate to the Registries page](/_fern-files/_img/53d63e2f0e85c2ffcd982bf28dc33eb4c556533d9e20f3a66b0646e4d0b8de7c.webp)

#### Create a new registry

Click **New registry** and fill in:

* **Visibility** — choose **Public** or **Private**
* **Registry Name** — letters, numbers, dots, underscores, and hyphens only (e.g. `production-prompts`)

Then click **Create Registry**.

![Create a new registry](/_fern-files/_img/2f666ff1ef608fafd8fe283f61ce60ad41974513135067a1cb68ef6335d7ed1b.webp)

### Public vs Private Registries

|                | Public                                                         | Private                                                                     |
| -------------- | -------------------------------------------------------------- | --------------------------------------------------------------------------- |
| **Access**     | Anyone on the internet can pull prompts without authentication | Restricted to org members and API keys from your organization               |
| **Use case**   | Open-source prompts, community templates, shared examples      | Proprietary prompts, internal agent logic, production systems               |
| **API access** | No API key header required                                     | Requires `X-API-Key` or `Authorization: Bearer` (see [API Keys](/api-keys)) |

Prompts are pulled from `/api/prompts/{org-slug}/{registry-name}/{prompt-name}/{version}`, with an optional `model` query parameter (defaults to `generic`).

**Accessing a public registry** — no authentication needed:

```bash
curl "https://platform.ellaworx.ai/api/prompts/your-org/public-prompts/greeting/1.0.0?model=generic"
```

**Accessing a private registry** — requires an API key from the registry's organization (`X-API-Key` or `Authorization: Bearer`; if both are sent, `X-API-Key` wins):

```bash
curl -H "X-API-Key: YOUR_API_KEY" \
  "https://platform.ellaworx.ai/api/prompts/your-org/internal-prompts/greeting/1.0.0?model=generic"
```

```bash
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://platform.ellaworx.ai/api/prompts/your-org/internal-prompts/greeting/1.0.0?model=generic"
```

> **Note**
>
> Public registries are great for sharing prompt templates with the community or across teams. Use private registries for anything you don't want exposed outside your organization. Requests for a private registry without valid access return `404 Not found`, so the registry's existence isn't revealed.

## Add an Environment

Environments let you isolate provider credentials, variables, and configuration per deployment stage. A typical setup includes `development`, `staging`, and `production` environments.

Every organization also has a **Global** environment, created automatically. Its variables and provider credentials are the base for every other environment; an individual environment only needs to define the values it overrides.

#### Navigate to Environments

Click **Environments** in the sidebar (under **Delivery**).

![Navigate to the Environments page](/_fern-files/_img/1e2b8fae8cd6cbe06f6b211afd873bce6bdb1fa5d2baf74488287e2ec66821b5.webp)

#### Create an environment

Click **Create Environment** and give it a **Name** (e.g. `development`). The name `*` is reserved for the Global environment.

![Create a new environment](/_fern-files/_img/07a542a6e5390036e200dcebbe4891a6810b304e3e2898cd9adad76e67b24dd4.webp)

#### Configure a provider

Under **Providers**, select a deployment provider, click **Add**, and fill in its credentials so Ellaworx can deploy agents on your behalf:

| Provider                         | Credentials                                                                                                                     |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Vapi, Retell, ElevenLabs, Telnyx | API key (see [Vapi](/providers/vapi) and [ElevenLabs](/providers/elevenlabs))                                                   |
| AWS Bedrock Agents               | AWS Access Key ID, AWS Secret Access Key, AWS Region, and an optional Session Token (see [AWS Bedrock](/providers/aws-bedrock)) |

Credentials are never stored inline: pick an existing secret or create a new one in place. The environment stores a reference such as `${VAPI_API_KEY}`, and the encrypted value lives on the **Secrets** page (under **Delivery**), where you can rotate it without editing each environment.

Providers configured on the Global environment apply to every environment automatically — add the same provider to an individual environment only to override its credentials there.

![Configure a provider in the environment](/_fern-files/_img/073473b11dc4c2dbfedb0d053644ce8caf787b39f368a6e5337d444e9cd1a765.webp)

#### Add variables

Under **Variables**, click **Add Variable** to define key-value pairs that get injected into your prompts at deployment time. Names may contain letters, numbers, dashes, and underscores. For example:

| Key                | Value                                                |
| ------------------ | ---------------------------------------------------- |
| `COMPANY_NAME`     | Acme Corp                                            |
| `SUPPORT_URL`      | [https://support.acme.com](https://support.acme.com) |
| `ESCALATION_PHONE` | +1-555-0100                                          |

Reference a variable in a prompt as `{{env.variables.COMPANY_NAME}}`. Ellaworx substitutes the values when it compiles the prompt for a deployment, so your prompt templates stay generic while each environment fills in the right values. Variables inherited from the Global environment are labeled **Inherited from Global**; setting the same key here overrides it.

![Add environment variables](/_fern-files/_img/aeb4ad230499ebcf751a89f817ea743fb34c2685f649055298fb420aa84af30e.webp)

#### Save

Optionally configure an approval gate and drift detection (see below), then click **Save**.

> **Tip**
>
> When the same variable is set at several levels, the most specific value wins: **Agent** overrides **Fleet**, which overrides the **Environment**, which overrides **Global**.

### Approval gates

Turn on **Approval Gate** for an environment and choose **Required approvers** from your organization's members. Deployments to that environment are then held as pending approval, and run only after every required approver has approved. Approval gates are available on every environment except Global.

When an integration such as Ellavox names the person who requested a deployment, that person cannot approve it, even if they are a required approver. They are not asked to: the deployment waits only for the other required approvers. If the requester is the environment's only required approver, the deployment is refused, so add a second approver to environments that are deployed this way. Deployments started from Ellaworx itself do not record a separate requester and are not affected.

### Drift detection

Turn on **Drift Detection** to have Ellaworx check daily that agents deployed to that environment still match their expected configuration on the provider. Only one environment per organization can have drift detection enabled — typically `production`.

> **Note**
>
> Your plan may limit how many environments you can create. The create form shows your current usage and offers an upgrade when you've reached the limit.

### Why use environments?

* **Safe testing** — validate changes in `development` before they reach `production`
* **Separate credentials** — each environment can use its own provider API keys, stored as encrypted secrets
* **Variable substitution** — the same prompt template produces different output per environment (e.g. different support URLs, company names, or escalation contacts)
* **Approval gates** — optionally require named approvers to sign off before deploying to sensitive environments

## Create a Fleet (Optional)

Fleets are logical groupings of agents. If you only have a few agents, you can skip this step and come back later.

#### Navigate to Fleets

Click **Fleets** in the sidebar, then click **New Fleet**.

![Create a new fleet](/_fern-files/_img/277d43008a9142288214eeb183ed95d12188ef660ac2eb780d3f9615abe03649.webp)

#### Configure the fleet

Enter a **Fleet Name**, an optional **Description**, and optionally assign agents, then click **Create Fleet**. Open the fleet afterwards to add or remove agents and define **Fleet Variables**. An agent can belong to only one fleet.

![Configure fleet details](/_fern-files/_img/736edb1e4227d06462be6527b60086157e7578a280611d47816f71cc8da57f8e.webp)

### Why use fleets?

* **Shared variables** — fleet variables apply to every agent in the fleet, overriding environment values (agents can still override them)
* **Organization** — group agents by function (e.g. "Customer Support", "Sales Outbound", "Internal Tools") and see each deployment's fleet in deployment details

## Set up an LLM Provider (Optional)

LLM providers give Ellaworx access to language models for the playground and for governance policy evaluations. This is separate from the deployment provider credentials you set in an environment.

#### Navigate to LLM Providers

In the sidebar, open **Organization settings → LLM Providers** (organization owners and admins only).

![Navigate to LLM Providers settings](/_fern-files/_img/deff980f8acad51163cffb3de4f1e8dc6a28d0c6aeefb0319b97a9ce265db4eb.webp)

#### Add a provider

Click **Add Provider**, choose a **Provider Type** (OpenAI, Anthropic, Google, OpenRouter, or **OpenAI-Compatible (Custom Endpoint)**), give it a **Name**, and enter your **API Key**. Optionally set a **Base URL Override** or mark it as the **Default Provider** for that type.

![Add an LLM provider](/_fern-files/_img/37d227c5a62d0c880c25cef889f14f13393c355074b22d252cf37bbdc8749be4.webp)

#### Test connectivity

After saving, click **Test Connection** to verify the API key works. Verified providers are marked **Verified** in the list.

![Test provider connectivity](/_fern-files/_img/1c38b2c03565c0b548bc301365c668dc718bd133b4c4732f0d2869e4ffc8eebc.webp)

### Custom endpoints (OpenAI-compatible)

Choose **OpenAI-Compatible (Custom Endpoint)** for any model host that implements the OpenAI **Chat Completions** API, such as Oumi or a self-hosted vLLM server. Ellaworx calls `{Base URL}/chat/completions`. The endpoint must accept OpenAI's request and streaming response format; the OpenAI Responses API is not used.

| Field                             | Required              | Description                                                                                                                                                                                                                                                                                                                                                                                  |
| --------------------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Base URL**                      | Yes                   | The API root including its version path, e.g. `https://inference.oumi.ai/v1`. Must use `https://` and resolve to a public address (see below).                                                                                                                                                                                                                                               |
| **API Key**                       | Yes                   | Stored encrypted and always sent as `Authorization: Bearer <key>`.                                                                                                                                                                                                                                                                                                                           |
| **Model IDs**                     | Yes                   | One per line, exactly as the endpoint expects them, e.g. `projects/EVYSUEX5ZT-1/deployments/1`. The first one is the default model. If the endpoint also serves `GET /models`, those IDs are added to the model pickers.                                                                                                                                                                     |
| **Also send API key in header**   | No                    | Header name that also receives the key, for endpoints that expect it outside `Authorization`, e.g. `X-API-Key`.                                                                                                                                                                                                                                                                              |
| **Additional headers**            | No                    | Static headers sent with every request. They are not encrypted, so keep secrets in the API key field. `Authorization` and `x-portkey-*` are reserved.                                                                                                                                                                                                                                        |
| **Reasoning model**               | No (off by default)   | Turn on for models that follow OpenAI's reasoning-model rules (o-series, gpt-5, and hosted deployments built on them, such as some Oumi deployments). Temperature, top-p, penalties and logit bias are left out of requests, and the token limit is sent as `max_completion_tokens` instead of `max_tokens`. Turn it on if the endpoint rejects `max_tokens` or a non-default `temperature`. |
| **Reasoning effort**              | No (Endpoint default) | Sent as `reasoning_effort` on every request: **None**, **Minimal**, **Low**, **Medium** or **High**. **Endpoint default** sends nothing. Some hosts only accept tool calls at **None**, and team agents always use tools. **Test Connection** warns when the endpoint rejects a tool call.                                                                                                   |
| **Route through Portkey gateway** | No (on by default)    | On: calls go through Portkey with the endpoint as a custom host, keeping request logs, guardrails, and usage analytics. Off: calls go straight to the endpoint, and the provider can't be used through environment proxy URLs.                                                                                                                                                               |

**Example (Oumi):** Base URL `https://inference.oumi.ai/v1`, your Oumi API key, model ID `projects/EVYSUEX5ZT-1/deployments/1`, and `X-API-Key` under **Also send API key in header**. If the deployment rejects `max_tokens` or `temperature` ("Only the default (1) value is supported"), turn on **Reasoning model**. For team agents, also set **Reasoning effort** to **None**: Oumi's gpt-5 deployments reject tool calls on chat completions at their default effort ("Function tools with reasoning_effort are not supported … set reasoning_effort to 'none'"). This matches Oumi's own OpenAI SDK setup:

```ts
const client = new OpenAI({
  apiKey: process.env.OUMI_API_KEY,
  baseURL: "https://inference.oumi.ai/v1",
  defaultHeaders: { "X-API-Key": process.env.OUMI_API_KEY ?? "" },
});
```

**Private and self-hosted endpoints.** Requests to a custom endpoint carry your API key, so the host must resolve to a public internet address. Loopback, private (RFC 1918), link-local (including the cloud metadata address `169.254.169.254`), carrier-grade NAT and IPv6 private ranges are refused, as are `localhost`, `*.local` and `*.internal` names. The check runs when the provider is saved and again on every connection, so a DNS change after saving can't redirect requests to an internal address. To use a model server on a private network or on localhost (for example vLLM or Ollama during development), set `ALLOW_PRIVATE_LLM_ENDPOINTS=true` on the Ellaworx server.

**Test Connection** checks `GET /models` first. If the endpoint doesn't implement it, Ellaworx sends a one-token chat completion to the first model ID instead. A failed test reports only the HTTP status (or that the address isn't allowed), never the endpoint's response body.

Custom endpoints are used for chat, playground, governance, and team agents. They aren't used for embeddings, so team memory search falls back to recency for teams on a custom endpoint. The provider type can't be changed after creation; create a new provider instead.

A team on a custom endpoint runs **every member on the team model**. Per-member model and provider overrides are turned off in the member editor and refused by the API, and the team model must be one of the endpoint's configured model IDs.

### Changing a team's LLM provider

An org admin can switch a team's provider and model under **Team → Settings → General**. Saving a new provider asks for confirmation, then:

* clears every member's model and provider override, so the whole team runs on the new provider and the team model;
* picks a model the new provider serves when none is chosen (a custom endpoint's first configured model);
* leaves semantic memory search on only for OpenAI providers; other providers fall back to recent memories.

### Why set up an LLM provider?

* **Playground** — test prompts interactively against real models before deploying
* **Governance** — the default provider is also used for automated governance policy evaluations
* **Encrypted storage** — API keys are encrypted at rest, not stored in plaintext
* **Shared access** — team members can use the playground without needing their own API keys

## Next steps

#### [Using the Prompt Registry](/using-the-prompt-registry)

Author, version, and pull prompts at runtime

#### [Deploying Agents](/deploying-agents)

Deploy a voice agent with tools to Vapi

#### [API Reference](/api-reference)

Explore the full API