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

# Migración de API 1.57 -> 1.58

> Adapta tus integraciones de la API de Workspace a las rutas, cuerpos y respuestas de la versión 1.58.

Zylon 1.58 unifica las rutas de artefactos y separa las membresías del espacio de trabajo de las cuentas. Usa esta guía para actualizar integraciones creadas para 1.57. Abarca cambios en APIs existentes de Workspace y los nuevos [bloques de herramientas de servidor](#bloques-de-herramientas-de-servidor) que devuelven los mensajes de chat, tanto en la API de Workspace como en la de ZylonGPT.

<Warning>
  Las rutas antiguas de artefactos, integraciones y miembros quedan obsoletas en 1.58 y su retirada está prevista para 1.59. Otros alias aceptados tienen sus propias notas de compatibilidad más abajo. Usa las rutas actuales de 1.58 para integraciones nuevas o mantenidas.

  **Si tu integración depende de la identidad del usuario, IDs de creador o filtros de creador, migra las llamadas afectadas a la API actual y actualiza tus mapeos de identidad.** Que una URL antigua funcione no restaura el modelo de identidad de 1.57. Los campos de creador ahora identifican cuentas; las rutas de membresía siguen usando IDs de miembro. Sigue la [migración de IDs de usuario guardados](#migrar-ids-de-usuario-guardados) antes de confiar en búsquedas, comparaciones o filtros existentes.
</Warning>

## Requisitos previos

* Un token de API y el nombre de host de Zylon. Consulta [Gestión de tokens de Workspace](/es/developer-manual/get-started/token-management).
* Envía `Authorization: Bearer {API_TOKEN}` y `x-org: {org_slug}` en las peticiones de Workspace.
* Envía `Content-Type: application/json` para cuerpos JSON. Deja que tu cliente HTTP establezca el delimitador de las peticiones multipart.

Las rutas de las tablas son relativas a `https://{BASE_URL}/api/v1`.

## Rutas de artefactos

Sustituye el prefijo de artefactos del proyecto o de la organización por `/app/artifact`. Indica explícitamente el proyecto para asignar la propiedad o filtrar cuando corresponda.

| Método | Ruta obsoleta | Ruta actual |
| - | - | - |
| `GET`, `POST` | `/app/project/{projectID}/artifact` o `/app/organization/artifact` | `/app/artifact` |
| `GET`, `PUT`, `DELETE` | Cualquiera de los prefijos antiguos + `/{artifactID}` | `/app/artifact/{artifactID}` |
| `POST` | Cualquiera de los prefijos antiguos + `/validate` | `/app/artifact/validate` |
| `POST` | Cualquiera de los prefijos antiguos + `/{artifactID}/validate` | `/app/artifact/{artifactID}/validate` |
| `GET` | Cualquiera de los prefijos antiguos + `/{artifactID}/download` | `/app/artifact/{artifactID}/download` |
| `GET` | `/app/project/{projectID}/artifact/{artifactID}/parsed-content` | `/app/artifact/{artifactID}/parsed-content` |
| `POST` | `/app/project/{projectID}/artifact/{artifactID}/retry` | `/app/artifact/{artifactID}/retry` |
| `POST` | `/app/project/{projectID}/artifact/{artifactID}/sync` | `/app/artifact/{artifactID}/sync` |
| `POST` | `/app/project/{projectID}/artifact/{artifactID}/ingest` | `/app/artifact/{artifactID}/ingest` |
| `PUT`, `DELETE` | `/app/project/{projectID}/artifact/bulk` | `/app/artifact/bulk` |

<Accordion title="Parametros del endpoint">
  | Operación | Qué cambiar |
  | - | - |
  | Listar | Mueve el `projectID` de la ruta al parámetro de consulta `project_id`. Mantén `x-org` para seleccionar el espacio de trabajo. |
  | Crear, validar creación, reintentar | Mueve el `projectID` de la ruta al campo `project_id` del cuerpo. Omítelo o envía `null` para artefactos de organización. |
  | Ingerir | Envía `project_id` en el cuerpo JSON específico del proveedor. Conserva los parámetros existentes del proveedor. |
  | Otras operaciones por ID | El ID del artefacto identifica su propietario. Conserva los parámetros específicos de cada operación. |
</Accordion>

```bash theme={null}
curl "https://{BASE_URL}/api/v1/app/artifact?project_id={projectID}" \
  -H "Authorization: Bearer {API_TOKEN}" \
  -H "x-org: {org_slug}"
```

Si usas `x-org`, no envíes también `organization_id`. Sin `x-org`, especificar `organization_id` requiere Operator o SuperAdmin. Crear artefactos de organización requiere AppAdmin o superior; los artefactos `Link` requieren un proyecto.

### Cuerpos de creación

El campo JSON actual `content` contiene **bytes de archivo o texto codificados en Base64**. Sustituye al antiguo campo de texto `raw_content`. Por ejemplo, el texto UTF-8 `Hello` se convierte en `SGVsbG8=`.

<Tabs>
  <Tab title="Petición 1.57">
    `POST /app/project/{projectID}/artifact`

    ```json theme={null}
    {
      "type": "SmartDoc",
      "name": "Draft",
      "raw_content": "Hello",
      "props": {}
    }
    ```
  </Tab>

  <Tab title="Petición 1.58">
    `POST /app/artifact`

    ```json theme={null}
    {
      "project_id": "{projectID}",
      "type": "SmartDoc",
      "name": "Draft",
      "content": "SGVsbG8=",
      "props": {}
    }
    ```
  </Tab>
</Tabs>

<Accordion title="Cambios en el cuerpo">
  | Campo | Migración |
  | - | - |
  | `raw_content` | Sustitúyelo por `content` codificado en Base64 en las peticiones JSON actuales de creación, validación de creación y reintento. |
  | `file_data` | Conserva este campo de archivo multipart, también para subir skills. Añade `project_id` como campo del formulario para crear en un proyecto. |
  | `project_id` | Nueva ubicación del selector de la ruta antigua. Cadena opcional o `null`; necesario para asignar el artefacto a un proyecto. |
  | `organization_id` | Omítelo si envías `x-org`. Sin esa cabecera, está disponible para Operator/SuperAdmin autorizados. |
  | `props`, `private_props`, `integration_id` | Usa estos nombres canónicos. Siguen aceptándose los alias `config`, `private_config` (solo creación) e `integration_artifact_id`. |
  | `source` | Por defecto `User`. Los clientes no pueden establecer `Assistant` ni `System`. |
</Accordion>

Los demás campos específicos de cada tipo mantienen sus reglas actuales. Consulta los [campos y tipos de artefactos](/es/developer-manual/build-with-zylon/workspace-api/content/artifacts#campos-de-petición-de-artefacto).

### Cuerpos de actualización

El antiguo `content` de actualización contenía **estado binario del editor codificado en Base64**. El `content` JSON actual contiene **texto UTF-8**, como Markdown. Exporta el documento del editor a Markdown; decodificar sus bytes Base64 no produce texto del documento.

<Tabs>
  <Tab title="Petición 1.57">
    `PUT /app/project/{projectID}/artifact/{artifactID}`

    ```json theme={null}
    {
      "content": "{BASE64_EDITOR_STATE}",
      "plain_text_content": "Hello"
    }
    ```

    `{BASE64_EDITOR_STATE}` representa tu documento del editor ya codificado.
  </Tab>

  <Tab title="Petición 1.58">
    `PUT /app/artifact/{artifactID}`

    ```json theme={null}
    {
      "content": "Hello"
    }
    ```
  </Tab>
</Tabs>

<Warning>
  Creación y actualización usan codificaciones distintas: **Base64 al crear con JSON, texto sin codificar al actualizar con JSON**. No envíes el antiguo estado del editor a la ruta actual de actualización: se trataría como texto literal.
</Warning>

El mismo formato se aplica a la validación de actualizaciones y a cada entrada `artifacts[].update` de las actualizaciones en lote. Las entradas siguen usando `artifactId` y `update`. Elimina `plain_text_content`: era un texto de búsqueda separado y ahora se deriva del documento. Para sustituir un archivo, usa `file_data` multipart en la ruta actual de actualización. Consulta [actualizar un artefacto](/es/developer-manual/build-with-zylon/workspace-api/content/artifacts#actualizar-un-artefacto).

### Qué peticiones antiguas siguen siendo compatibles

* La creación, validación y reintento con JSON aceptan `raw_content`; la creación multipart también acepta bytes de archivo. La creación antigua obtiene el proyecto de la URL y rechaza `project_id`, `organization_id` y el nuevo `content` JSON en el cuerpo.
* Las actualizaciones JSON antiguas convierten el estado del editor de Base64 a Markdown antes de guardar. El servicio de conversión de documentos de la instalación debe estar disponible. Se puede enviar contenido binario con o sin `plain_text_content`; este último campo por sí solo no sustituye el contenido.
* La actualización, validación de actualización y actualización en lote antiguas solo aceptan JSON. Usa el endpoint actual para sustituir archivos con multipart.
* Se rechaza una creación que combine `raw_content` y un archivo: no se pueden conservar ambos en el único campo de contenido actual. Envía una sola representación del contenido.
* Se rechazan campos desconocidos y tipos de datos no válidos. La creación en una organización solo acepta ámbitos de esa organización.

### Respuestas y selección de artefactos

Las respuestas antiguas conservan `has_content`, siempre `false`: este campo describía el contenido binario del editor, no la existencia de un archivo. Los bytes originales del editor no se pueden reconstruir, por lo que `content` es nulo/se omite.

En las consultas de detalle de artefactos por la URL antigua, añade `include_content=true` para recibir el texto UTF-8 disponible como `raw_content`. El valor por defecto es `false`; los listados y las respuestas de escritura no incluyen texto. Se conservan los espacios y el texto vacío. Los archivos no textuales y el UTF-8 inválido no generan `raw_content`. Se aplican los permisos actuales de descarga: si están desactivadas, devuelve `403`; si falta el archivo almacenado, devuelve el error actual de descarga.

<Accordion title="Campos de contenido antiguos (respuesta parcial)">
  ```json theme={null}
  {
    "has_content": false,
    "raw_content": "# Documento actual"
  }
  ```

  Los campos nulos se omiten. No se genera `content` binario del editor en Base64 a partir del texto.
</Accordion>

Las respuestas actuales de artefactos omiten estos campos de contenido antiguos. Usa `/app/artifact/{artifactID}/download` para obtener el contenido almacenado. `/app/artifact/{artifactID}/parsed-content` devuelve texto extraído y requiere un índice vectorial inicializado. La descarga devuelve una URL prefirmada por defecto; con `Content-Disposition: attachment` devuelve los bytes del archivo. Las URLs antiguas de descarga también admiten ambos modos.

`created_by` ahora representa una **cuenta**. Actualiza el código que lee los datos del creador o compara sus IDs; consulta [IDs de cuenta y campos renombrados](#ids-de-cuenta-y-campos-renombrados).

`scopes[].ws_auto_select` y `scopes[].enabled` ya existían en las versiones publicadas de 1.57 y siguen siendo compatibles, incluido `enabled: false`. El campo anterior `ws_auto_select` de nivel superior no se acepta. Las skills siguen usando `file_data`; no hay una migración independiente de su cuerpo. Consulta los [ámbitos de artefactos](/es/developer-manual/build-with-zylon/workspace-api/content/artifacts#añadir-o-eliminar-un-alcance).

## Miembros del espacio de trabajo

Los datos de usuario se unifican en la **cuenta**: la identidad, el nombre, el correo y la imagen de perfil pertenecen a la cuenta. El antiguo usuario pasa a ser una **membresía del espacio de trabajo**, que mantiene los roles, permisos y estado activo/inactivo de esa cuenta dentro del espacio.

Sustituye `/app/user` por `/app/member`. Los IDs de estas rutas siguen siendo **IDs de miembro del espacio de trabajo**, no IDs de cuenta.

| Método | Ruta obsoleta | Ruta actual |
| - | - | - |
| `GET`, `POST` | `/app/user` | `/app/member` |
| `GET`, `PUT` | `/app/user/{wsMemberId}` | `/app/member/{wsMemberId}` |
| `POST` | `/app/user/{wsMemberId}/activate` o `/deactivate` | `/app/member/{wsMemberId}/activate` o `/deactivate` |
| `GET` | `/app/user/{wsMemberId}/project` | `/app/member/{wsMemberId}/project` |
| `GET` | `/app/user/{wsMemberId}/latest-artifacts` | `/app/member/{wsMemberId}/latest-artifacts` |

Las respuestas antiguas de `/app/user` al listar, consultar, crear, cambiar el rol, activar o desactivar un miembro conservan `name`, `email` y `profile_picture` (si está disponible) en el primer nivel, tomados del perfil actual de la cuenta. Se mantienen `id`, `org_id`, `account_id`, `state`, `roles` y `created_at` de la membresía. Los datos eliminados del puesto de trabajo no se pueden recuperar y son nulos/se omiten. Estos campos de respuesta no restauran las actualizaciones de perfil mediante la ruta antigua del miembro.

`GET /app/me` conserva su URL, pero también devuelve el nuevo modelo de miembro. El nombre, el correo y la imagen de perfil son datos de la cuenta y ya no son campos de primer nivel del miembro. Solicita `include=Account` al listar miembros, consultar un miembro o llamar a `/app/me` para recibir la cuenta anidada.

<Accordion title="Parametros del endpoint">
  | Operación | Petición |
  | - | - |
  | `POST /app/member` | `account_id` y `role` son cadenas obligatorias. No se restaura el antiguo campo `user_info`. |
  | `PUT /app/member/{wsMemberId}` | `role` es una cadena obligatoria. Los campos de perfil ya no se actualizan aquí, tampoco mediante la URL antigua. |
  | Listado de miembros | `state` opcional: `Active`, `Inactive`, separados por comas; ambos por defecto. No se conserva la ordenación antigua con `order_by`/`order`. |
  | Lecturas de miembros | `include=Account` opcional. |

  Roles del espacio de trabajo: `AppGuest`, `AppMember`, `AppAdmin`, `AppOwner`.
</Accordion>

Actualiza los campos de perfil con `POST /account/{accountId}` (`me` permite actualizar tu propia cuenta), en lugar del endpoint de miembros. Los antiguos campos `job_position_name` y `job_position_description` se eliminan del miembro; no forman parte del modelo de cuenta.

<Accordion title="Respuesta actual de miembro">
  | Campo | Tipo | Significado |
  | - | - | - |
  | `id` | string | ID de miembro del espacio de trabajo. |
  | `org_id` | string | ID de organización. |
  | `account_id` | string | ID de cuenta, distinto del ID de miembro. |
  | `state` | string | `Active` o `Inactive`. |
  | `roles` | string\[] | Roles del espacio de trabajo. |
  | `created_at` | timestamp | Fecha de creación de la membresía, generada por el servidor. |
  | `account` | object o null | Datos de la cuenta cuando se solicitan. Consulta el [ejemplo completo de miembro y cuenta](/es/developer-manual/build-with-zylon/workspace-api/users/user#obtener-el-miembro-actual). |
</Accordion>

## IDs de cuenta y campos renombrados

### Migrar IDs de usuario guardados

Si tu cliente guardó `userId` a partir del campo `id` de una respuesta `/app/user` de 1.57, ese valor es un ID de miembro del espacio de trabajo. **No sustituyas todos los `userId` por `accountId`: identifican registros distintos.** Una cuenta puede tener IDs de miembro diferentes en distintas organizaciones.

1. Conserva el ID de miembro guardado y su organización. Usa el endpoint actual de miembros para leer el ID de cuenta asociado:

<Accordion title="Parametros del endpoint">
  | Tipo | Nombre | Obligatorio | Notas |
  | - | - | - | - |
  | Ruta | `wsMemberId` | Si | El ID de miembro que antes devolvía `id` en el usuario antiguo. |
  | Cabecera | `x-org` | Si | La organización que contiene esa membresía. |
</Accordion>

```bash theme={null}
curl "https://{BASE_URL}/api/v1/app/member/{wsMemberId}" \
  -H "Authorization: Bearer {API_TOKEN}" \
  -H "x-org: {org_slug}"
```

<Accordion title="Respuesta de mapeo de IDs (campos seleccionados)">
  ```json theme={null}
  {
    "id": "{wsMemberId}",
    "org_id": "{orgId}",
    "account_id": "{accountId}"
  }
  ```

  `account_id` se devuelve sin un parámetro `include`. Añade `include=Account` si también necesitas el perfil de cuenta; consulta la [respuesta completa de miembro](/es/developer-manual/build-with-zylon/workspace-api/users/user#obtener-el-miembro-actual).
</Accordion>

2. Guarda ambos IDs con nombres distintos. Usa `account_id` para comparar con `created_by.id` de artefactos, hilos, interacciones e incidencias, y para los filtros `created_by` de artefactos o incidencias. Conserva el `id` de miembro para `/app/member/{wsMemberId}`, miembros de proyecto, transferencia de propiedad y `metadata.ws_member_id` del chat.
3. Actualiza las llamadas afectadas a las rutas actuales y nombres canónicos, y comprueba tus relaciones y filtros guardados. Por ejemplo, un filtro de creador de artefactos debe usar `created_by={accountId}`; una petición de miembro de proyecto sigue usando `ws_member_id: "{wsMemberId}"`.

Para tu propia identidad, `GET /api/v1/app/me` devuelve la misma distinción entre `id` y `account_id`. Para migrar un directorio, pagina `/app/member` por separado en cada organización y crea un mapeo de IDs de miembro a IDs de cuenta. Si tu aplicación necesita un ID de miembro para la cuenta de un creador, resuelve su membresía en la organización seleccionada; un ID de cuenta por sí solo no identifica una membresía concreta.

### Qué conservan los alias antiguos

Las lecturas de `/app/user` antiguo pueden restaurar campos de perfil seleccionados, como `name` y `email`, pero `id` sigue siendo un ID de miembro y `account_id` sigue siendo un ID de cuenta. Los objetos de creador de artefactos antiguos ya usan IDs de cuenta. `include=User` en las consultas de creador compatibles selecciona datos de cuenta; no restaura el antiguo objeto de usuario del espacio de trabajo ni convierte IDs de creador.

Usa los alias antiguos solo como puente temporal para los formatos de petición documentados en esta guía. Si tu integración necesita las relaciones antiguas de IDs de usuario, filtros de creador o comportamiento de actualización de perfil, migra a la API actual y al modelo de cuenta/miembro descrito arriba. Cambiar solo la URL o el nombre de campo no basta.

### Usar nombres de campo canónicos

Los alias temporales siguientes aceptan ciertos nombres de entrada antiguos. Las respuestas mantienen el modelo y los nombres de campo actuales; los alias no convierten IDs de miembro en IDs de cuenta.

| Dónde | Anterior | Actual / acción necesaria |
| - | - | - |
| Entradas de creación/actualización de miembros de proyecto | `user_id` | Usa `ws_member_id`; el nombre anterior sigue siendo un alias de entrada. El valor sigue siendo un ID de miembro. |
| Metadatos de chat (Workspace y ZylonGPT) | `metadata.user_id` | Usa `metadata.ws_member_id`; `user_id` sigue siendo un alias de entrada. Envía solo un nombre. El valor sigue siendo un ID de miembro, no de cuenta. |
| Transferencia de propiedad de proyecto | `old_owner_id`, `new_owner_id` | Usa `old_owner_ws_member_id`, `new_owner_ws_member_id`; los nombres anteriores siguen siendo alias de entrada. |
| Consulta `include` de artefactos, hilos, interacciones e incidencias | `User` | Usa `Account`; `User` sigue siendo un alias de entrada. |
| Consulta `include` del listado de cuentas | `Users` | Usa `WorkspaceMembers`; `Users` sigue siendo un alias de entrada. |
| Membresías en la respuesta de cuenta | `users` | Lee `workspace_members`. |
| Respuesta de miembro de proyecto | `user` | Lee `account`; `id` sigue siendo un ID de miembro del espacio de trabajo. |
| Respuesta `created_by` de artefactos, hilos, interacciones e incidencias | Miembro del espacio de trabajo | Lee un objeto de cuenta y su ID de cuenta. |
| Filtro `created_by` de artefactos | ID de miembro | Envía un ID de cuenta. No se convierten los IDs automáticamente. |
| Filtro `created_by` de incidencias | IDs de miembro | Envía IDs de cuenta separados por comas. No se convierten los IDs automáticamente. |

Consulta [miembros de proyecto](/es/developer-manual/build-with-zylon/workspace-api/projects/project-member), [transferencia de propiedad](/es/developer-manual/build-with-zylon/workspace-api/projects/project) y [filtros de incidencias](/es/developer-manual/build-with-zylon/workspace-api/general/issues) para ver los cuerpos y respuestas actuales completos.

## Chats e hilos

### Mover el chat de proyecto a la ruta unificada

Sustituye `POST /app/project/{projectID}/chat` por `POST /app/chat` y mueve el selector de proyecto al cuerpo. Usa una petición de mensajes envuelta en `pgpt` (`private_gpt` sigue siendo un alias de entrada). La ruta actual también acepta una petición antigua sin envolver para contexto del espacio de trabajo, pero los selectores de proyecto y artefactos requieren el cuerpo envuelto. `/app/chat/validate` recibe la petición de mensajes sin envolver.

```bash theme={null}
curl -N -X POST "https://{BASE_URL}/api/v1/app/chat" \
  -H "Authorization: Bearer {API_TOKEN}" \
  -H "x-org: {org_slug}" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "project_id": "{projectID}",
    "pgpt": {
      "messages": [{ "role": "user", "content": "Resume el proyecto." }]
    }
  }'
```

<Accordion title="Parametros del endpoint">
  | Tipo | Nombre | Obligatorio | Migración |
  | - | - | - | - |
  | Body | `project_id` | No | Antes se indicaba en la ruta. Inclúyelo para contexto de proyecto; omítelo para contexto del espacio de trabajo. |
  | Body | `pgpt` | Si | Petición de mensajes. Consulta [Mensajes](/es/developer-manual/build-with-zylon/working-with-messages). |
  | Body | `artifacts` | No | Objeto de selección por ámbito descrito abajo. |
</Accordion>

<Warning>
  La respuesta actual de `/app/chat` es **siempre SSE**, incluso con `pgpt.stream: false`. La URL de chat de proyecto conservada devuelve JSON cuando ese indicador es `false` y SSE cuando es `true`. Adapta los clientes que esperan JSON antes de cambiar la URL. El alias de chat de proyecto no tiene asignada una versión de retirada.
</Warning>

Para seleccionar artefactos, usa `artifacts.document`, `artifacts.connector`, `artifacts.skill` o `artifacts.agent_flow`. Cada campo es un array de selectores con `scope` (`organization` o `project`), `all_artifacts` opcional y `artifacts_ids` opcional (observa el plural). Por ejemplo:

```json theme={null}
{
  "artifacts": {
    "document": [
      { "scope": "project", "artifacts_ids": ["{artifactID}"] }
    ]
  }
}
```

Es un cuerpo parcial que debes combinar con `pgpt` y, para el ámbito de proyecto, `project_id`. No envíes los campos de los ejemplos antiguos de referencia `artifact_ids` o `all_artifacts` en el nivel superior: los campos desconocidos se ignoran y no seleccionan artefactos. Una categoría no puede repetir el mismo ámbito ni combinar `all_artifacts: true` con `artifacts_ids` no vacío. Consulta [peticiones de chat](/es/developer-manual/build-with-zylon/workspace-api/chats/threads#chat-puntual).

### Archivos de hilo y estado de lectura

1.58 añade la escritura de archivos sin multipart con `PUT /app/thread/{threadID}/put-file/{path...}`. Envía los bytes en el cuerpo. `POST /app/thread/{threadID}/upload-file` sigue usando el campo multipart `file` y ahora acepta `path` y `namespace` opcionales. Las subidas multipart, escrituras sin multipart y descargas seleccionan `session` (por defecto), `artifacts` o `skills` mediante `namespace`; la descarga también acepta `disposition=attachment` (por defecto) o `inline`. Consulta [archivos de hilo](/es/developer-manual/build-with-zylon/workspace-api/chats/threads#archivos-del-hilo) para subida, descarga y conversión de artefactos MDX.

En los listados de hilos del proyecto, solicita `include=ReadState` para recibir `read_state.last_read_at` y `read_state.has_unread_response`. Un hilo nuevo creado por otra cuenta también puede contar como no leído. Listar interacciones con `GET /app/thread/{threadID}/interaction` ahora avanza el punto de lectura del solicitante hasta las respuestas completadas devueltas. Los clientes que consultan este endpoint periódicamente pueden marcar así el contenido como leído; tenlo en cuenta en la lógica de notificaciones y sondeo.

## Peticiones de filesystem

| Método | Ruta obsoleta | Ruta actual |
| - | - | - |
| `GET` | `/app/project/{projectID}/artifact/{integrationArtifactID}/files` | `/app/artifact/{integrationArtifactID}/files` |
| `POST` | `/app/project/{projectID}/artifact/integration/filesystem/validate` | `/app/artifact/integration/filesystem/validate` |

La validación de credenciales requiere el **cuerpo anidado actual en ambas URLs**. Las credenciales antiguas sin anidar no se adaptan.

<Accordion title="Cuerpo de la petición">
  | Campo | Tipo | Obligatorio | Notas |
  | - | - | - | - |
  | `organization_id` | string | Si | Debe coincidir con el espacio de trabajo autenticado. Es obligatorio en esta operación incluso al enviar `x-org`. |
  | `project_id` | string o null | No | Indica el proyecto explícitamente; su validación requiere Project Admin. Sin él, se requiere AppAdmin o superior en el espacio de trabajo. |
  | `credentials` | object | Si | Campos de credenciales anidados que se detallan a continuación. |
  | `credentials.username` | string | Si | Usuario de filesystem. |
  | `credentials.password` | string | Si | Contraseña de filesystem. |
</Accordion>

```json theme={null}
{
  "organization_id": "{orgId}",
  "project_id": "{projectID}",
  "credentials": {
    "username": "***",
    "password": "***"
  }
}
```

Esta operación devuelve un booleano. Consulta [validar credenciales de filesystem](/es/developer-manual/build-with-zylon/workspace-api/integrations/filesystem#validar-credenciales) para ver un ejemplo completo. La ingestión desde integraciones usa la ruta unificada `/ingest` y `project_id` en el cuerpo, como se describe arriba.

## Bloques de herramientas de servidor

En 1.57, cada llamada a herramienta de un mensaje se devolvía como un bloque `tool_use` seguido de un bloque `tool_result`, tanto si la ejecutaba Zylon como si la ejecutaba tu aplicación. En 1.58, las herramientas que **Zylon ejecuta en el servidor** usan el formato de herramientas de servidor de la API de Mensajes de Anthropic. Las herramientas que **ejecuta tu aplicación** (herramientas personalizadas) no cambian y siguen usando `tool_use` y `tool_result`.

Esto afecta al contenido de los mensajes en los eventos en streaming, en las interacciones guardadas de los hilos y en las respuestas de `/messages`. Actualiza cualquier código que detecte llamadas a herramientas comprobando `type == "tool_use"` o `type == "tool_result"`.

| Nombre en 1.57 | Nombre en 1.58 | Bloque de llamada en 1.58 | Bloque de resultado en 1.58 |
| - | - | - | - |
| `web_search` | `web_search` | `server_tool_use` | `web_search_tool_result` |
| `web_extract` (`web_fetch` en la ZylonGPT API) | Sin cambios | `server_tool_use` | `web_fetch_tool_result` |
| `bash` | `bash_code_execution` | `server_tool_use` | `bash_code_execution_tool_result` |
| `view`, `create`, `str_replace`, `insert` | `text_editor_code_execution`, con la operación en `input.command` | `server_tool_use` | `text_editor_code_execution_tool_result` |
| `semantic_search`, `summarize`, `tabular_analysis`, `database_query`, `present_files`, `present_server`, herramientas de skills, herramientas MCP | Sin cambios | `server_tool_use` | `server_tool_result` |
| Herramientas personalizadas que ejecuta tu aplicación | Sin cambios | `tool_use` (sin cambios) | `tool_result` (sin cambios) |

* `server_tool_use.name` es el `name` de la herramienta en la solicitud. Los chats del Workspace envían la herramienta web fetch como `web_extract`, así que sus llamadas aparecen como `web_extract`; los clientes de la ZylonGPT API ven el nombre que enviaron (`web_extract` o `web_fetch`). Identifica el resultado por el tipo de bloque (`web_fetch_tool_result`) en lugar del nombre.
* Los IDs de las llamadas a herramientas de servidor empiezan por `srvtoolu_`, y los de herramientas de cliente, por `tool_`. El `tool_use_id` del resultado hace referencia al ID de la llamada, como antes.
* Zylon ya ha ejecutado las herramientas de servidor, así que no envíes un resultado para ellas. `stop_reason: "tool_use"` sigue aplicándose solo a las herramientas que ejecuta tu aplicación.
* Los bloques siguen el [formato de herramientas de servidor de Anthropic](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools), por lo que los SDKs de Anthropic pueden leerlos directamente. Ignora los campos que no reconozcas, porque Zylon puede añadir campos adicionales.

### Reglas de migración

* **Herramientas de servidor genéricas** (`server_tool_result`): solo cambian los valores de `type` de los bloques y el prefijo del ID. `content` e `is_error` funcionan como antes, así que puedes reutilizar tu parser de 1.57.
* **Herramientas web y de ejecución de código**: `content` es ahora un objeto tipado (o una lista de objetos tipados en la búsqueda web) en lugar de una lista de bloques `text`. Estos bloques **no tienen campo `is_error`**. Para detectar un fallo, comprueba si `content.type` termina en `_error` y lee `content.error_code`.
* **Fallos que 1.57 devolvía como texto**: en 1.57, las herramientas del editor de texto devolvían los fallos como un `tool_result` correcto cuyo texto empezaba por `Error:`. En 1.58 devuelven un objeto de error.
* **Códigos de salida distintos de cero**: un comando bash que termina con un código distinto de cero no es un error en ninguna de las dos versiones. En 1.58, lee `return_code` en lugar de extraer `exit_code:` del texto.

| Qué leías en 1.57 | Dónde leerlo en 1.58 |
| - | - |
| `tool_use.name` | `server_tool_use.name` (consulta la tabla de nombres anterior) |
| `tool_use.input` | `server_tool_use.input` (las llamadas al editor de texto añaden `command`) |
| `tool_result.is_error: true` | `server_tool_result.is_error: true`, o `content.type` terminado en `_error` en los resultados tipados |
| Líneas `exit_code`, `stdout` y `stderr` del texto de bash | `content.return_code`, `content.stdout`, `content.stderr` |
| Texto de salida del editor de texto | `content` tipado según el comando: resultado de `view`, `create` o `str_replace` |
| Lista de texto de la búsqueda web | `content[]` de `web_search_result` (`url`, `title`, `encrypted_content`, `page_age`) |
| Texto Markdown de web fetch | `content.content.source.data` |

### Ejemplos de migración por herramienta

Cada ejemplo muestra el bloque de llamada y el bloque de resultado de una llamada correcta y de una llamada fallida. Los IDs, las entradas y los textos de resultado son solo ejemplos.

<AccordionGroup>
  <Accordion title="web_search">
    <Tabs>
      <Tab title="1.57">
        ```json theme={null}
        [
          { "type": "tool_use", "id": "tool_1a2b", "name": "web_search", "input": { "query": "support backlog report" } },
          {
            "type": "tool_result",
            "tool_use_id": "tool_1a2b",
            "content": [
              {
                "type": "text",
                "text": "1. Quarterly Report\nDescription: Support metrics for Q3\nURL: https://example.com/report\nAge: 2 days ago\nContent: Support backlog dropped 8%.\n"
              }
            ],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        {
          "type": "tool_result",
          "tool_use_id": "tool_1a2b",
          "content": "Web search provider timed out",
          "is_error": true
        }
        ```
      </Tab>

      <Tab title="1.58">
        ```json theme={null}
        [
          { "type": "server_tool_use", "id": "srvtoolu_1a2b", "name": "web_search", "input": { "query": "support backlog report" } },
          {
            "type": "web_search_tool_result",
            "tool_use_id": "srvtoolu_1a2b",
            "content": [
              {
                "type": "web_search_result",
                "url": "https://example.com/report",
                "title": "Quarterly Report",
                "encrypted_content": "Support backlog dropped 8%.",
                "page_age": "2 days ago"
              }
            ]
          }
        ]
        ```

        Zylon ejecuta la búsqueda, así que `encrypted_content` contiene el texto del resultado en texto plano, no datos cifrados.

        Error (`content` es un objeto, no una lista):

        ```json theme={null}
        {
          "type": "web_search_tool_result",
          "tool_use_id": "srvtoolu_1a2b",
          "content": { "type": "web_search_tool_result_error", "error_code": "unavailable" }
        }
        ```
      </Tab>

      <Tab title="1.58 con extensión de Zylon">
        ```json theme={null}
        [
          { "type": "server_tool_use", "id": "srvtoolu_1a2b", "name": "web_search", "input": { "query": "support backlog report" } },
          {
            "type": "tool_result",
            "tool_use_id": "srvtoolu_1a2b",
            "content": [
              {
                "type": "source",
                "sources": [
                  {
                    "object": "context.website",
                    "url": "https://example.com/report",
                    "title": "Quarterly Report",
                    "description": "Support metrics for Q3",
                    "content": "Support backlog dropped 8%."
                  }
                ]
              },
              { "type": "text", "text": "Support backlog dropped 8%." }
            ],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        {
          "type": "tool_result",
          "tool_use_id": "srvtoolu_1a2b",
          "content": [{ "type": "text", "text": "Web search error: Web search provider timed out" }],
          "is_error": true
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="web_extract (web fetch)">
    <Tabs>
      <Tab title="1.57">
        ```json theme={null}
        [
          { "type": "tool_use", "id": "tool_3c4d", "name": "web_extract", "input": { "url": "https://example.com" } },
          {
            "type": "tool_result",
            "tool_use_id": "tool_3c4d",
            "content": [{ "type": "text", "text": "# Example page\n\nWelcome to the example page." }],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        {
          "type": "tool_result",
          "tool_use_id": "tool_3c4d",
          "content": "403 Forbidden",
          "is_error": true
        }
        ```
      </Tab>

      <Tab title="1.58">
        ```json theme={null}
        [
          { "type": "server_tool_use", "id": "srvtoolu_3c4d", "name": "web_extract", "input": { "url": "https://example.com" } },
          {
            "type": "web_fetch_tool_result",
            "tool_use_id": "srvtoolu_3c4d",
            "content": {
              "type": "web_fetch_result",
              "url": "https://example.com",
              "retrieved_at": "2026-09-24T10:00:00Z",
              "content": {
                "type": "document",
                "title": "Example",
                "source": {
                  "type": "text",
                  "media_type": "text/plain",
                  "data": "# Example page\n\nWelcome to the example page."
                }
              }
            }
          }
        ]
        ```

        Error:

        ```json theme={null}
        {
          "type": "web_fetch_tool_result",
          "tool_use_id": "srvtoolu_3c4d",
          "content": { "type": "web_fetch_tool_result_error", "error_code": "unavailable" }
        }
        ```

        Valores posibles de `error_code`: `invalid_tool_input`, `url_too_long`, `url_not_allowed`, `url_not_in_prior_context`, `url_not_accessible`, `unsupported_content_type`, `too_many_requests`, `max_uses_exceeded`, `unavailable`.
      </Tab>

      <Tab title="1.58 con extensión de Zylon">
        ```json theme={null}
        [
          { "type": "server_tool_use", "id": "srvtoolu_3c4d", "name": "web_extract", "input": { "url": "https://example.com" } },
          {
            "type": "tool_result",
            "tool_use_id": "srvtoolu_3c4d",
            "content": [{ "type": "text", "text": "# Example page\n\nWelcome to the example page." }],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        {
          "type": "tool_result",
          "tool_use_id": "srvtoolu_3c4d",
          "content": [{ "type": "text", "text": "Web fetch error: 403 Forbidden" }],
          "is_error": true
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="bash → bash_code_execution">
    <Tabs>
      <Tab title="1.57">
        ```json theme={null}
        [
          { "type": "tool_use", "id": "tool_5e6f", "name": "bash", "input": { "command": "ls /tmp/outputs" } },
          {
            "type": "tool_result",
            "tool_use_id": "tool_5e6f",
            "content": [{ "type": "text", "text": "exit_code: 0\n\nstdout:\nreport.csv\n" }],
            "is_error": false
          }
        ]
        ```

        Un comando con código de salida distinto de cero:

        ```json theme={null}
        {
          "type": "tool_result",
          "tool_use_id": "tool_5e6f",
          "content": [{ "type": "text", "text": "exit_code: 2\n\nstderr:\nls: cannot access 'missing': No such file or directory\n" }],
          "is_error": false
        }
        ```

        Error (la herramienta no se pudo ejecutar):

        ```json theme={null}
        {
          "type": "tool_result",
          "tool_use_id": "tool_5e6f",
          "content": "code_execution provider is not configured.",
          "is_error": true
        }
        ```
      </Tab>

      <Tab title="1.58">
        ```json theme={null}
        [
          { "type": "server_tool_use", "id": "srvtoolu_5e6f", "name": "bash_code_execution", "input": { "command": "ls /tmp/outputs" } },
          {
            "type": "bash_code_execution_tool_result",
            "tool_use_id": "srvtoolu_5e6f",
            "content": {
              "type": "bash_code_execution_result",
              "stdout": "report.csv\n",
              "stderr": "",
              "return_code": 0
            }
          }
        ]
        ```

        Un comando con código de salida distinto de cero:

        ```json theme={null}
        {
          "type": "bash_code_execution_tool_result",
          "tool_use_id": "srvtoolu_5e6f",
          "content": {
            "type": "bash_code_execution_result",
            "stdout": "",
            "stderr": "ls: cannot access 'missing': No such file or directory\n",
            "return_code": 2
          }
        }
        ```

        Error (la herramienta no se pudo ejecutar):

        ```json theme={null}
        {
          "type": "bash_code_execution_tool_result",
          "tool_use_id": "srvtoolu_5e6f",
          "content": { "type": "bash_code_execution_tool_result_error", "error_code": "unavailable" }
        }
        ```

        Valores posibles de `error_code`: `unavailable`, `execution_time_exceeded`, `invalid_tool_input`, `too_many_requests`, `output_file_too_large`, `file_not_found`.
      </Tab>

      <Tab title="1.58 con extensión de Zylon">
        Los resultados correctos son iguales que sin la extensión. Los objetos de error incluyen además `detail`, con el error original:

        ```json theme={null}
        {
          "type": "bash_code_execution_tool_result",
          "tool_use_id": "srvtoolu_5e6f",
          "content": {
            "type": "bash_code_execution_tool_result_error",
            "error_code": "unavailable",
            "detail": { "code": "execution_failed", "explanation": "code_execution provider is not configured." }
          }
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="view, create, str_replace, insert → text_editor_code_execution">
    En 1.57, cada operación era una herramienta distinta. En 1.58 todas son `text_editor_code_execution` y la operación se indica en `input.command`. El resto de campos de entrada mantienen su nombre. En `insert`, 1.58 acepta tanto `insert_text` como `new_str`.

    | Llamada en 1.57 | Llamada en 1.58 |
    | - | - |
    | `view` `{ "path" }` | `text_editor_code_execution` `{ "command": "view", "path" }` |
    | `create` `{ "path", "file_text" }` | `text_editor_code_execution` `{ "command": "create", "path", "file_text" }` |
    | `str_replace` `{ "path", "old_str", "new_str" }` | `text_editor_code_execution` `{ "command": "str_replace", "path", "old_str", "new_str" }` |
    | `insert` `{ "path", "insert_line", "new_str" }` | `text_editor_code_execution` `{ "command": "insert", "path", "insert_line", "insert_text" }` |

    | Comando | Texto de resultado en 1.57 | `content.type` en 1.58 |
    | - | - | - |
    | `view` | Líneas del archivo numeradas | `text_editor_code_execution_view_result` |
    | `create` | `Created <path>` | `text_editor_code_execution_create_result` |
    | `str_replace` | `Updated <path>` | `text_editor_code_execution_str_replace_result` |
    | `insert` | `Updated <path>` | `text_editor_code_execution_str_replace_result` |

    <Tabs>
      <Tab title="1.57">
        `view`:

        ```json theme={null}
        [
          { "type": "tool_use", "id": "tool_7a8b", "name": "view", "input": { "path": "/tmp/outputs/app.py" } },
          {
            "type": "tool_result",
            "tool_use_id": "tool_7a8b",
            "content": [{ "type": "text", "text": "1: total = 0\n2: print(total)" }],
            "is_error": false
          }
        ]
        ```

        `create`:

        ```json theme={null}
        [
          { "type": "tool_use", "id": "tool_7a8c", "name": "create", "input": { "path": "/tmp/outputs/app.py", "file_text": "total = 0\n" } },
          { "type": "tool_result", "tool_use_id": "tool_7a8c", "content": [{ "type": "text", "text": "Created /tmp/outputs/app.py" }], "is_error": false }
        ]
        ```

        `str_replace`:

        ```json theme={null}
        [
          { "type": "tool_use", "id": "tool_7a8d", "name": "str_replace", "input": { "path": "/tmp/outputs/app.py", "old_str": "total = 0", "new_str": "total = 100" } },
          { "type": "tool_result", "tool_use_id": "tool_7a8d", "content": [{ "type": "text", "text": "Updated /tmp/outputs/app.py" }], "is_error": false }
        ]
        ```

        `insert`:

        ```json theme={null}
        [
          { "type": "tool_use", "id": "tool_7a8e", "name": "insert", "input": { "path": "/tmp/outputs/app.py", "insert_line": 1, "new_str": "print(total)" } },
          { "type": "tool_result", "tool_use_id": "tool_7a8e", "content": [{ "type": "text", "text": "Updated /tmp/outputs/app.py" }], "is_error": false }
        ]
        ```

        Error. Los errores de archivo se devolvían como un resultado correcto cuyo texto empezaba por `Error:`:

        ```json theme={null}
        {
          "type": "tool_result",
          "tool_use_id": "tool_7a8b",
          "content": [{ "type": "text", "text": "Error: File not found: /tmp/outputs/missing.py" }],
          "is_error": false
        }
        ```
      </Tab>

      <Tab title="1.58">
        `view`:

        ```json theme={null}
        [
          { "type": "server_tool_use", "id": "srvtoolu_7a8b", "name": "text_editor_code_execution", "input": { "command": "view", "path": "/tmp/outputs/app.py" } },
          {
            "type": "text_editor_code_execution_tool_result",
            "tool_use_id": "srvtoolu_7a8b",
            "content": {
              "type": "text_editor_code_execution_view_result",
              "file_type": "text",
              "content": "total = 0\nprint(total)",
              "num_lines": 2,
              "start_line": 1,
              "total_lines": 2
            }
          }
        ]
        ```

        `create`:

        ```json theme={null}
        [
          { "type": "server_tool_use", "id": "srvtoolu_7a8c", "name": "text_editor_code_execution", "input": { "command": "create", "path": "/tmp/outputs/app.py", "file_text": "total = 0\n" } },
          {
            "type": "text_editor_code_execution_tool_result",
            "tool_use_id": "srvtoolu_7a8c",
            "content": { "type": "text_editor_code_execution_create_result", "is_file_update": false }
          }
        ]
        ```

        `str_replace`:

        ```json theme={null}
        [
          { "type": "server_tool_use", "id": "srvtoolu_7a8d", "name": "text_editor_code_execution", "input": { "command": "str_replace", "path": "/tmp/outputs/app.py", "old_str": "total = 0", "new_str": "total = 100" } },
          {
            "type": "text_editor_code_execution_tool_result",
            "tool_use_id": "srvtoolu_7a8d",
            "content": {
              "type": "text_editor_code_execution_str_replace_result",
              "old_start": 1,
              "old_lines": 1,
              "new_start": 1,
              "new_lines": 1,
              "lines": ["- total = 0", "+ total = 100"]
            }
          }
        ]
        ```

        `insert` (devuelve un resultado de `str_replace` con `old_lines: 0`):

        ```json theme={null}
        [
          { "type": "server_tool_use", "id": "srvtoolu_7a8e", "name": "text_editor_code_execution", "input": { "command": "insert", "path": "/tmp/outputs/app.py", "insert_line": 1, "insert_text": "print(total)" } },
          {
            "type": "text_editor_code_execution_tool_result",
            "tool_use_id": "srvtoolu_7a8e",
            "content": {
              "type": "text_editor_code_execution_str_replace_result",
              "old_start": 2,
              "old_lines": 0,
              "new_start": 2,
              "new_lines": 1,
              "lines": ["+ print(total)"]
            }
          }
        ]
        ```

        Error. Los errores de archivo devuelven ahora un objeto de error:

        ```json theme={null}
        {
          "type": "text_editor_code_execution_tool_result",
          "tool_use_id": "srvtoolu_7a8b",
          "content": { "type": "text_editor_code_execution_tool_result_error", "error_code": "unavailable" }
        }
        ```

        Los códigos de error son los mismos que en `bash_code_execution`.
      </Tab>

      <Tab title="1.58 con extensión de Zylon">
        Los resultados correctos son iguales que sin la extensión. Los objetos de error incluyen además `detail`, con el error original:

        ```json theme={null}
        {
          "type": "text_editor_code_execution_tool_result",
          "tool_use_id": "srvtoolu_7a8b",
          "content": {
            "type": "text_editor_code_execution_tool_result_error",
            "error_code": "unavailable",
            "detail": { "code": "execution_failed", "explanation": "File not found: /tmp/outputs/missing.py" }
          }
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="semantic_search">
    <Tabs>
      <Tab title="1.57">
        ```json theme={null}
        [
          { "type": "tool_use", "id": "tool_9c0d", "name": "semantic_search", "input": { "query": "billing issues" } },
          {
            "type": "tool_result",
            "tool_use_id": "tool_9c0d",
            "content": [
              { "type": "source", "sources": [{ "object": "context.chunk", "id": "chunk_1", "text": "Customers reported duplicate charges..." }] },
              { "type": "text", "text": "Customers reported duplicate charges after the plan change." }
            ],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        { "type": "tool_result", "tool_use_id": "tool_9c0d", "content": "context_filter is required", "is_error": true }
        ```
      </Tab>

      <Tab title="1.58">
        ```json theme={null}
        [
          { "type": "server_tool_use", "id": "srvtoolu_9c0d", "name": "semantic_search", "input": { "query": "billing issues" } },
          {
            "type": "server_tool_result",
            "tool_use_id": "srvtoolu_9c0d",
            "content": [
              { "type": "source", "sources": [{ "object": "context.chunk", "id": "chunk_1", "text": "Customers reported duplicate charges..." }] },
              { "type": "text", "text": "Customers reported duplicate charges after the plan change." }
            ],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        { "type": "server_tool_result", "tool_use_id": "srvtoolu_9c0d", "content": "context_filter is required", "is_error": true }
        ```

        Los bloques `source` son específicos de Zylon. Solo se devuelven cuando la extensión de Zylon está activada.
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="summarize">
    <Tabs>
      <Tab title="1.57">
        ```json theme={null}
        [
          { "type": "tool_use", "id": "tool_1e2f", "name": "summarize", "input": { "instructions": "Summarize in three bullets" } },
          {
            "type": "tool_result",
            "tool_use_id": "tool_1e2f",
            "content": [{ "type": "text", "text": "- Revenue grew 12%\n- Churn fell to 3%\n- Two new regions launched" }],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        { "type": "tool_result", "tool_use_id": "tool_1e2f", "content": "context_filter is required", "is_error": true }
        ```
      </Tab>

      <Tab title="1.58">
        ```json theme={null}
        [
          { "type": "server_tool_use", "id": "srvtoolu_1e2f", "name": "summarize", "input": { "instructions": "Summarize in three bullets" } },
          {
            "type": "server_tool_result",
            "tool_use_id": "srvtoolu_1e2f",
            "content": [{ "type": "text", "text": "- Revenue grew 12%\n- Churn fell to 3%\n- Two new regions launched" }],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        { "type": "server_tool_result", "tool_use_id": "srvtoolu_1e2f", "content": "context_filter is required", "is_error": true }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="tabular_analysis">
    <Tabs>
      <Tab title="1.57">
        ```json theme={null}
        [
          { "type": "tool_use", "id": "tool_3a4b", "name": "tabular_analysis", "input": { "query": "Total sales by region" } },
          {
            "type": "tool_result",
            "tool_use_id": "tool_3a4b",
            "content": [{ "type": "text", "text": "region,total\nNorth,1200\nSouth,950" }],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        { "type": "tool_result", "tool_use_id": "tool_3a4b", "content": "context_filter is required", "is_error": true }
        ```
      </Tab>

      <Tab title="1.58">
        ```json theme={null}
        [
          { "type": "server_tool_use", "id": "srvtoolu_3a4b", "name": "tabular_analysis", "input": { "query": "Total sales by region" } },
          {
            "type": "server_tool_result",
            "tool_use_id": "srvtoolu_3a4b",
            "content": [{ "type": "text", "text": "region,total\nNorth,1200\nSouth,950" }],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        { "type": "server_tool_result", "tool_use_id": "srvtoolu_3a4b", "content": "context_filter is required", "is_error": true }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="database_query">
    <Tabs>
      <Tab title="1.57">
        ```json theme={null}
        [
          { "type": "tool_use", "id": "tool_5c6d", "name": "database_query", "input": { "query": "How many open tickets are there?" } },
          {
            "type": "tool_result",
            "tool_use_id": "tool_5c6d",
            "content": [{ "type": "text", "text": "Query result: \nopen_tickets\n42" }],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        { "type": "tool_result", "tool_use_id": "tool_5c6d", "content": "At least one SQL database artifact is required.", "is_error": true }
        ```
      </Tab>

      <Tab title="1.58">
        ```json theme={null}
        [
          { "type": "server_tool_use", "id": "srvtoolu_5c6d", "name": "database_query", "input": { "query": "How many open tickets are there?" } },
          {
            "type": "server_tool_result",
            "tool_use_id": "srvtoolu_5c6d",
            "content": [{ "type": "text", "text": "Query result: \nopen_tickets\n42" }],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        { "type": "server_tool_result", "tool_use_id": "srvtoolu_5c6d", "content": "At least one SQL database artifact is required.", "is_error": true }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="present_files">
    <Tabs>
      <Tab title="1.57">
        ```json theme={null}
        [
          { "type": "tool_use", "id": "tool_7e8f", "name": "present_files", "input": { "filepaths": ["/tmp/outputs/report.csv"] } },
          {
            "type": "tool_result",
            "tool_use_id": "tool_7e8f",
            "content": [
              { "type": "local_resource", "file_path": "/tmp/outputs/report.csv", "file_id": "L3RtcC9vdXRwdXRzL3JlcG9ydC5jc3Y", "name": "report", "mime_type": "text/csv" },
              { "type": "text", "text": "Presented 1 file(s): report.csv" }
            ],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        { "type": "tool_result", "tool_use_id": "tool_7e8f", "content": "code_execution provider is not configured.", "is_error": true }
        ```
      </Tab>

      <Tab title="1.58">
        ```json theme={null}
        [
          { "type": "server_tool_use", "id": "srvtoolu_7e8f", "name": "present_files", "input": { "filepaths": ["/tmp/outputs/report.csv"] } },
          {
            "type": "server_tool_result",
            "tool_use_id": "srvtoolu_7e8f",
            "content": [
              { "type": "local_resource", "file_path": "/tmp/outputs/report.csv", "file_id": "L3RtcC9vdXRwdXRzL3JlcG9ydC5jc3Y", "name": "report", "mime_type": "text/csv" },
              { "type": "text", "text": "Presented 1 file(s): report.csv" }
            ],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        { "type": "server_tool_result", "tool_use_id": "srvtoolu_7e8f", "content": "code_execution provider is not configured.", "is_error": true }
        ```

        En ambas versiones, un archivo que no se puede presentar añade un bloque de texto `Error presenting <path>: ...` y el resultado mantiene `is_error: false`.
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="present_server">
    <Tabs>
      <Tab title="1.57">
        ```json theme={null}
        [
          { "type": "tool_use", "id": "tool_9a0b", "name": "present_server", "input": { "port": 8000, "service_name": "Dashboard" } },
          {
            "type": "tool_result",
            "tool_use_id": "tool_9a0b",
            "content": [
              { "type": "resource_link", "uri": "https://app-8000.example.com/", "name": "Dashboard", "mime_type": "text/html" },
              { "type": "text", "text": "The service 'Dashboard' is available at https://app-8000.example.com/." }
            ],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        { "type": "tool_result", "tool_use_id": "tool_9a0b", "content": "code_execution provider is not configured.", "is_error": true }
        ```
      </Tab>

      <Tab title="1.58">
        ```json theme={null}
        [
          { "type": "server_tool_use", "id": "srvtoolu_9a0b", "name": "present_server", "input": { "port": 8000, "service_name": "Dashboard" } },
          {
            "type": "server_tool_result",
            "tool_use_id": "srvtoolu_9a0b",
            "content": [
              { "type": "resource_link", "uri": "https://app-8000.example.com/", "name": "Dashboard", "mime_type": "text/html" },
              { "type": "text", "text": "The service 'Dashboard' is available at https://app-8000.example.com/." }
            ],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        { "type": "server_tool_result", "tool_use_id": "srvtoolu_9a0b", "content": "code_execution provider is not configured.", "is_error": true }
        ```

        Si el sandbox no puede exponer el puerto, ambas versiones devuelven un resultado correcto que solo contiene el texto `No HTTP endpoint is available for port 8000. ...`.
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="Herramientas de skills (load_skill, unload_skill, list_skills)">
    Las herramientas de skills devuelven JSON como texto. Si no se encuentra una skill, la herramienta devuelve una clave `error` en el JSON y mantiene `is_error: false`.

    <Tabs>
      <Tab title="1.57">
        ```json theme={null}
        [
          { "type": "tool_use", "id": "tool_1c2d", "name": "load_skill", "input": { "name": "pdf-report" } },
          {
            "type": "tool_result",
            "tool_use_id": "tool_1c2d",
            "content": [{ "type": "text", "text": "{\"name\": \"pdf-report\", \"skill_id\": \"skl_123\", \"version\": 2, \"loaded\": true}" }],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        {
          "type": "tool_result",
          "tool_use_id": "tool_1c2d",
          "content": [{ "type": "text", "text": "{\"error\": \"Skill 'pdf-report' not found in current skill_filter\"}" }],
          "is_error": false
        }
        ```
      </Tab>

      <Tab title="1.58">
        ```json theme={null}
        [
          { "type": "server_tool_use", "id": "srvtoolu_1c2d", "name": "load_skill", "input": { "name": "pdf-report" } },
          {
            "type": "server_tool_result",
            "tool_use_id": "srvtoolu_1c2d",
            "content": [{ "type": "text", "text": "{\"name\": \"pdf-report\", \"skill_id\": \"skl_123\", \"version\": 2, \"loaded\": true}" }],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        {
          "type": "server_tool_result",
          "tool_use_id": "srvtoolu_1c2d",
          "content": [{ "type": "text", "text": "{\"error\": \"Skill 'pdf-report' not found in current skill_filter\"}" }],
          "is_error": false
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="Herramientas MCP">
    Las herramientas MCP mantienen el nombre de la herramienta del servidor MCP y devuelven los bloques de contenido que genera el servidor MCP.

    <Tabs>
      <Tab title="1.57">
        ```json theme={null}
        [
          { "type": "tool_use", "id": "tool_3e4f", "name": "create_issue", "input": { "title": "Login fails on Safari" } },
          {
            "type": "tool_result",
            "tool_use_id": "tool_3e4f",
            "content": [{ "type": "text", "text": "Created issue #128" }],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        { "type": "tool_result", "tool_use_id": "tool_3e4f", "content": "MCP server returned 401 Unauthorized", "is_error": true }
        ```
      </Tab>

      <Tab title="1.58">
        ```json theme={null}
        [
          { "type": "server_tool_use", "id": "srvtoolu_3e4f", "name": "create_issue", "input": { "title": "Login fails on Safari" } },
          {
            "type": "server_tool_result",
            "tool_use_id": "srvtoolu_3e4f",
            "content": [{ "type": "text", "text": "Created issue #128" }],
            "is_error": false
          }
        ]
        ```

        Error:

        ```json theme={null}
        { "type": "server_tool_result", "tool_use_id": "srvtoolu_3e4f", "content": "MCP server returned 401 Unauthorized", "is_error": true }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="Herramientas personalizadas (sin cambios)">
    Nada cambia para las herramientas que define y ejecuta tu aplicación. La respuesta se detiene con `stop_reason: "tool_use"`, tu aplicación ejecuta la herramienta y envía de vuelta un bloque `tool_result`, como en 1.57.

    ```json theme={null}
    [
      { "type": "tool_use", "id": "tool_5a6b", "name": "get_weather", "input": { "city": "Madrid" } }
    ]
    ```

    ```json theme={null}
    { "type": "tool_result", "tool_use_id": "tool_5a6b", "content": [{ "type": "text", "text": "24°C, sunny" }], "is_error": false }
    ```
  </Accordion>
</AccordionGroup>

### Peticiones con la extensión de Zylon activada

Si una petición activa la extensión de Zylon (`system.extensions` incluye `zylon`):

* Los resultados de `web_search` y `web_fetch` se devuelven como un bloque `tool_result` normal, como muestran los ejemplos anteriores. El bloque de llamada sigue siendo `server_tool_use` y el ID de la llamada sigue empezando por `srvtoolu_`.
* Los objetos de error de `bash_code_execution_tool_result` y `text_editor_code_execution_tool_result` incluyen un campo `detail` con el error original.
* Los bloques específicos de Zylon, como `source`, se conservan en el contenido de `server_tool_result`.

### Envío del historial de conversación

Puedes enviar de vuelta en `messages` los bloques `server_tool_use` y los resultados de herramientas de servidor tal como los recibiste. Zylon los convierte internamente, así que no necesitas cambios si reenvías sin modificar los turnos anteriores del asistente. El historial con los bloques `tool_use` y `tool_result` de 1.57 se sigue aceptando.

## Antes de actualizar tu cliente

1. Sustituye las URLs obsoletas y mueve el selector de proyecto a la consulta o al cuerpo correspondiente.
2. Usa bytes Base64 para crear artefactos con JSON, texto para actualizarlos y `file_data` para archivos multipart.
3. Adapta la lectura de respuestas a la separación entre cuenta y miembro y a la eliminación del contenido inline de artefactos. Revisa los IDs de usuario/cuenta almacenados, relaciones, comparaciones y filtros aunque las llamadas sigan funcionando.
4. Usa IDs de cuenta en los filtros de creador y los nombres canónicos de campos e inclusiones.
5. Adapta el procesado de mensajes a `server_tool_use` y a los bloques de resultado de herramientas de servidor, y devuelve `tool_result` solo para tus herramientas personalizadas.
6. Adapta los cuerpos de chat, selectores de artefactos por ámbito, SSE, archivos de hilo y sondeo del estado de lectura.
7. Prueba con 1.58, incluidos permisos, validación, conversión de contenido y validación de filesystem. Las URLs antiguas usan la autorización, las respuestas y el comportamiento de servicio actuales; no reproducen todos los comportamientos de 1.57.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.