CodeGym /Cursos /ChatGPT Apps /De las instrucciones al diseño de tools y metadatos: desc...

De las instrucciones al diseño de tools y metadatos: descubrimiento y enrutamiento

ChatGPT Apps
Nivel 5 , Lección 4
Disponible

1. Por qué las instrucciones no bastan sin buenos tools y metadatos

Conviene fijar una verdad incómoda: el modelo no ve tu código. No sabe qué controladores hay en Next.js, qué funciones en TypeScript ni qué maravillosas heurísticas has reunido en el servicio de recomendaciones.

Ve tu App a través de varios interfaces:

  1. System‑prompt (contrato de rol).
  2. Descripciones de herramientas: nombre, description, inputSchema, outputSchema, anotaciones, etc.
  3. Metadatos de la propia aplicación: nombre, icono, descripción corta y larga, categorías, conversation starters, etc.

Al procesar una solicitud, el modelo mira el contexto del diálogo y esos metadatos para decidir:

  • si merece la pena sugerir alguna App;
  • si sí — cuál de las disponibles;
  • y si se elige una App — qué herramienta concreta de esa App encaja con la solicitud actual.

En la parte anterior del Módulo 5 nos ocupamos de lo que se puede «contar» al modelo con palabras — system‑prompt e instrucciones de UX. Ahora pasamos a lo que ve además del texto: tools y metadatos.

Por tanto, la tarea del Módulo 5 es en realidad doble. Primero, en el system‑prompt formulas «qué debe hacer esta App y cómo debe comportarse», y luego, en el diseño de tools y metadatos, lo empaquetas en una forma que el modelo realmente sabe usar — incluso para el descubrimiento y el enrutamiento.

Podemos formularlo así: el system‑prompt es la constitución, y los tools y metadatos son las leyes y toda la burocracia alrededor: formularios, esquemas de bases de datos, etc. Si nos quedamos solo con la constitución, no llegaremos muy lejos.

2. Decomposición: «una tarea — un tool», pero con cabeza

Empecemos por lo más doloroso: cuántas herramientas hacer y cómo recortarlas.

Principio intuitivo: una herramienta — una tarea clara. Esto facilita mucho la elección del modelo: no tiene una función monstruosa do_everything, sino varias acciones ordenadas con buenos nombres.

Para GiftGenius podemos tener estas herramientas básicas:

  • profile_to_segments — convertir una descripción libre del destinatario (edad, intereses, relación, contexto) en segmentos normalizados como "tech", "fitness", "gamer".
  • recommend_gifts — seleccionar una lista de id de regalos según segmentos, presupuesto, locale y ocasión.
  • get_gift — obtener la ficha completa del regalo elegido (descripción, medios, SKU/variantes) por su id.
  • (opcional) similar_gifts — a partir de un regalo elegido, sugerir 3–5 alternativas similares.

Teóricamente podrías hacer un único gift_tool con un parámetro mode: "profile_to_segments" | "recommend" | "details" | "similar", pero así os complicáis la vida tú y el modelo: la descripción se convierte en un testamento, el inputSchema crece, y al elegir la herramienta el modelo tiene menos anclas claras.

Anti‑patrón: God Tool

Imagina este esquema:

server.registerTool(
  "gift_tool",
  {
    description: "Varias operaciones con regalos.",
    inputSchema: { /* 50 campos y flags */ },
  },
  async ({ input }) => { /* un switch enorme según mode */ }
);

En la cabeza del modelo esto se ve como «hay alguna herramienta abstracta sobre regalos y ya veremos». Esto empeora la precisión de la elección, dificulta el descubrimiento y complica el mantenimiento.

Pero caer en el extremo contrario — crear 50 herramientas microscópicas para cada minucia — también es malo. Cada herramienta adicional entra en el contexto, carga la atención del modelo y aumenta el riesgo de errores de enrutamiento. La documentación avisa claramente: demasiados tools pequeños restan calidad, especialmente cuando sus descripciones se solapan.

Regla práctica útil:

  • todo lo que el usuario percibe como un «paso» en el flujo (por ejemplo, la primera selección de regalos por perfil) — buen candidato a tool independiente;
  • lo que siempre se ejecuta estrictamente dentro de ese paso y no tiene sentido por sí mismo (por ejemplo, calcular el scoring o registrar la vista de tarjetas) es mejor dejarlo dentro de la implementación de la herramienta.

Supongamos que ya has cortado los escenarios en 2–4 herramientas siguiendo este principio. La siguiente pregunta clave — cómo describir las entradas de esos tools para que el modelo pueda usarlos sin adivinanzas. Empecemos por ahí.

3. Proyectar los use‑cases al Input Schema

Ahora tomamos un use‑case concreto y miramos sinceramente qué datos necesita realmente la herramienta.

Escenario: «Donante a contrarreloj: seleccionar 5–7 ideas para un amigo de 25 años, le encanta el fútbol y los juegos de mesa, presupuesto hasta 50 $».

Desde jobs‑to‑be‑done está claro que la tarea del núcleo de recomendación de GiftGenius es acotar la selección a una lista pequeña y reducir la ansiedad de «y si elijo algo malo». A nivel de chat, el asistente necesita:

  • información básica del destinatario (edad, sexo, relación con el donante);
  • intereses/aficiones;
  • presupuesto y divisa;
  • ocasión (cumpleaños, aniversario, Año Nuevo, etc.);
  • opcionalmente — país/ciudad para filtrar por envío.

En la arquitectura de GiftGenius esto se descompone en dos pasos:

  1. profile_to_segments(input) recibe datos «en bruto» (edad, intereses, descripción en texto) y los transforma en segmentos normalizados con los que es cómodo trabajar.
  2. recommend_gifts(segments, budget, locale, occasion) ya selecciona por segmentos y presupuesto id concretos de regalos del catálogo.

En el contrato ChatGPT ↔ MCP nos interesa describir precisamente el segundo paso — el esquema de recommend_gifts, porque es la herramienta que se usará en la mayoría de escenarios de selección.

Al mismo tiempo, no hay que exigir todo al usuario de entrada: el modelo puede completar parte con un follow‑up («¿cuál es el presupuesto aproximado?»). Así que parte de los campos del perfil pueden ser opcionales; pero cuando llegamos a recommend_gifts, ya debe haber un conjunto normalizado de parámetros.

Ejemplo: TypeScript + JSON Schema para recommend_gifts

En el servidor MCP en TypeScript puede verse así:

// apps/mcp/server.ts
import { McpServer } from "@openai/mcp-server";

const server = new McpServer();

server.registerTool(
  "recommend_gifts",
  {
    title: "Recomendaciones de regalos",
    description:
      "Usa esta herramienta cuando necesites seleccionar regalos por segmentos del destinatario, presupuesto, locale y ocasión.",
    inputSchema: {
      type: "object",
      properties: {
        segments: {
          type: "array",
          description:
            "Lista de segmentos del destinatario, por ejemplo ['tech', 'football_fan']. Normalmente se toma de profile_to_segments.",
          items: { type: "string" },
          minItems: 1
        },
        budget: {
          type: "object",
          description:
            "Rango de presupuesto para el regalo en la divisa del usuario (mínimo/máximo).",
          properties: {
            min: {
              type: "number",
              minimum: 0,
              description: "Cantidad mínima que el usuario está dispuesto a gastar."
            },
            max: {
              type: "number",
              minimum: 0,
              description: "Cantidad máxima que el usuario está dispuesto a gastar."
            },
            currency: {
              type: "string",
              minLength: 3,
              maxLength: 3,
              description: "Código de divisa de tres letras (por ejemplo, USD, EUR, RUB)."
            }
          },
          required: ["min", "max", "currency"]
        },
        locale: {
          type: "string",
          description:
            "Configuración regional del usuario en formato BCP‑47 (por ejemplo, 'ru-RU' o 'en-US')."
        },
        occasion: {
          type: "string",
          description:
            "Ocasión para el regalo, por ejemplo 'birthday', 'new_year', 'anniversary'."
        }
      },
      required: ["segments", "budget", "locale", "occasion"]
    }
  },
  async ({ input }) => {
    // De momento no nos complicamos: devolvemos una respuesta simulada
    return {
      content: [
        {
          type: "text",
          text: `Estoy seleccionando regalos por segmentos ${input.segments?.join(
            ", "
          )} dentro del presupuesto de ${input.budget?.min}–${input.budget?.max} ${input.budget?.currency}...`
        }
      ],
      structuredContent: {}
    };
  }
);

Fíjate en un par de puntos.

Primero, usamos activamente restricciones tipo enum y descripciones claras. Incluso si formalmente son cadenas, el description le sugiere al modelo qué valores se esperan, lo que aumenta notablemente la probabilidad de que rellene bien los argumentos. En lugar de una cadena difusa "ocasión": "algo tipo cumpleaños" tenemos una occasion: "birthday" ordenada.

Segundo, las descripciones de campos no se escriben «para la gente del equipo», sino literalmente como pistas para el modelo: qué es el campo, qué valores típicos tiene, si hay ejemplo. Los autores de la documentación de Apps SDK recomiendan añadir descripciones y ejemplos comprensibles para cada parámetro.

Qué no debe estar en el esquema de entrada

Campos parásitos típicos que a menudo se intentan colar:

  • identificadores internos (tenantId, internalSegment), que puedes añadir en el servidor;
  • cosas que el modelo no puede saber (por ejemplo, deploymentRegion) — eso es tu responsabilidad;
  • campos duplicados del historial del chat (por ejemplo, userPrompt): el modelo ya ve el mensaje original, no le obligues a copiar y pegar.

Input Schema — es exactamente lo que el modelo debe decidir y rellenar, no un cajón de sastre.

4. Output Schema: no solo datos, también significado

En Apps SDK el resultado de la herramienta vuelve al diálogo como un mensaje con role: tool. Luego el modelo decide qué hacer con él: cómo dar formato a la respuesta, qué follow‑up preguntar, si abrir un widget, etc. Por eso el diseño del esquema de salida es tan importante como el de entrada.

Hay dos enfoques.

La variante de «datos en bruto» se ve así:

{
  "items": [
    { "id": "GIFT_1" },
    { "id": "GIFT_2" }
  ]
}

El modelo ve solo una lista de id, sin entender por qué están ahí, cuántos candidatos había o cuáles son los mejores. Puede inventar algo, pero la probabilidad de rarezas aumenta.

Variante semánticamente rica:

{
  "items": [
    {
      "id": "GIFT_1",
      "score": 0.92,
      "reason": "Coincide fuertemente con el segmento 'football_fan' y entra en el presupuesto."
    },
    {
      "id": "GIFT_2",
      "score": 0.81,
      "reason": "Adecuado para un aficionado a los juegos de mesa, algo cerca del límite superior del presupuesto."
    }
  ],
  "meta": {
    "totalCandidates": 27,
    "returned": 5,
    "segmentsUsed": ["football_fan", "board_games"],
    "budget": { "min": 20, "max": 50, "currency": "USD" },
    "advice": "Mejor empezar por las opciones con mayor score y una explicación clara."
  }
}

Ahora el modelo puede explicar honestamente por qué esos regalos, y construir follow‑ups: «He encontrado 27 opciones, muestro las 5 mejores y por esto».

Ejemplo: describir el Output Schema para recommend_gifts

Añadimos al descriptor de la herramienta el esquema del resultado (aunque técnicamente se pueda omitir, es mejor incluirlo: forma parte del contrato con el modelo):

const recommendGiftsOutputSchema = {
  type: "object",
  properties: {
    items: {
      type: "array",
      items: {
        type: "object",
        properties: {
          id: { type: "string", description: "ID del regalo en el catálogo." },
          score: {
            type: "number",
            description: "Puntuación de adecuación al perfil (0..1)."
          },
          reason: {
            type: "string",
            description:
              "Breve explicación de por qué el regalo encaja (puede generarse en el backend)."
          }
        },
        required: ["id", "score"]
      },
      description: "Lista de regalos recomendados con puntuaciones de relevancia."
    },
    meta: {
      type: "object",
      properties: {
        totalCandidates: {
          type: "integer",
          description: "Cuántos candidatos se han encontrado en el catálogo."
        },
        returned: {
          type: "integer",
          description: "Cuántos regalos devuelve esta llamada."
        },
        advice: {
          type: "string",
          description:
            "Recomendación general: por ejemplo, con qué tipo de regalos conviene empezar."
        }
      }
    }
  },
  required: ["items"]
};

Y usamos este esquema dentro de la implementación:

server.registerTool(
  "recommend_gifts",
  {
    title: "Recomendaciones de regalos",
    description:
      "Úsalo cuando necesites seleccionar 3–7 regalos por segmentos y presupuesto. Devuelve id de regalos y sus puntuaciones; obtén fichas detalladas con get_gift.",
    inputSchema: /* como arriba */,
    // No siempre se especifica formalmente outputSchema, pero es útil para documentación:
    // outputSchema: recommendGiftsOutputSchema
  },
  async ({ input }) => {
    const recommendations = await recommendFromCatalog(input); // nuestra lógica de negocio

    return {
      content: [
        {
          type: "text",
          text: `He encontrado ${recommendations.items.length} ideas adecuadas. Ahora mostraré las mejores.`
        }
      ],
      structuredContent: {
        items: recommendations.items,
        meta: {
          totalCandidates: recommendations.meta.totalCandidates,
          returned: recommendations.items.length,
          advice: recommendations.meta.advice
        }
      }
    };
  }
);

Hacemos dos cosas: damos al modelo un texto mínimo para el usuario y a la vez le aportamos un JSON semántico con el que puede seguir el diálogo y los follow‑ups.

Mientras, get_gift ya traerá por id las fichas completas (nombre, medios, SKU, etc.), y el widget de GiftGenius las renderizará como tarjetas de regalos.

5. Naming y descripciones de herramientas como base del descubrimiento

Ahora lo interesante: cómo los nombres y descripciones de los tools influyen en que el modelo los ejecute o no.

La documentación y las buenas prácticas sobre metadatos aconsejan:

  • usar nombres orientados a la acción: profile_to_segments, recommend_gifts, get_gift, similar_gifts, y no tool1, search, do_stuff;
  • empezar la descripción con «Use this when… / Usa esta herramienta cuando…», describiendo escenarios disparadores y limitaciones («no la uses para…»).

Esto se relaciona directamente con tu golden prompt set. Las formulaciones de la descripción deben cruzarse con las solicitudes reales de los usuarios. Si pones «Úsalo cuando el usuario pida seleccionar un regalo por presupuesto e intereses del destinatario», y en tu golden prompt tienes «elige un regalo para un amigo gamer hasta 50 $», al modelo le es mucho más fácil asociar la solicitud con el tool.

Ejemplo de buena descripción de herramienta

Consideremos una herramienta adicional de GiftGenius — similar_gifts, que ayuda a ampliar la selección con ideas similares basadas en un regalo concreto:

server.registerTool(
  "similar_gifts",
  {
    title: "Regalos similares",
    description:
      "Usa esta herramienta cuando el usuario haya elegido un regalo concreto y quiera ver varias alternativas similares. No la uses para la primera selección desde cero — para eso está recommend_gifts.",
    inputSchema: {
      type: "object",
      properties: {
        giftId: {
          type: "string",
          description:
            "Identificador del regalo de la selección anterior para el que hay que encontrar opciones similares."
        },
        limit: {
          type: "integer",
          description:
            "Cuántos regalos similares devolver (por defecto 3–5).",
          minimum: 1,
          default: 5
        }
      },
      required: ["giftId"]
    }
  },
  async () => {
    /* ... */
  }
);

Puntos importantes:

  • Decimos explícitamente cuándo usar la herramienta y cuándo no.
  • En la descripción aparecen palabras como «alternativas similares», «eligió un regalo concreto» — justo las que suelen figurar en solicitudes reales de usuarios.
  • Evitamos solaparnos con el ámbito de recommend_gifts — reduce la competencia entre herramientas al elegir.

Ejemplo de mala descripción

description: "Trabajo con regalos."

Con esto el modelo entiende muy poco. Puede funcionar solo si GPT ya está intentando «tirar de algo» al azar.

6. Anotaciones y hints: cómo indicar al modelo la seriedad de la acción

Un tool no es solo nombre y esquema, sino también anotaciones que indican a ChatGPT cuán peligrosa/importante es la acción y si hay que pedir confirmación al usuario. En la especificación de Apps SDK hay distintos hints, como readOnlyHint, destructiveHint, openWorldHint y otros.

  • readOnlyHint: true indica que la herramienta solo lee datos y no cambia el estado. El asistente puede omitir confirmaciones extra y llamarla con más libertad.
  • destructiveHint: true señala que la herramienta puede borrar algo o cambiarlo de forma irreversible, por lo que hay que mostrar al usuario un «¿Está seguro?» claro.
  • openWorldHint: true indica que la acción afecta al mundo exterior (publicar en redes, crear un registro fuera de la cuenta, etc.), y también conviene avisar.

Nivel mínimo — sin confirmaciones

Si tienes public readonly tools, conviene marcarlos como readOnlyHint: true. Ejemplo:

"annotations": {
  "readOnlyHint": true,
  "destructiveHint": false,
  "openWorldHint": false
}

Estas herramientas se pueden invocar sin confirmaciones adicionales por parte de GPT.

Una confirmación

Si tienes tools que cambian algo en el servidor, es lógico marcarlos como readOnlyHint: false:

"annotations": {
  "readOnlyHint": false,
  "destructiveHint": false,
  "openWorldHint": false
}

El modelo, al ver una herramienta así, probablemente pedirá una confirmación al usuario una vez (normalmente es una ventana de diálogo modal en la UI de ChatGPT).

Acción peligrosa

Si tienes un tool que elimina algo en el servidor, márcalo como destructiveHint: true:

"annotations": {
  "readOnlyHint": false,
  "destructiveHint": true,
  "openWorldHint": false
}

El modelo llamará a esta herramienta con mucha cautela y confirmará dos veces:

  • primero pedirá confirmación al usuario en el texto,
  • después la plataforma mostrará una ventana de diálogo estándar.

Para nuestro GiftGenius, dentro de este módulo aún no escribimos herramientas de comercio, pero podemos perfilar cómo sería el futuro create_gift_order:

server.registerTool(
  "create_gift_order",
  {
    title: "Creación de pedido de regalo",
    description:
      "Úsalo solo tras el consentimiento explícito del usuario para comprar el regalo elegido. Crea un pedido en el sistema y devuelve el estado.",
    inputSchema: {
      type: "object",
      properties: {
        giftId: {
          type: "string",
          description: "ID del regalo que el usuario ha elegido."
        },
        deliveryEmail: {
          type: "string",
          description: "Email al que enviar el regalo digital."
        }
      },
      required: ["giftId", "deliveryEmail"]
    },
    annotations: {
      destructiveHint: true,
      openWorldHint: true
    }
  },
  async () => {
    /* ... */
  }
);

Las anotaciones no sustituyen tus comprobaciones de permisos en el servidor, solo ayudan a ChatGPT a construir el UX: pedir confirmación, mostrar advertencias y no ejecutar estas herramientas «a escondidas».

7. Metadatos de la App y dos niveles de descubrimiento

Las herramientas son la mitad de la historia. La otra mitad — cómo el usuario encuentra y lanza tu App.

En el ecosistema de ChatGPT hay dos niveles clave de descubrimiento.

Primero — in‑conversation discovery. Cuando el usuario escribe algo en el chat (incluso sin mencionar explícitamente la App), el modelo mira:

  • el texto del mensaje y el historial del diálogo;
  • las descripciones de las aplicaciones disponibles y sus herramientas;
  • las menciones de marca, temática y frases clave.

Con esto decide si conviene sugerir alguna App, y si sí — cuál y con qué escenario. Aquí son especialmente importantes las descripciones de las herramientas y de la App. Si incluyen «disparadores» como «selección de regalos», «idea de regalo», «presupuesto de regalo», la probabilidad de que el modelo elija tu App aumenta mucho.

Segundo nivel — descubrimiento global: catálogo y launcher. Ahí decide la persona: elige la App por nombre, icono, descripción corta y tags. Es importante explicar de forma honesta y clara qué hace tu aplicación, para quién es y cuál es su propuesta de valor principal.

Podemos resumirlo en una pequeña tabla:

Capa Qué ve el modelo/usuario Qué importa en los metadatos
In‑conversation Texto del diálogo, descripciones de tools y de la App Formulaciones disparadoras, nombres orientados a la acción, limitaciones
Catálogo/launcher Nombre, icono, short/long description, tags Posicionamiento claro, propuesta de valor comprensible

Para GiftGenius podemos, por ejemplo, formular:

  • Nombre: GiftGenius — selección de regalos en 60 segundos.
  • Descripción corta: Recopila el perfil del destinatario y propone 5–7 ideas de regalos con opción de compra instantánea dentro de ChatGPT.
  • Descripción para in‑conversation: Usa esta aplicación cuando el usuario pida ayuda para elegir un regalo, no sepa qué regalar, mencione presupuesto, intereses del destinatario u ocasión.

Estas formulaciones conviene sincronizarlas con lo que ya escribiste en el system‑prompt y en la descripción de la herramienta recommend_gifts. Así el modelo ve un conjunto coherente y no textos contradictorios.

8. Cómo funciona el enrutamiento «en la cabeza» de ChatGPT

Juntamos todo y miramos un recorrido típico de una solicitud — sin entrar en el protocolo MCP, eso será en los siguientes módulos.

Supongamos que el usuario escribe:

«Ayúdame a idear un regalo para mi hermano; le encantan el fútbol y los juegos de mesa, presupuesto hasta 50 dólares.»

Algoritmo muy simplificado:

  1. El modelo analiza el mensaje y el historial. Ve palabras como «regalo», «hermano», «fútbol», «juegos de mesa», «presupuesto 50».
  2. Lo compara con las descripciones de las Apps disponibles y sus herramientas. Para GiftGenius, las descripciones incluyen explícitamente «selección de regalos por intereses y presupuesto», así que la probabilidad de que la App sea relevante es alta.
  3. Si la App aún no está activa en esta sesión, el modelo forma una réplica‑anuncio: «Puedo abrir la aplicación GiftGenius, que te ayudará a seleccionar un regalo según tus parámetros. ¿Abrir?» — esto lo prescribimos en las instrucciones de UX.
  4. Tras el consentimiento del usuario, el modelo elige dentro de la App la herramienta recommend_gifts, porque su descripción es la que mejor se ajusta a la intención actual. Aquí el nombre, el description y la estructura del inputSchema actúan como señales de entrada.
  5. El modelo rellena los argumentos de la herramienta a partir de la solicitud: primero (si es necesario) llama a profile_to_segments para obtener de «hermano, le gusta el fútbol y los juegos de mesa» los segmentos ["football_fan", "board_games"], luego llama a recommend_gifts con segments, budget: {min: 0, max: 50, currency: "USD"}, locale, occasion: "birthday".
  6. El servidor MCP ejecuta la herramienta, forma la salida estructurada con items y meta y la devuelve.
  7. El modelo lee el JSON que describiste en el outputSchema y compone la respuesta: explica qué encontró, por qué esos regalos, y propone follow‑ups («¿Quieres acotar por categoría?», «¿Mostrar similares a este regalo?» o «¿tramitar la compra de este regalo?»).

He aquí un diagrama de flujo simple del proceso:

flowchart TD
  A[Usuario: solicitud sobre un regalo] --> B[ChatGPT analiza el contexto]
  B --> C[Comparación con los metadatos del App y sus tools]
  C -->|relevante| D[Anuncio de GiftGenius]
  D -->|el usuario acepta| E["Llamada a recommend_gifts (+ profile_to_segments)"]
  E --> F[Servidor MCP de GiftGenius]
  F --> G[Resultado JSON con items/meta]
  G --> H[El modelo compone la respuesta y los follow‑up]

Cuanto mejor hayas descrito los tools y los use‑cases, menos azar habrá aquí y más estable será el enrutamiento.

Insight: Tool Call SEO

En el ecosistema de Apps pronto tendrás no solo competencia por la atención de las personas en el catálogo, sino también competencia por la atención del propio modelo. Para una misma solicitud, ChatGPT puede llamar a una decena de aplicaciones, y la elección no se hará por quién tiene mejor diseño de presentación, sino en la «página de resultados de búsqueda» dentro de la cabeza del modelo. Esta capa invisible cada vez se parece más al SEO, solo que en vez de páginas tienes tools y servidores MCP.

El modelo en esencia clasifica candidatos: primero a nivel de App, luego a nivel de herramientas. Mira el nombre, descriptions, esquemas, anotaciones y los compara con la formulación de la solicitud. Si en la descripción de recommend_gifts aparece «selección de regalos por presupuesto e intereses del destinatario», y en la solicitud suena «elige un regalo para un amigo gamer por 50 $», esa herramienta tiene más probabilidades de «entrar en el top» que un search abstracto con descripción «trabajo con regalos».

De ahí surge la idea práctica del Tool Call SEO: trata nombres, descriptions, valores enum y metadatos como palabras clave y snippets. No solo describes un contrato para desarrolladores — lo optimizas para el tráfico real de solicitudes de tu golden prompt set. Formulaciones demasiado generales, ámbitos solapados de varios tools, herramientas God sin nicho claro — todo esto reduce el «CTR» de tu App en la cabeza del modelo.

9. Un pequeño ejercicio práctico

Prueba mentalmente (o en tu repositorio) lo siguiente.

Primero elige uno de los escenarios clave de GiftGenius — por ejemplo, «Seleccionar un regalo para un compañero de trabajo con presupuesto limitado».

Formula para él:

  1. Qué herramienta independiente se necesita para este escenario: ¿es recommend_gifts «puro», o necesitas otra herramienta especializada para el caso B2B, o, por ejemplo, basta con usar similar_gifts tras recommend_gifts para variaciones?
  2. Qué campos son realmente necesarios en el esquema de entrada de recommend_gifts. Qué campos se pueden preguntar aparte al usuario (vía follow‑up) en lugar de obligar al modelo a adivinar.
  3. Cómo debería ser el outputSchema para que el modelo pueda explicar la elección y proponer los siguientes pasos (por ejemplo, cambiar a modo B2B, mostrar solo regalos digitales, acotar por rango de precios).

Luego revisa tu golden prompt set de la lección anterior y comprueba:

  • si para cada solicitud de referencia hay un tool obvio (recommend_gifts, get_gift, similar_gifts, etc.);
  • si no ha ocurrido que dos herramientas «encajan» igual en la misma solicitud (overlapping tools);
  • si necesitas reforzar descripciones o renombrar algún tool para que el modelo se confunda menos.

Este es exactamente el proceso que repetirás antes de cada cambio serio de prompt, esquemas o lógica — en esencia, un mini‑eval de la calidad del descubrimiento.

Si resumimos todo lo anterior en un checklist, en esta etapa necesitas:

  • cortar honestamente los escenarios en 2–4 herramientas con sentido;
  • describir con cuidado inputSchema/outputSchema con ejemplos y enum;
  • poner en orden los nombres, descriptions y anotaciones;
  • sincronizarlo con el system‑prompt y los metadatos de la App.

En los siguientes módulos veremos cómo funciona todo esto a través de MCP y cómo diagnosticar comportamientos extraños de descubrimiento/enrutamiento.

10. Errores típicos al diseñar tools y metadatos

Error n.º 1: «Lo hemos descrito todo en el system‑prompt, las herramientas ya se apañarán».
Si has descrito a la perfección el rol de la App, los límites de responsabilidad y el comportamiento de UX, pero dejas herramientas con nombres como tool1, search, do_stuff y esquemas sin descripciones, el modelo no podrá conectar tu bonito texto con llamadas reales. Para ChatGPT los tools son la interfaz principal; sin buenos metadatos ningún system‑prompt te salvará.

Error n.º 2: God Tool que hace de todo.
La tentación de «optimizar» y hacer una única función con el parámetro mode se entiende, pero conduce a JSON‑schemas monstruosos, confusión en descripciones y peor enrutamiento. El modelo empieza a adivinar qué modo usar y tú acabas manteniendo un enorme switch en el servidor. Mejor varias herramientas claras para pasos concretos que un «hazlo todo».

Error n.º 3: Esquema de entrada sobrecargado con campos «por si acaso».
A menudo los desarrolladores intentan pasar por el inputSchema todos los parámetros que podrían hacer falta alguna vez, más un par de campos internos. Al final el modelo intenta adivinar lo que no puede saber (por ejemplo, tenantId) y luego os sorprenden valores extraños. El Input Schema debe contener solo lo que el modelo puede inferir del diálogo o aclarar con una pregunta. Los detalles internos añádelos en el servidor.

Error n.º 4: Datos de salida «mudos» sin metainformación.
Devolver simplemente un array de objetos es tentador. Pero así privas al modelo de entender por qué aparecieron esos resultados. Sin campos como score, reason, searchCriteria, totalCandidates le cuesta más construir explicaciones honestas y follow‑ups. Añadir un pequeño envoltorio meta con criterios de búsqueda y consejos a menudo mejora radicalmente la calidad de la respuesta.

Error n.º 5: Tablas rasas en las descripciones: «Trabajo con regalos», «Búsqueda de cursos», «Procesamiento de datos».
Estas descripciones son malas porque no dan al modelo ni disparadores ni limitaciones. No sabe cuándo llamar a la herramienta ni su ámbito. Una buena descripción empieza con «Usa esta herramienta cuando…» e incluye escenarios concretos y prohibiciones tipo «No la uses para…». Idealmente, estas formulaciones se cruzan con las solicitudes de tu golden prompt set.

Error n.º 6: Ignorar anotaciones y mezclar acciones de solo lectura y de modificación.
Si no marcas las herramientas que solo leen datos (readOnlyHint) y las que realizan acciones (destructiveHint, openWorldHint), el modelo no puede construir un UX correcto de confirmaciones. Resultado: o «¿Estás seguro?» de más en cada paso, o compras y cambios silenciosos sin el consentimiento del usuario. Las anotaciones son una forma barata y efectiva de indicar la importancia de la operación.

Error n.º 7: Los metadatos para el catálogo y los metadatos para in‑conversation viven en universos distintos.
A veces la descripción corta del catálogo la escribe marketing («Un asistente de IA revolucionario que cambia tu vida»), y las descriptions de tools y el system‑prompt las escribe un desarrollador («selección de regalos por presupuesto»). Resultado: en el catálogo no se entiende de qué va la App, y el modelo en el chat no puede asociar solicitudes tipo «¿de qué va este servicio?» con las capacidades reales de la App. Escribe los metadatos como una especificación unificada, no como dos textos de marketing independientes.

1
Cuestionario/control
Comportamiento de ChatGPT App, nivel 5, lección 4
No disponible
Comportamiento de ChatGPT App
Instrucciones para el modelo y comportamiento de ChatGPT App
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION