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

# Training Studio

> Train a policy-specific adapter from an imported custom policy, then enforce against it.

Training Studio is where you train your own enforcement model on ZeroDrift's base. Anchor handles regulations. Your adapter handles your policies.

Training Studio turns an imported custom policy into a **policy-specific adapter**. After the adapter is ready, enforcement scoped to that import uses the trained adapter instead of the base Anchor path.

By default, activated custom rules run automatically during enforcement for your account; supplying `validation_scope` narrows evaluation to the selected active rules, rule packs, and imports. Training is the extra adapter step: it teaches the engine from the original policy document, not only from the extracted rule definitions.

## Terms

| Term             | Meaning                                                                                                              |
| ---------------- | -------------------------------------------------------------------------------------------------------------------- |
| **Policy**       | The imported policy document and the rules extracted from it. In the product this is also the adapter you train.     |
| **Adapter**      | The policy-specific model trained from that import. After a successful training poll, scoped enforcement can use it. |
| **Rules**        | Extracted, reviewed, and activated requirements from the import. Edit them before activation if needed.              |
| **Training run** | One Training Studio job for an import. Identified by `training_run_id`.                                              |

## What you need

* A **full-access** API key (`x-api-key`). Training returns `403` for a read-only key.
* An import whose extracted rules are **activated**. Training returns `409` while the import is still pending review, or if another training run is already in progress.
* The **original imported document** still retained. Default content retention is **7 days** ([Data Retention](/data-retention)). If the document is gone, training returns `410` — re-import the policy, activate the rules, then train again.
* Training enabled for your environment. If it is not configured, training returns `503`.

## Flow

```
import → poll extraction → review → activate → train → poll training → enforce
```

| Step                   | What to do                                                                                                                | API                                                                                                                                                                                                                                                              |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1. Intake              | Upload the policy as a file or plain text, or sync it from a connected source. Large files use the presigned upload flow. | [Import Policy](/api-reference/custom-policies/import-policy), [Get Import Presigned URL](/api-reference/custom-policies/import-presigned-url) then [Start Import](/api-reference/custom-policies/start-import), or [Connecting the MCP server](/connecting-mcp) |
| 2. Wait for extraction | Poll until status is no longer `processing`. Continue when it is `pending_review`.                                        | [Get Import Details](/api-reference/custom-policies/get-import-details)                                                                                                                                                                                          |
| 3. Review              | Inspect extracted rules. Edit a pending rule if needed. Extracted rule severity is `low`, `medium`, or `high`.            | [Edit Imported Rule](/api-reference/custom-policies/edit-imported-rule)                                                                                                                                                                                          |
| 4. Activate            | Activate all extracted rules or a subset. Training is rejected until this succeeds.                                       | [Activate Rules](/api-reference/custom-policies/activate-rules)                                                                                                                                                                                                  |
| 5. Train               | Start adapter training. Body is optional: `cost_cap_usd` and `examples_per_rule`.                                         | [Train Policy Adapter](/api-reference/training-studio/train-policy)                                                                                                                                                                                              |
| 6. Poll                | Poll until `status` is `succeeded` or `failed`. Stop on either terminal status.                                           | [Get Training Status](/api-reference/training-studio/get-training-status)                                                                                                                                                                                        |
| 7. Enforce             | After `succeeded`, send `validation_scope.imports` with that `import_id`.                                                 | [Enforce Content](/api-reference/validate/validate-content)                                                                                                                                                                                                      |

<Warning>
  Do not enforce against a still-training run. ZeroDrift promotes `training_run_id` only after a successful status poll. Until then, scoped enforcement follows its configured fallback path.
</Warning>

## Intake

You need an `import_id` before you can train. Three ways to get one:

1. **Inline upload** — [Import Policy](/api-reference/custom-policies/import-policy) with `source: "file"` (base64) or `source: "text"`. Payload size is limited; use the presigned flow for large files.
2. **Presigned upload** — [Get Import Presigned URL](/api-reference/custom-policies/import-presigned-url), put the file on S3, then [Start Import](/api-reference/custom-policies/start-import).
3. **Connected source** — In Command, connect Notion, Linear, Confluence, or Google Drive and sync a document. That produces the same import pipeline. See [Connecting the MCP server](/connecting-mcp).

Extraction runs in the background. Poll [Get Import Details](/api-reference/custom-policies/get-import-details) until status is `pending_review`. `no_rules_found` and `failed` are not trainable — fix the document and import again.

While the import is pending review, you can edit a rule's prompt, fix note, or extraction confidence with [Edit Imported Rule](/api-reference/custom-policies/edit-imported-rule). Then [Activate Rules](/api-reference/custom-policies/activate-rules). Training returns `409` until activation succeeds.

Activated rules run on every enforcement request for your API key. Training does not replace that step.

## What training does

[Train Policy Adapter](/api-reference/training-studio/train-policy) starts an asynchronous run. Training Studio:

1. Re-reads the **original imported document** (not only the extracted rule list).
2. Generates and judges training examples from that document.
3. Trains a policy-specific adapter for that import.

POST returns `202` with `training_run_id` and a `poll` object pointing at GET on the same path. Omit the body to use Training Studio defaults, or set:

| Field               | Meaning                                                                                              |
| ------------------- | ---------------------------------------------------------------------------------------------------- |
| `cost_cap_usd`      | Optional maximum generation spend in US dollars for this run.                                        |
| `examples_per_rule` | Optional number of generated training examples per extracted rule. More examples usually costs more. |

Only one training run can be in progress for an import. A second POST while a run is active returns `409`.

## Training status

Poll [Get Training Status](/api-reference/training-studio/get-training-status) after you start a run. GET returns `404` if no run has been started.

| `status`    | Meaning                                                              |
| ----------- | -------------------------------------------------------------------- |
| `queued`    | Run accepted; training has not finished.                             |
| `succeeded` | Terminal. ZeroDrift records this run as the import's active adapter. |
| `failed`    | Terminal. Read `error`. Stop polling.                                |

`stage` and `progress` (`completed` / `total`) appear when Training Studio reports them. Treat `succeeded` and `failed` as the only stop conditions.

A successful poll is what **promotes** the adapter. Until that poll reports `succeeded`, enforcement scoped to the import uses the configured fallback path — not a half-trained run.

A failed retraining attempt does not replace an earlier working adapter.

## Train then poll

Reuse the same `import_id` for `POST` and `GET` on `/api/policies/import/{import_id}/train`.

```python theme={null}
import time
import requests

API_BASE = "https://api.zerodrift.ai"
API_KEY = "YOUR_API_KEY"
IMPORT_ID = "550e8400-e29b-41d4-a716-446655440000"
URL = f"{API_BASE}/api/policies/import/{IMPORT_ID}/train"
HEADERS = {"x-api-key": API_KEY}

started = requests.post(URL, headers=HEADERS, json={})
started.raise_for_status()
print(started.json())

while True:
    response = requests.get(URL, headers=HEADERS)
    response.raise_for_status()
    training = response.json()
    print(training["status"])

    if training["status"] in ("succeeded", "failed"):
        break
    time.sleep(10)

if training["status"] == "failed":
    raise SystemExit(training.get("error", "Training failed"))
```

A successful start looks like:

```json theme={null}
{
  "import_id": "550e8400-e29b-41d4-a716-446655440000",
  "training_run_id": "run-808961af",
  "status": "queued",
  "message": "Training started. Poll the training status endpoint for progress.",
  "poll": {
    "method": "GET",
    "url": "/api/policies/import/550e8400-e29b-41d4-a716-446655440000/train"
  }
}
```

A successful poll looks like:

```json theme={null}
{
  "import_id": "550e8400-e29b-41d4-a716-446655440000",
  "training_run_id": "run-808961af",
  "status": "succeeded",
  "stage": "complete",
  "progress": {
    "completed": 4,
    "total": 4
  },
  "error": null
}
```

Optional training options (omit the body to use defaults):

```json theme={null}
{
  "cost_cap_usd": 25,
  "examples_per_rule": 8
}
```

## Enforce against the trained import

After status is `succeeded`, submit content with `validation_scope.imports` set to that `import_id`. Use `model_engine: "anchor_3_0"`.

```bash theme={null}
curl -X POST "https://api.zerodrift.ai/api/v3/content/validate" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Our fund guarantees 20% returns with zero risk!",
    "document_category": "scenario_retail_investor_letter",
    "mode": "async",
    "model_engine": "anchor_3_0",
    "validation_scope": {
      "imports": ["550e8400-e29b-41d4-a716-446655440000"]
    }
  }'
```

Async submissions return a `job_id`. Poll [Get Results](/api-reference/validate/get-results) until the job is `done` or `failed`.

## Errors

Field-level detail lives on the endpoint pages. Typical training responses:

| Status | Meaning                                                                                       | See                                                                                                                                            |
| ------ | --------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| 400    | Invalid training options (`cost_cap_usd` or `examples_per_rule`)                              | [Train Policy Adapter](/api-reference/training-studio/train-policy)                                                                            |
| 403    | Full-access key required (POST), invalid key (GET), or the import belongs to another customer | [Train Policy Adapter](/api-reference/training-studio/train-policy), [Get Training Status](/api-reference/training-studio/get-training-status) |
| 404    | Import not found, or no training run has been started (GET)                                   | Same pages                                                                                                                                     |
| 409    | Import is not activated, or another training run is already in progress                       | [Train Policy Adapter](/api-reference/training-studio/train-policy)                                                                            |
| 410    | Original document expired; re-import and activate, then train                                 | [Train Policy Adapter](/api-reference/training-studio/train-policy), [Data Retention](/data-retention)                                         |
| 422    | Stored document is too short to train, or Training Studio rejected it                         | [Train Policy Adapter](/api-reference/training-studio/train-policy)                                                                            |
| 502    | Training Studio request failed                                                                | Both training endpoints                                                                                                                        |
| 503    | Training is not configured in this environment                                                | Both training endpoints                                                                                                                        |

## FAQ

<AccordionGroup>
  <Accordion title="Do I have to train before custom rules run?">
    No. [Activate Rules](/api-reference/custom-policies/activate-rules) puts extracted rules into enforcement immediately. Training Studio adds a policy-specific adapter on top of that.
  </Accordion>

  <Accordion title="Can I train a document I synced from Notion or Drive?">
    Yes. A connected-source import is the same `import_id` as a file upload. Activate it, then call the train endpoints. See [Connecting the MCP server](/connecting-mcp).
  </Accordion>

  <Accordion title="What if retraining fails?">
    Stop polling when `status` is `failed`. A failed run does not replace an earlier working adapter. Fix the cause (document, options, or environment) and start a new training run.
  </Accordion>

  <Accordion title="Why did training return 410?">
    Training needs the original imported file or text. After default [content retention](/data-retention) (7 days unless your contract says otherwise), that document is deleted. Import again, activate the new rules, then train.
  </Accordion>

  <Accordion title="Why did GET training return 404?">
    No training run has been started for that import. POST first, then poll.
  </Accordion>
</AccordionGroup>

## API reference

<CardGroup cols={2}>
  <Card title="Train Policy Adapter" icon="play" href="/api-reference/training-studio/train-policy">
    POST `/api/policies/import/{import_id}/train`
  </Card>

  <Card title="Get Training Status" icon="loader" href="/api-reference/training-studio/get-training-status">
    GET `/api/policies/import/{import_id}/train`
  </Card>

  <Card title="Import Policy" icon="file-import" href="/api-reference/custom-policies/import-policy">
    Upload a policy and extract rules.
  </Card>

  <Card title="Activate Rules" icon="toggle-on" href="/api-reference/custom-policies/activate-rules">
    Activate extracted rules so they run during enforcement.
  </Card>

  <Card title="Enforce Content" icon="paper-plane" href="/api-reference/validate/validate-content">
    Scope enforcement with `validation_scope.imports`.
  </Card>

  <Card title="Connecting the MCP server" icon="plug" href="/connecting-mcp">
    Import a policy from a connected source instead of uploading a file.
  </Card>
</CardGroup>
