# Run a saved agent from code

Save a harness with its model, instructions, skills and connections once, then start each run with its id and a task.

When every run of a job uses the same model, the same instructions and the same tools, repeating
them in each request is how they drift apart. A **saved agent** holds those choices in one place.
In this lesson you save one, start a run from it with two fields, change it, and see what the model
check refuses.

## Save the agent

### 1. Pick a model it can run

A saved agent's `model` and `effort` must be ones the harness lists.
[`getAgentsAvailable`](/docs/api/get-agents-available) returns each harness with its models:

```bash
curl https://api.prix.dev/o/$ORG/agents/available \
  -H "Authorization: Bearer $RUSH_API_KEY"
```

Each model has a `name`, the value `model` takes, and the `effort` levels it accepts. A model with no
`effort` list takes none.

### 2. Create it

[`createSavedAgent`](/docs/api/create-saved-agent) takes the harness and the choices every run of it
uses:

```bash
curl -X POST https://api.prix.dev/o/$ORG/agents \
  -H "Authorization: Bearer $RUSH_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "name": "Plugin reviewer",
    "harness": "claude",
    "model": "claude-opus-5-5",
    "effort": "high",
    "instructions": "Review each plugin.json and report every problem with its file and a fix.",
    "skills": [{"url": "https://github.com/anthropics/skills/tree/main/skills/frontend-design"}],
    "connections": ["deepwiki"]
  }'
```

The answer is `201` with the agent and its `id`. Skills are fetched and pinned when you save: a GitHub
source to its commit, any other to its content. `connections` take ids or names, as on a run, and
read back as `[{"id": "...", "name": "deepwiki"}]`.

### 3. List what you have

```bash
curl https://api.prix.dev/o/$ORG/agents -H "Authorization: Bearer $RUSH_API_KEY"
```

[`listSavedAgents`](/docs/api/list-saved-agents) answers `{"agents": [...]}`, 50 a page. A key sees
the saved agents of the admin who created it.

## Run it

### 4. Start a session with agent_id

```bash
curl -X POST https://api.prix.dev/o/$ORG/sessions \
  -H "Authorization: Bearer $RUSH_API_KEY" -H "Content-Type: application/json" \
  -d '{"agent_id": "<agent id>", "input": "Review the plugins added this week.",
       "resources": [{"url": "https://github.com/acme/plugins"}]}'
```

The agent fixes the harness, model, effort, instructions, skills and connections, so the request
names none of them. You can still add `skills`, `connections` and `resources`: the run gets exactly
the connections the agent names plus the ones the run names. The session it returns carries
`agent_id`, and so does every later read of it.

## Change it

### 5. Edit only what changes

[`updateSavedAgent`](/docs/api/update-saved-agent) changes only the fields you send and keeps the
rest:

```bash
curl -X PATCH https://api.prix.dev/o/$ORG/agents/$AGENT_ID \
  -H "Authorization: Bearer $RUSH_API_KEY" -H "Content-Type: application/json" \
  -d '{"effort": "max"}'
```

`harness` is fixed once saved. Each save is a new version of the agent: runs started after it use the
new choices, and sessions already started keep what they started with. Send `If-Match` with the
`ETag` you read to refuse an edit made on top of someone else's; a stale one is `412 STALE_ETAG`.

### 6. Remove it

`DELETE /o/{org}/agents/{id}` answers `{"id": "...", "deleted": true}`. The agent starts no new run and
is no longer listed or readable; runs already started from it finish.

## What the model check refuses

The model and effort are checked against today's list each time you save, and again when a run of the
agent starts:

| Request | Answer |
| --- | --- |
| A `model` the harness does not list | `422 UNSUPPORTED_PROFILE`, with `UNKNOWN_MODEL` on the field |
| An `effort` the model does not take | `422 UNSUPPORTED_PROFILE`, with `INVALID_EFFORT` on the field |
| A field the route does not take | `400 UNKNOWN_FIELD` |
| A pinned skill file that has since changed | `422 SKILL_INVALID` until you save the agent again |

A refused save names the field in `fields`, so you can show the exact problem to whoever configured
the agent.

## Next

[Saved agents](/docs/concepts/saved-agents) covers saved agents in the console and the CLI, and
[Models](/docs/concepts/models) explains how the model list is kept current.
