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

# Get an agent conversation

> Fetches the conversation's metadata plus its current `version`. Use the `version`
immediately before posting a run as `expected_version` — that's how the platform's
compare-and-swap guard knows whether the conversation has advanced since you last
looked.

## When to call this

- Before starting a new run: read `version`, post it as `expected_version`. If you
  cache the value across long delays you'll hit
  [Version Conflict](https://docs.narrative.io/reference/architecture/agent-conversations/errors/version-conflict)
  more often.
- When resuming a `requires_action` run: the conversation's version has advanced
  because the assistant turn was persisted on the run row's finalize. Re-read it
  before posting `tool_outputs`.
- To inspect a conversation's `defaults` if you've forgotten what was pinned.

## What you cannot do here

There is no `PATCH` / `PUT` for conversations. The `system_prompt` and `defaults` are
immutable at the conversation level. To change behavior, override per-run via
`config_override`, or create a new conversation.

## Scope: per-user, not per-company

Conversations are scoped to the **`(company_id, user_id)`** pair that created them.
Peers in the same company cannot see each other's conversations — the endpoint
returns 404 for "does not exist", "belongs to a different company", and "belongs to
a different user in the same company" alike. This is deliberate: distinguishing them
would leak existence.

## Permission

`agent_conversations` resource with `read` verb.



## OpenAPI

````yaml https://docs-cdn.narrative.io/api-reference/main/openapi.json get /agents/conversations/{id}
openapi: 3.1.1
info:
  contact:
    email: support@narrative.io
    name: Narrative Support
    url: https://www.narrative.io
  termsOfService: https://www.narrative.io/legal/terms-of-service
  x-logo:
    url: >-
      https://cdn.narrative.io/images/company-logos/prod/narrative-logo-text-white.svg
    backgroundColor: rgb(9, 34, 166)
    altText: Narrative Logo
  description: >-
    The [Narrative Data Collaboration Platform](https://app.narrative.io) API is
    organized around REST. Our API has predictable resource-oriented URLs,
    accepts form-encoded request bodies, returns JSON-encoded responses, and
    uses standard HTTP response codes, authentication, and verbs.



    The current version is a pre-release beta.  It may result in unexpected
    behavior and there may be breaking changes in future releases up to the 1.0
    release.
  title: Narrative Data Collaboration Platform API
  version: 2.4.x
servers:
  - url: https://api-dev.narrative.io
  - url: https://api.narrative.io
security: []
tags:
  - name: Access Rules
    description: >-
      Access rules let data providers control who can purchase their data and
      the terms of purchase.


      The `access-rules` API allows you to manage access rules for your
      datasets.


      Related guides:
        - [What is an access rule?](https://kb.narrative.io/access-rules)
  - name: Agent Conversations
    description: >-
      Build LLM-driven workflows that can call MCP tools, ask the caller for
      input, and return structured answers.


      A conversation pins a model, a system prompt, and a tool catalog. Each run
      sends the model a user message (or

      a batch of tool outputs from a previously-paused run); the model decides
      whether to answer directly, call a

      server-side tool (resolved by the platform via Model Context Protocol), or
      call a client-side tool (which pauses

      the run with `requires_action` and waits for the caller to reply).


      Related guides:
        - [Agent Conversations Reference](https://docs.narrative.io/reference/architecture/agent-conversations)
        - [Error catalog](https://docs.narrative.io/reference/architecture/agent-conversations/errors/conversation-not-found)
  - name: MCP Connections
    description: >-
      Connect external (non-Narrative) MCP servers so agent runs can call their
      tools with the

      calling user's own OAuth authorization.


      A connection is created interactively: `POST /mcp-connections` runs OAuth
      discovery and

      Dynamic Client Registration against the server and returns a consent URL;
      the user authorizes

      in a browser; the authorization server redirects to `GET
      /mcp-connections/callback`, which

      finishes the token exchange and marks the connection `connected`. Tokens
      are stored encrypted

      and used server-side — they are never returned by the API. Once connected,
      reference the

      connection by id from an agent run's `mcp_servers[].connection_id`.
  - name: App Invites
    description: >-
      App invites allow applications to create one-time, shareable links on
      behalf of their users. These links

      enable users to invite third parties who do not have a Narrative account
      to perform actions within the

      application.


      For example, a Narrative user can send an invite link to a third party who
      then completes a Pinterest

      OAuth flow and creates a connector profile in the inviter's account,
      allowing the inviter to deliver

      audience data to the third party's Pinterest account without the third
      party needing a Narrative account.


      This API is intended to be used by applications (via app client
      credentials) to create and manage invites

      on behalf of their users, which can then be shared with invitees.
  - name: Apps
    description: >-
      Apps are applications bundled with a UI that can perform various actions
      on behalf of a user utilizing the Narrative API.

      Related guides:
        - [Building a Narrative Native App](https://www.narrative.io/knowledge-base/how-to-guides/building-a-narrative-native-app)
  - name: Access Tokens
    description: API Access Token management
  - name: Attributes
    description: >-
      An attribute models a standardized data point available for sale on the
      Narrative marketplace.


      Narrative automatically turns data points from provider datasets into
      attributes so that buyers can purchase well-formed, standardized data from
      any supplier on the marketplace.
  - name: Auth
    description: >-
      API token is a crucial step for developers to securely authenticate
      requests to the Narrative API

      Related guides:
        - [How to Create an API Token](https://www.narrative.io/knowledge-base/how-to-guides/understanding-narratives-apis/create-an-api-token)
  - name: Authentication
    description: User login and registration
  - name: Billings
    description: Used by Narrative internally to bill customers
  - name: Companies
    description: A collection of employees
  - name: Company Marketing Information
    description: Useful information related to companies
  - name: Compute Pools
    description: >-
      Compute pools represent compute resources (e.g. Snowflake warehouses)
      provisioned within a data plane.

      Companies can manage and share compute pools, assign them to jobs, and set
      a default compute pool on data planes.
  - name: Connections
    description: Associations between connectors and datasets
  - name: Data Shops
    description: |-
      Self-hosted website to sell your data
      Related guides:
        - [Setting up your datashop](https://www.narrative.io/knowledge-base/how-to-guides/shop-builder/settting-up-your-data-shop)
  - name: Data Streams
    description: >-
      The `data-stream` API endpoints allows one to create and update
      data-streams. Additionally the endpoints allow

      finding data-streams using free text search. A few of the endpoints are
      behind authorization.


      Update endpoint allows a client to post an edited data-stream document as
      is, without having to change its shape.

      The API ensures that only certain fields are allowed to be modified.
      Attempts to modify fields not up for client

      modifications are ignored.


      Related guides:
        - [What is a data stream?](https://kb.narrative.io/what-is-a-data-stream)
  - name: Contracts
    description: Contracts related APIs
  - name: Datasets
    description: >-
      Any kind of data, in any schema, can be pushed into the Narrative Data
      Collaboration Platform as a dataset exactly as it is stored in your own
      system.


      The `datasets` API allows you to manage your datasets.
  - name: Destinations
    description: >-
      Destinations associate a subscription to a profile. Optionally, ad-hoc
      quick settings can be configured to a destination.

      Those quick settings have to match the format defined on the app manifest.
  - name: Installations
    description: Installations of Applications for a profile
  - name: Jobs
    description: >-
      Jobs represent an operation done on a given data plane. All jobs today are
      tied to a query that represents a forecast or a materialized view.


      The jobs API provides an interface for interacting with the jobs table,
      which stores various operations involving reading or writing data. This
      API allows users to retrieve detailed information about specific jobs,
      including cost forecasts, data forecasts, NQL forecasts and materialized
      views.
  - name: Mappings
    description: >-
      A mapping is a transformation from a dataset to an attribute. Defining a
      mapping between a dataset and an attribute makes the dataset eligible to
      participate in subscriptions where a buyer is purchasing the target
      attribute.
  - name: Model Inference
    description: Model Inference
  - name: Models
    description: >-
      Machine learning models for training and inference.


      Models can be stored in HuggingFace or Narrative repositories and have
      configurable

      collaborator permissions for training and inference access.


      The `models` API allows you to list, retrieve, and update models
      accessible to your company.
  - name: NQL
    description: >-
      Narrative Query Language (NQL) is a specialized, SQL-inspired language
      designed to query and manipulate data within the Narrative platform. While
      it looks and feels much like standard SQL, it offers extended
      functionality and syntax that let you leverage platform-specific
      features—such as referencing datasets by their IDs, creating materialized
      views, or generating forecasts—without having to manage the complexities
      of different query engines behind the scenes. NQL queries can ultimately
      compile down to multiple underlying engines (e.g., Snowflake, Spark) to
      execute your requests efficiently in the Narrative ecosystem.
  - name: Payment Methods
    description: Payment methods used to purchase data
  - name: Products
    description: Internal routes used to offer datastream as products
  - name: Profiles
    description: >-
      App profiles are associated with an installation. They represent a
      reference to a configuration that the app can use to save confidential
      information outside of Narrative's control.

      Profiles are currently used to configure settings for connector apps.
  - name: Resources
    description: >-
      Narrative gives you access to managed resources, like your own AWS S3
      bucket, so that you can effortlessly buy and sell data on the platform.


      The `resources` API allows you to manage your resources.
  - name: Schema Inference
    description: >-
      The `schema-inference` API analyzes submitted files to automatically infer
      and return their structure as a dataset schema.
  - name: Schema Presets
    description: >-
      The `schema-presets` API allows you to list the available schema presets,
      get detailed information about a specific one and manage its life cycle.


      You can create a schema preset from scratch or create one based on an
      existing one, administrators can create platform wide available (public)
      schema preset.
  - name: Subscriptions
    description: >-
      In the Narrative Data Collaboration Platform a subscription represents a
      set of rules dictating the commercial terms related to the licensing of
      data.


      The `subscriptions` API allows you to set and get information about
      `subscription` objects owned by the authenticated account.
  - name: Uploads
    description: >-
      The `uploads` API allows you to send files to Narrative and use them to
      perform tasks like creating a list or adding data to a dataset.
  - name: Usage
    description: >-
      The `usage` API enables the recording of usage events associated with a
      product.
  - name: Workflows
    description: >-
      The `workflows` API allows you to create, schedule, trigger, and archive
      workflows.

      Workflows are defined using a serverlessworkflow YAML specification.
paths:
  /agents/conversations/{id}:
    parameters:
      - in: path
        name: id
        required: true
        schema:
          $ref: '#/components/schemas/ConversationId'
        description: The conversation's UUID.
    get:
      tags:
        - Agent Conversations
      summary: Get an agent conversation
      description: >-
        Fetches the conversation's metadata plus its current `version`. Use the
        `version`

        immediately before posting a run as `expected_version` — that's how the
        platform's

        compare-and-swap guard knows whether the conversation has advanced since
        you last

        looked.


        ## When to call this


        - Before starting a new run: read `version`, post it as
        `expected_version`. If you
          cache the value across long delays you'll hit
          [Version Conflict](https://docs.narrative.io/reference/architecture/agent-conversations/errors/version-conflict)
          more often.
        - When resuming a `requires_action` run: the conversation's version has
        advanced
          because the assistant turn was persisted on the run row's finalize. Re-read it
          before posting `tool_outputs`.
        - To inspect a conversation's `defaults` if you've forgotten what was
        pinned.


        ## What you cannot do here


        There is no `PATCH` / `PUT` for conversations. The `system_prompt` and
        `defaults` are

        immutable at the conversation level. To change behavior, override
        per-run via

        `config_override`, or create a new conversation.


        ## Scope: per-user, not per-company


        Conversations are scoped to the **`(company_id, user_id)`** pair that
        created them.

        Peers in the same company cannot see each other's conversations — the
        endpoint

        returns 404 for "does not exist", "belongs to a different company", and
        "belongs to

        a different user in the same company" alike. This is deliberate:
        distinguishing them

        would leak existence.


        ## Permission


        `agent_conversations` resource with `read` verb.
      operationId: getAgentConversation
      responses:
        '200':
          description: The conversation row.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConversationResponse'
        '401':
          description: Missing or invalid bearer token.
        '403':
          description: Token does not have `agent_conversations:read` permission.
        '404':
          description: >-
            Conversation does not exist, belongs to a different company than the
            token's, or

            was created by a different user in the same company. The response
            body's `type`

            URL is

            `https://docs.narrative.io/reference/architecture/agent-conversations/errors/conversation-not-found`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RFCError'
      security:
        - BearerAuth: []
components:
  schemas:
    ConversationId:
      description: >-
        UUID identifying a conversation. Returned from `POST
        /agents/conversations` and used

        in every other agent endpoint that operates on this conversation.
      type: string
      format: uuid
      example: bc2505b7-068d-44ed-8055-a6f6ffe54ab1
    ConversationResponse:
      description: >-
        The conversation row as the API returns it. The same shape comes back
        from

        `POST /agents/conversations` (201 Created) and `GET
        /agents/conversations/{id}` (200 OK).
      type: object
      required:
        - id
        - company_id
        - user_id
        - defaults
        - version
        - created_at
        - updated_at
      properties:
        id:
          $ref: '#/components/schemas/ConversationId'
        company_id:
          type: integer
          description: >-
            Company ID derived from the bearer token. Pinned for the
            conversation's lifetime.
          example: 1
        user_id:
          type: integer
          description: >-
            User ID derived from the bearer token. Pinned for the conversation's
            lifetime and

            gates every subsequent read endpoint — only the originating user can
            fetch the

            conversation, its messages, or its runs. Peers in the same company
            see 404.
          example: 407
        name:
          type:
            - string
            - 'null'
        system_prompt:
          type:
            - string
            - 'null'
        defaults:
          $ref: '#/components/schemas/ConversationDefaults'
        version:
          $ref: '#/components/schemas/ConversationVersion'
        created_at:
          type: string
          format: date-time
          example: '2026-05-18T13:21:30.355180Z'
        updated_at:
          type: string
          format: date-time
          example: '2026-05-18T13:21:51.983952Z'
    RFCError:
      description: >-
        RFC 7807 Problem Details. Returned with `Content-Type: application/json`
        for every

        4xx/5xx response on `/agents/*`.


        **Field semantics:**


        - `type` — stable URL to the docs page describing this error class.
        Treat it as the
          machine-readable identifier; the same URL is referenced by `RunError.docs_url` on
          failed runs. Optional on 500 errors that don't map to a documented class.
        - `title` — short human-readable summary.

        - `status` — HTTP status code echoed in the body (so clients that read
        only the body
          can still dispatch on status).
        - `detail` — request-specific detail. Includes which alias was
        malformed, which
          `tool_use_id` was missing, etc.
        - `instance` — the API surface group (`/agents` for all agent
        endpoints). Stable —
          it's the prefix you call, not the full path.
        - `log_id` — UUID correlated with server logs. Always include this when
        reporting an
          issue to support.
        - `debug` — usually `null`. Reserved for richer payloads in specific
        failure modes.


        Common error pages indexed by `type`:


        | HTTP | Common cause | Docs page |

        |------|--------------|-----------|

        | 400 | Bad request body, validation failure | various — see `type` |

        | 404 | Resource not found, or owned by a different company |
        `/conversation-not-found`, `/agent-run-not-found` |

        | 409 | Conversation version moved while you were preparing the run |
        `/version-conflict` |

        | 500 | Internal error (schema drift, workflow start failure) |
        `/invalid-stored-field`, `/workflow-start-failed` |
      type: object
      required:
        - title
        - status
        - log_id
      properties:
        type:
          type:
            - string
            - 'null'
          format: uri
          example: >-
            https://docs.narrative.io/reference/architecture/agent-conversations/errors/invalid-tool-alias
        title:
          type: string
          example: Invalid Tool Alias
        status:
          type: integer
          example: 400
        detail:
          type: string
          example: >-
            invalid tool aliases (must match ^[a-zA-Z][a-zA-Z0-9]{0,7}$):
            with_underscore
        instance:
          type: string
          example: /agents
        log_id:
          type: string
          format: uuid
          example: 1f6e5d4c-3b2a-1098-7654-3210fedcba98
        debug:
          type:
            - object
            - 'null'
      example:
        type: >-
          https://docs.narrative.io/reference/architecture/agent-conversations/errors/invalid-tool-alias
        title: Invalid Tool Alias
        status: 400
        detail: >-
          invalid tool aliases (must match ^[a-zA-Z][a-zA-Z0-9]{0,7}$):
          with_underscore
        instance: /agents
        log_id: 1f6e5d4c-3b2a-1098-7654-3210fedcba98
        debug: null
    ConversationDefaults:
      description: >-
        The configuration applied to every run on this conversation by default.
        Each field

        can be overridden per-run via `config_override` on the `POST .../runs`
        body, **except

        `system_prompt`** which is fixed at conversation creation time.


        For `mcp_servers` and `tools`, overrides **replace the whole list**, not
        individual

        entries. There is no per-server or per-tool merge — set the complete
        catalog you want

        for that run.
      type: object
      required:
        - model
        - data_plane_id
        - execution_cluster
      properties:
        model:
          type: string
          description: >-
            The language model identifier. The platform exposes a fixed set;
            check the

            [Model Inference
            reference](https://docs.narrative.io/reference/model-inference)

            for current supported values.
          example: anthropic.claude-opus-4.6
        data_plane_id:
          type: string
          format: uuid
          description: >-
            UUID of the data plane (compute environment) that hosts the
            inference job

            executor. Each company has at least one data plane. Get it from your
            platform

            admin or `GET /data-planes`.
          example: f79cbdae-4848-47ca-95e8-69588364d185
        execution_cluster:
          type: string
          enum:
            - shared
            - dedicated
          description: >-
            Which job-executor pool dispatches the inference call to AWS Bedrock
            or Snowflake

            Cortex. The executor doesn't run the model itself — that happens in
            the external

            service — it only routes the HTTP request.


            **Use `shared` for almost every case.** `dedicated` is only relevant
            if your

            company runs a dedicated executor pool for isolation reasons.
          example: shared
        compute_pool_id:
          type: string
          format: uuid
          description: >-
            Optional compute pool override. Only relevant for
            `execution_cluster: dedicated`

            — pinpoints a specific compute pool inside that cluster.
        max_iterations:
          type: integer
          minimum: 1
          default: 3
          description: >-
            Maximum number of inference rounds the workflow may perform before
            failing with

            [Max Iterations
            Exceeded](https://docs.narrative.io/reference/architecture/agent-conversations/errors/max-iterations-exceeded).

            Each iteration is one inference job (one Bedrock/Cortex call).
            Multi-step

            research flows often need 8–15; a one-shot question needs 1–2
            (default 3 gives

            you some headroom).
          example: 8
        max_tokens:
          type: integer
          minimum: 1
          default: 2048
          description: >-
            Cap on the model's reply length **per iteration** (does not include
            the prompt).

            Bedrock-side enforced. If the model hits this limit mid-JSON, the
            response will

            fail to validate against `output_format_schema` —

            [Schema Decode
            Failed](https://docs.narrative.io/reference/architecture/agent-conversations/errors/schema-decode-failed).
          example: 2048
        temperature:
          type: number
          minimum: 0
          maximum: 1
          default: 0
          description: >-
            Sampling temperature. `0.0` is deterministic-ish (best for
            structured / factual

            answers); higher values introduce randomness (helpful for
            brainstorming).
          example: 0
        output_format_schema:
          type: object
          description: >-
            JSON Schema describing the final answer's structure. The platform
            extracts a

            `text` field from the model's reply for `final_text` on the terminal
            run.


            **Supports a subset of Draft 2020-12** — the same subset Bedrock
            structured

            output accepts. Not supported: `oneOf`, `anyOf`, `allOf`, `not`,
            `$ref`,

            `$defs`, `if/then/else`, `pattern`, `format`. Supported: `type`,
            `properties`,

            `required`, `enum`, `additionalProperties: false`,
            `minimum`/`maximum` on

            numbers, `minLength`/`maxLength` on strings, `minItems`/`maxItems`
            on arrays.


            See

            [JSON Schema
            Reference](https://docs.narrative.io/reference/model-inference/json-schema-reference)

            for the canonical supported-feature list.
          example:
            type: object
            additionalProperties: false
            required:
              - text
            properties:
              text:
                type: string
        mcp_servers:
          type: array
          default: []
          description: >-
            List of MCP servers and their tools the model can call server-side.
            Each

            server's tools appear to the model with the `{alias}-` prefix. Empty
            list means

            "no MCP tools." Wholesale-replaced when overridden in
            `config_override`.
          items:
            $ref: '#/components/schemas/McpServerConfig'
        tools:
          type: array
          default: []
          description: >-
            List of caller-declared tools. When the model calls one of these,
            the run pauses

            at `requires_action` and the platform expects you to start a
            follow-up run with

            `payload.kind: tool_outputs`. Caller-declared tool `name`s have no
            alias prefix

            and must not contain a dash. Wholesale-replaced when overridden in

            `config_override`.
          items:
            $ref: '#/components/schemas/ToolSpec'
    ConversationVersion:
      description: >-
        Monotonic per-conversation counter, bumped by 1 (or more) every time a
        successful run

        appends messages. Two roles:


        1. **Delta cursor** for `GET .../messages?since=N` — fetch only messages
        with
           `sequence_no > N`.
        2. **Compare-and-swap token** for `POST .../runs` — set
        `expected_version` to the
           conversation's current head; if it doesn't match at run-creation time, you get a
           [Version Conflict](https://docs.narrative.io/reference/architecture/agent-conversations/errors/version-conflict)
           (HTTP 409).

        Always start a new run cycle by reading the current `version` from

        `GET /agents/conversations/{id}` rather than caching a value from
        earlier.
      type: integer
      minimum: 0
      example: 4
    McpServerConfig:
      description: >-
        A Model Context Protocol (MCP) server the platform will call **on your
        behalf** during

        a run. The platform discovers the server's tool catalog at run start via
        the JSON-RPC

        `tools/list` method — you do **not** declare individual tools here. When
        the model

        emits a call to `{alias}-{tool_name}`, the platform makes the
        `tools/call` request,

        parses the response, persists the tool result, and feeds it back into
        the next

        inference round, all inside the same run.


        The server must implement [Model Context
        Protocol](https://modelcontextprotocol.io/)

        over HTTP with JSON-RPC 2.0 (both `tools/list` and `tools/call`).


        **Authentication.** Public servers and Narrative-owned MCPs need no auth
        field. For an

        external server that requires user authorization, first connect it via

        `POST /mcp-connections` (OAuth) and pass the resulting id as
        `connection_id` here — the

        platform attaches and refreshes that connection's bearer token
        server-side at call time.

        The token never appears in the payload or run history.


        **Discovery happens per run.** Each new run re-fetches `tools/list` —
        there is no

        catalog caching between runs. If a server adds, removes, or changes a
        tool, the next

        run picks it up automatically.


        **Error handling:** transient transport errors (5xx, network) during
        discovery are

        surfaced as

        [MCP Discovery
        Failed](https://docs.narrative.io/reference/architecture/agent-conversations/errors/mcp-discovery-failed).

        `tools/call` errors follow the same classification as before:

        [MCP error
        pages](https://docs.narrative.io/reference/architecture/agent-conversations/errors/mcp-unknown-tool).
      type: object
      required:
        - alias
        - url
      properties:
        alias:
          $ref: '#/components/schemas/ToolAlias'
        url:
          type: string
          format: uri
          description: >-
            Fully-qualified HTTPS URL to the MCP server's JSON-RPC endpoint. The
            platform's

            outbound workers must be able to reach this URL — for private MCP
            servers, ensure

            the URL is reachable from the company's data plane.
          example: https://docs.narrative.io/mcp
        description:
          type: string
          description: >-
            Optional free-form description, exposed in the assembled tool
            catalog the model sees.
          example: Public Mintlify-hosted Narrative docs MCP server
        connection_id:
          type: string
          format: uuid
          description: >-
            Reference to a registered external-MCP OAuth connection (from `POST
            /mcp-connections`).

            Set this for an external server that requires user authorization:
            the platform resolves

            and refreshes that connection's bearer token server-side at call
            time — never in the

            payload or run history. Omit for public servers or Narrative-owned
            MCPs. The connection

            must belong to the calling user and be in `connected` status.
            Optional; defaults to none.
          example: b3f1c2a4-5d6e-47f8-9a0b-1c2d3e4f5a6b
    ToolSpec:
      description: >-
        A single tool definition. Mirrors the relevant fields from the
        underlying inference

        contract (Bedrock/Cortex).


        **For MCP tools (discovered at run start from `mcp_servers[]`
        entries):** the model sees the bare

        `name` prefixed with the parent server's `alias` and a dash (so a tool
        `search` on a server with

        `alias: "docs"` becomes `docs-search` on the wire). The wire-name length
        cap is

        `len(alias) + 1 + len(name) ≤ 64` (Bedrock).


        **For caller-declared tools (declared under top-level `tools[]`):** the
        model sees the

        bare `name` directly. The name must **not contain a dash** — the dash is
        reserved as

        the MCP alias separator and is the routing discriminator at call time.
        See

        [Invalid Caller-Declared Tool
        Name](https://docs.narrative.io/reference/architecture/agent-conversations/errors/invalid-caller-tool-name).


        **`input_schema` constraints:** must be a subset of JSON Schema Draft
        2020-12. Features

        like `oneOf`, `anyOf`, `allOf`, `not`, `$ref`, `$defs`, `if/then/else`,
        `pattern`, and

        `format` are **not supported** — the platform forwards the schema to the
        model

        provider, which rejects unsupported features. See

        [JSON Schema
        Reference](https://docs.narrative.io/reference/model-inference/json-schema-reference)

        for the supported subset.


        **Wire-name length:** total wire name (whether bare or `{alias}-{name}`)
        must be

        ≤ 64 characters (Bedrock limit). See

        [Tool Wire Name Too
        Long](https://docs.narrative.io/reference/architecture/agent-conversations/errors/tool-name-too-long).
      type: object
      required:
        - name
        - description
        - input_schema
      properties:
        name:
          type: string
          description: >-
            The tool's bare name. For MCP tools the model sees
            `{parent_alias}-{name}`; for

            caller-declared tools the model sees `name` directly.
            Caller-declared names must

            not contain a dash.
          example: search_narrative_i_o_knowledge_base
        description:
          type: string
          description: >-
            Human-readable description the model uses to decide when to call
            this tool.

            Keep it focused — vague descriptions cause the model to call the
            tool when it

            shouldn't, or skip it when it should.
          example: Search the Narrative.io documentation knowledge base.
        input_schema:
          type: object
          description: >-
            JSON Schema describing the tool's input arguments. The model
            produces an arguments

            object matching this schema for every call. Use
            `additionalProperties: false` and

            `required` aggressively — tighter schemas reduce model mistakes.
          example:
            type: object
            additionalProperties: false
            required:
              - query
            properties:
              query:
                type: string
        strict:
          type: boolean
          description: >-
            Whether to enforce the input schema strictly. Defaults to `true`.
            Leave it true

            for production — turning it off lets the model send arguments that
            don't validate,

            which is almost never what you want.
          default: true
    ToolAlias:
      description: >-
        A 1–8 character namespace prefix for an MCP server's tools. The platform
        stitches

        `{alias}-{tool_name}` into the wire name the model sees, so the alias is
        how every

        MCP-resolved tool call gets routed back to the right server at execution
        time.


        **Rules:**

        - Must match the regex `^[a-zA-Z][a-zA-Z0-9]{0,7}$` — 1–8 characters
        total, starts
          with an ASCII letter, contains only ASCII letters and digits.
        - **No underscores**, **no dashes**, **no other punctuation**. Dashes
        are reserved as
          the alias↔name separator.
        - Must be **unique across `mcp_servers`** within a single conversation.
        The platform
          validates this on `POST /agents/conversations`.

        Caller-declared tools (in `tools[]`) have no alias — the model sees
        their bare `name`

        on the wire. The dash in MCP wire names is the routing discriminator: a
        dash-prefixed

        name comes from an MCP server; a dash-free name is caller-declared and
        triggers

        `requires_action`.


        See the [Invalid Tool
        Alias](https://docs.narrative.io/reference/architecture/agent-conversations/errors/invalid-tool-alias)

        and [Duplicate Tool
        Alias](https://docs.narrative.io/reference/architecture/agent-conversations/errors/duplicate-tool-alias)

        error pages for the exact validation behavior.
      type: string
      pattern: ^[a-zA-Z][a-zA-Z0-9]{0,7}$
      minLength: 1
      maxLength: 8
      example: docs
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer

````