Skip to main content

Create a provider

By the end of this tutorial you will have a working, validated AI provider — the model credential every agent in your project generates through.

Don't have a vendor account?

You don't need one. Enable naturali models gives your project a working provider in a single call, with no credential of your own — this tutorial is the path for bringing your own key.

Four steps:

  1. Create a project — the tenancy boundary everything else lives in.
  2. Store your model credential as a secret.
  3. Register the provider that uses it.
  4. Validate it by asking the vendor which models the credential can run.

Every step is one API call, shown for all three clients. The ids in the responses are examples — copy the ones your own calls return.

Prerequisites​

You need an account-scoped nat_sk_… API key (or a session JWT from Auth) exported as NATURALI_TOKEN, and an API key from a model vendor — this tutorial uses OpenAI. A project-scoped key cannot create projects: step 1 answers 403 access_denied with one.

export NATURALI_TOKEN=nat_sk_...
export OPENAI_API_KEY=sk-...

Then set your client up:

pnpm add -g @naturali/cli

The CLI reads NATURALI_TOKEN from the environment. See the CLI guide.

1. Create a project​

A project is the isolation boundary: providers, secrets, agents and everything else belong to exactly one, and your credential is authorized against it per request.

naturali create-project --name "getting started"
{
"id": "proj_V1StGXR8Z5jdHi6B",
"name": "getting started",
"role": "owner",
"owner_user_id": "user_V1StGXR8Z5jdHi6B",
"status": "active"
}

You are the project's owner — the role that may do anything in it, including delete it — and its billing owner.

export PROJECT=proj_V1StGXR8Z5jdHi6B

2. Store your model credential​

Credentials are never passed inline to a provider. Store the key as a secret first: the value is encrypted on write and no endpoint ever reads it back.

naturali create-secret \
--project-id "$PROJECT" \
--name openai-production \
--value "$OPENAI_API_KEY"
{
"id": "sec_l4gKTvGnouZ68huG",
"project_id": "proj_V1StGXR8Z5jdHi6B",
"name": "openai-production",
"has_value": true,
"created_at": "2026-10-03T08:12:11.407Z",
"updated_at": "2026-10-03T08:12:11.407Z"
}

has_value is how a read reports that a value is stored — the value itself is gone from the API surface the moment you write it.

export SECRET=sec_l4gKTvGnouZ68huG

3. Register the provider​

The provider record names the vendor, the model to use when an agent names none, and the secret to authenticate with.

naturali create-ai-provider \
--project-id "$PROJECT" \
--name openai-production \
--provider openai \
--default-model gpt-4o-mini \
--secret-id "$SECRET"
{
"id": "aip_JPvMSUTATh7C6Bn6",
"project_id": "proj_V1StGXR8Z5jdHi6B",
"secret_id": "sec_l4gKTvGnouZ68huG",
"name": "openai-production",
"provider": "openai",
"default_model": "gpt-4o-mini",
"created_at": "2026-10-03T08:12:12.364Z",
"updated_at": "2026-10-03T08:12:12.364Z"
}

The provider is created whether or not the key works — nothing calls the vendor yet. The next step is what proves it.

export PROVIDER=aip_JPvMSUTATh7C6Bn6

A vendor that needs no credential — a local ollama, say — takes a base_url and no secret_id instead.

4. Validate it​

Ask the vendor which models this record can actually run. The call goes out with this provider's credential, so a 200 proves the whole chain — secret, provider, vendor — works.

naturali list-ai-provider-models \
--project-id "$PROJECT" \
--ai-provider-id "$PROVIDER"
{
"provider": "openai",
"models": [
{ "id": "gpt-4o-mini" },
{ "id": "gpt-4o" },
{ "id": "o3-mini" }
]
}

Each id is ready to use as default_model or as an agent's model. A key the vendor rejects answers 502:

{
"error": {
"code": "MODEL_LISTING_FAILED",
"message": "The openai provider rejected the model listing request (HTTP 401)."
}
}

Rotate the secret's value and try again; the provider record does not need recreating.

What's next​

  • Your first agent generation — create an agent on this provider and run it.
  • Model Routes — put two providers behind one ordered route so a vendor outage fails over instead of failing.
  • Secrets — rotation, and how a tool interpolates a secret into an outbound request.