Arquitectura: del filesystem compartido a A2A
El problema
Sección titulada «El problema»En el sistema local, todos los agentes comparten un directorio de salida. Cada agente escribe sus decisiones en archivos y el siguiente los lee directamente:
OUTPUT_DIR = os.getenv('ADK_OUTPUT_DIR', '/app/outputs')Esto funciona porque todos corren en el mismo contenedor Docker con acceso al mismo filesystem. En Cloud Run, cada servicio tiene su propio contenedor aislado — no hay /app/outputs/ compartido.
Por qué no filesystem compartido en Cloud Run
Sección titulada «Por qué no filesystem compartido en Cloud Run»Existen opciones como GCS FUSE o Filestore NFS para montar volúmenes compartidos. Sin embargo, Google no las recomienda para comunicación entre servicios. El patrón correcto en arquitecturas serverless es: el estado viaja en los mensajes, no en el filesystem.
La solución: protocolo A2A
Sección titulada «La solución: protocolo A2A»Agent-to-Agent (A2A) es un protocolo abierto bajo la Linux Foundation. Cada agente se expone como un servidor HTTP independiente con su propia URL. La comunicación es via mensajes JSON — el orquestador envía una tarea y recibe una respuesta.
Contexto acumulado
Sección titulada «Contexto acumulado»El orquestador encadena los 7 agentes y acumula el contexto de cada uno. Cada agente recibe todo lo que generaron los anteriores:
Orquestador │ ├──→ Platform Architect (recibe: tarea) │ ├──→ Infrastructure (recibe: tarea + contexto PA) │ ├──→ Security (recibe: tarea + contexto PA + Infra) │ ├──→ CI/CD (recibe: tarea + contexto PA + Infra + Sec) │ ├──→ Observability (recibe: tarea + PA + Infra + Sec + CICD) │ ├──→ DevEx (recibe: tarea + PA + Infra + Sec + CICD + Obs) │ └──→ Web Portal (recibe: tarea + todos los 6 anteriores)El contexto crece en cada paso. Web Portal recibe el output acumulado de los 6 agentes previos para construir el portal con toda la información del IDP.
El refactor clave
Sección titulada «El refactor clave»El cambio principal está en cómo cada agente obtiene el contexto de los anteriores.
Antes (sistema local) — lee del disco:
def get_platform_config() -> dict: """Lee platform-config.yaml del filesystem compartido.""" config_path = os.path.join(OUTPUT_DIR, 'platform-config.yaml') with open(config_path) as f: return yaml.safe_load(f)Después (Cloud Run) — lee del mensaje, con fallback a disco:
def get_platform_config(context_json: str = "") -> dict: """Lee contexto del mensaje A2A. Fallback a disco si está vacío.""" if context_json: return json.loads(context_json) # Fallback para ejecución local config_path = os.path.join(OUTPUT_DIR, 'platform-config.yaml') with open(config_path) as f: return yaml.safe_load(f)Este patrón se repite en 6 de los 7 agentes. Platform Architect no lo necesita porque es el primero de la cadena — no tiene contexto previo que recibir.
Siguiente paso: Los 7 agentes — Dockerfile, agent.json y tools →