<!-- Source: https://docs.squirro.com/en/latest/technical/neo/admin-guide/agent-config/resource-reference.html -->
# Resource Reference

> **Warning**
>
> Project Neo is currently in [Technical Preview](../../../../a-z/squirro-glossary.md#term-Technical-Preview). Features described in this section may change before general availability.

Configuration is made up of typed resources, and each kind has its own set of fields. This page is the field-by-field reference for every kind: which fields are required, their types, their allowed values and defaults, and a minimal working example for each. For the conceptual model behind resources and preferences, see the [Overview](overview.md#neo-agent-config-overview) page. For the authoring workflow and worked examples, see the [Authoring Agents](authoring-agents.md#neo-agent-config-authoring) page.

## Common Structure

Every authored file begins with the same envelope:

- **kind**

  The resource kind, for example `Model` or `Agent`. Case-sensitive, and it must match the exact spelling used in this reference.
- **schema**

  The schema version of the kind. The current version is `v1`.
- **metadata.id**

  The identifier for the resource, such as `claude-sonnet`. Two resources of the same kind cannot share one. Whether you write it depends on the kind. A project can hold any number of `Model`, `Agent`, `MCP`, `KnowledgeGraph`, and `TraitDimension` resources, so each one needs an identifier to tell it apart from the rest. The remaining three kinds occur once at most, so they carry no identifier: every project has exactly one `Project`, and `DocumentSourceSettings` and `CodeInterpreter` are each written once or left out.

An identifier consists of letters, digits, underscores, and hyphens, and it starts with a letter. Letters can be upper or lower case. For example, `claude-sonnet`, `deep_research`, `kg2`, and `Assistant` are valid, while `2nd-model` starts with a digit, `deep research` contains a space, `company.kg` contains a dot, and `research!` contains a symbol, so all four are rejected at deploy.

The resource kinds that surface in the Chat interface also accept two optional display fields, `title` and `summary`. Both are cosmetic labels shown in pickers and detail views, and neither affects how a request resolves. When `title` is omitted, the Chat interface falls back to the resource identifier.

The fields of each kind are a fixed set, and every resource forbids unknown fields. A misspelled field name, or a custom field of your own such as `internalref: EDFGGA654`, causes the deploy to fail rather than being silently ignored. To attach your own reference to a resource, add a YAML comment, which the parser ignores and which stays in your version-controlled files. To attach metadata to a whole deploy instead, use a deploy label, described on the [CLI Reference](cli-reference.md#neo-agent-config-cli) page. For example, a comment records the internal reference without adding a field:

```text
---
kind: Agent
schema: v1
metadata:
  id: research
# internalref: EDFGGA654
entrypoint: true
---

You are a research analyst...
```

### Writing a Description

Several kinds also accept a `description`, and on two of them it is not a display field. Where `title` and `summary` are written for people, these descriptions are written for the agents. A `KnowledgeGraph` description is advertised to an agent alongside the graph identifier and title, so it is what the agent goes on when deciding whether to query that graph rather than another. An `Agent` description is what a calling agent reads when choosing among the delegates available to it. In both cases a vague description does not merely read poorly, it leads the agent to the wrong choice or to no choice at all.

Write it as a selection rule rather than a label. Say what the resource covers and when to reach for it. This description gives an agent enough to act on:

```text
description: Company product and organizational graph. Query it for team ownership, reporting lines, and product hierarchy.
```

Whereas this one names the resource without saying when it applies:

```text
description: Company knowledge graph.
```

Three habits keep descriptions useful:

- **Name the boundary, not just the subject.** What the resource does not cover is as informative as what it does, because it tells the agent when to look elsewhere.
- **Keep them distinct from each other.** Two delegates with near-identical descriptions give a calling agent no basis to choose between them, and it will pick one more or less at random.
- **Describe, do not insist.** Wording such as _always use this first_ pushes an agent to reach for a resource in situations it does not fit. State the fit and let the agent judge.

A `description` is optional on most kinds, but it is **required on any agent with** `delegate: true`. A deploy fails without one, because a calling agent would have nothing to go on when choosing among delegates.

## Predicate Syntax for Constraints

Both the `Project` and an `Agent` accept a `constrains` block, which restricts the values a preference path allows. The block is keyed by preference path, and each entry is a predicate written in the small language below.

| Predicate | Meaning |
| --- | --- |
| `in` | The value must be one of a list, for example `{in: [claude-sonnet, claude-opus]}`. |
| `not_in` | The value must not be one of a list. |
| `gt`, `ge`, `lt`, `le` | Numeric comparisons: greater than, greater than or equal, less than, less than or equal. |
| `matches` | The value must match an anchored regular expression, for example `{matches: "claude-.*"}`. |

Three paths constrained at once:

```text
constrains:
  inference.model:
    in: [claude-sonnet, claude-opus]
  source.documents.limit:
    le: 50
  trait.style:
    not_in: [verbose]
```

A predicate can carry several clauses, and a value has to satisfy all of them. This one admits a limit from 10 to 50:

```text
constrains:
  source.documents.limit:
    ge: 10
    le: 50
```

Clauses that contradict each other admit no value at all, so `genai lint` rejects them rather than letting you deploy a path nothing can satisfy. `ge: 50` together with `lt: 10` is reported as unsatisfiable.

A value that falls outside a predicate does not fail the request. The resolver passes over it and carries on to the next source, so an agent that constrains `inference.model` to two models simply ignores a user who asks for a third, and answers with whatever the agent or the project prefers instead.

> **Note**
>
> The pattern in a `matches` constraint is an anchored regular expression that must match the entire value. It is a different language from the shell-style wildcards used in conditional segments of agent instructions.

## Authentication

The `Model` and `KnowledgeGraph` kinds reach external services through an `auth` block that accepts any of the variants below. The `CodeInterpreter` kind authenticates the same way, but accepts only the `bearer` variant, nested under `backend.auth`. The block never contains credential material. Instead, a variant that needs a credential carries a `secret` handle, a name bound to a credential stored securely on the cluster. The platform resolves the handle at request time. For how to register a handle, see the [Registering a Handle](#neo-agent-config-register-handle) section.

When the `auth` block is omitted, the connection is unauthenticated. When it is present, `type` is required and selects one of the following variants.

| `type` | Fields | Description |
| --- | --- | --- |
| `bearer` | `secret` | Static bearer-token authentication. `secret` is the handle that resolves to the token. |
| `basic` | `secret` | HTTP basic authentication. `secret` resolves to the user name and password pair. |
| `aws_sigv4` | `secret`, `region` | AWS Signature Version 4 authentication, for example for Amazon Bedrock. `secret` resolves to the AWS credentials, and `region` is the signing region. |
| `oauth` | none | OAuth authentication, where each user authorizes the service themselves rather than sharing one credential. The platform stores each user token and uses the one belonging to the person making the request, so there is no `secret` handle to declare and nothing for an operator to register. |

A minimal bearer block:

```text
auth:
  type: bearer
  secret: anthropic_token
```

### Registering a Handle

A handle is a name, not a value. You author the name in the `auth` block, and the name travels in the deployed configuration. The credential itself is bound to the handle separately, on the cluster, and never appears in the project. This split means the person who authors the configuration does not need to hold the provider API key, and the key is never committed to version control.

Registering a handle is a two-part responsibility:

- **You (the configuration author)** choose a handle name and reference it from the `auth` block of a `Model`, `KnowledgeGraph`, or `CodeInterpreter` resource.
- **An operator** binds that handle to the real credential on the cluster, using the mechanism below. Binding is a deployment operation, so it is performed by whoever manages the GenAI service configuration, not from within the project.

During Technical Preview, the operator provides the credential to the GenAI service as an environment variable whose name is `SQ_` followed by the handle name in uppercase. For the handle `anthropic_token`, the variable is `SQ_ANTHROPIC_TOKEN`. The variable set depends on the `auth` type:

| `auth.type` | Environment variables for a handle named `<handle>` |
| --- | --- |
| `bearer` | `SQ_<HANDLE>` holds the token. |
| `basic` | `SQ_<HANDLE>_USERNAME` and `SQ_<HANDLE>_PASSWORD`. |
| `aws_sigv4` | `SQ_<HANDLE>_ACCESS_KEY_ID` and `SQ_<HANDLE>_SECRET_ACCESS_KEY`, with an optional `SQ_<HANDLE>_SESSION_TOKEN`. |
| `oauth` | None. Each user authorizes the service themselves, so there is no shared credential and no handle to bind. |

Deploy verifies that every referenced handle resolves and that the resolved credential matches the `auth` type. A handle that is missing or unbound fails the deploy with a `422` response, and the previous snapshot stays in place. A handle that resolves at deploy time but is later removed causes the resource that references it to become unavailable at runtime.

Rotating or revoking a credential is done at the cluster, by replacing the bound value. The project is not affected and does not need to be redeployed, because it references the handle name, not the value.

## Project

The project manifest, introduced on the [Overview](overview.md#neo-agent-config-overview) page. Every configuration must have exactly one, so a deploy fails if it carries none and fails again if it carries two. A `Project` has no `metadata.id`, and by convention it is written in a file named `project.yaml`, although the platform reads the `kind` rather than the file name.

| Field | Type | Requirement | Description |
| --- | --- | --- | --- |
| `prefers` | map of path to value | Optional, empty by default | Project-wide soft defaults, keyed by preference path. |
| `constrains` | map of path to predicate | Optional, empty by default | Project-wide restrictions on which values a path allows. See the [Predicate Syntax for Constraints](#neo-agent-config-predicates) section. |
| `pins` | map of path to value | Optional, empty by default | Project-wide locked values that nothing can override. |
| `instructions` | string | Optional | A default chat body used when a request resolves without a selected agent. |
| `context_budget` | object | Optional, defaults listed below | Policy that keeps each turn within the model context window. |
| `hitl` | object | Optional, no rules by default | Operator approval policy for tool calls. |
| `title` / `summary` | string | Optional | Display label and description. |

The `context_budget` object controls two independent safety behaviors. It is policy, not a preference, so a user or a request cannot turn it off.

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `tool_output_pruning` | boolean | `true` | Clear older tool results once their token count crosses the trigger. |
| `tool_output_pruning_trigger_tokens` | integer | `100000` | Token count above which older tool results are cleared. Match it to the window of the models you run. |
| `keep_recent_tool_results` | integer | `4` | Number of most-recent tool results never cleared by pruning. |
| `turn_truncation` | boolean | `true` | Drop the oldest whole turns when the input approaches the model context window. |
| `turn_truncation_trigger_fraction` | number | `0.9` | Fraction of the context window that turn truncation aims to stay below. |
| `keep_recent_turns` | integer | `4` | Number of most-recent turns that turn truncation always preserves. |

The `hitl` object holds an ordered list of approval `rules`. Each rule matches a tool by name and assigns a disposition. The last matching rule wins. For what the dispositions mean and how these rules combine with the rules on a scheduled task, see the [Scheduled Tasks and Approvals](tasks-and-approvals.md#neo-agent-config-tasks) page.

| Field | Type | Requirement | Description |
| --- | --- | --- | --- |
| `pattern` | string | Required | A glob matched against the tool name visible to the model. |
| `disposition` | string | Required | One of `approve` (let the call run without asking anyone), `reject` (refuse the call), `interactive` (ask the person in the conversation to approve the call), `defer` (park the run and wait for someone to approve the call later), or `hide` (take the tool away from the agent). |

Example, the manifest authored as `project.yaml`:

```text
kind: Project
schema: v1
title: Research workspace

prefers:
  inference.model: claude-sonnet

context_budget:
  turn_truncation: true
  tool_output_pruning: true

hitl:
  rules:
    - pattern: "delete_*"
      disposition: reject
    - pattern: "send_email"
      disposition: approve
```

## Model

An agent, a user, or a request selects a model through the `inference.model` preference, whose value is the `metadata.id` of a `Model` resource.

| Field | Type | Requirement | Description |
| --- | --- | --- | --- |
| `provider` | string | Required | The model provider, for example `anthropic` or `openai`. |
| `model_name` | string | Required | The model identifier as the provider publishes it, for example `claude-sonnet-5`. For where to find it, see the [Model Providers](#neo-agent-config-model-providers) section. |
| `auth` | object | Optional | The authentication block used to reach the provider. See the [Authentication](#neo-agent-config-authentication) section. |
| `description` | string | Optional | Prose describing the model, recorded in the configuration for your own reference. |
| `group` | string | Optional | A label for grouping models in the Chat interface. |
| `backend_kwargs` | map | Optional, empty by default | Additional provider parameters passed through to the model backend. |
| `enable_reasoning` | boolean | Optional, default `false` | Authorizes the platform to send reasoning parameters to this model. Leave off unless the model supports reasoning at the provider and version you have configured. |
| `enable_image_input` | boolean | Optional, default `false` | Authorizes this model to receive image content. Leave off unless the model accepts images at the provider and version you have configured. |
| `context_window` | integer | Optional, the provider profile by default | Maximum input tokens the model accepts, used by the context budget. Set it to the real window for smaller-window models so truncation engages before the provider rejects the request. |
| `title` / `summary` | string | Optional | Display label and description. |

Example, a model authored as `models/claude-sonnet.yaml`:

```text
kind: Model
schema: v1
metadata:
  id: claude-sonnet

provider: anthropic
model_name: claude-sonnet-5
auth:
  type: bearer
  secret: anthropic_token
```

### Model Providers

On a `Model` resource, `provider` selects which backend the platform routes to. The platform supports the following providers. A `provider` value outside this set is not rejected at deploy time. Instead, the model fails when a request first tries to use it, so check the spelling against the table below.

| `provider` | Example `model_name` | Notes |
| --- | --- | --- |
| `anthropic` | `claude-sonnet-5` | Anthropic Claude models. |
| `openai` | the OpenAI model ID | OpenAI models. |
| `google` | the Gemini model ID | Google Gemini models. |
| `azure` | the Azure deployment name | Azure OpenAI. Supply the endpoint, API version, and deployment name through `backend_kwargs`. |
| `cerebras` | the Cerebras model ID | Cerebras-hosted models. |

Write `model_name` exactly as the provider spells it. The platform does not check the name at deploy, so a typo surfaces only when a request first tries to use the model. Take the value from the model list in the API documentation of the provider rather than from memory or from another tool, because providers rename and retire models over time.

Each supported provider authenticates with a bearer token. Set `auth.type` to `bearer` and reference a secret handle bound to the provider API key. For the full authentication reference, see the [Authentication](#neo-agent-config-authentication) section.

Provider-specific parameters, such as sampling options or the Azure endpoint, API version, and deployment name, are passed through `backend_kwargs`. The platform forwards these to the provider as written, and a user or a request cannot override them.

Example, an OpenAI model authored as `models/gpt-5.yaml`:

```text
kind: Model
schema: v1
metadata:
  id: gpt-5

provider: openai
model_name: gpt-5.2
auth:
  type: bearer
  secret: openai_token
```

Example, a Google Gemini model with a provider-specific parameter, authored as `models/gemini-flash.yaml`:

```text
kind: Model
schema: v1
metadata:
  id: gemini-flash

provider: google
model_name: gemini-3.5-flash
auth:
  type: bearer
  secret: google_token
backend_kwargs:
  temperature: 0.2
```

## Agent

An agent is authored in one of two file formats. A `.md` agent carries its instructions as the markdown body after the frontmatter. A `.yaml` agent carries configuration only and is typically used as a shared template through `extends`.

| Field | Type | Requirement | Description |
| --- | --- | --- | --- |
| `prefers` | map of path to value | Optional, empty by default | Soft defaults the user can override. |
| `constrains` | map of path to predicate | Optional, empty by default | Restrictions on which values a path allows for this agent. See the [Predicate Syntax for Constraints](#neo-agent-config-predicates) section. |
| `pins` | map of path to value | Optional, empty by default | Locked values that nothing can override. |
| `extends` | list of identifiers | Optional, empty by default | Parent agents whose configuration folds into this one. Configuration composes through `extends`, instructions do not. |
| `description` | string | Required with `delegate: true` | Prose that a calling agent reads to decide whether to call this agent. |
| `entrypoint` | boolean | Optional, default `false` | Whether the agent appears in the conversation picker for users to select. |
| `delegate` | boolean | Optional, default `false` | Whether another agent can call this agent as a subagent. |
| `entrypoint_order` | integer | Optional | Display order in the picker for entrypoints, ascending, starting at zero. |
| `opening` | string | Optional | A static first message the agent speaks before the user does. When absent, the user starts the conversation. |
| `pin_to_conversation` | boolean | Optional, default `false` | When set, selecting this agent fixes it for the conversation, and later turns ignore attempts to switch agents. |
| `title` / `summary` | string | Optional | Display label and description. |

Example, an agent authored as a markdown file named `agents/assistant.md`. The `---` lines fence the frontmatter, which is YAML and holds the fields listed above. Everything after the closing fence is markdown, and it becomes the agent instructions:

```text
---
kind: Agent
schema: v1
metadata:
  id: assistant
entrypoint: true
prefers:
  inference.model: claude-sonnet
---

You are a helpful assistant. Answer questions clearly and concisely.
```

Example, a template authored as `agents/house-style.yaml`. A `.yaml` agent has no fences and no instructions, so the whole file is the field block. Because `entrypoint` and `delegate` both default to `false`, a template never appears in the picker and no agent can call it as a subagent:

```text
kind: Agent
schema: v1
metadata:
  id: house-style

prefers:
  trait.style: concise
pins:
  capability.code_interpreter.enabled: false
```

Another agent, `agents/research.md`, folds that template in through `extends` and adds its own instructions:

```text
---
kind: Agent
schema: v1
metadata:
  id: research
entrypoint: true
extends:
  - house-style
---

You are a research analyst. Cite a source for every claim.
```

## TraitDimension

A `TraitDimension` resource groups reusable prompt fragments under one name. The `metadata.id` is the dimension name, and it appears in preference paths as `trait.<id>`. Agents and the project activate a trait through the `trait.<dimension>` preference.

| Field | Type | Requirement | Description |
| --- | --- | --- | --- |
| `traits` | map of identifier to trait | Required | The trait entries in the dimension, each keyed by a unique identifier. |

Each trait entry carries the following fields:

| Field | Type | Requirement | Description |
| --- | --- | --- | --- |
| `prompt_fragment` | string | Required | The prose appended to the agent instructions when this trait is active. |
| `title` / `summary` | string | Optional | Display label and description. |

Example, a dimension authored as `trait-dimensions/style.yaml`. Markdown is only for agents, so every other kind, including this one, is written as YAML with no frontmatter fences:

```text
kind: TraitDimension
schema: v1
metadata:
  id: style

traits:
  concise:
    prompt_fragment: |
      Keep your responses tight. No preamble, no recap.
  detailed:
    prompt_fragment: |
      Be exhaustive. Walk through your reasoning and cite each step.
```

## KnowledgeGraph

A `KnowledgeGraph` resource points at a SPARQL endpoint the agents can query. Retrieval is active only when `source.knowledge_graph.enabled` resolves to `true`, at which point every `KnowledgeGraph` resource the project publishes becomes reachable.

| Field | Type | Requirement | Description |
| --- | --- | --- | --- |
| `endpoint.sparql` | URL | Required | The SPARQL query endpoint URL. |
| `auth` | object | Optional | The authentication block used to reach the endpoint. See the [Authentication](#neo-agent-config-authentication) section. |
| `timeout_s` | integer | Optional, default `5` | Query timeout in seconds. |
| `lang` | string | Optional, default `en` | Language code used for the query. |
| `format` | string | Optional, default `table` | Result format returned to the agent. |
| `variant` | string | Optional, default `agent` | Query variant used against the endpoint. |
| `prefixes` | map of string to string | Optional, empty by default | Namespace prefixes made available to queries. |
| `description` | string | Optional | Prose describing the graph, advertised to the agents that can query it. |
| `title` / `summary` | string | Optional | Display label and description. |

Example, a graph authored as `knowledge-graphs/company_kg.yaml`:

```text
kind: KnowledgeGraph
schema: v1
metadata:
  id: company_kg

endpoint:
  sparql: https://kg.example.com/sparql
auth:
  type: bearer
  secret: kg_token
description: Company organizational and product knowledge graph.
```

## MCP

An `MCP` resource points at an external Model Context Protocol server. Its tools are active only when `capability.mcp.enabled` resolves to `true`, at which point every `MCP` resource the project publishes becomes reachable.

| Field | Type | Requirement | Description |
| --- | --- | --- | --- |
| `url` | URL | Required | The server URL. |
| `transport` | string | Optional, default `sse` | The transport used to reach the server, either `sse` or `streamable_http`. |
| `auth_mode` | string | Optional, default `anonymous` | How the platform authenticates to the server. One of `anonymous`, `static_bearer`, or `per_user_oauth`. |
| `bearer_handle` | string | Required with `static_bearer` | The secret handle resolving to the shared bearer token. Not accepted for the other two modes. |
| `requires_approval` | boolean | Optional, default `true` | Whether tool calls on this server require human approval before they run. |
| `tool_approval_overrides` | map of string to boolean | Optional, empty by default | Per-tool approval overrides, keyed by the upstream tool name. A value of `false` runs the named tool without approval, and `true` requires it. |
| `description` | string | Optional | Prose describing the server, recorded in the configuration for your own reference. The tools the server exposes carry their own descriptions, which is what an agent reads when it decides to call one. |
| `title` / `summary` | string | Optional | Display label and description. |

The three `auth_mode` values are:

- **anonymous**

  The server is open or trusts the cluster network. No handle is declared.
- **static_bearer**

  A single shared bearer token, named by `bearer_handle`.
- **per_user_oauth**

  Each user authorizes the server individually. The platform looks up the per-user token at runtime, so no handle is declared.

Example, a server authored as `mcp/tickets.yaml`:

```text
kind: MCP
schema: v1
metadata:
  id: tickets

url: https://mcp.example.com/
transport: streamable_http
auth_mode: static_bearer
bearer_handle: tickets_token
requires_approval: true
```

## DocumentSourceSettings

A `DocumentSourceSettings` resource sets how the agents search and read documents. A project has one at most, and it carries no `metadata.id`. The `implementation` field selects the retrieval engine for the whole deployment, which changes the tools an agent sees and the citation contract, so it is a deployment-wide decision rather than a per-turn setting.

| Field | Type | Requirement | Description |
| --- | --- | --- | --- |
| `implementation` | string | Optional, default `split` | The retrieval engine. `split` gives the agent a two-step search-then-fetch retriever that controls read depth. `legacy` gives the earlier single-step retriever. |
| `default_search_count` | integer | Optional, default `10` | Number of results a search returns. Applies to the `split` engine. |
| `split_fetch_budget_tokens` | integer | Optional, default `128000` | Token budget for a single fetch. Applies to the `split` engine. |
| `fetch_timeout_s` | integer | Optional, default `120` | Per-request retrieval timeout in seconds. Applies to both engines. |

The `legacy` engine accepts additional advanced tuning fields: `retrieval_mode`, `fetch_top_n_search`, `fetch_top_n_summarize`, `context_expansion`, `intent_filters`, `semantic_profile_config`, `phrase_filter`, and `retrieval_budget_tokens`. These fields have no effect under the `split` engine, and `genai lint` warns when a `split` deployment sets them. Squirro recommends the `split` engine for new projects.

Example, the settings authored as `document-source-settings.yaml`:

```text
kind: DocumentSourceSettings
schema: v1

implementation: split
default_search_count: 10
```

## CodeInterpreter

A `CodeInterpreter` resource sets up the sandbox the agents run code in. A project has one at most, and it carries no `metadata.id`. Code execution is active only when `capability.code_interpreter.enabled` resolves to `true`.

The `backend` object selects the execution provider through its `type` field. The supported backend is `openai`.

| Field | Type | Requirement | Description |
| --- | --- | --- | --- |
| `backend.type` | string | Required | The execution provider. The supported value is `openai`. |
| `backend.model_name` | string | Required | The model identifier as the provider publishes it, used for code execution. As with a `Model` resource, the name is not checked at deploy. |
| `backend.auth` | object | Required | A `bearer` authentication block whose `secret` handle resolves to the provider token. |

Example, the sandbox configuration authored as `code-interpreter.yaml`:

```text
kind: CodeInterpreter
schema: v1

backend:
  type: openai
  model_name: gpt-5.2
  auth:
    type: bearer
    secret: openai_token
```
