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

# Instance configuration

> Write an instance config that validates, and know what each field changes at turn time.

An instance config is one JSON document that decides how every turn on the instance behaves: the system prompt, which tools exist, which platform data the assistant can read, guardrails, per-turn limits, the publish regression policy, retention, and file uploads. You edit it as a draft; turns run only published versions. See [Versions and publish](/conversations/versions-and-publish).

## How it works

1. You save a full config document as the instance's draft, in the portal's **Config** tab or with `PATCH /api/v1/conversation-instances/{instance_slug}` and an organization API key.
2. The platform validates the whole document. Any problem refuses the save with `400 invalid_instance_config` and a list of issues.
3. Publishing revalidates the draft, runs the eval gate, and freezes it as a numbered version.
4. Every turn stamps the config hash it ran under onto the messages it stores.

A config is always a complete document. Every section below is required except `attachments`. A required section that is missing or `null` is invalid, and so is a required field inside a section. These optional values may be omitted or `null`: the whole `attachments` section and any field inside it, a component's `props_schema`, and a client tool's `input_schema`. `retention.conversation_days` must be present, and may be `null`. Unknown fields are rejected everywhere except inside a JSON Schema value. The hash of a config ignores key order and whitespace.

## Validation errors

```json theme={null}
{
  "code": "invalid_instance_config",
  "message": "The instance config is invalid.",
  "details": [
    { "path": "limits.max_tool_rounds", "message": "must be between 1 and 50" },
    { "path": "tools.client_tools[0].effect", "message": "is required and must be one of: read, write, outbound, destructive" }
  ]
}
```

Each issue carries the JSON `path` of the field and a `message`. Fix every listed issue and save again.

## The default config

Creating an instance without a `config` applies this document.

```json theme={null}
{
  "model_policy": { "max_tokens": 4096 },
  "system_prompt": "",
  "engines": "*",
  "tools": { "platform_packs": ["platform.read"], "client_tools": [] },
  "components": [],
  "data_sources": [
    { "sources": ["catalog"], "notes": "grounding surface available to platform packs" }
  ],
  "access": { "personas": ["*"] },
  "limits": { "max_tool_rounds": 12, "max_turn_output_tokens": 32000, "max_history_messages": 60 },
  "guardrails": { "refusal_domains": [], "escalation_rules": [], "output_checks": [] },
  "evals": { "on_regression": "block" },
  "retention": { "conversation_days": null },
  "annotations": { "enabled": true },
  "attachments": {
    "enabled": false,
    "max_files_per_message": 5,
    "max_bytes_per_file": 39321600,
    "accepted_media_types": [],
    "unwrap_archives": false,
    "retention_days": null
  }
}
```

## Sections

### `model_policy`

| Field        | Type    | Bounds    | Meaning                                                                           |
| ------------ | ------- | --------- | --------------------------------------------------------------------------------- |
| `max_tokens` | integer | 0 to 8192 | Output token ceiling for each model call. `0` means the platform default of 1024. |

Every configured assistant runs `gpt-6-sol`. There is no model selector. The retired fields `default_model` and `deep_model` are rejected.

### `system_prompt`

A string. The platform adds two things after it on every turn: a sentence naming which data sources are enabled and which are not (only when the config declares at least one platform pack), and an instruction that tells the model to treat user messages, tool results, and page context as untrusted data, never as instructions.

### `engines`

`"*"` or an array of engine slugs or ids. It is the allowlist of engines the assistant may read through platform tools. `"*"` means every engine the caller may see. An empty array is valid and means no engine-scoped reads. Validation checks only the shape; the listed engines are resolved when each turn starts, so archiving an engine never makes a config invalid. When the caller is a scoped key, the allowlist is intersected with the engines the key is bound to.

### `tools`

| Field            | Type                                           | Meaning                                                                                                                     |
| ---------------- | ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `platform_packs` | array of `"platform.read"`, `"platform.write"` | Server-executed tool packs. `platform.write` requires `platform.read`. See [Platform tools](/conversations/platform-tools). |
| `client_tools`   | array of client tool objects                   | Tools your application executes. See [Client tools and confirmations](/conversations/client-tools).                         |

A client tool:

| Field                   | Type                                       | Rules                                                                                                                                             |
| ----------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`                  | string                                     | Matches `^[a-zA-Z0-9_-]+$`, contains no `__`, at most 64 characters, unique in the config.                                                        |
| `description`           | string                                     | Shown to the model.                                                                                                                               |
| `input_schema`          | JSON Schema object                         | Must compile. Every call the model makes is validated against it; a call that fails is answered to the model as an error and never handed to you. |
| `effect`                | `read`, `write`, `outbound`, `destructive` | Required. `write`, `outbound`, and `destructive` always pause for a confirmation.                                                                 |
| `requires_confirmation` | boolean, optional                          | `true` makes a `read` tool pause for a confirmation. `false` on a `write`, `outbound`, or `destructive` tool is rejected.                         |

```json theme={null}
{
  "name": "open_supplier_record",
  "description": "Open the named supplier record in the user's screen.",
  "input_schema": {
    "type": "object",
    "properties": { "supplier_id": { "type": "string" } },
    "required": ["supplier_id"]
  },
  "effect": "read"
}
```

### `components`

An array of `{component, version, props_schema}` declarations. `component` is non-empty, `version` is at least 1, and `component@version` is unique. A `component` frame is emitted only for a declared identity whose props validate against `props_schema`. No platform tool emits a component today, so declaring one has no effect on turns yet.

### `data_sources`

At least one entry. Each entry is either `{sources, notes}` or `{ref}`, never both.

`sources` lists data-access keys. A tool whose key is not enabled is absent from the turn, not refused, and the system prompt tells the model what it can and cannot read.

| Key            | What it enables                                                                                                          | Tools in API-key conversations                     |
| -------------- | ------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------- |
| `engines`      | The org's engines, versions, and groups                                                                                  | Yes                                                |
| `runs`         | Run status, timing, and errors, plus run traces                                                                          | Yes, except run traces, which are portal chat only |
| `run_payloads` | The input a run was given and the output it produced                                                                     | Yes                                                |
| `metrics`      | Run counts by engine and status over a time range                                                                        | No, portal chat only                               |
| `catalog`      | Records the organization's data connection serves, and the graph over them. See [Served data](/connections/served-data). | Yes                                                |
| `connections`  | Data connections, their type, sync history, and health                                                                   | No, portal chat only                               |
| `webhooks`     | Webhook endpoints and recent delivery outcomes                                                                           | Yes                                                |
| `feedback`     | Ratings and comments left on assistant answers, and assistant usage                                                      | No, portal chat only                               |
| `team`         | The signed-in seat's team, derived at read time from the connected system of record                                      | No, portal chat only                               |

The tools behind each key are listed on [Platform tools](/conversations/platform-tools).

A config whose only declared key is `catalog` (the default shape) enables `catalog`, `engines`, `runs`, `metrics`, `connections`, and `webhooks`. Naming any other key switches to the literal list: only the keys you name are enabled. `run_payloads`, `feedback` and `team` are never enabled by that default; name them to turn them on.

`ref` is accepted and grants nothing today. `notes` is free text for authors.

### `access`

`personas` is a non-empty array of strings; `"*"` means any persona. The value is validated and stored. The platform does not check it on turns today.

### `limits`

| Field                    | Bounds      | Default | Meaning                                                                                                                             |
| ------------------------ | ----------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `max_tool_rounds`        | 1 to 50     | 12      | Model rounds that may call tools in one turn. After the last one the model gets one more round with no tools to write its answer.   |
| `max_turn_output_tokens` | 1 to 128000 | 32000   | Output tokens across every round of the turn, including resumes. When spent, the turn ends with `stop_reason: "max_output_tokens"`. |
| `max_history_messages`   | 1 to 100    | 60      | Stored messages replayed to the model on each turn.                                                                                 |

### `guardrails`

Three rule families: `refusal_domains`, `escalation_rules`, `output_checks`. Rule ids are unique across all three, and every rule lists at least one eval scenario id in `scenarios`. See [Guardrails](/conversations/guardrails).

### `evals`

`on_regression` is `block` or `warn`. It decides whether a publish that regresses a gate scenario is refused or released with the result recorded. See [Versions and publish](/conversations/versions-and-publish).

### `retention`

`conversation_days` is `null` (keep conversations) or a positive integer. The legacy name `thread_days` is still read. See [Export and retention](/conversations/export-and-retention).

### `annotations`

`enabled` is a boolean. It is validated and stored. The platform does not check it when an annotation is created today, so annotations are accepted either way.

### `attachments` (optional)

Absent or `enabled: false` means the instance takes no files.

| Field                   | Bounds                     | Meaning                                                                                                                                                                     |
| ----------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`               | boolean                    | Turns uploads on.                                                                                                                                                           |
| `max_files_per_message` | 0 to 10                    | Attachments one message may carry. `0` means 5.                                                                                                                             |
| `max_bytes_per_file`    | 0 to 39,321,600            | Per-file limit in bytes. `0` means the ceiling, 37.5 MiB.                                                                                                                   |
| `accepted_media_types`  | array of media types       | Narrows the accepted set. Empty means every type the platform accepts. A type outside the platform list, or a container type while `unwrap_archives` is false, is rejected. |
| `unwrap_archives`       | boolean                    | Accepts `.zip` and `.eml` containers and opens them. A turn also needs it to read the files of an uploaded folder.                                                          |
| `retention_days`        | positive integer or `null` | How long stored files live. `null` follows the conversation.                                                                                                                |

See [Attachments](/conversations/attachments).

## Legacy shapes still read

Older configs keep working. When a stored config is read, `retention.thread_days` becomes `retention.conversation_days`, a single `data_scope` object becomes a one-entry `data_sources` list, and the retired `model_policy.default_model` and `model_policy.deep_model` fields are ignored, so released versions that carry them still run. A new save or a publish that includes either retired field is refused with `invalid_instance_config` and the message "field is retired: every configured assistant uses gpt-6-sol".

## What you configure (portal)

* **Conversations**, then the instance, then **Config**: edit every section. The **Data access** checkboxes set `data_sources` and show whether each source is available in your org.

## What you call (API)

* [Get an instance](/api-reference/conversations/instances/get-instance) returns the draft config and its `config_hash`.
* [Update an instance](/api-reference/conversations/instances/update-instance) replaces the draft config. Organization API keys only.

<CardGroup cols={2}>
  <Card title="Versions and publish" href="/conversations/versions-and-publish">
    Release the draft through the eval gate.
  </Card>

  <Card title="Client tools and confirmations" href="/conversations/client-tools">
    Run your own tools inside a turn.
  </Card>
</CardGroup>
