Este es el episodio 4 de 6 del curso: conectamos Microsoft Agent Framework (MAF) con Google Gemini, gratis, y lo integramos con el VoiceService que construimos en el episodio anterior. Al final, el agente responde en consola y en voz, y recuerda lo que dijiste dos turnos atrás sin que hayamos escrito una sola línea para lograrlo.
La API key de Google, primero
Antes del código, la cuenta en Google AI Studio:
- Entras a Google AI Studio
- Clic en “Get API Key”
- Creas un proyecto nuevo o usas uno existente
- Generas la key y la copias
- La guardas en User Secrets, nunca en el código fuente
{ "Google": { "ApiKey": "tu-api-key" }}Mismo mecanismo que las claves de Azure y Telegram del episodio 2: vive en tu máquina, no en el repositorio.
De Gemini a IChatClient
El primer bloque de código convierte el cliente de Google en algo que Microsoft Agent Framework entiende:
IChatClient chatClient = new Client(apiKey: config["Google:ApiKey"]!) .AsIChatClient("gemini-2.5-flash");Client es la clase del SDK de Google para conectarse a Gemini. AsIChatClient es un método de extensión que convierte ese cliente en un IChatClient, la interfaz estándar de Microsoft.Extensions.AI. A partir de esta línea, MAF no sabe que está hablando con Google: solo ve un IChatClient. Si más adelante quieres cambiar a OpenAI o Azure OpenAI, esta es la única línea que cambia.
ChatClientAgent: tu primer agente
Con el chatClient listo, se construye el agente:
AIAgent agent = new ChatClientAgent( chatClient, instructions: "Eres un asistente de la Clínica Dental Sonrisa. " + "Respondes preguntas sobre servicios, precios y horarios. " + "Eres amable, profesional y conciso. " + "Responde siempre en español.", name: "DentalBot");ChatClientAgent es la implementación de agente que trae MAF. Recibe tres cosas: el chatClient, las instrucciones de sistema que definen el comportamiento del agente, y un nombre. Las instrucciones son el system prompt: le dicen al agente quién es, qué puede responder y en qué idioma. Todavía están escritas a mano en el código. En el episodio 5 crecen porque le inyectamos la información real del negocio desde un archivo Markdown, en lugar de describir la clínica en un párrafo fijo.
El loop de conversación en consola
El resto de Program.cs es un loop simple que conecta el agente con el VoiceService del episodio anterior:
Console.WriteLine("🦷 Clínica Dental Sonrisa — Asistente Virtual\n");
await voiceService.SpeakAsync( "Hola, soy el asistente de Clínica Dental Sonrisa. ¿En qué puedo ayudarte hoy?");
while (true){ Console.Write("\nTú: "); var input = Console.ReadLine();
if (input?.ToLower() == "salir") break; if (string.IsNullOrWhiteSpace(input)) continue;
// 1. Agente piensa con Gemini var response = await agent.RunAsync(input); var responseText = response.Text;
// 2. Mostramos en consola Console.WriteLine($"Agente: {responseText}");
// 3. Azure TTS habla await voiceService.SpeakAsync(responseText);}Dos validaciones antes de llamar al agente. La primera sale del loop limpiamente si escribes salir. La segunda ignora mensajes vacíos o solo con espacios: sin esta línea, un Enter en blanco haría una llamada innecesaria a Gemini.
RunAsync es la llamada central del video. MAF toma el texto del usuario, lo envía a Gemini con las instrucciones del agente, y devuelve la respuesta. response.Text extrae el texto plano de esa respuesta.
Memoria de conversación, sin configurarla
Lo que no se ve en el código pero ocurre por dentro: MAF mantiene el historial completo de la conversación mientras el objeto agent sigue vivo. Una demo real:
🦷 Clínica Dental Sonrisa — Asistente Virtual
Tú: ¿Tienen doctora disponible?Agente: Sí, contamos con doctoras disponibles para atenderte.
Tú: Me llamo ByronAgente: Hola Byron, ¿en qué puedo ayudarte hoy?
Tú: ¿Cómo me llamo?Agente: Te llamas Byron.El agente recuerda el nombre sin ChatHistory manual ni configuración adicional. Es memoria de conversación nativa de ChatClientAgent.
Qué sigue
El agente ya responde y ya recuerda, pero todavía no conoce el negocio real: las respuestas son genéricas porque las instrucciones del sistema son un párrafo fijo de cuatro líneas. En el episodio 5 le damos al agente un archivo Markdown con toda la información de la clínica (servicios, precios, horarios, doctores) y pasa de respuestas genéricas a respuestas precisas, sin tocar una base de datos.
Si estás siguiendo el curso: consigue tu API key de Gemini, corre este loop en consola, y prueba la memoria de conversación con dos o tres turnos antes de avanzar. El código completo está en el repositorio del proyecto.