Microsoft Lanza AI Agent Framework: Explicación Detallada con Ejemplos

Este artículo tiene un vídeo corto:TikTok

1. Descripción general

Microsoft acaba de lanzar oficialmente (GA – General Availability) un framework unificado para construir, orquestar y operar AI Agent, al unificar sus dos productos anteriores: Semantic Kernel y AutoGen. Esto no es solo una noticia de producto — redefinió cómo deberías diseñar un sistema con LLM que “toma decisiones autónomas sobre acciones” en lugar de simplemente responder una pregunta.

Este artículo explica en qué difiere un AI Agent de un chatbot convencional, qué lanzó específicamente Microsoft, y luego construirás tu propio agent minimalista con Java 21 + Spring Boot 3 + Spring AI (integrado con Azure OpenAI) para entender bien el mecanismo subyacente, aunque el framework original de Microsoft se ejecuta en .NET y Python.

2. ¿Qué es un AI Agent?

Un chatbot convencional recibe una pregunta, llama al LLM una vez, devuelve una respuesta. Un Agent es diferente en que repite el ciclo razonamiento–acción varias veces, decidiendo autónomamente si necesita llamar a una herramienta (API, base de datos, archivo…) antes de dar su respuesta final.

Característica Chatbot AI Agent
Llamadas al LLM 1 por pregunta Múltiples, auto-iterativo
Uso de herramientas Típicamente no Sí, herramientas elegidas por el modelo
Estado Sin estado o historial de chat Con memoria, puede hacer checkpoint
Latencia Baja Mayor (múltiples round-trips)
Confiabilidad Fácil de controlar Requiere guardrails, human-in-the-loop

2.1. Ciclo Reason–Act (ReAct)

El mecanismo central que la mayoría de frameworks de agent usan hoy en día es ReAct: el modelo “piensa” (Thought), elige una acción (Action) que es llamar a una herramienta, recibe el resultado (Observation), y luego repite hasta que tiene suficiente información para responder (Final Answer).

Thought: El usuario pregunta sobre el estado del pedido ORD-001, necesito consultarlo.
Action: lookupOrder("ORD-001")
Observation: Pedido ORD-001: estado SHIPPED, monto total 450000 VND
Thought: Tengo suficiente información.
Final Answer: Tu pedido ORD-001 está siendo entregado, monto total 450.000đ.

Esta es la parte que Microsoft Agent Framework (y Spring AI que usarás abajo) automatiza — no necesitas escribir manualmente este ciclo, solo declarar herramientas y el system prompt.

3. ¿Qué lanzó Microsoft para AI Agent?

Antes de unificarse, Microsoft tenía dos direcciones de desarrollo en paralelo:

  • Semantic Kernel: SDK orientado a producción, enfatiza plugins type-safe, integración empresarial (Azure, .NET), adecuado para despliegues estables.
  • AutoGen: orientado a investigación, fuerte en conversación multi-agent — múltiples agents se “comunican” entre sí para resolver tareas complejas.

El nuevo framework combina ambos puntos fuertes, incluyendo estas capacidades clave:

  • Patrones de orquestación predefinidos: secuencial (agente A termina, luego B), concurrente (múltiples agents corren en paralelo y se sintetizan), hand-off (un agent traspasa la tarea a otro especializado), group chat (múltiples agents discuten antes de responder).
  • Ejecución durable/stateful: los agents pueden hacer checkpoint en medio, reanudar si el proceso falla — importante para tareas largas (minutos a horas).
  • Observabilidad integrada: trazas conforme al estándar OpenTelemetry, puedes ver cada paso Thought/Action/Observation en producción.
  • Human-in-the-loop: pausar el agent para esperar aprobación antes de ejecutar acciones sensibles (reembolsos, borrado de datos…).
  • Azure AI Foundry Agent Service: runtime alojado para desplegar agents, catálogo de herramientas predefinidas (búsqueda Bing, intérprete de código, recuperación de archivos) y soporte para Model Context Protocol (MCP) para conectar herramientas externas conforme a estándares abiertos, sin dependencia de proveedor.

El framework original se ejecuta en .NET/Python, pero el patrón es universal. La siguiente sección reconstruye ese patrón exacto en Java para que veas cómo funciona a nivel de código.

4. Arquitectura central de un AI Agent

Un agent minimalista necesita 4 componentes: Planner (que es el LLM), Tool (funciones que el agent puede llamar), Memory (historial de conversación/resultados de herramientas), Executor (ciclo de orquestación). Spring AI empaqueta Executor y Planner a través de ChatClient, solo necesitas declarar Tools.

4.1. Dependencia Maven

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-azure-openai-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>

Configuración para conectar con Azure OpenAI (servicio GPT de Microsoft, desplegado en Azure):

spring.ai.azure.openai.api-key=${AZURE_OPENAI_KEY}
spring.ai.azure.openai.endpoint=${AZURE_OPENAI_ENDPOINT}
spring.ai.azure.openai.chat.options.deployment-name=gpt-4o-mini

4.2. Definición de Tools para el agent

Una Tool es un método Java ordinario, marcado con @Tool para que el modelo sepa que puede llamarlo y con qué parámetros.

public record Order(String id, String status, BigDecimal total) {}

public interface OrderService {
    Order findById(String orderId);
}

@Service
public class OrderTools {

    private final OrderService orderService;

    public OrderTools(OrderService orderService) {
        this.orderService = orderService;
    }

    @Tool(description = "Buscar el estado y monto total de un pedido por código de pedido")
    public String lookupOrder(String orderId) {
        Order order = orderService.findById(orderId);
        return "Pedido %s: estado %s, monto total %s VND"
            .formatted(order.id(), order.status(), order.total());
    }
}

El description en @Tool es lo que el modelo lee para decidir si debe llamar a lookupOrder o no — escribe descripciones claras y específicas para que el agent elija la herramienta más precisa.

4.3. El Agent llama Tools automáticamente vía ChatClient

@Service
public class SupportAgentService {

    private final ChatClient chatClient;

    public SupportAgentService(ChatClient.Builder builder, OrderTools orderTools) {
        this.chatClient = builder
            .defaultSystem("""
                Eres un asistente de soporte al cliente de una tienda en línea.
                Si la pregunta está relacionada con un pedido, usa la herramienta lookupOrder.
                Responde de forma concisa, amigable, en español.
                """)
            .defaultTools(orderTools)
            .build();
    }

    public String handle(String userMessage) {
        return chatClient.prompt()
            .user(userMessage)
            .call()
            .content();
    }
}

La línea .defaultTools(orderTools) registra el conjunto de herramientas, ChatClient ejecuta automáticamente el ciclo ReAct internamente: envía el prompt con la lista de herramientas al modelo, si el modelo solicita llamar lookupOrder, Spring AI ejecuta automáticamente el método Java correspondiente, devuelve el resultado (Observation) al modelo, y solo entonces recibe la respuesta final. No escribes manualmente el ciclo — esta es la parte que Microsoft Agent Framework y Spring AI automatizan de la misma manera.

> handle("¿Dónde está mi pedido ORD-001?")
¡Tu pedido ORD-001 está siendo entregado (SHIPPED), monto total 450.000đ!

Nota: El modelo solo llama a una herramienta cuando “decide” que es necesario — no toda pregunta activa una herramienta. Si el usuario pregunta “¿la tienda envía internacionalmente?”, el modelo responderá directamente sin llamar lookupOrder.

5. Multi-agent: cuando un agent no es suficiente

Una de las capacidades destacadas que Microsoft lanzó es el hand-off — transferir la conversación entre agentes especializados. Para problemas pequeños, puedes simularlo con un router simple, sin necesidad de un framework multi-agent complejo:

@Service
public class AgentRouter {

    private final SupportAgentService orderAgent;
    private final RefundAgentService refundAgent;

    public AgentRouter(SupportAgentService orderAgent, RefundAgentService refundAgent) {
        this.orderAgent = orderAgent;
        this.refundAgent = refundAgent;
    }

    public String route(String userMessage) {
        String lower = userMessage.toLowerCase();
        if (lower.contains("reembolso") || lower.contains("refund")) {
            return refundAgent.handle(userMessage);
        }
        return orderAgent.handle(userMessage);
    }
}

Este router actúa como un “orchestrator” minimalista. A mayor escala, la selección de qué agent manejará la solicitud también debería ser decidida por el propio LLM (clasificación de intención mediante el modelo), en lugar de hard-codear contains() — escribir manualmente solo es apropiado para demostraciones o conjuntos de intención muy pequeños y estables.

6. Escribir pruebas para Tools y Agents

La parte más fácil de probar en un sistema de agent es la herramienta — porque es un método Java puro, sin dependencias de LLM. Deberías probar esta parte cuidadosamente, porque un agent solo es “inteligente” según la calidad de las herramientas que llama.

class OrderToolsTest {

    @Test
    void shouldReturnOrderSummaryWithStatusAndTotal() {
        OrderService fakeOrderService = orderId ->
            new Order(orderId, "SHIPPED", new BigDecimal("450000"));

        OrderTools tools = new OrderTools(fakeOrderService);

        String result = tools.lookupOrder("ORD-001");

        assertThat(result)
            .contains("ORD-001")
            .contains("SHIPPED")
            .contains("450000");
    }
}

Dado que OrderService solo tiene un método findById, usamos una lambda para crear una implementación falsa en lugar de agregar una dependencia de framework de mocking — limpio y suficiente para esta prueba unitaria.

class AgentRouterTest {

    @Test
    void shouldRouteRefundKeywordToRefundAgent() {
        SupportAgentService orderAgent = mock(SupportAgentService.class);
        RefundAgentService refundAgent = mock(RefundAgentService.class);
        when(refundAgent.handle(anyString())).thenReturn("Solicitud de reembolso registrada");

        AgentRouter router = new AgentRouter(orderAgent, refundAgent);

        String result = router.route("Quiero un reembolso para el pedido ORD-002");

        assertThat(result).isEqualTo("Solicitud de reembolso registrada");
        verify(refundAgent).handle(anyString());
        verify(orderAgent, never()).handle(anyString());
    }
}

Nota: No deberías escribir pruebas “end-to-end llamando realmente al LLM” en tests unitarios — los resultados no son determinísticos (el modelo puede responder diferente cada vez), cuesta dinero llamar a la API, y ralentiza/hace flaky el CI. Mock ChatClient o prueba partes específicas como tool/router arriba; mantén un conjunto separado de pruebas de integración (ejecutadas manualmente o nightly) para verificar que el agent elija la herramienta correcta en situaciones reales.

7. Errores comunes y cuándo no usar agentes

  • Usar agents para lógica que se puede resolver con if-else: si la lógica de selección de acciones es conocida y fija de antemano (por ejemplo: siempre buscar un pedido cuando hay un código con patrón ORD-\d+), escribir código es típicamente más barato, rápido y fácil de probar que dejar que el LLM “piense” cada vez.
  • Omitir guardrails para acciones sensibles: los agents tienen permiso para llamar tools que borren datos, emitan reembolsos, envíen emails a clientes — si no hay un paso de confirmación (human-in-the-loop) o restricciones de permisos en las tools, una inyección de prompt o un error de razonamiento del modelo pueden tener consecuencias reales.
  • No limitar el número de iteraciones: si el modelo elige herramientas incorrectamente o no tiene suficientes datos para concluir, el ciclo ReAct puede iterar indefinidamente, desperdiciando tokens y dinero. Siempre establece un número máximo de pasos y timeout.
  • Falta de observabilidad: cuando el agent responde incorrectamente, necesitas poder revisar toda la cadena Thought/Action/Observation para hacer debug — sin logs/traces detallados es casi imposible descubrir qué “pensó” el modelo que llevó al resultado incorrecto.
  • Latencia y costo: cada paso en el ciclo es una llamada al LLM. Una pregunta simple puede requerir 2-3 llamadas al modelo (y cada una tarda cientos de ms a varios segundos). Para APIs que necesitan respuestas inmediatas (ej. menos de 200ms), este tipo de agent no es apropiado.

8. Conclusión

La unificación de Semantic Kernel y AutoGen por parte de Microsoft en un único framework revela una tendencia clara: los AI Agents están transitando de “demos interesantes” a infraestructura de producción que requiere orquestación, estado, observabilidad y control de permisos tan riguroso como cualquier otro sistema empresarial. Ya sea que uses .NET, Python o Java/Spring AI como en los ejemplos de este artículo, la arquitectura fundamental sigue girando alrededor de cuatro bloques: Planner, Tool, Memory, Executor — domina estos cuatro bloques y podrás comprender y aplicar cualquier framework de agent que surja en el futuro.

AI AgentMicrosoftSpring AIAzure OpenAILLM