Formato de salida
Cada llamada que termina bien devuelve las mismas dos cosas, en todas las superficies de herramientas:
structuredContent: el valor completo que devolvió Arcane, sin cambios (las listas bajoitems, conpaginational lado cuando Arcane pagina la lista). Los clientes y scripts que necesitan todos los campos leen esto. La única excepción son los esquemas de salida experimentales (ARCANE_MCP_OUTPUT_SCHEMAS, desactivados por defecto): con ellos activos, una parte de la respuesta de Arcane que no encaja con el esquema declarado de la herramienta se envía comonull, y el texto enumera entonces cada una de esas partes con el valor original de Arcane.- Un bloque de texto: una representación en Markdown de ese valor, dimensionada para que la lea un modelo. Lleva la anotación de audiencia
assistant.
El texto no repite el JSON. En su lugar dice qué deja fuera, para que un modelo que solo lee el texto sepa dónde buscar.
Los errores son distintos: una llamada fallida devuelve isError con un mensaje en texto plano y un siguiente paso (por ejemplo, qué acción de listado encuentra identificadores válidos). No tiene contenido estructurado ni representación en Markdown.
Qué contiene el texto
Sección titulada «Qué contiene el texto»| El resultado es | El texto muestra |
|---|---|
| una lista | un título, el número de elementos y la página (3 item(s) — 12 total, page 1 of 4), y una tabla con los campos que identifican y describen cada elemento. Una lista vacía dice No items. o, en las listas principales (contenedores, imágenes, proyectos, volúmenes, redes, entornos), qué puede dejarla vacía y cómo ampliarla, como No containers match. If search, label, standalone or updates was set, drop it to widen the list; … |
| un objeto | un título y una línea - **campo**: valor por campo, primero los de identidad y estado; el texto de varias líneas tiene su propia sección delimitada y los objetos y listas anidados, un bloque JSON |
| una descarga de texto (logs, ficheros compose, PEM) | el nombre del fichero, su tamaño y tipo, y el propio texto en un bloque delimitado |
| una descarga binaria (tarballs, copias de seguridad, perfiles) | los metadatos; el fichero va aparte como recurso incrustado con audiencia user |
| la salida de un manejador de logs o de exec | esa salida, tal como la escribió el manejador |
Los tamaños en bytes también aparecen en unidades legibles (1500000000 (1.5 GB)), y las celdas largas de una tabla se recortan, salvo los identificadores y nombres, que una llamada posterior necesita enteros.
Qué deja fuera, y lo dice
Sección titulada «Qué deja fuera, y lo dice»- Columnas. Una tabla muestra los campos que identifican y describen cada elemento (los que elige la propia acción, o hasta seis escogidos por su nombre). Cuando los elementos tienen más campos, una nota final los enumera y nombra la acción que devuelve un elemento completo, por ejemplo
container.get. - Filas. Una tabla muestra como mucho 50 filas. Cuando una página tiene más, el texto dice cuántas se han recortado y cómo leer el resto (
startylimit, o los filtros de la lista). - Campos nulos. Se omiten de las líneas de un objeto.
structuredContent siempre tiene todas las filas y todos los campos.
Un enlace al recurso del objeto
Sección titulada «Un enlace al recurso del objeto»Los resultados de environment.get, container.get y project.get terminan con un bloque de contenido más, un resource_link al recurso que sirve el mismo objeto: arcane://environment/{environmentId}, …/container/{containerId} o …/project/{projectId}, rellenado con los argumentos de la llamada (el entorno predeterminado si se omitió environmentId). Lleva el nombre y el título del recurso y application/json; un cliente puede adjuntarlo a la conversación o volver a leerlo más tarde con resources/read. El recurso es la vista con datos ocultos que describe esa página, así que el enlace no añade nada que la llamada no devolviera ya. El texto y structuredContent no cambian, una llamada fallida no lleva enlace, y es igual en todas las superficies.
Siguientes pasos
Sección titulada «Siguientes pasos»Tras una llamada que termina bien, el texto puede acabar con una sección breve de Next steps, de cuatro líneas como mucho:
- los seguimientos conocidos declarados para la acción (por ejemplo, tras descargar una imagen, volver a desplegar el proyecto que la usa);
- las acciones relacionadas de la acción, con sus títulos. Las destructivas se marcan como que necesitan
confirm.
Nunca se sugieren acciones que el servidor no sirve: el modo de solo lectura y ARCANE_MCP_EXCLUDE_TOOLS las quitan de la lista. En modo seguro, las acciones que cambian el estado siguen apareciendo, pero marcadas «(safe mode: preview only)»: llamarlas devuelve la petición que se enviaría, no el cambio. La sección se omite donde no aporta nada: descargas, salida de logs y de exec, y vistas previas del modo seguro (no se ejecutó nada). Vive solo en el texto y nunca se añade a structuredContent.
Los nombres de acción siguen a la superficie
Sección titulada «Los nombres de acción siguen a la superficie»Los nombres de acción que escribe el servidor (los siguientes pasos y la nota sobre la acción que devuelve el elemento completo) se escriben como los acepta la superficie que hace la llamada:
| Superficie | Se escribe |
|---|---|
| dynamic | container.get (se pasa a arcane_execute_action) |
| meta | arcane_container (action get) |
| individual | arcane_container_get |
Los valores que vienen de Arcane nunca se reescriben, aunque parezcan un nombre de acción.
Escapado de los valores de Arcane
Sección titulada «Escapado de los valores de Arcane»Arcane guarda lo que Docker, los ficheros compose, las etiquetas de las imágenes, los registros y los usuarios ponen ahí, así que el servidor trata cada valor como texto no fiable. Los modelos suelen leer el Markdown en bruto y copiar de él los valores para su siguiente llamada, así que el escapado persigue dos objetivos: que nada de un valor pueda cambiar la estructura del texto y que un identificador llegue al modelo exactamente como es.
- Se eliminan las secuencias de terminal y los caracteres invisibles. Se quitan las secuencias ANSI de color y cursor, las secuencias OSC (títulos de terminal, hipervínculos), los bytes de control C0 y C1 salvo el salto de línea y el tabulador, los caracteres Unicode de control bidireccional y los caracteres de anchura cero (ZWSP, ZWNJ, ZWJ, word joiner, la marca de orden de bytes). El retorno de carro se conserva delante de un salto de línea, así que un texto CRLF sigue siendo CRLF; un retorno de carro suelto, que un terminal usa para sobrescribir la línea, se convierte en salto de línea, igual que los separadores Unicode de línea y de párrafo. Se aplica a cada valor, y el texto terminado pasa una vez más por el filtro, lo haya escrito quien lo haya escrito.
- Los valores normales quedan como están. Un valor que Markdown leería como texto normal se escribe tal cual:
my_container,/var/lib/docker/volumes/x/_data,app_,*/5 * * * *,nginx@sha256:…,C:\data. - Un único token que formaría Markdown se escribe como fragmento de código. Por ejemplo, el
<none>:<none>de una imagen colgante va entre comillas invertidas, donde Markdown no lo interpreta, y el modelo lo sigue leyendo exactamente igual. La valla es más larga que cualquier secuencia de comillas invertidas del valor. - El texto con espacios recibe una barra invertida solo donde Markdown formaría algo: un
<que abre una etiqueta, un comentario o un enlace automático, un[seguido más adelante de](o][(un enlace o una imagen), los delimitadores*o_que tienen pareja de cierre (énfasis) y las secuencias de comillas invertidas que se emparejan (un fragmento de código). Los nombres de campo, las claves en negrita y los valores de una lista corta se escapan algo más estrictamente, porque la pareja de un*, una`, un[o un_al borde de una palabra podría estar en el valor siguiente. - Las celdas de tabla y los títulos escapan además
|(celdas) y una secuencia final de#(títulos). Un elemento de lista que empezaría un bloque propio (un título, una cita, una lista anidada, una línea horizontal, una valla, una casilla de tarea) se mantiene literal. - Los bloques delimitados son literales. El texto de varias líneas y los bloques JSON conservan su contenido tal cual (normalizado como arriba), dentro de una valla más larga que cualquier secuencia de comillas invertidas que contengan, así que nada del contenido puede cerrar el bloque antes de tiempo.
Nada de esto toca structuredContent: lleva el valor original, byte a byte como lo devolvió Arcane (salvo las partes ajustadas para encajar con un esquema de salida, cuando están activos).