Nota 47 · Microsoft Foundry (10/12)

Web apps de agentes en Foundry: ¿Cosmos o Azure SQL para el estado del backend, y cuándo?

Separa el estado propio de la app de los almacenes de Foundry. Cosmos para chat en forma de documento, Azure SQL si necesitas operaciones relacionales.

17 de septiembre de 2026 11 min de lectura

Puntos clave

  • Separa el estado de backend propio de la app de los almacenes de la plataforma Foundry antes de discutir Cosmos frente a Azure SQL.
  • Los diagramas de ejemplo de RAG y chat suelen guardar el historial en Cosmos por defecto; tómalo como la inercia de los tutoriales, no como un mandato de producto.
  • Elige Cosmos cuando la carga sea una bolsa de documentos flexible con pocas uniones relacionales.
  • Elige Azure SQL + EF Core cuando los registros propios de la app deban unirse limpiamente detrás de una API HTTP estable.
  • Congela rutas y JSON durante cualquier cambio (la API se queda; el almacén se mueve), migra una vez, cambia los repositorios y borra la ruta de datos de la app en Cosmos.
  • Comprueba el firewall de SQL y las migraciones de EF antes de dar por bueno que "la API escucha"; nunca migres los almacenes de la plataforma Foundry con la base de datos del shell.

En los hilos de la comunidad se sigue preguntando por qué los ejemplos de chatbots RAG de Microsoft recomiendan Cosmos para el historial de chat cuando una pequeña base de datos de Azure SQL también guardaría los mensajes. Pregunta justa. Los almacenes de documentos encajan bien con bolsas de mensajes, los tutoriales de Learn se montan rápido y Cosmos aparece en los diagramas que la gente copia.

Esa pregunta es contexto, no toda la tesis para una web app de agentes con Microsoft Foundry. Los shells de agentes publicados suelen dejar el historial duradero del producto en manos de tu backend. Los registros que tu backend escribe para el producto son tus tablas. Los agentes, threads, archivos, conocimiento/Search y la memoria de la plataforma se quedan en Foundry. La decisión real es qué motor respalda el plano propio de la app detrás de una única API de producto.

Modelo con nombre: la API se queda; el almacén se mueve

  • La API se queda: las rutas HTTP y las formas del JSON de cada colección propia de la app se congelan para que el shell y quienes llaman no tengan que reaprender el contrato.
  • El almacén se mueve: las colecciones propias de la app (A a D) pasan de Cosmos a Azure SQL + EF Core en una migración única cuando ganan las operaciones relacionales; después se borra la ruta de datos de la app en Cosmos.
  • La plataforma se queda: los agentes, threads, archivos, conocimiento/Search y memoria de la plataforma de Foundry no están en esa checklist de migración.
  • Cuándo gana Cosmos: bolsas de documentos flexibles de chat o RAG, acceso particionado por conversación, poca presión de joins, la velocidad de los ejemplos.
  • Cuándo gana SQL: joins, restricciones, migraciones como código, consultas de soporte con pinta de SQL y una única ruta de conexión de repositorios en todos los entornos.
  • Contrato: los valores por defecto de los ejemplos explican Cosmos en el diagrama; tu web app sigue siendo dueña del estado del producto detrás de una API estable.

Modelo con nombre: la API HTTP se queda mientras el estado propio de la app pasa de Cosmos a Azure SQL

Figura 1. Modelo con nombre: la API se queda; el almacén se mueve. Congela el contrato de la interfaz. Mueve solo las colecciones propias de la app. Deja en paz los almacenes de la plataforma Foundry.

Dos planos antes que un motor

La mayoría de las discusiones entre Cosmos y SQL fracasan porque mezclan dos planos.

El estado de backend propio de la app es lo que la API de tu web app de agentes persiste para el producto: las colecciones A a D (registros con id como clave, un índice y un log en el que solo se añade). Ese plano es tuyo y puedes ponerlo en Cosmos, Azure SQL u otra cosa. A quienes llaman les importan las rutas y el JSON, no qué SKU de Azure hay debajo del repositorio.

Los almacenes de la plataforma Foundry son lo que posee el servicio: definiciones de agentes y herramientas, threads y runs, archivos y conocimiento (incluido el grounding con Search) y la memoria de la plataforma. Eso se queda en Foundry. Hacer un cambio de Cosmos a SQL para las colecciones propias del shell no significa que tengas que mudar los threads de la plataforma a la base de datos de tu App Service.

La figura 2 dibuja el límite. El debate sobre el motor solo se aplica a la columna de la izquierda.

Colecciones propias de la app A a D frente a agentes, threads, archivos y memoria de la plataforma de Foundry

Figura 2. Dos planos de almacenamiento. Cosmos frente a Azure SQL es una decisión sobre el estado de backend propio de la app. Confundir los planos es la razón por la que los debates de foro no se entienden.

Por qué los ejemplos usan Cosmos por defecto (y por qué eso se queda corto)

Haz la pregunta de Reddit en voz alta y luego acótala.

  1. ¿Dónde guardan las demos RAG de ejemplo sus documentos de mensajes?
  2. ¿Dónde guarda tu web app de agentes con Foundry el estado del producto que la SPA y las herramientas de soporte necesitan consultar?

Cosmos suele ser la respuesta a (1). Los documentos de mensajes son naturales, los tutoriales de particionado están listos y el diagrama de arquitectura se parece al tutorial de Learn. Luego los equipos tratan ese valor por defecto como una ley de la plataforma.

Microsoft Foundry cambia la segunda mitad. Cuando una experiencia de agente publicada deja el historial de producto de varios turnos en manos de tu backend, la API del shell se convierte en el plano del historial del producto, te guste Cosmos o no. Las notas de despliegue de la comunidad ya describen cómo persistir threads y mensajes en Cosmos o en Postgres/SQL detrás de la API de la web app. La responsabilidad no es opcional. El motor, sí.

Así que guarda el valor por defecto de los ejemplos como contexto. Úsalo para explicar por qué aparece Cosmos en los diagramas. No lo uses como ADR para cada tabla propia de la app.

Cuándo Cosmos, cuándo Azure SQL

La figura 3 es la tarjeta de decisión para el plano propio de la app.

Tarjeta de decisión: Cosmos para bolsas de documentos; Azure SQL con EF Core para estado relacional propio de la app

Figura 3. Cuándo Cosmos, cuándo Azure SQL. Las bolsas de documentos y la velocidad de los ejemplos favorecen a Cosmos. El estado de producto relacional y un cambio con el contrato HTTP congelado favorecen a Azure SQL + EF Core.

Elige Cosmos cuando

  • La carga es una bolsa flexible de mensajes de chat o RAG y la forma todavía cambia de una semana a otra.
  • El acceso es sobre todo por conversación o por partición de usuario, con pocos joins entre colecciones.
  • Estás siguiendo un ejemplo y soporte rara vez hace preguntas con forma de SQL.
  • La velocidad del prototipo importa más que las migraciones como código para esta parte del estado.

Elige Azure SQL (+ EF Core) cuando

  • Las colecciones propias de la app deben unirse limpiamente entre sí.
  • Quieres restricciones, migraciones de EF y una única ruta de conexión de repositorios en local, staging y prod.
  • El contrato de la SPA debe seguir estable mientras cambia el motor de almacenamiento (la API se queda; el almacén se mueve).
  • Los equipos de soporte y auditoría hacen preguntas relacionales (quién cambió qué, en qué registros, para qué usuarios).

Nunca

  • Trates el valor por defecto de un ejemplo de Learn como un mandato de Foundry para cada tabla del producto.
  • Migres los almacenes de la plataforma Foundry (agentes, threads, archivos, conocimiento, memoria de la plataforma) a la base de datos del shell.
  • Dejes Cosmos y SQL activos a la vez para la misma ruta de datos de la app después del cambio.

Los valores por defecto no son el destino. Los requisitos, sí.

Un cambio típico (genérico): congelar, migrar, conmutar, borrar

Un cambio así puede empezar cuando el estado propio de la app está en Cosmos y un equipo quiere operaciones relacionales y una única ruta de conexión. La decisión no es "Cosmos está mal para cualquier bolsa de chat". Es "estas colecciones necesitan operaciones relacionales y una única ruta de conexión".

Haz el cambio como la API se queda; el almacén se mueve:

  1. Congela la interfaz. Mantén las mismas rutas y el mismo JSON para cada colección propia de la app. Quienes llaman no deberían notar el cambio de motor.
  2. Primero el esquema y el firewall. Introduce las tablas de Azure SQL y las migraciones de EF Core. Comprueba la ruta del firewall (o un SQL local) para que las migraciones funcionen antes de depurar timeouts de la SPA.
  3. Migración única. Mueve las colecciones A a D con comprobaciones de paridad (recuentos más muestras de las cargas).
  4. Conmuta los repositorios. SQL pasa a ser la fuente de verdad detrás de la misma superficie HTTP.
  5. Borra la ruta de datos de la app en Cosmos. Quita credenciales y rutas de código para que los entornos no puedan volver a un segundo almacén.

Un puente temporal puede ayudar durante la migración. Un producto permanente con dos almacenes es la forma en que vuelven las derivas de conexión. Deja en paz los almacenes de la plataforma Foundry todo el tiempo.

Errores comunes

Tratar el Cosmos de los ejemplos como un mandato de Foundry. Los diagramas de Learn son material didáctico. El contrato del estado de tu producto es un ADR.

Mover los almacenes de la plataforma Foundry con la base de datos del shell. Los agentes, threads, archivos, conocimiento y memoria de la plataforma no son más colecciones en tu checklist de migración.

Cambiar las formas del JSON durante el cambio de motor. Entonces cada bug de quien llama parece un bug de base de datos. Congela primero el formato de la interfaz.

Deriva entre entornos: Cosmos en uno, SQL en otro. Llegan los fallos que solo pasan en un entorno. Una única ruta de conexión de repositorios después del cambio.

El firewall de SQL bloquea EF antes de escuchar. El arranque local nunca llega a "la API está arriba" si las migraciones no pueden conectarse. Abre la ruta del firewall antes de perseguir timeouts de la SPA.

Escribir en los dos almacenes para siempre. Un puente temporal está bien. Un producto permanente con dos almacenes reabre la deriva que acabas de cerrar.

Úsalo tal cual o adáptalo

Úsalo tal cual

  • Separación explícita: estado de backend propio de la app frente a almacenes de la plataforma Foundry.
  • Regla de decisión: Cosmos para bolsas de documentos; Azure SQL cuando el trabajo es estado de producto relacional.
  • HTTP + JSON estables durante un cambio de Cosmos a SQL.
  • Migración única, conmutación y borrado de la ruta antigua de datos de la app.
  • Firewall y migraciones de EF sanos antes de dar la API por lista.

Adáptalo antes de usarlo

No arranques Cosmos de un prototipo que solo maneja bolsas de mensajes y no tiene presión relacional solo para encajar con esta nota. No "arregles el historial de chat" migrando los threads de Foundry a tu base de datos SQL. No dejes credenciales de Cosmos en la configuración de prod cuando la ruta de datos de la app ya no exista.

Relacionado

Fuentes (comunidad): Why does MS recommend Cosmos for RAG chat history vs Azure SQL?, Foundry published app / store behavior and backend-owned multi-turn state, Deploy Foundry agents: persist threads in Cosmos or Postgres/SQL behind your API, Anyone here using Cosmos DB?.

Los valores por defecto de los ejemplos explican Cosmos en el diagrama. Tu web app de agentes sigue decidiendo dónde vive el estado del producto. Mantén honestos los dos planos. Mantén estable una única API de producto. Mueve solo lo que es tuyo.