¡Bienvenidos de nuevo a la serie «Building Blocks for AI in .NET»! En las entregas anteriores, exploramos las Microsoft Extensions for AI (MEAI) como una interfaz unificada para trabajar con modelos de lenguaje grandes, y Microsoft.Extensions.VectorData, que introduce la búsqueda semántica y patrones RAG en .NET. En esta tercera parte, nos adentraremos en un componente fundamental: el Microsoft Agent Framework.
Hasta ahora, hemos sentado las bases. MEAI nos proporcionó una forma universal de comunicarnos con los modelos, y VectorData nos dio la capacidad de almacenar y buscar conocimiento. Pero, ¿qué sucede si queremos que una IA no solo responda preguntas, sino que realice acciones? Que use herramientas, recuerde el contexto a través de conversaciones y coordine con otros agentes para resolver problemas complejos. Aquí es donde los agentes cobran protagonismo.
¿Qué es un agente de IA?
Un agente de IA va más allá de un simple chatbot. Mientras un chatbot recibe una entrada, la pasa a un modelo y devuelve una salida, un agente posee autonomía. Es capaz de razonar sobre una tarea, decidir qué herramientas utilizar, invocarlas, evaluar los resultados y determinar el siguiente paso. Todo esto lo logra sin que sea necesario escribir instrucciones explícitas y detalladas para cada escenario.
Piensa en ello de esta manera: si MEAI es como tener una conversación con un colega, un agente es como entregarle a ese colega una lista de tareas pendientes y dejar que él descubra cómo realizarlas. Podría buscar información, ejecutar cálculos, consultar el clima, revisar una base de datos y utilizar cualquier herramienta que le hayas puesto a su disposición.
El Microsoft Agent Framework es un SDK listo para producción diseñado para construir estos agentes inteligentes en .NET (y otros lenguajes como Python, aunque aquí nos centramos en C#). Alcanzó su versión 1.0 en abril de 2026 y soporta desde escenarios simples de un solo agente hasta flujos de trabajo multi-agente complejos con orquestación basada en grafos.
Tu primer agente
Empecemos de forma sencilla. Si ya has utilizado MEAI y/o leído la Parte 1, el Agent Framework te resultará familiar, ya que se construye directamente sobre la interfaz IChatClient. Para empezar, crea una aplicación de consola e instala el paquete del framework:
dotnet add package Microsoft.Agents.AI
Crear un agente es tan sencillo como esto:
using Microsoft.Agents.AI;
// ... configuración del cliente OpenAI ...
AIAgent agent = openAIClient.GetChatClient(deploymentName)
.AsAIAgent(
instructions: "Eres bueno contando chistes.",
name: "Bromista");
Console.WriteLine(await agent.RunAsync("Cuéntame un chiste de piratas."));
El método de extensión .AsAIAgent() es clave. Al igual que .AsIChatClient() conecta un SDK de proveedor con la abstracción de MEAI, .AsAIAgent() lo lleva un paso más allá, encapsulándolo en un agente capaz de gestionar sesiones, herramientas y memoria. Funciona con diversos proveedores, incluyendo Azure OpenAI, OpenAI, GitHub Models, Microsoft Foundry o incluso modelos locales como Foundry Local u Ollama.
El agente también soporta streaming de forma nativa para respuestas en tiempo real:
await foreach (var update in agent.RunStreamingAsync("Cuéntame un chiste de piratas."))
{
Console.Write(update);
}
Dota a tu agente de herramientas
Un agente que cuenta chistes es divertido, pero los agentes se vuelven verdaderamente potentes cuando se les proporcionan herramientas. Las herramientas son funciones que el modelo puede decidir invocar basándose en la solicitud del usuario. El Agent Framework utiliza el mismo AIFunctionFactory de MEAI, lo que significa que las herramientas que ya hayas definido para tu cliente de chat también son compatibles aquí.
Aquí tienes un ejemplo de un agente equipado con una herramienta para el clima:
using System.ComponentModel;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
[Description("Obtiene el clima para una ubicación dada.")]
static string GetWeather(
[Description("La ubicación para obtener el clima.")] string location)
=> $"El clima en {location} está nublado con una máxima de 15°C.";
AIAgent agent = openAIClient.GetChatClient(deploymentName)
.AsAIAgent(
instructions: "Eres un asistente útil",
tools: [AIFunctionFactory.Create(GetWeather)]);
Console.WriteLine(await agent.RunAsync("¿Qué tiempo hace en Ámsterdam?"));
Cuando el usuario pregunta sobre el clima, el agente no solo adivina, sino que reconoce la disponibilidad de la herramienta GetWeather, la invoca con el parámetro adecuado y utiliza el resultado para formular su respuesta. No es necesario codificar lógica condicional del tipo «si el usuario pregunta sobre el clima, llama a esta función»; el modelo lo deduce por sí mismo.
Los atributos Description son fundamentales. Proporcionan al modelo una descripción de la función de la herramienta y el significado de cada parámetro, ayudándole a decidir cuándo y cómo usarla. Son, en esencia, el manual de instrucciones de la herramienta para la IA.
Conversaciones multi-turno con sesiones
Las conversaciones reales no se limitan a un único intercambio. Los usuarios hacen preguntas de seguimiento, aportan contexto adicional y esperan que el agente recuerde lo que se ha discutido. El Agent Framework gestiona esto mediante AgentSession:
AgentSession session = await agent.CreateSessionAsync();
Console.WriteLine(
await agent.RunAsync("Cuéntame un chiste de piratas.", session));
Console.WriteLine(
await agent.RunAsync(
"Ahora añade algunos emojis al chiste y cuéntalo con la voz de un loro pirata.",
session));
La sesión conserva el historial de la conversación entre llamadas. Cuando el usuario solicita «añadir algunos emojis al chiste», el agente sabe a qué chiste se refiere porque la sesión mantiene ese contexto.
Las sesiones también pueden serializarse y deserializarse, una capacidad crucial para escenarios de producción donde el agente opera en un servicio sin estado:
// Guardar el estado de la sesión
JsonElement sessionState = await agent.SerializeSessionAsync(session);
// Más tarde, restaurarla
var restoredSession = await agent.DeserializeSessionAsync(sessionState);
Console.WriteLine(
await agent.RunAsync("¿De qué estábamos hablando?", restoredSession));
Enseña a tu agente a recordar (Memoria a largo plazo)
Las sesiones mantienen el historial de conversación, pero ¿qué hay de la memoria a largo plazo? ¿Cómo hacer que tu agente recuerde datos sobre el usuario (su nombre, preferencias, interacciones previas) entre diferentes sesiones?
El Agent Framework ofrece AIContextProvider, un mecanismo para inyectar información contextual en el flujo de trabajo del agente. Este es un ejemplo simplificado que extrae y recuerda información del usuario:
internal sealed class UserInfoMemory : AIContextProvider
{
// ... Implementación de StoreAIContextAsync para extraer el nombre del usuario ...
// ... Implementación de ProvideAIContextAsync para inyectar el nombre del usuario o pedirlo ...
}
AIContextProvider consta de dos métodos clave:
StoreAIContextAsync: Se ejecuta después de cada interacción. Es la oportunidad del agente para aprender de lo que acaba de suceder, como extraer el nombre del usuario de la conversación.ProvideAIContextAsync: Se ejecuta antes de cada interacción. Suministra contexto adicional al agente, por ejemplo, informándole del nombre del usuario o instruyéndolo a preguntar por él.
Se vincula al crear el agente:
AIAgent agent = chatClient.AsAIAgent(new ChatClientAgentOptions()
{
ChatOptions = new() { Instructions = "Eres un asistente amigable. Siempre dirígete al usuario por su nombre." },
AIContextProviders = [new UserInfoMemory(chatClient.AsIChatClient())]
});
Este patrón es muy potente porque disocia lo que el agente recuerda de cómo conversa. Puedes apilar múltiples proveedores de contexto: uno para preferencias del usuario, otro para interacciones recientes y un tercero que extraiga documentos relevantes de tu almacén VectorData.
Flujos de trabajo: orquestando múltiples agentes
Los agentes individuales son útiles, pero muchos problemas del mundo real se benefician de dividir el trabajo entre múltiples agentes especializados. El Agent Framework proporciona un sistema de flujos de trabajo basado en grafos, donde se conectan ejecutores (unidades de procesamiento) con aristas (rutas de flujo de datos).
Un flujo de trabajo simple que encadena dos procesadores de texto, por ejemplo, convertir a mayúsculas y luego invertir el texto, se vería así:
using Microsoft.Agents.AI.Workflows;
var uppercase = ((Func<string, string>)(s => s.ToUpperInvariant())).BindAsExecutor("UppercaseExecutor");
var reverse = new ReverseTextExecutor(); // Suponiendo una implementación de ReverseTextExecutor
WorkflowBuilder builder = new(uppercase);
builder.AddEdge(uppercase, reverse).WithOutputFrom(reverse);
var workflow = builder.Build();
// ... Ejecución y procesamiento de eventos del workflow ...
Aunque el ejemplo de procesamiento de texto es sencillo, la verdadera potencia de los flujos de trabajo se manifiesta al utilizar agentes como ejecutores. El framework soporta diversos patrones:
- Flujos de trabajo secuenciales: Los agentes procesan uno tras otro, donde la salida de cada agente alimenta al siguiente.
- Flujos de trabajo concurrentes: Se distribuye el trabajo a varios agentes en paralelo, y luego se consolidan los resultados.
- Enrutamiento condicional («hand-off»): Se dirige dinámicamente el trabajo a diferentes agentes según la salida de un paso anterior.
- Bucles de retroalimentación: Un patrón «escritor-crítico» donde un agente produce contenido y otro lo evalúa, repitiendo el ciclo hasta que se cumplen los criterios de calidad.
- Sub-flujos de trabajo: Se componen flujos de trabajo de forma jerárquica incrustando uno dentro de otro.
Ejemplo de escritor-crítico
Un patrón muy práctico es el flujo de trabajo escritor-crítico. Imagina un agente que redacta textos de marketing y otro que los revisa en busca de calidad:
WorkflowBuilder builder = new(writerAgent);
builder
.AddEdge(writerAgent, criticAgent)
.AddEdge(criticAgent, writerAgent, condition: result => !result.IsApproved)
.WithOutputFrom(criticAgent, condition: result => result.IsApproved);
var workflow = builder.Build();
El agente escritor produce un borrador, el crítico lo evalúa y, si no es aprobado, el borrador regresa al escritor para su revisión. Este bucle continúa hasta que el crítico queda satisfecho. Por supuesto, por seguridad, es recomendable establecer un número máximo de iteraciones.
Human-in-the-loop (El humano en el bucle)
La IA no reemplaza a los humanos y, a menudo, requiere su intervención. Piensa en los agentes como trabajadores especializados dirigidos por humanos a través de código. El Agent Framework soporta flujos de trabajo de aprobación de herramientas, donde el agente propone una llamada a una herramienta y espera la aprobación humana antes de ejecutarla. Esto es crucial para escenarios de producción que implican operaciones sensibles, como escrituras en bases de datos, transacciones financieras o envío de comunicaciones.
El mecanismo de aprobación se basa en FunctionApprovalRequestContent y FunctionApprovalResponseContent, tipos de contenido que forman parte del modelo de contenido de MEAI introducido en la Parte 1. Cuando el agente desea llamar a una herramienta que requiere aprobación, genera una solicitud y espera. El código de tu aplicación puede presentar esta solicitud al usuario, y la respuesta determinará si la llamada a la herramienta procede.
Uniendo todas las piezas
La belleza de este enfoque de «building blocks» radica en cómo cada pieza se compone naturalmente con las demás. Así es como encajan:
- MEAI (
IChatClient): Proporciona la base, la interfaz universal para interactuar con cualquier modelo. - VectorData: Habilita los patrones RAG (Generación Aumentada por Recuperación), permitiendo a tus agentes buscar en la base de conocimiento de tu organización utilizando búsqueda semántica para fundamentar sus respuestas en tus propios datos.
- Agent Framework: Orquesta todo. Los agentes usan
IChatClientinternamente, pueden incorporar búsqueda vectorial a través de proveedores de contexto y coordinarse mediante flujos de trabajo.
Por ejemplo, podrías construir un AIContextProvider que busque en tu almacén de VectorData antes de cada invocación del agente, proporcionando documentos relevantes como contexto adicional, replicando exactamente el patrón RAG de la Parte 2, pero ahora ejecutándose automáticamente como parte de cada interacción del agente.
Resumen
El Microsoft Agent Framework transforma las primitivas de las Partes 1 y 2 en agentes autónomos, con capacidad de usar herramientas, conscientes de la memoria, que pueden trabajar solos o en conjunto en flujos de trabajo sofisticados. Hemos cubierto:
- Creación de agentes con
AsAIAgent()y su ejecución conRunAsync(). - Equipar agentes con herramientas utilizando
AIFunctionFactoryy atributosDescription. - Gestión de conversaciones en múltiples turnos con
AgentSession. - Construcción de memoria con
AIContextProviderpara conocimiento persistente entre sesiones. - Orquestación de flujos de trabajo con ejecutores, aristas y patrones como bucles escritor-crítico.
- Aprobación «Human-in-the-loop» para operaciones sensibles.
En la próxima y última publicación, exploraremos el Model Context Protocol (MCP) y cómo proporciona una forma estandarizada para que los agentes descubran y utilicen herramientas y recursos externos, haciendo que tus agentes sean interoperables con el ecosistema de IA más amplio.
¡Feliz codificación!