Saltar al contenido
Programemos.net Un espacio para compartir conocimientos relacionados con la programación.
AZURE / IA / ARQUITECTURA DE SOFTWARE / PROGRAMACIÓN

Agentes serverless en Azure Functions: Microsoft mueve el foco del código al agente

Hay algo en el nuevo runtime de agentes serverless de Azure Functions que me parece más importante que la lista de triggers, herramientas o conectores.

Microsoft está moviendo el centro de la conversación. Hasta ahora pensábamos primero en la Function, el handler y el código que recibía un evento. Ahora la propuesta es pensar primero en el agente: qué intenta resolver, cuándo debe ejecutarse, qué instrucciones necesita y a qué capacidades puede acceder.

Después viene el código, si hace falta.

Ese cambio me parece interesante porque el agente se convierte en la unidad de trabajo que Azure Functions descubre, registra, dispara y ejecuta. Ya no es solamente algo externo que llama una Function o usa una Function como herramienta.

La propuesta es markdown-first: defines el agente en un archivo .agent.md, declaras su trigger en el frontmatter y escribes sus instrucciones en Markdown. El runtime se ocupa de componer el modelo, las herramientas, las skills y el trigger. Cuando existe una conversación de varios turnos, también puede recuperar y persistir su historial de sesión.

No conviene exagerarlo. El runtime está en preview y actualmente la aplicación es un proyecto Python. Pero la dirección sí vale la pena analizarla porque acerca dos mundos que normalmente terminamos pegando a mano: agentes y procesamiento orientado a eventos. También revela cómo Microsoft quiere que construyamos parte de estas soluciones: menos código ceremonial alrededor del agente y más intención explícita sobre lo que el agente debe hacer.

La novedad no es ejecutar IA en una Function

Ejecutar una llamada a un modelo desde Azure Functions no es nuevo. Tampoco lo es usar una Function como herramienta de un agente.

Lo interesante es que ahora un archivo puede declarar un agente completo:

resumen-diario.agent.md
---
name: Resumen diario
description: Resume los eventos técnicos pendientes y prepara un reporte.
trigger:
type: timer_trigger
args:
schedule: "0 0 15 * * *"
---
Revisa los eventos técnicos pendientes.
Agrupa los problemas por severidad y prepara un resumen breve.
Incluye los riesgos que requieran atención del equipo.

El frontmatter indica cuándo se ejecuta. El cuerpo en Markdown indica qué debe hacer.

Cuando arranca la Function App, el runtime lee los .agent.md, carga la configuración compartida, descubre herramientas y skills, valida la composición y registra los triggers. Cuando ocurre el evento, construye y ejecuta el agente mediante Microsoft Agent Framework.

La aplicación mínima sigue teniendo piezas conocidas de Azure Functions como host.json, requirements.txt y function_app.py. La diferencia es que este último puede reducirse a crear la aplicación configurada por el runtime:

function_app.py
from azure_functions_agents import create_function_app
app = create_function_app()

Eso elimina bastante código de infraestructura, pero también mueve más comportamiento hacia configuración y convenciones del runtime.

La complejidad no desaparece. Cambia de lugar.

Los eventos pasan a iniciar agentes

Para mí, aquí está la parte importante.

Un chatbot empieza normalmente porque alguien escribe un mensaje. Un agente de negocio no siempre funciona así. Puede tener que reaccionar cuando llega una orden, cambia un documento, aparece una alerta o se cumple una hora determinada.

El runtime permite usar triggers conocidos de Azure Functions como:

  • HTTP
  • Timer
  • Queue Storage
  • Blob Storage
  • Event Grid
  • Service Bus

También contempla eventos provenientes de servicios conectados, por ejemplo mensajes, correos o cambios en aplicaciones empresariales cuando el conector correspondiente los soporta.

Diagrama donde eventos HTTP, programados y de colas activan un agente en Azure Functions que usa MCP, skills, herramientas Python y ejecución aislada
El runtime convierte los triggers de Azure Functions en puntos de entrada para agentes con herramientas y capacidades configuradas.

Esto encaja especialmente bien cuando el evento necesita razonamiento o selección dinámica de herramientas. Por ejemplo, una alerta que debe correlacionarse con incidentes anteriores, consultar varios sistemas y decidir si escalar.

Pero si cada mensaje de una cola siempre termina ejecutando tres pasos conocidos en el mismo orden, probablemente no necesitas un agente. Necesitas una Function o un workflow determinista.

Poner un modelo en medio de un proceso predecible añade costo, latencia y una nueva forma de fallar sin aportar necesariamente una mejor decisión.

La apuesta de Microsoft: el agente primero

Para mí, esta es la lectura más interesante del runtime.

Microsoft no está diciendo que el código dejó de importar. Está proponiendo que, para este tipo de aplicación, el código ya no tiene que ser la primera abstracción que veamos.

En una Function tradicional empiezas normalmente por una función, un trigger, parámetros y servicios. Aquí empiezas por otra pregunta: ¿qué agente necesito y qué resultado espero de él?

El archivo .agent.md se convierte en la pieza principal. El trigger, el modelo y las capacidades se configuran alrededor de sus instrucciones. El código aparece cuando el comportamiento propio del negocio no cabe razonablemente en MCP, conectores, skills o ejecución aislada.

Me gusta esa dirección porque obliga a expresar mejor la intención. También me genera una reserva: un archivo Markdown puede hacer que el sistema parezca más simple de lo que realmente es. Cuando el agente tiene permisos para enviar correos, crear tickets, consultar datos o ejecutar código, ya no estamos escribiendo solo instrucciones. Estamos definiendo comportamiento operativo.

La propuesta intenta que las capacidades comunes no tengan que implementarse todas como clientes personalizados.

Un agente puede descubrir servidores MCP remotos desde mcp.json, cargar instrucciones reutilizables desde carpetas de skills y ejecutar Python en sesiones aisladas de Azure Container Apps. Para lógica propia del negocio, puedes agregar herramientas Python en tools/.

La estructura puede verse así:

mi-agente/
├── function_app.py
├── resumen-diario.agent.md
├── agents.config.yaml
├── mcp.json
├── host.json
├── requirements.txt
├── skills/
│ └── respuesta-incidentes/
│ └── SKILL.md
└── tools/
└── crear_ticket.py

Las cinco opciones no resuelven lo mismo:

CapacidadCuándo la usaría
MCP remotoUna capacidad ya vive en otro servicio o debe compartirse entre aplicaciones.
ConectoresNecesito acciones o eventos de sistemas empresariales sin mantener cada cliente API.
SkillsQuiero instrucciones de dominio reutilizables que el agente cargue cuando correspondan.
Herramientas PythonLa lógica es propia de esta aplicación y necesita código explícito.
SandboxEl agente debe ejecutar código potencialmente no confiable en un entorno aislado.

El runtime hace disponibles por defecto varias capacidades descubiertas y permite excluirlas por agente. Eso es cómodo, pero yo sería conservador: un agente no debería heredar una herramienta solo porque está disponible en el proyecto. Cuantas más acciones tenga, mayor es la superficie de permisos, errores y decisiones difíciles de evaluar.

Aquí es donde “menos código” no puede convertirse en “menos revisión”. Las descripciones de las herramientas, los esquemas de parámetros, los permisos y las instrucciones pasan a ser parte del contrato del sistema, aunque no estén escritos como una clase o una interfaz.

Lo operativo sigue importando

La ventaja real de apoyarse en Azure Functions no es que el prompt viva en Markdown. Es reutilizar un modelo operativo conocido: escalado orientado a eventos, identidad administrada, red, Application Insights y despliegue como Function App.

En Flex Consumption, Microsoft destaca scale-to-zero, facturación por segundo, integración con redes virtuales e identidades administradas. Para interacciones de varios turnos, el runtime guarda el historial de sesión en Blob Storage usando la cuenta configurada en AzureWebJobsStorage.

Eso reduce piezas, pero no evita las decisiones serias:

  • El scale-to-zero no garantiza costo irrelevante si cada ejecución llama modelos y herramientas varias veces.
  • La identidad administrada simplifica secretos, pero todavía debes asignar permisos mínimos a modelos, Storage, MCP y sandboxes.
  • El historial persistido necesita políticas de retención, clasificación de datos y revisión de privacidad.
  • Una ejecución de agente puede durar y variar mucho más que una Function determinista.
  • La observabilidad debe explicar tanto el trigger como las decisiones y llamadas del agente.

También hay una interfaz de chat y APIs integradas de chat y streaming. La propia documentación recomienda esas superficies para desarrollo, pruebas y diagnóstico, no como interfaz principal de producción. El endpoint MCP es distinto: sirve para exponer la composición del agente a clientes MCP y está protegido por una system key, salvo que la aplicación configure acceso anónimo.

Cuándo sí lo usaría

Veo un buen encaje en agentes que reaccionan a eventos y necesitan combinar contexto con acciones:

  • clasificación y escalamiento de incidentes
  • resúmenes programados que consultan varias fuentes
  • procesamiento de correos o mensajes con decisiones posteriores
  • conciliaciones donde aparecen excepciones que requieren razonamiento
  • automatizaciones empresariales apoyadas en conectores y MCP

En esos casos, Azure Functions ya resuelve una parte importante del problema: cómo iniciar el trabajo, escalarlo, identificarlo y observarlo. El runtime agrega la composición del agente encima de esa base.

No lo usaría todavía para un núcleo transaccional que exige resultados totalmente deterministas, ni movería a esta abstracción una Function que solo transforma un mensaje y escribe una salida conocida. En ese segundo caso, incluso Microsoft señala la extensión MCP de Azure Functions como un punto de partida más simple si lo único que necesitas es exponer funciones deterministas como herramientas para otro cliente de IA.

Tampoco basaría una plataforma crítica en este runtime sin aceptar que está en preview y que sus capacidades, nombres de configuración y conectores compatibles pueden cambiar antes de disponibilidad general.

Y hay otro límite concreto: si el equipo trabaja principalmente con .NET, hoy tendrá que decidir si introducir un proyecto Python para adoptar este runtime compensa el beneficio. Microsoft Agent Framework participa en la ejecución, pero la anatomía documentada para esta preview es la de una aplicación Python de Azure Functions.

Lo valioso no es poder escribir un prompt en Markdown. Eso por sí solo no mejora una arquitectura ni convierte una automatización en un agente.

Lo valioso es que Microsoft está tratando de llevarnos a pensar en la intención del agente antes que en el código del handler: declarar que reacciona a un evento y darle acceso controlado a herramientas, skills, estado e identidad sin construir manualmente todo el pegamento operativo.

La idea tiene sentido porque Azure Functions ya entiende eventos. El runtime está intentando que también entienda agentes como una unidad nativa de ejecución.

Mi recomendación sería probarlo en automatizaciones internas y procesos con revisión humana, donde el razonamiento tenga valor y el impacto de un error esté acotado. Mediría latencia, costo por ejecución, calidad de decisiones y facilidad de diagnóstico antes de llevarlo a un flujo crítico.

Y mantendría una regla sencilla: si la parte más importante del sistema sigue siendo una secuencia conocida de pasos, escribiría código. Si la parte importante es interpretar contexto, elegir capacidades y decidir una acción dentro de límites claros, entonces sí empezaría a pensar en el agente como la unidad de trabajo.

No porque los agentes serverless sean una mala idea. El problema es otro: serverless resuelve cómo ejecutar y escalar; no resuelve por sí solo cómo confiar en una decisión probabilística.

Si quieres seguir aprendiendo sobre estos temas, te invito a ver mis otras publicaciones.

Referencias

Jose Antonio Arias
Jose Antonio Arias

Soy un Ingeniero en Informática, apasionado de la tecnología y, siempre trato de estar aprendiendo para estar al día con las últimas tecnologías, me especializo en el desarrollo Backend con .NET, pero durante estos años, he trabajado con muchas otras tecnologías que me han ayudado en mi crecimiento profesional.