> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getmillwork.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Run a model

> Submit a public test task and confirm which model and provider answered.

**Goal:** Submit one public test task using a model available to your
organization.

**You are done when:** the run completes, the result contains model output, and
the receipt names the model and provider that answered.

At the end, you will have three records:

* a run showing final status;
* a result containing model output; and
* a receipt showing what ran.

Millwork is not a drop-in chat endpoint. You send a task and limits. Millwork
selects from the registered models that match them.

## Before you begin

* Your Millwork organization is approved.
* You created an organization API key in the dashboard.
* You have `curl` and `jq`.
* Your account has enough credit and quota for a live run.

Not ready for a provider call? Complete the
[first API call](/get-started/first-api-call) first.

```bash theme={null}
export MILLWORK_API_URL="https://api.getmillwork.dev/v1"
export MILLWORK_API_KEY="<organization API key>"
export RUN_SUFFIX="$(date +%s)"
```

<Warning>
  Use only public information or test data created for this run. Read
  [Data and credentials](/guides/security-and-data) before sending a live task.
</Warning>

<Warning>
  Never paste a provider key into a model registration, run request, support
  message, or documentation playground. Provider credentials use a separate
  secure connection flow.
</Warning>

## 1. Choose an available model

```bash theme={null}
curl --fail-with-body \
  --header "Authorization: Bearer $MILLWORK_API_KEY" \
  "$MILLWORK_API_URL/model-catalog" > catalog.json

jq -r '.models | to_entries[] |
  "\(.key): \(.value.model.display_name // .value.model.model_key) | provider: \(.value.source.source_id) | access: \(.value.connection.access_lane)"' \
  catalog.json
```

**Expected result:** `models` contains the models your organization can use
now.

Choose the number shown at the start of one row:

```bash theme={null}
export MODEL_INDEX=0
jq --argjson i "$MODEL_INDEX" -e '.models[$i]' catalog.json
```

If the catalog is empty, [connect a provider](/get-started/enterprise) or
[email support](mailto:support@getmillwork.dev) to ask whether a model provided
by Millwork is available.

## 2. Add the model to Millwork

Add the selected catalog model to your organization before running it. The
`/arms` endpoint performs this step; `arm` is the API field name for the saved
model. Send the selected model's registration template without changing it.

```bash theme={null}
jq --argjson i "$MODEL_INDEX" \
  '.models[$i].arm_registration_template' \
  catalog.json > arm-request.json

curl --fail-with-body \
  --request POST \
  --header "Authorization: Bearer $MILLWORK_API_KEY" \
  --header "Idempotency-Key: arm-$RUN_SUFFIX" \
  --header "Content-Type: application/json" \
  --data @arm-request.json \
  "$MILLWORK_API_URL/arms" | tee arm-response.json
```

**Expected result:** the response contains an `arm_id` and a ready registered
model. If it does not, read `status_reason` and choose another catalog row.

Registering a model makes it available to routing. It does not force Millwork
to choose it when other registered models also match the task. The receipt
confirms what answered.

## 3. Submit a live task

```bash theme={null}
curl --fail-with-body \
  --request POST \
  --header "Authorization: Bearer $MILLWORK_API_KEY" \
  --header "Idempotency-Key: run-$RUN_SUFFIX" \
  --header "Content-Type: application/json" \
  --data '{
    "mode": "live",
    "task": {
      "objective": "Explain idempotency keys in one short sentence.",
      "inputs_ref": {
        "kind": "inline_json",
        "json": { "audience": "API developers" }
      }
    },
    "policy": {
      "data_classes": ["public"],
      "budget": { "max_cost_usd": 1, "max_runtime_s": 60 },
      "cost_coefficient": 0.5,
      "on_eval": []
    }
  }' \
  "$MILLWORK_API_URL/executions" | tee execution.json

EXECUTION_ID="$(jq -r '.execution_id' execution.json)"
```

If you do not provide `verifier_id`, Millwork uses its built-in basic output
check. A live run also needs available credit and quota. If the API
returns `insufficient_credit`, add credit in **Usage & spend** before retrying.

<Note>
  `max_cost_usd` can stop Millwork from starting another provider call after
  recorded spend reaches the limit. It cannot cancel a call already in
  progress or reverse its cost.
</Note>

## 4. Wait for a final status

```bash theme={null}
STATUS="unknown"
DEADLINE=$((SECONDS + 90))

while [ "$SECONDS" -lt "$DEADLINE" ]; do
  if ! curl --fail-with-body \
    --header "Authorization: Bearer $MILLWORK_API_KEY" \
    --output execution-status.json \
    "$MILLWORK_API_URL/executions/$EXECUTION_ID"; then
    echo "The status request failed. Read execution-status.json before retrying." >&2
    exit 1
  fi

  STATUS="$(jq -r '.status' execution-status.json)"

  case "$STATUS" in
    completed|failed|cancelled|expired) break ;;
    *) sleep 2 ;;
  esac
done

if [ "$STATUS" != "completed" ] &&
   [ "$STATUS" != "failed" ] &&
   [ "$STATUS" != "cancelled" ] &&
   [ "$STATUS" != "expired" ]; then
  echo "The run did not finish within 90 seconds. Keep the run ID and check it again later." >&2
  exit 1
fi

echo "$STATUS"
```

Final statuses are `completed`, `failed`, `cancelled`, and `expired`.

## 5. Read the result and receipt

Fetch the result only when the status is `completed`:

```bash theme={null}
if [ "$STATUS" = "completed" ]; then
  curl --fail-with-body \
    --header "Authorization: Bearer $MILLWORK_API_KEY" \
    --output result.json \
    "$MILLWORK_API_URL/executions/$EXECUTION_ID/result"
fi

curl --fail-with-body \
  --header "Authorization: Bearer $MILLWORK_API_KEY" \
  "$MILLWORK_API_URL/receipts/$EXECUTION_ID" \
  | tee receipt.json
```

If the run failed, read the events before retrying:

```bash theme={null}
curl --fail-with-body \
  --header "Authorization: Bearer $MILLWORK_API_KEY" \
  "$MILLWORK_API_URL/executions/$EXECUTION_ID/events"
```

## Check your work

* the registered model is ready;
* the run reaches `completed`;
* the result contains model output and may include an expiry time; and
* the receipt records provider, route, attempts, usage, and checks without the prompt or output.

Compare the requested and provider-reported model:

```bash theme={null}
jq '{
  requested: .model_provenance.requested.upstream_ref,
  provider_reported: .model_provenance.resolved.upstream_ref,
  provider: .model_provenance.source.source_id
}' result.json
```

## What this confirmed

Your application submitted one task format without a provider credential.
Millwork selected an eligible registered model. The result contains the useful
output. The receipt records the model, provider, attempts, usage, and checks
without copying the task or output.

## Next steps

<CardGroup cols={2}>
  <Card title="Connect a provider" icon="plug" href="/guides/connect-a-source">
    Use an account your organization owns.
  </Card>

  <Card title="Retry safely" icon="refresh-cw" href="/cookbook/retry-without-duplicates">
    Recover from a network failure without creating duplicate work.
  </Card>

  <Card title="Read the run record" icon="file-check-2" href="/concepts/results-and-receipts">
    Store the output and receipt separately.
  </Card>

  <Card title="Review data limits" icon="shield" href="/guides/security-and-data">
    Confirm what the private preview may process.
  </Card>
</CardGroup>

## Common fixes

| What happened         | What to do                                                                            |
| --------------------- | ------------------------------------------------------------------------------------- |
| Catalog is empty      | Connect a provider, or ask support whether a model provided by Millwork is available. |
| `insufficient_credit` | Add credit before submitting another live run.                                        |
| Run failed            | Read its events and receipt before retrying.                                          |
| No result             | Check the final status. Only completed live work can have a result.                   |

For retry rules and common errors, read
[Errors and retries](/guides/errors-and-retries).
