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

# PATCH /v1/agents/{id}

> Update an agent's config: name, model, language, goal, channels, reengagement, tools, knowledge nodes or active flag.

Partial update. Only the fields present in the body change; everything else is left alone.

**To change one prompt section, use [`PUT /v1/agents/{id}/prompts/{section}`](/dev/endpoints/agents-prompt-set) instead.** Sending `prompts` here replaces them all, which is what you want when your system owns the whole prompt and a mistake when it does not.

## Endpoint

```
PATCH https://api.keebai.com/v1/agents/{id}
```

## Required scope

`agents:write`

## Headers

| Header          | Required | Value                    |
| --------------- | -------- | ------------------------ |
| `Authorization` | Yes      | `Bearer kbai_pk_<token>` |
| `Content-Type`  | Yes      | `application/json`       |

## Path parameters

| Parameter | Type     | Description              |
| --------- | -------- | ------------------------ |
| `id`      | `string` | `ObjectId` of the agent. |

## Body

Every field is optional.

| Field                | Type       | Description                                                    |
| -------------------- | ---------- | -------------------------------------------------------------- |
| `name`               | `string`   | Up to 150 characters, non-empty.                               |
| `description`        | `string`   | Up to 500 characters.                                          |
| `language`           | `string`   | Locale, for example `es-CL`.                                   |
| `timezone`           | `string`   | IANA name.                                                     |
| `goal`               | `object`   | `{ type, instructions? }`.                                     |
| `prompts`            | `array`    | **Replaces every section.**                                    |
| `channels`           | `string[]` | Channel types from the catalogue.                              |
| `reengagement`       | `object`   | Cadence for coming back to a cold conversation.                |
| `tools`              | `string[]` | `ObjectId`s of webhook tools.                                  |
| `model`              | `string`   | Model id. Validated only when it differs from the current one. |
| `knowledge_node_ids` | `string[]` | Replaces the whole list. Send `[]` to unassign everything.     |
| `is_active`          | `boolean`  | `false` stops the agent answering without deleting anything.   |

## Example request

<CodeGroup>
  ```bash curl theme={"system"}
  curl -X PATCH https://api.keebai.com/v1/agents/6650a1b2c3d4e5f6a7b8c9d0 \
    -H "Authorization: Bearer kbai_pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
    -H "Content-Type: application/json" \
    -d '{ "model": "gemini-2.5-pro", "is_active": true }'
  ```

  ```js JavaScript theme={"system"}
  const resp = await fetch(
    "https://api.keebai.com/v1/agents/6650a1b2c3d4e5f6a7b8c9d0",
    {
      method: "PATCH",
      headers: {
        Authorization: `Bearer ${process.env.KEEBAI_API_TOKEN}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ model: "gemini-2.5-pro" }),
    },
  );
  const { agent } = await resp.json();
  ```

  ```python Python theme={"system"}
  import os, requests

  resp = requests.patch(
      "https://api.keebai.com/v1/agents/6650a1b2c3d4e5f6a7b8c9d0",
      headers={"Authorization": f"Bearer {os.environ['KEEBAI_API_TOKEN']}"},
      json={"model": "gemini-2.5-pro"},
      timeout=10,
  )
  resp.raise_for_status()
  agent = resp.json()["agent"]
  ```
</CodeGroup>

## Response

### 200 OK

The full agent, same shape as [`GET /v1/agents/{id}`](/dev/endpoints/agents-get).

### 400 Bad Request

A field over its length limit, a malformed `ObjectId`, an unknown property, or `INVALID_MODEL` when the new model is not supported.

### 401 Unauthorized

Missing, invalid, revoked, or expired token.

### 403 Forbidden

The token does not have the `agents:write` scope.

### 404 Not Found

No agent with that id in the token's company and project.

### 502 Bad Gateway

The agent service is unreachable.

## Operational notes

* **`knowledge_node_ids` replaces, it does not append.** Sending one id leaves the agent with exactly that one. Read the current list from [`GET /v1/agents/{id}`](/dev/endpoints/agents-get) and send the union if you mean to add.
* **The model is only validated when it changes.** An agent already configured with a model that has since been retired keeps working through updates that do not touch `model`, and starts failing validation the moment you send it explicitly.
* **`is_active: false` is the reversible way to take an agent out of service.** It keeps every section, version and knowledge assignment; [deleting](/dev/endpoints/agents-delete) does not.
* **Changing `goal.type` changes which tools the agent can use.** It is not a rename: an agent moved from informing to booking needs the services and availability behind it to exist.
* **Removing a channel stops it answering there**, and a customer who writes gets nothing back.
* **Omitting a field and sending `null` are not the same.** Omit it to leave the value alone. `null` is not accepted for these fields.
* **A change takes effect within about fifteen minutes at worst.** The rendered prompt and bound tools are cached per agent; the cache is dropped on every write, but a request already in flight can still answer with the previous configuration.


## OpenAPI

````yaml PATCH /v1/agents/{id}
openapi: 3.0.0
info:
  title: Keebai Public API
  description: Superficie pública REST autenticada con Personal Access Tokens (PAT).
  version: 1.0.0
  contact: {}
servers:
  - url: https://api.keebai.com
    description: Production
security: []
tags: []
paths:
  /v1/agents/{id}:
    patch:
      tags:
        - agents
      summary: Actualizar un agente
      description: >-
        Actualiza solo los campos presentes en el body. Los bloques no se tocan
        por aca: se manejan con los endpoints de /blocks.
      operationId: PublicAgentsController_update
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PublicAgentUpdateDto'
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicAgentEnvelopeDto'
      security:
        - PAT: []
components:
  schemas:
    PublicAgentUpdateDto:
      type: object
      properties:
        name:
          type: string
          maxLength: 150
        description:
          type: string
          maxLength: 500
        model:
          type: string
          description: >-
            Identificador del modelo. Se valida solo si cambia respecto del
            actual.
        language:
          type: string
          example: es-CL
        timezone:
          type: string
          example: America/Santiago
        goal:
          $ref: '#/components/schemas/PublicAgentGoalDto'
        prompts:
          maxItems: 20
          description: >-
            REEMPLAZA todas las secciones. Para cambiar una sola sin tocar el
            resto, usar `PUT /v1/agents/{id}/prompts/{section}`.
          type: array
          items:
            $ref: '#/components/schemas/PublicPromptDto'
        channels:
          maxItems: 10
          type: array
          items:
            type: string
        reengagement:
          type: object
        tools:
          maxItems: 100
          type: array
          items:
            type: string
        knowledge_node_ids:
          maxItems: 200
          type: array
          items:
            type: string
        is_active:
          type: boolean
    PublicAgentEnvelopeDto:
      type: object
      properties:
        agent:
          $ref: '#/components/schemas/PublicAgentDto'
      required:
        - agent
    PublicAgentGoalDto:
      type: object
      properties:
        type:
          type: string
          description: >-
            Tipo de objetivo, del catalogo (`GET /v1/prompt-types?kind=goal`).
            Decide que herramientas se encienden.
          example: appointment_management
        instructions:
          type: string
          maxLength: 600
          description: >-
            Solo para el objetivo `custom`: que tiene que lograr el agente,
            escrito por el negocio.
      required:
        - type
    PublicPromptDto:
      type: object
      properties:
        section:
          type: string
          description: >-
            Tipo de seccion, del catalogo. Una seccion desconocida devuelve 404
            PROMPT_SECTION_NOT_FOUND.
          example: business_context
        label:
          type: string
          maxLength: 150
          description: Titulo propio de la seccion. Sin esto se usa el del catalogo.
        markdown:
          type: string
          description: El texto de la seccion, en markdown.
          example: |-
            # Quienes somos

            Barberia en Providencia, atendemos con hora.
      required:
        - section
        - markdown
    PublicAgentDto:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type: string
        avatar_url:
          type: string
        model:
          type: string
        voice_response_enabled:
          type: boolean
          description: Indica si la respuesta de voz está habilitada.
        created_at:
          type: string
      required:
        - id
        - name
        - model
        - voice_response_enabled
  securitySchemes:
    PAT:
      scheme: bearer
      bearerFormat: kbai_pk_<hex>
      type: http
      description: >-
        Personal Access Token con prefijo `kbai_pk_`. Generar desde el portal
        con permiso `developer.manage_tokens`.

````