En la era de la IA generativa, ya no basta con construir chatbots que solo hablan. El mercado actual demanda agentes de IA: sistemas capaces de razonar, utilizar herramientas externas y seguir reglas de negocio.
En este taller práctico, vamos a construir un Smart Retail. Utilizaremos Genkit, el framework de Google diseñado para llevar a la IA a entornos de producción con la seguridad y escalabilidad que caracteriza al ecosistema de Firebase.
A lo largo de este codelab, aprenderás a dominar a utilizar diferentes LLMs para que actuen como un asistente de compras expertos y confiable.
Un asistente inteligente que:
Primero, preparemos el terreno.
Crear carpeta:
mkdir workshop-genkit-agents-101 && cd workshop-genkit-agents-101
Inicializar el proyecto de Node.js, instalar TypeScript y crear la estructura base:
# Initialize a new Node.js project
npm init -y
npm pkg set type=module
# Install and configure TypeScript
npm install -D typescript tsx
npx tsc --init
# Set up your source directory
mkdir src
touch src/index.ts
Primero, instala la CLI de Genkit globalmente. Esto te dará acceso a las herramientas de desarrollo locales, incluida la interfaz de usuario para desarrolladores:
npm install -g genkit-cli
A continuación, añade los siguientes paquetes a tu proyecto:
npm install genkit @genkit-ai/google-genai
genkit — Proporciona las funcionalidades principales de Genkit.@genkit-ai/google-genai — Proporciona acceso a los modelos Gemini de Google AI.Genkit puede trabajar con varios proveedores de modelos. Este taller utiliza la API de Gemini, que ofrece un generoso plan gratuito y no requiere tarjeta de crédito para empezar.
Para usarla, necesitarás una clave API de Google AI Studio:
Una vez que tengas tu clave, configura la variable de entorno GOOGLE_GENAI_API_KEY:
export GOOGLE_GENAI_API_KEY=<your API key>
Un flujo es una función especial de Genkit con observabilidad integrada, seguridad de tipos e integración de herramientas.
Actualiza src/index.ts con lo siguiente:
import { googleAI } from '@genkit-ai/google-genai';
import { genkit, z } from 'genkit';
const ai = genkit({
plugins: [googleAI()],
model: googleAI.model('gemini-2.5-flash'),
});
export const basicScoutFlow = ai.defineFlow(
{
name: 'basicScoutFlow',
},
async (productType) => {
const { text } = await ai.generate(
`Eres un experto en retail. Dame los detalles de este producto: ${productType}`
);
return text;
}
);
Este ejemplo de código:
gemini-2.5-flash.La interfaz de usuario para desarrolladores es una herramienta local para probar e inspeccionar componentes de Genkit, como flujos, mediante una interfaz visual.
Iniciar la interfaz de usuario para desarrolladores
Se requiere la CLI de Genkit para ejecutar la interfaz de usuario para desarrolladores. Si seguiste los pasos de instalación anteriores, ya la tienes instalada.
Ejecuta el siguiente comando desde la raíz de tu proyecto:
genkit start -- npx tsx --watch src/index.ts
Abre http://localhost:4000 en tu navegador.
En la barra lateral, haz clic en Flows y selecciona basicScoutFlow.
Escribe un producto (ej. "Iphone 15") y presiona Run.
Añade este nuevo flujo a tu archivo src/index.ts:
const ProductDetailsSchema = z.object({
name: z.string(),
brand: z.string(),
features: z.array(z.string()),
recommendation_text: z.string()
});
export const basicScoutFlow = ai.defineFlow(
{
name: 'basicScoutFlow',
inputSchema: z.string(),
outputSchema: ProductDetailsSchema,
},
async (productName) => {
const { output } = await ai.generate({
prompt: `Eres un experto en retail. Dame los detalles de este producto: ${productName}`,
output: { schema: ProductDetailsSchema },
});
if (!output) throw new Error("La IA no pudo generar el formato correcto.");
return output;
}
);
output.brand con autocompletado)."recommendation_text" te sugiere si el producto te conviene o no.Vuelve a la Developer UI (localhost:4000). Verás que ahora aparece structuredScoutFlow. Al ejecutarlo, notarás que la respuesta ya no es un párrafo, sino un objeto JSON limpio y listo para ser usado en una aplicación de producción.
Los modelos de lenguaje (LLMs) tienen un límite: su conocimiento llega hasta su fecha de entrenamiento. No saben qué hay en tu almacén hoy ni qué precio tiene un producto en este segundo.
Tool Calling permite que la IA use funciones de TypeScript para interactuar con APIs externas. La IA no solo "habla", ahora "actúa".
Vamos a crear una herramienta que realice una búsqueda real en el catálogo de DummyJSON. Genkit utiliza la descripción que escribes para que la IA entienda cuándo debe usar esta función.
Añade este código a src/index.ts:
export const searchProductTool = ai.defineTool(
{
name: 'searchProduct',
description: 'Busca productos en el catálogo oficial de la tienda GenkitStore para obtener precios y stock en tiempo real.',
inputSchema: z.object({ query: z.string() }),
outputSchema: z.any(),
},
async (input) => {
const response = await fetch(`https://dummyjson.com/products/search?q=${input.query}`);
const data = await response.json();
return data.products;
}
);
Una vez definida la herramienta, puedes abrirla y probarla directamente en la Developer UI de Genkit (localhost:4000), donde ya aparece listada junto con tus flujos.
La magia de Genkit es que tú no llamas a la función manualmente. Se la entregas al modelo y él, basándose en la pregunta del usuario, decide si necesita usarla.
Primero, actualiza el esquema ProductDetailsSchema que definiste anteriormente para que acepte una lista de productos:
const ProductDetailsSchema = z.array(z.object({
name: z.string(),
brand: z.string(),
features: z.array(z.string()),
recommendation_text: z.string()
}));
Añade este nuevo flujo a src/index.ts:
export const agentFlow = ai.defineFlow(
{
name: 'agentFlow',
inputSchema: z.string(),
outputSchema: ProductDetailsSchema,
},
async (userInput) => {
const { output } = await ai.generate({
prompt: userInput,
tools: [searchProductTool],
output: { schema: ProductDetailsSchema },
});
if (!output) throw new Error("La IA no pudo generar el formato correcto.");
return output;
}
);
Una regla de negocio es una restricción impuesta por el desarrollador que la IA no puede ignorar. En este paso, aprenderás a interceptar los datos de la API y aplicar lógica de negocio para que el asistente sea responsable y confiable.
Primero, actualiza ProductDetailsSchema para incluir los nuevos campos de precio, rating, advertencia y disponibilidad:
const ProductDetailsSchema = z.array(z.object({
name: z.string(),
brand: z.string(),
price: z.number(),
rating: z.number(),
features: z.array(z.string()),
recommendation_text: z.string(),
warning: z.string().optional(),
availability: z.enum(['En Stock', 'Pocas Unidades', 'Agotado']).optional()
}));
Vamos a modificar nuestro flujo para que analice el campo rating. Si el rating es menor a 4.0, obligaremos a la IA a incluir un mensaje de advertencia.
Añade este flujo a src/index.ts:
export const guardedScoutFlow = ai.defineFlow(
{
name: 'guardedScoutFlow',
inputSchema: z.string(),
outputSchema: ProductDetailsSchema,
},
async (userInput) => {
const { output } = await ai.generate({
prompt: userInput,
tools: [searchProductTool],
output: { schema: ProductDetailsSchema },
system: `
Eres un asistente de compras honesto.
REGLA DE ORO: Si un producto tiene un rating menor a 3.0,
debes llenar el campo 'warning' indicando que la satisfacción
del cliente es baja.
`,
});
if (!output) throw new Error("Error al generar respuesta");
return output;
}
);
A veces, la regla no es solo un mensaje, sino filtrar la información antes de que la IA la vea. Si un producto supera el presupuesto del usuario, es mejor excluirlo para que la IA no lo recomiende.
Modifica el cuerpo de tu searchProductTool para añadir este filtro:
async (input) => {
const response = await fetch(`https://dummyjson.com/products/search?q=${input.query}`);
const data = await response.json();
// Regla de precios: Filtramos productos que superen el presupuesto máximo
const affordableProducts = data.products.filter((p: any) => p.price <= 1900);
return affordableProducts;
}
guardedScoutFlow preguntando por: ""Estoy buscando laptop""."recommendation_text te genera una recomendación del producto.system prompt para darle reglas éticas a la IA.¿Alguna vez te has preguntado qué pasa exactamente entre que el usuario hace una pregunta y la IA responde? En el desarrollo tradicional hacemos console.log o usamos el debugger. En Genkit, tenemos Tracing.
Es una vista detallada (como el "Network Tab" de Chrome) que registra cada paso de un Flow:
Para ver un Trace interesante, necesitamos un flujo que haga varias cosas. Asegúrate de tener corriendo tu Developer UI:
genkit start -- npx tsx --watch src/index.ts
guardedScoutFlow."Busco una laptop de menos de 3000 USD que tenga buenas reseñas".Una vez que el flujo termine:
Hasta ahora, hemos ejecutado nuestro agente en la Developer UI. En un entorno profesional, necesitamos que nuestro flujo sea accesible a través de una URL segura (HTTPS) para que pueda ser consumido por una app en Angular, React o Flutter.
Si aún no tienes un proyecto de Firebase con Cloud Functions en TypeScript, sigue estos pasos:
firebase login
firebase login --reauth # alternativa, si es necesario
firebase login --no-localhost # si ejecutas en un shell remoto
firebase init
El asistente de inicialización te hará una serie de preguntas. Estas son las respuestas recomendadas:
Pregunta | Respuesta |
Which Firebase features do you want to set up? | Functions: Configure a Cloud Functions directory and its files |
Please select an option | Use an existing project |
Select a default Firebase project | Selecciona tu proyecto (ej. |
What language would you like to use? | TypeScript |
Do you want to use ESLint? | No |
Do you want to install dependencies with npm now? | Yes |
Would you like to install agent skills for Firebase? | No |
Al finalizar, verás el mensaje Firebase initialization complete! y se habrá creado la carpeta functions/ con toda la estructura necesaria.
Actualiza el final de tu archivo functions/src/index.ts:
import { googleAI } from '@genkit-ai/google-genai';
import { genkit, z } from 'genkit';
import { defineSecret } from "firebase-functions/params";
import { onCallGenkit } from "firebase-functions/https";
// enableFirebaseTelemetry();
const googleAIapiKey = defineSecret("GOOGLE_GENAI_API_KEY");
const ai = genkit({
plugins: [googleAI()],
model: googleAI.model('gemini-2.5-flash'),
});
const ProductDetailsSchema = z.array(z.object({
name: z.string(),
brand: z.string(),
price: z.number(),
rating: z.number(),
features: z.array(z.string()),
recommendation_text: z.string(),
warning: z.string().optional(),
availability: z.enum(['En Stock', 'Pocas Unidades', 'Agotado']).optional()
}));
export const basicScoutFlow = ai.defineFlow(
{
name: 'basicScoutFlow',
inputSchema: z.string(),
outputSchema: ProductDetailsSchema,
},
async (productName) => {
const { output } = await ai.generate({
prompt: `Eres un experto en retail. Dame los detalles de este producto: ${productName}`,
output: { schema: ProductDetailsSchema },
});
if (!output) throw new Error("La IA no pudo generar el formato correcto.");
return output;
}
);
export const generateBasicScoutFlow = onCallGenkit(
{
cors: '*',
authPolicy: () => true,
secrets: [googleAIapiKey],
},
basicScoutFlow
);
En producción, nunca debemos dejar las API Keys en el código o en archivos .env locales. Usaremos el gestor de secretos de Firebase para que Gemini pueda autenticarse de forma segura.
Ejecuta este comando en tu terminal para subir tu clave de Google AI Studio:
firebase functions:secrets:set GOOGLE_GENAI_API_KEY
Pega tu clave cuando la terminal te lo solicite.
Edita src/index.ts y agrega esto luego de los imports.
import { defineSecret } from 'firebase-functions/params';
const googleAIapiKey = defineSecret('GOOGLE_GENAI_API_KEY');
Asegúrate de haber iniciado sesión con firebase login y de haber seleccionado tu proyecto. Luego ejecuta:
firebase deploy --only functions
Una vez que el despliegue termine, la terminal te entregará una URL similar a:
https://us-central1-tu-proyecto.cloudfunctions.net/generateBasicScoutFlow
Has pasado de tener un script local a una API de IA generativa con orquestación profesional, conexión real a base de datos (Tools), contratos de datos garantizados (Zod) y reglas de negocio activas.
Has construido un Agente de Retail Inteligente desde cero usando el ecosistema de Google Genkit.