Au-delà des tableaux de bord : création d’un agent analyste de données BigQuery autonome avec
Un agent d’analyse de données BigQuery autonome avec Google ADK et Gemini : pourquoi les tableaux de bord et les méthodes naïves de conversion texte en SQL échouent à la dernière étape, et quels correctifs en CI/CD peuvent y remédier.
Cette démarche reconstitue le parcours allant des matières premières à un système fonctionnel pour : « Beyond Dashboards : Construire un agent d’analyste de données BigQuery autonome avec Google ADK pour Customer 360 ». L’accent est mis sur des étapes opérationnelles, des vérifications explicites et du code que vous pouvez intégrer directement dans un dépôt sans devoir deviner son intention. Pour l’étape d’aperçu, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans avoir à deviner l’état caché. Préférez des unités petites et testables plutôt que des scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un pipeline embrouillé.
1. Le goulot d’étranglement final : pourquoi les outils BI traditionnels et les méthodes naïves de conversion texte en SQL échouent
Lors de la phase 1 « goulot d’étranglement de la dernière étape », notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des vérifications de succès et refusez les terminations partielles silencieuses. Faites des points de contrôle après les étapes coûteuses. Le système de reprise ne doit pas facturer à nouveau la même appel du LLM lorsque l’opérateur réessaie un nœud ultérieur.
Pourquoi les tableaux de bord BI traditionnels échouent
Lors de l’étape « Pourquoi les tableaux de bord BI traditionnels ? », notez d’abord le cahier des charges : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de l’environnement de démonstration à des environnements partagés. Faites un point après les étapes coûteuses. Le système de reprise ne doit pas facturer à nouveau la même appel d’LLM lorsque l’opérateur réessaie un nœud ultérieur.
Pourquoi les wrappers naïfs « Text-to-SQL » d’LLM échouent dans les entreprises
Lors de l’étape « Why Naive Text-to-SQL LLM », notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’honnêteté des modifications ultérieures du code. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les administrateurs peuvent auditer sans devoir lire l’ensemble du système. Mémorisez les instructions stables du système ainsi que les schémas des outils. Envoyer à nouveau un préambule identique est une cause fréquente de gaspillage. Lors de l’étape « Why Naive Text-to-SQL LLM », notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’honnêteté des modifications ultérieures du code. Préférez des unités petites et testables à des scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un processus embrouillé.
2. Architecture agente : le framework Google ADK
L’architecture agente fonctionne au mieux lorsque cette étape est considérée comme une surface mesurable. Capturez un exemple réussi exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des critères de succès et refusez toute complétion partielle silencieuse. Maintenez l’état du graphe plat et typé. Les blocs imbriqués masquent le fait que tel nœud a écrit telle champ et perturbent la reprise après interruption.
3. Pilier d’ingénierie 1 : ancrage des connaissances et mise en cache du contexte Vertex AI
La première étape du Pilier 3 d’ingénierie fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de la démonstration aux environnements partagés. Gardez l’état des graphes plat et typé ; les blocs imbriqués masquent le fait que tel nœud a écrit telle champ et perturbent la reprise après interruption.
Compilation des dictionnaires Markdown dans le prompt du système
La compilation des dictionnaires Markdown en phase de préparation fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Gardez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Fixez des limites de tokens par tour et par session. Les outils agents élargissent lourdement le contexte ; des plafonds stricts empêchent que les démonstrations ne se transforment en factures inattendues. La compilation des dictionnaires Markdown en phase de préparation fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’échec doit pointer vers une seule responsabilité plutôt que vers un processus embrouillé.
# c360_agent/config.py
import os
import glob
def compile_knowledge_base(knowledge_dir: str) -> str:
"""Recursively compiles markdown architecture guides into structured agent context."""
context_chunks = []
guide_files = glob.glob(os.path.join(knowledge_dir, "**/*.md"), recursive=True)
for file_path in sorted(guide_files):
with open(file_path, "r", encoding="utf-8") as f:
rel_name = os.path.relpath(file_path, knowledge_dir)
content = f.read()
context_chunks.append(f"### KNOWLEDGE GUIDE: {rel_name}\n\n{content}\n")
return "\n---\n".join(context_chunks)
KNOWLEDGE_CONTEXT = compile_knowledge_base("c360_agent/knowledge")
SYSTEM_PROMPT = f"""
You are an expert BigQuery Data Analyst Agent for an Enterprise Customer 360 (C360) Lakehouse.
Your mission is to answer business and analytical questions by generating and executing accurate, cost-effective SQL queries.
CRITICAL OPERATIONAL RULES:
1. TARGET CONFORMED MARTS FIRST: Always query `c360_curated_unified` for golden demographics or cross-system questions. Use Spoke marts (`c360_curated_*`) only for system-specific line-item grain.
2. MANDATORY DRY RUN: You MUST execute `dry_run_bq_query` on every generated SQL statement before calling `execute_bq_query`. Inspect syntax and bytes scanned.
3. CLUSTER AWARENESS: Always filter or join on clustered keys (`UnifiedCustomerDimId`, `UnifiedOrderDimId`) to minimize BigQuery slot consumption.
4. STRICT READ-ONLY: You are strictly forbidden from executing INSERT, UPDATE, DELETE, DROP, or ALTER statements.
DOMAIN ARCHITECTURE CONTEXT:
{KNOWLEDGE_CONTEXT}
"""
Le facteur de changement des coûts : le cache de contexte Vertex AI
Pour l’étape Vertex qui modifie les coûts, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définites des vérifications de succès et refusez les terminations partielles silencieuses. Faites approuver par un humain les étapes qui entraînent des dépenses ou modifient des données de production. La connexion en temps de compilation ne garantit pas la complétude du processus métier.
# c360_agent/agent.py
from google.adk.agents.llm_agent import Agent
from google.adk.apps import App
from google.adk.agents.context_cache_config import ContextCacheConfig
from .config import SYSTEM_PROMPT
from .tools import (
execute_bq_query,
dry_run_bq_query,
get_table_schema,
list_dataset_tables,
get_table_preview
)
# 1. Initialize the Google ADK Agent
root_agent = Agent(
name="c360_data_analyst",
model="projects/enterprise-c360-prod/locations/us-central1/publishers/google/models/gemini-2.5-flash",
description="Autonomous BigQuery Data Analyst for the Enterprise Customer 360 Lakehouse.",
instruction=SYSTEM_PROMPT,
tools=[
dry_run_bq_query,
execute_bq_query,
get_table_schema,
list_dataset_tables,
get_table_preview
]
)
# 2. Wrap in App with Vertex AI Context Caching
app = App(
name="c360_agent_app",
root_agent=root_agent,
context_cache_config=ContextCacheConfig(
ttl_seconds=1800, # Cache prompt for 30 minutes
cache_intervals=10 # Reuse across up to 10 conversational turns
)
)
4. Pilier d’ingénierie 2 : exécution sécurisée des outils avec contrôle des coûts
Pour la phase 2 du Pilier d’Ingénierie 4, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Enregistrez les temps d’exécution ainsi que le coût des jetons ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe d’un environnement de démonstration à des environnements partagés. Authentifiez-vous au niveau du gateway et réautorisez-vous au niveau du plan de données. Un simple jeton porteur ne constitue pas une frontière entre les tenants.
# c360_agent/tools.py
import subprocess
import re
def dry_run_bq_query(query: str) -> str:
"""Dry-runs a BigQuery SQL query to validate syntax and estimate bytes scanned."""
clean_query = query.strip().upper()
# Layer 1: Strict Read-Only Guard
if not (clean_query.startswith("SELECT") or clean_query.startswith("WITH")):
return "SECURITY ERROR: Only SELECT queries are permitted. DDL/DML is strictly forbidden."
try:
# Executes 'bq query --dry_run' to inspect execution planner without billing slots
result = subprocess.run(
["bq", "query", "--use_legacy_sql=false", "--dry_run", query],
capture_output=True,
text=True,
check=True
)
# bq CLI outputs estimated bytes scanned to stderr on dry run
dry_run_output = result.stderr if result.stderr else result.stdout
return f"DRY_RUN SUCCESS: {dry_run_output.strip()}"
except subprocess.CalledProcessError as e:
return f"DRY_RUN SYNTAX ERROR: {e.stderr.strip()}"
def execute_bq_query(query: str) -> str:
"""Executes a validated BigQuery SQL query and returns the formatted tabular results."""
clean_query = query.strip().upper()
if not (clean_query.startswith("SELECT") or clean_query.startswith("WITH")):
return "SECURITY ERROR: Only SELECT queries are permitted."
try:
result = subprocess.run(
["bq", "query", "--use_legacy_sql=false", "--format=pretty", "--max_rows=50", query],
capture_output=True,
text=True,
check=True
)
return result.stdout
except subprocess.CalledProcessError as e:
return f"EXECUTION ERROR: {e.stderr.strip()}"
5. Pilier d’Ingénierie 3 : Le cycle autonome de correction
Pour la phase 3 du Pilier 3 d’ingénierie, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Imposez une approbation humaine pour les actions qui entraînent des dépenses ou modifient des données de production. La connexion en temps de compilation ne garantit pas la complétude du processus métier. Pour la phase 3 du Pilier 3 d’ingénierie, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un ensemble d’éléments entremêlés.
Trace de production réelle : le cycle d’autoguérison en action
Lorsque vous travaillez sur la trace de production réelle, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’honnêteté des modifications ultérieures du code. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des vérifications de succès et refusez les terminations partielles silencieuses. Créez des points de contrôle après les étapes coûteuses. Le système de reprise ne doit pas facturer à nouveau la même appel du LLM lorsque l’opérateur réessaie un nœud ultérieur.
La question de l’utilisateur métier
Lors de la phase destinée à l’utilisateur métier, notez d’abord le contrat : les données requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de l’environnement de démonstration à des environnements partagés. Faites un point après les étapes coûteuses. Le système de reprise ne doit pas facturer à nouveau la même appel du LLM lorsque l’opérateur réessaie un nœud ultérieur.
Étape 1 : Première tentative et rejet par le compilateur
Lors de la phase de première tentative du Étape 1, notez d’abord les conditions requises : les entrées nécessaires, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’intégrité des modifications ultérieures du code. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Créez des points de contrôle après les étapes coûteuses. Le mécanisme de reprise ne doit pas facturer à nouveau la même appel du LLM lorsque l’opérateur réessaie un nœud ultérieur. Lors de la phase de première tentative du Étape 1, notez d’abord les conditions requises : les entrées nécessaires, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’intégrité des modifications ultérieures du code. Préférez des unités petites et testables plutôt que des scripts complexes. Lorsqu’une étape échoue, l’erreur doit indiquer une seule responsabilité et non un processus embrouillé.
-- Attempt 1: Generated by Agent (Pre-Flight Dry Run)
SELECT
SUM(c.total_spent) AS total_vip_revenue
FROM `enterprise-c360-prod.c360_curated_shopify.dim_customer` c
JOIN `enterprise-c360-prod.c360_curated_shopify.CustomerWarranties` w
ON c.customer_id = w.customer_id;
Étape 2 : Diagnostic autonome et auto-correction
La phase de diagnostic autonome de l’Étape 2 fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définites des vérifications de succès et refusez toute complétion partielle silencieuse. Maintenez l’état du graphe plat et typé. Les blocs imbriqués masquent le fait que tel nœud a écrit telle champ et perturbent la reprise après interruption.
SELECT SUM(c.total_spent) AS total_vip_revenue
FROM `enterprise-c360-prod.c360_curated_shopify.dim_customer` c
JOIN `enterprise-c360-prod.c360_curated_shopify.CustomerWarranties` w
- ON c.customer_id = w.customer_id;
+ ON c.UnifiedCustomerDimId = w.UnifiedCustomerDimId;
Étape 3 : Validation des coûts avant le lancement
La phase de calcul des coûts pré-vol du Étape 3 fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût des jetons ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe d’un environnement de démonstration à des environnements partagés. Gardez l’état du graphique simple et bien typé ; les blocs imbriqués masquent l’identité du nœud qui a écrit tel champ et perturbent la reprise après interruption.
Étape 4 : Exécution bornée et synthèse exécutive
La phase d’exécution bornée de l’Étape 4 fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du graphe. Gardez l’état du graphe plat et typé. Les blocs imbriqués masquent le fait que tel nœud a écrit telle champ et perturbent la reprise après interruption. La phase d’exécution bornée de l’Étape 4 fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’échec doit pointer vers une seule responsabilité plutôt que vers un processus embrouillé.
6. De la CLI en terminal à l’interface web interactive
Pour l’étape 6 « From Terminal CLI », définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définissez des vérifications de succès et refusez toute exécution partielle silencieuse. Faites approuver par un humain les cas où de l’argent est dépensé ou des données de production sont modifiées. Une connexion en temps de compilation ne garantit pas la complétude du processus métier.
Mode 1 : Terminal CLI pour les ingénieurs de données et CI/CD
Pour l’étape CLI du Mode 1 Terminal, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Enregistrez les temps d’exécution ainsi que le coût des jetons ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le parcours passe de l’environnement de démonstration à des environnements partagés. Faites approuver par un humain les actions qui entraînent des dépenses ou modifient des données de production. La configuration en temps de compilation ne garantit pas la complétude du processus métier.
python3 c360_agent/agent.py "Show me top 5 customers by SAP delivery volume in 2026"
Mode 2 : Console de débogage web interactive (adk web)
Pour l’étape Web interactive Mode 2, définissez les entrées, le responsable de l’étape et les critères de sortie avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Mettez en place une approbation humaine pour les actions qui entraînent des dépenses ou modifient des données de production. La connexion en temps de compilation ne garantit pas la complétude du processus métier. Pour l’étape Web interactive Mode 2, définissez les entrées, le responsable de l’étape et les critères de sortie avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un ensemble de processus embrouillés.
adk web --port 8001 c360_agent --reload
Résumé : La liste de contrôle pour l’agent autonome d’entreprise
Lors de la phase du résumé concernant l’agent autonome d’entreprise, notez d’abord les éléments requis : entrées nécessaires, signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’intégrité des modifications ultérieures du code. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des vérifications de succès et refusez toute exécution partielle silencieuse. Créez des points de contrôle après les étapes coûteuses. Le système de reprise ne doit pas facturer à nouveau la même appel du LLM lorsque l’opérateur réessaie un nœud ultérieur.
La trilogie achevée : Les fondations des données d’entreprise modernes
Lorsque vous travaillez sur l’étape « La Trilogie terminée », notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de la démonstration aux environnements partagés. Créez un point de contrôle après les étapes coûteuses. Le système de reprise ne doit pas facturer à nouveau la même appel d’LLM lorsque l’opérateur réessaie un nœud ultérieur.
Liste de contrôle opérationnelle
L’étape de la liste de contrôle opérationnelle fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement exemplaire, un cas d’échec et une note de réversion avant d’élargir le périmètre. Documentez ensemble le parcours optimal et le parcours de récupération. Les tentatives de réessai, les contrôles humains et la gestion des messages non livrés font partie du produit, et non d’une mise en forme ultérieure.
Gardez l’état du graphe plat et typé. Les blocs imbriqués cachent le fait que tel nœud a écrit telle champ et empêchent la reprise après interruption.
Ajoutez un test de base qui met à l’épreuve le chemin critique dans les processus d’intégration continue en utilisant des fixtures, et non des API payantes en temps réel, chaque fois que le budget le permet.
Préférez des unités petites et testables à des scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un pipeline embrouillé.
Gardez l’état du graphe plat et typé. Les blocs imbriqués cachent le fait que tel nœud a écrit telle champ et empêchent la reprise après interruption.