Connect a model
At the end of this page, the config of your Instance names a model. jr2.config.ts names its key or its endpoint, .env holds the value, and the cluster has the new config. The next page gives the model its first task.
Before you start
Do Create an Instance first. The Instance my-instance must be in the kind cluster.
Choose a tab. Choose Anthropic for a model of the Anthropic API. Choose Local for a model that you serve on a computer on your network. Each page after this one uses the model of the tab that you choose.
You need an Anthropic API key. Make one on the Anthropic website.
Add the model to jr2.config.ts
Open jr2.config.ts. Find the line that starts with // secrets:. Remove the //. Keep the other lines and their comments. This is the result. Its comments are shorter than the comments in your file:
import { defineConfig } from "@jr2/orchestrator";
export default defineConfig({
git: {
// The credentials that the cluster uses to clone and push. The token comes from JR2_GIT_TOKEN in .env.
credentials: [{ match: "*", token: "JR2_GIT_TOKEN", sshKey: "jr2-git-ssh" }],
},
// The model key. jr2 up gives it only to the Custodian of each pod whose Agents use Anthropic.
secrets: [{ name: "ANTHROPIC_API_KEY", value: process.env.ANTHROPIC_API_KEY }],
});The secrets line gives jr2 the value of ANTHROPIC_API_KEY from .env. An Agent that names an anthropic/ model uses this key.
The config reference gives each field of secrets and of harness.provider.
Put the value in .env
Make the file .env in my-instance. Put this line in it, with your key in place of <your key>:
ANTHROPIC_API_KEY=<your key>The jr2 CLI reads .env before each command, and names each key that it takes from .env. A variable that you set in your shell has priority over .env. Do not put .env in git: the .gitignore that jr2 init wrote keeps it out.
Start the model server
There is no server to start. Go to the next step.
Check the model server
There is no server to check. Go to the next step.
Converge the Instance again
Run:
jr2 upjr2 up reads the new config and converges the cluster again. The namespace is there, so it does not ask this time.
→ .env: ANTHROPIC_API_KEY
jr2 up — instance "my-instance" → context kind-jr2 / namespace my-instance
…
warning: secrets[0] (ANTHROPIC_API_KEY) is named by nothing; goes nowhere — no workspace() lists it, no Agent's provider reads it, and no Effect names it (ADR-0059, ADR-0068)
…
converged — `jr2 run <workflow>` when readyThe warning is correct for now. No Workflow has an Agent that names an anthropic/ model, so no pod gets the key.
The next page adds a Workflow with an Agent that names the model. On the next page, jr2 up gives the key to the Custodian of the pod where the Agent works. Then it asks the model for one tool call through a Custodian that holds the key, before it converges. It is the first jr2 up that reaches the model.
jr2 up published the new jr2.config.ts to the Orchestrator in the Assembly. The Orchestrator loaded it with no restart, so the port forward of Create an Instance stays open.
What happened
The API key is a Held secret. In this Instance, jr2 up gives its value only to the Custodian of each pod whose Agents use an anthropic/ model. The Custodian is a container next to the Harness container, where the Agent works. The Harness container holds only a Stand-in: a value that is worth nothing outside the pod. The Custodian puts the real key into each request to the Anthropic API. Thus the Agent never holds the key (ADR-0059).
To use a gateway or a different hosted provider, read Use a hosted provider or a gateway.
Secrets and trust explains where each secret goes, and who can use it.