Tecnología0 阅读

De función a Tool: Abriendo la puerta a la invocación de herramientas con Vercel AI SDK

Si ya estás acostumbrado a escribir API Routes en Next.js y a llamar a interfaces de terceros, ahora estás a solo medio paso de «crear un asistente de modelos grandes que pueda llamar a sus propias interfaces»: envolver estas funciones como Tool, y dejar que el modelo decida cuándo usarlas.

Este artículo no hablará de esos «grandes términos» como MCP o marcos de Agent, solo haremos una cosa:

Ayudarte a pasar de «escribir una función normal» a «escribir un Tool que pueda ser invocado por un modelo grande», y de paso aclarar el modelo mental detrás de ello.

Después de leerlo, deberías poder:

1. ¿Por qué necesitamos la capa de «herramienta»?

Imaginemos primero una necesidad simple: quieres hacer un «chatbot que consulta el clima».

El enfoque más ingenuo sería:

  1. El usuario escribe «Consulta el clima de hoy en Pekín».

  2. En el servidor recibes esa frase en lenguaje natural.

  3. Escribes un if/else o una expresión regular para extraer el nombre de la ciudad.

  4. Llamas a la API del clima y obtienes el resultado.

  5. Insertas el resultado de vuelta en el prompt, dejas que el modelo lo organice en un párrafo y se lo envías al usuario.

Este esquema funciona, pero tiene problemas evidentes:

La capa de Tool consiste en elevar «ese if/else + llamada a interfaz» a una capacidad visible para el modelo.

Dicho de otro modo:

Esta abstracción es precisamente lo que el SDK de Vercel AI hace por ti con los Tools.

2. ¿Qué es un Tool en el SDK de Vercel AI?

Puedes entender un Tool como:

Una «función con manual de instrucciones»; el manual es para que lo lea el modelo, y el cuerpo de la función es para tu propio código.

En el SDK de Vercel AI, un Tool generalmente contiene tres partes de información:

  1. description: una frase que explica para qué sirve esta herramienta.

  2. parameters: describe los parámetros de entrada usando JSON Schema (o Zod).

  3. execute: la función que realmente se ejecuta, por ejemplo, llamar a una API HTTP o consultar una base de datos.

Su aspecto general es algo así (pseudocódigo, para que te hagas una idea):

ts
import { tool } from 'ai';

const getWeather = tool({
  description: 'Consulta el clima en tiempo real de una ciudad específica',
  parameters: {
    type: 'object',
    properties: {
      city: { type: 'string', description: 'Nombre de la ciudad, por ejemplo Beijing' },
    },
    required: ['city'],
  },
  execute: async ({ city }) => {
    // Aquí va el código de negocio que normalmente escribirías
    const res = await fetch(`https://api.example.com/weather?city=${city}`);
    return await res.json();
  },
});

Después, al invocar el modelo, le pasas ese getWeather al SDK de AI:

Ya no tienes que escribir tú mismo la lógica de «extraer el nombre de la ciudad» o «decidir cuándo llamar a la interfaz»; le entregas la «iniciativa» al modelo.

3. Un ejemplo mínimo funcional de Tool

Escribamos un ejemplo mínimo que realmente se pueda ejecutar: consultar la hora actual.

3.1 Define un Tool simple

Supón que ya tienes instalado el paquete ai (SDK de Vercel AI) en tu proyecto de Next.js. En el lado del servidor creamos un Tool simple:

ts
// app/api/chat/tools.ts
import { tool } from 'ai';

export const getCurrentTime = tool({
  description: 'Obtiene la hora actual del servidor (cadena ISO)',
  parameters: {
    type: 'object',
    properties: {},
  },
  async execute() {
    return {
      now: new Date().toISOString(),
    };
  },
});

Aquí hay algunos puntos a destacar:

3.2 Usar el Tool en una API Route

A continuación, escribimos la API de chat más simple que permita al modelo invocar este Tool durante la conversación. Los detalles de invocación pueden variar ligeramente según la versión; aquí solo destacamos la «estructura» y la «idea», el pseudocódigo se vería así:

ts
// app/api/chat/route.ts
import { NextRequest } from 'next/server';
import { streamText } from 'ai'; // Suponiendo que se usa algún método de invocación del SDK de AI
import { getCurrentTime } from './tools';
import { openai } from '@ai-sdk/openai';

export async function POST(req: NextRequest) {
  const { messages } = await req.json();

  const response = await streamText({
    model: openai('gpt-4o'), // El modelo que elijas
    messages,
    tools: {
      getCurrentTime,
    },
  });

  return response.toAIStreamResponse();
}

Aquí hay algunos puntos clave:

3.3 Una interfaz de chat simple en el frontend

En el frontend puedes usar hooks como useChat para crear una UI de chat mínima; esta parte no es el foco de este artículo, así que no la desarrollaremos. Lo importante es que, desde la perspectiva del frontend, no hay diferencia con una API de chat normal; la única diferencia es que el modelo ahora «puede consultar la hora por sí mismo».

4. La diferencia esencial entre Tool y una función normal

Llegado a este punto, podrías preguntarte: ¿acaso no puedo simplemente escribir new Date().toISOString() directamente en la ruta para consultar la hora? ¿Por qué darle la vuelta con un Tool?

La diferencia clave radica en quién se encarga de la «decisión»:

Esto trae varios beneficios prácticos:

  1. Menos if/else

    • No necesitas analizar lenguaje natural, emparejar palabras clave ni elegir ramas.

    • El modelo decide según el contexto si debe usar un Tool determinado.

  2. Soporte para orquestación automática de múltiples Tools

    • Defines varias herramientas (consultar hora, clima, agenda) y el modelo puede invocarlas según sea necesario dentro de una misma conversación.

    • A medida que aumentan las herramientas, no necesitas mantener un montón de «tablas de enrutamiento de negocio»; el modelo «se las arregla» solo.

  3. Uniformidad entre modelos

    • Las interfaces de Tool / Function Calling de diferentes proveedores de modelos varían, y el SDK de AI unifica esos detalles por ti.

    • Solo necesitas mantener un conjunto de definiciones de Tool y puedes cambiar entre diferentes modelos.

Puedes ver los Tools como:

Una capa de «función con metadatos estructurados» añadida entre «el modelo ↔ tu código», haciendo que esta cadena sea tanto inteligente como controlable.

5. Diseñar un Tool útil: parámetros y valores de retorno

Escribir un Tool no es solo «que funcione»; si diseñas bien los parámetros y los valores de retorno, el modelo podrá usarlo de manera más estable y controlada.

5.1 Parámetros: ayuda al modelo a expresarse claramente

Para la definición de parámetros, se recomiendan algunos principios pequeños:

Ejemplo:

ts
const getWeather = tool({
  description: 'Consulta el clima de una ciudad en una fecha específica',
  parameters: {
    type: 'object',
    properties: {
      city: {
        type: 'string',
        description: 'Nombre de la ciudad, por ejemplo Beijing, Shanghai',
      },
      date: {
        type: 'string',
        description: 'Fecha en formato YYYY-MM-DD, por ejemplo 2025-05-17',
      },
      unit: {
        type: 'string',
        enum: ['celsius', 'fahrenheit'],
        description: 'Unidad de temperatura, por defecto celsius',
      },
    },
    required: ['city', 'date'],
  },
  async execute({ city, date, unit = 'celsius' }) {
    // ...
  },
});

5.2 Valor de retorno: procura que sea estructurado, no un montón de texto

Aunque puedes devolver directamente en execute una frase como «Hoy en Pekín hace 25 grados y está soleado», esto perdería mucha flexibilidad:

Se recomienda devolver un objeto claro:

ts
async execute({ city, date, unit = 'celsius' }) {
  const data = await fetchWeather(city, date, unit);
  return {
    city,
    date,
    unit,
    temperature: data.temp,
    condition: data.condition, // sunny, cloudy, etc.
  };
}

De esta forma, el modelo puede tanto organizar el lenguaje para responder al usuario como seguir usando estos campos en pasos posteriores (por ejemplo, invocar otro Tool).

6. Conectar múltiples Tools a la vez: que el modelo elija

Antes solo usábamos un getCurrentTime, ahora podemos añadir un getWeather y pasarle ambos al modelo.

ts
// app/api/chat/tools.ts
export const tools = {
  getCurrentTime,
  getWeather,
};

Al invocar el modelo:

ts
const response = await streamText({
  model: openai('gpt-4o'),
  messages,
  tools,
});

En ese momento, si el usuario dice:

«Mira el clima de mañana en Shanghái; si es soleado, de paso recuérdame la hora actual.»

El modelo tiene la oportunidad de hacer algo así (a nivel lógico):

  1. Primero invocar getWeather para determinar «si es soleado».

  2. Luego invocar getCurrentTime para obtener la hora actual.

  3. Generar una respuesta final que combine los resultados de ambas invocaciones.

No necesitas escribir ningún «diagrama de flujo de negocio» para esta secuencia; solo:

Ese es el verdadero poder de las «invocaciones a herramientas»: pasas de «escribir flujos» a «definir capacidades».

7. Cierre de este artículo: primero domina los Tools, luego piensa en la capa de protocolo

En este artículo hicimos solo tres cosas:

  1. Desglosamos el concepto de Tool: es una «función con manual de instrucciones»; el manual es para que lo lea el modelo.

  2. Escribimos un ejemplo mínimo de Tool y mostramos cómo usarlo en una API Route de Next.js.

  3. Explicamos cómo diseñar parámetros y valores de retorno para que el modelo use mejor tu herramienta.

Solo con los Tools del SDK de Vercel AI ya puedes crear:

Yen esta fase, puedes ignorar por completo cosas como la capa de protocolo MCP— estas principalmente resuelven el problema de «reutilizar herramientas entre diferentes anfitriones y proyectos», y es más adecuado introducirlas gradualmente cuando la cantidad de herramientas y el entorno de invocación se vuelvan más complejos.

En el próximo artículo, sobre la base de «solo usar Tools», hablaremos específicamente sobre: a medida que aumentan las herramientas y el entorno de invocación se vuelve más complejo, qué límites y puntos débiles se encuentran al depender solo de Tools, y por qué surgen protocolos como MCP.

Compartir

Compartir

Comparte este artículo.