An intelligent, secure, and feature-rich data analysis web application powered by a Gemini ReAct agent. Users can upload CSV files, perform complex mathematical or statistical operations, generate premium interactive Plotly visualizations, and chat with their files in natural language.
The application implements full user authentication (email + password), persistent multi-device sessions, automatic GCS/Firestore cleanups, and a glassmorphic Administrative Control Panel for user and system management.
- Powered by GenAI SDK: Implements the modern
google-genaiclient for prompt processing and tools invocation. - Isolated Subprocess Code Execution: Executes generated Python code in a separate
spawnprocess (via FileSavingLocalCodeExecutor), capturing stdout and generated file artifacts (like Plotly figures) dynamically. System-level sandbox isolation is offloaded to the container layer (Docker/Cloud Run). - Automated Data Profiling (ADK Pre-processing): When a new CSV file is uploaded, the ADK framework automatically triggers an exploration step before the agent begins reasoning. It runs an isolated python script (
explore_df) in the sandbox to extract the data schema, column types, row counts, and preview unique values. This context is automatically injected into the LLM prompt context, allowing the agent to plan and write code correctly on the very first turn.- Session-Scoped Caching: Within the same conversation thread, profiling results are saved in the persistent session state (even across logouts and logins). Subsequent messages instantly reuse this context, bypassing re-execution and eliminating extra LLM queries.
- New Session Separation: For data privacy and security, starting a new chat thread (session) initializes a clean slate. Uploading the same file in a new thread will trigger a one-time profile run to initialize that session's isolated cache.
- Interactive Visualizations: Generates rich dynamic graphics, exporting output directly as interactive Plotly charts rendered seamlessly on the frontend.
- Ephemeral Shareable Dashboards (here.now Integration): With a single click on the "Share" button, users can securely publish their latest analysis insights and accompanying Plotly graphic as a standalone, beautifully styled dashboard. Powered by share_service.py.
- Dynamic Layout Toggling: The shared dashboard provides a responsive layout-toggle button, allowing viewers to switch instantly between a side-by-side Split View and a vertical Stacked View. Plotly charts dynamically resize automatically to occupy optimal visual real estate.
- 24h Expiration & Claim Link: Anonymous shared dashboards expire automatically after 24 hours. The publisher is also provided with a unique Claim URL, allowing them to authenticate on
here.nowto retain, update, password-protect, or delete their shared page.
- Secure Credentials: Hashes and verifies passwords securely using bcrypt.
- JWT Session Tokens: Signs and validates session states using PyJWT (HS256 algorithm) stored locally in browser storage.
- Glassmorphic UI: Beautiful signup and login overlays styled using modern dark-theme glassmorphism and subtle animations.
- Local Developer Mode: Zero-configuration runs utilizing SQLite (
local_users.db) for user credentials and an in-memory session engine. - Production Mode (Hybrid Store):
- Firestore (Native): Stores lightweight user account records and session metadata documents to keep database reads/writes extremely fast.
- GCS Offloading: Large multi-turn conversation event logs (which contain Python code execution strings, base64 file payloads, and data summaries) are saved as type-safe JSON files in Google Cloud Storage (GCS). This completely bypasses Firestore's 1,500-byte Native Mode indexing limit and standard JSON byte serialization errors.
- Complete Workspace & File Recovery: Instantly reconstructs chat history turns, collapsible executed Python code accordions, and fully interactive Plotly graphics when resuming a session.
- No File Resubmission Required: All dataset files uploaded within a session are saved directly inside the persistent session state. When you resume a session, all previously uploaded files are automatically restored to the code execution workspace. You can continue querying them immediately without resubmitting them.
- Multi-File Reasoning: If multiple files are uploaded inside the same session, they are all written to the active workspace environment concurrently, allowing the agent to dynamically select, load, and perform cross-file operations (like SQL-like joins) based on your natural language queries.
- Background FastAPI tasks automatically identify and clean up sessions, artifacts, and GCS storage objects older than 7 days.
- Admins can trigger manual sweeping runs on-demand.
Designate a primary administrator via environment variables to gain access to a dedicated dashboard modal containing:
- Users Portal: Lists all registered accounts, shows registration dates, and supports role promotion or demotion.
- Active Sessions Monitor: Real-time listing of active sessions across the entire system. Allows admins to force-terminate and delete storage artifacts for any session.
- Stats & System Control: Glowing analytics cards (counters for total users, active sessions, admins), database backend details, and manual broom triggers.
ask-your-data/
├── app/ # Core application source
│ ├── app_utils/ # Helpers and database models
│ │ ├── auth_service.py # BCrypt hashing, JWTs, SQLite/Firestore UserStore
│ │ ├── firestore_session.py # Hybrid GCS/Firestore session persistence engine & GCS purging
│ │ ├── share_service.py # Ephemeral here.now sharing client & standalone HTML generator
│ │ ├── telemetry.py # Google Cloud Trace and metrics setup
│ │ └── typing.py # Pydantic telemetry & feedback schemas
│ ├── static/ # Frontend web application assets
│ │ ├── app.js # UI controller, Plotly renderer, Admin/Share API clients
│ │ ├── index.html # Glassmorphic layout, chat panels, admin & share modals
│ │ └── style.css # Custom CSS tokens, animation keyframes, scrollbars
│ ├── agent.py # Agent prompt logic and tools registry
│ ├── fast_api_app.py # FastAPI routing, security dependencies, admin & share endpoints
│ └── local_executor.py # Isolated subprocess code runner (sandbox offloaded to container)
├── tests/ # Automated validation suite
│ ├── eval/ # Systematic evaluation suite (ADK)
│ │ ├── datasets/ # Target evaluation JSON datasets
│ │ └── eval_config.yaml # Custom LLM-as-judge metrics & run settings
│ ├── integration/ # Server and Agent end-to-end tests
│ └── unit/ # Core unit logic tests
├── .env.example # Template for developer configuration
├── agents-cli-manifest.yaml # ADK settings for evaluation and deployment
├── Dockerfile # Build configuration for containerization
├── docker-compose.yml # Host-container port and volume mappings
├── eval_data.csv # Sample database for testing data analysis
├── pyproject.toml # Package declarations and dependencies
└── GEMINI.md # Development workflows
Copy .env.example to .env and adjust the variables:
cp .env.example .env| Key | Description | Default |
|---|---|---|
ENVIRONMENT |
'local' (uses SQLite/in-memory) or 'production' (uses GCS/Firestore) |
local |
JWT_SECRET |
Secret key used to sign JWT authentication tokens | Auto-generated |
ADMIN_EMAIL |
Email address automatically promoted to Administrator role | admin@example.com |
GEMINI_MODEL |
Gemini model name used for processing chat and analysis | gemini-3.5-flash |
GOOGLE_CLOUD_PROJECT |
GCP Project ID (required for Firestore and Vertex AI in production) | your-gcp-project-id |
GOOGLE_CLOUD_LOCATION |
Region location for Vertex API calls | global |
LOGS_BUCKET_NAME |
GCP Storage Bucket name for session file artifacts | your-gcs-bucket-name |
GOOGLE_GENAI_USE_VERTEXAI |
Backend selector: 'True' for GCP Vertex AI, 'False' for Gemini Developer API |
True |
GEMINI_API_KEY |
API Key for Gemini Developer API (required when GOOGLE_GENAI_USE_VERTEXAI=False) |
None |
HERENOW_API_KEY |
Optional here.now API key to publish to a specific user account. If omitted, pages are published anonymously | None |
Ensure you have the following installed:
- uv: Fast Python package manager.
- Google Cloud SDK: For authenticating with Google Cloud services.
Install project dependencies:
uv syncBefore launching the application, you must decide how the agent will communicate with the Gemini LLM. You have two options:
Option 1: Google AI Studio (Gemini Developer API Key) — Recommended for free, zero-config local runs
- Pros: 100% free standard usage; requires no GCP infrastructure or billing setup.
- Setup:
- Generate a free API key from Google AI Studio.
- Add the key to your
.envfile and setGOOGLE_GENAI_USE_VERTEXAItoFalse:GOOGLE_GENAI_USE_VERTEXAI=False GEMINI_API_KEY=AIzaSy...your_key_here
- Pros: Much higher rate limits; production-grade monitoring, trace logging, and IAM security.
- GCP Setup Steps:
- Select or Create a GCP Project: Ensure you have an active Google Cloud project with billing enabled.
- Enable Vertex AI API: Enable the Vertex AI service inside your project:
gcloud services enable aiplatform.googleapis.com --project your-gcp-project-id - Generate Application Default Credentials (ADC): Run the following in your terminal to authenticate your local development machine:
gcloud auth application-default login
- Configure
.env: SetGOOGLE_GENAI_USE_VERTEXAItoTrueand specify your project details:GOOGLE_GENAI_USE_VERTEXAI=True GOOGLE_CLOUD_PROJECT=your-gcp-project-id GOOGLE_CLOUD_LOCATION=global
Run the FastAPI development server:
uv run uvicorn app.fast_api_app:app --reload --host 127.0.0.1 --port 8000Open your browser and navigate to http://127.0.0.1:8000.
- Register a new account.
- If your credentials match
ADMIN_EMAIL, the violet Admin Panel button will become visible in the header. - You can set the admin email in the
.envfile with theADMIN_EMAILvariable on your first time running the application.
To isolate code execution and protect your host machine from untrusted AI-generated Python code:
- Ensure Docker Desktop is running.
- (Only if using Vertex AI backend) Authenticate Google Cloud SDK locally to generate Application Default Credentials (ADC):
Note: Ensure the
gcloud auth application-default login
GOOGLE_CLOUD_PROJECTvariable in your.envmatches the active project ID returned by runninggcloud config get-value projecton your host, otherwise Vertex AI requests will return a 403 Permission Denied error. - Launch the container stack:
docker compose up --build
- Access the interface at
http://localhost:8000. The application and all Python code executed by the agent will run isolated inside the container. Your host machine files and processes are fully protected.
The application's Dockerfile implements a highly optimized Multi-Stage Build designed for rapid local developer rebuilds, secure non-root runtime permissions, and a minimal production storage footprint:
# Stage 1: Build virtual environment
FROM python:3.12-slim AS builder
# OPTIMIZATION 1: Instant binary copy instead of pip install
COPY --from=ghcr.io/astral-sh/uv:0.8.13 /uv /uvx /bin/
# OPTIMIZATION 3: Disable bytecode compilation to reduce image footprint.
# - PRO: Saves ~320MB of storage in GCP Artifact Registry (helps stay within/close to the 500MB free tier).
# - CON: Increases container cold start latency by 1-2s as Python compiles modules to bytecode in-memory on startup.
# Set UV_COMPILE_BYTECODE=1 to trade registry storage for faster container startup in production.
ENV UV_COMPILE_BYTECODE=0 \
UV_LINK_MODE=copy
WORKDIR /code
# Copy package config files
COPY ./pyproject.toml ./uv.lock* ./README.md ./
# OPTIMIZATION 2: Cache mount ensures blazing-fast local iterations
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev --no-editable
# Stage 2: Final minimal runtime image
FROM python:3.12-slim AS runner
# Production logging optimization for GCP Cloud Logging
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PATH="/code/.venv/bin:$PATH"
WORKDIR /code
# OPTIMIZATION 4: Security Hardening (Non-root user for GCP)
# Create appuser first so we can copy files with correct ownership
RUN useradd -m -u 8888 appuser && chown appuser:appuser /code
# Copy the virtual environment from the builder stage with correct ownership
COPY --chown=appuser:appuser --from=builder /code/.venv /code/.venv
# Copy the application source code with correct ownership
COPY --chown=appuser:appuser ./app ./app
USER appuser
ARG COMMIT_SHA=""
ENV COMMIT_SHA=${COMMIT_SHA}
ARG AGENT_VERSION=0.0.0
ENV AGENT_VERSION=${AGENT_VERSION}
EXPOSE 8080
CMD ["uvicorn", "app.fast_api_app:app", "--host", "0.0.0.0", "--port", "8080"]-
Optimization 1: Direct Binary Copy of
uv- The Issue: Standard Dockerfiles use
pip install uv, which performs an external python network request, dependency checks, and setups on every Docker cache miss. - The Fix: We copy the precompiled rust-based binary directly from the official
ghcr.io/astral-sh/uvimage (COPY --from=ghcr.io/astral-sh/uv...). This is instantaneous, has zero python environment setup overhead, and runs in milliseconds.
- The Issue: Standard Dockerfiles use
-
Optimization 2: BuildKit Cache Mounts (
--mount=type=cache)- The Issue: Adding a new package to
pyproject.tomlnormally invalidates Docker's cached layers, forcinguvorpipto re-download every single library from scratch during build time. - The Fix: We mount a persistent cache directory
target=/root/.cache/uvduring the package installation step. Docker Desktop/engine preserves this cache across builds on the host. When you add a new library, only the new library is fetched, reducing rebuild times from ~1 minute to ~2 seconds.
- The Issue: Adding a new package to
-
Optimization 3: Disabling Bytecode Compilation (
UV_COMPILE_BYTECODE=0)- The Trade-Off: We configured
UV_COMPILE_BYTECODE=0to balance storage footprint versus initial execution latency:- PRO (Storage / Cost): Disabling bytecode compilation saves roughly 320 MB of registry and disk space, shrinking the final image from
1.21 GBto884 MB. This is critical for staying within or close to the GCP Artifact Registry free storage tier (500 MB). - CON (Cold Start Latency): Disabling compilation adds a small 1–2 second overhead to the container cold-start time because Python has to compile modules to bytecode in-memory on application startup.
- Production Tuning: If minimizing cold-start latency is a higher priority than registry storage costs, set
UV_COMPILE_BYTECODE=1in the Dockerfile.
- PRO (Storage / Cost): Disabling bytecode compilation saves roughly 320 MB of registry and disk space, shrinking the final image from
- The Trade-Off: We configured
-
Optimization 4: Security Hardening & Permission Alignment
- Non-Root Execution: Running containers as
rootexposes the host system to vulnerabilities. We create a dedicated non-root userappuser(UID8888) and switch execution toUSER appuser. - SQLite and Workspace Permission Requirements:
- In-memory agent frameworks (like ADK) and SQLite databases require a writable working directory. SQLite needs to create temporary transaction journal files (e.g.,
local_users.db-journalorlocal_users.db-wal) in the parent directory where the.dbfile resides. - To support this securely, we pre-assign the parent
/codedirectory to the non-root user:chown appuser:appuser /codeBEFORE we copy files. - When copying files from the builder or host, we use
COPY --chown=appuser:appuser. This assigns correct permissions during file transfer, entirely avoiding expensive recursivechown -R appuser:appuser /codecalls which delay the build process by processing thousands of virtualenv files.
- In-memory agent frameworks (like ADK) and SQLite databases require a writable working directory. SQLite needs to create temporary transaction journal files (e.g.,
- Non-Root Execution: Running containers as
The codebase includes comprehensive unit and integration tests (validating session life cycles, security parameters, and role-based access).
Run the tests locally:
uv run pytestThe application includes a systematic evaluation suite built using the ADK (Agent Development Kit) CLI (agents-cli). While standard integration tests assert API and route logic, the evaluation suite measures the actual behavior of the AI Data Analyst agent (its code execution logic, Plotly visualization generation, response quality, and guardrails).
Evaluation cases are located in tests/eval/datasets/basic-dataset.json. It currently defines four distinct scenarios testing different aspects of the agent:
greeting: Tests if the agent introduces its capabilities properly.weather_query: Tests agent guardrails—verifying it declines live real-time queries and suggests analyzing uploaded data instead.data_analysis_summary: Tests pandas code execution by asking the agent to read eval_data.csv and compute total sales per category.data_analysis_plot: Tests Plotly generation by asking the agent to generate and write a categorized sales bar chart toplotly_chart.json.
Running evaluations requires the enterprise Vertex AI backend (GOOGLE_GENAI_USE_VERTEXAI=True) and Application Default Credentials (ADC) for the following reasons:
- API Key Quota Limits: The Gemini Developer API (AI Studio) Free Tier enforces a strict quota of 20 requests per day for models. The multiple model calls required to run the agent plus the LLM-as-Judge evaluations will quickly exhaust this limit. Vertex AI provides much higher limits suitable for testing loops.
- Region Routing: Configured as
region: "global"in agents-cli-manifest.yaml to ensure Vertex AI routes request parameters to the global routing gateway where the agent's defaultgemini-3.5-flashmodel is fully available. - Environment Key Conflicts: If
GOOGLE_API_KEYorGEMINI_API_KEYis present in your shell environment, the Google GenAI SDK will try to authenticate using API keys, causing401 UNAUTHENTICATEDerrors on Vertex AI. The app automatically cleanses these conflicting environment variables at runtime to ensure ADC is utilized.
Before running evaluations, ensure you are authenticated locally on your host:
gcloud auth application-default loginTo run the full evaluation loop (inference + grading) in a single command, run:
agents-cli eval run --dataset tests/eval/datasets/basic-dataset.json --config tests/eval/eval_config.yamlAlternatively, you can run them as two discrete steps:
- Generate Traces: Execute the agent over the dataset and record action traces (e.g. executed code and intermediate events):
Traces are saved locally in the
agents-cli eval generate --dataset tests/eval/datasets/basic-dataset.jsonartifacts/traces/directory. - Grade Traces: Run the LLM-as-Judge evaluation on the traces:
Results are saved as JSON and HTML files in
agents-cli eval grade --config tests/eval/eval_config.yamlartifacts/grade_results/(e.g.,results_<timestamp>.html).
You can compare current results against a baseline to check for regressions:
agents-cli eval compare artifacts/grade_results/baseline.json artifacts/grade_results/results_<ts>.jsonTo add a new scenario, append a case object to the eval_cases array in basic-dataset.json:
{
"eval_case_id": "your_custom_scenario",
"prompt": {
"role": "user",
"parts": [{"text": "Read eval_data.csv. Calculate the average sales."}]
}
}Evaluations are graded using custom LLM-as-judge metrics defined in eval_config.yaml.
Custom criteria are written as Python functions in the config file. For example, our custom_response_quality metric parses the trace, extracts the prompt and the agent's final text response, and formats a detailed grading prompt for a judge model (gemini-3.5-flash-lite):
custom_metrics:
- name: custom_response_quality
custom_function: |
def evaluate(instance):
# Extract prompt & final response from the agent_data trace
# ...
judge_prompt = """Evaluate the agent's response from 1 to 5:
1 (Poor): Fails to address the query.
5 (Excellent): Comprehensive and flawlessly accurate.
User Prompt: {prompt}
Final Response: {final_resp}
Return JSON: {"score": <int>, "explanation": "<str>"}
"""
# Invoke client.models.generate_content to score the response
# Return {"score": score, "explanation": explanation}You can add more custom metrics under the custom_metrics key and list them under metrics_to_run to run them during evaluation.
The application features built-in distributed tracing using OpenTelemetry (OTel), which exports request traces, agent executions, and model calls to Google Cloud Trace (Trace Explorer).
When you interact with the agent, the backend generates a hierarchy of spans:
fast_api_request(The root HTTP request)agent_run(The ADK agent logic)call_llm(Gemini API prompts and completions)execute_tool(Python sandbox execution steps)
You can route traces from your local environment (host execution or container) to your Google Cloud Trace Explorer before deploying:
- Enable the Cloud Trace API in your GCP project console or via terminal:
gcloud services enable cloudtrace.googleapis.com --project your-gcp-project-id - Generate Application Default Credentials (ADC) on your local machine:
gcloud auth application-default login
Set the following variables in your .env file:
GOOGLE_CLOUD_PROJECT=your-gcp-project-id
ENABLE_CLOUD_TRACE=True- Spin up the application (either standard
uv run uvicorn...or containerizeddocker compose up --build). - Ask the agent a question in the chat UI.
- Open the Google Cloud Console Trace Explorer.
- Select your project (
GOOGLE_CLOUD_PROJECT) and you will see waterfall latency/execution charts for every local run, letting you debug bottlenecks or tool failures in real-time.
To temporarily turn off local tracing to the cloud, set ENABLE_CLOUD_TRACE=False in your .env.
The application is deployed on Google Cloud Run using a fully automated GitOps CI/CD pipeline and Infrastructure-as-Code (IaC) via Terraform.
We provisioned a production environment inside your GCP project consisting of:
- Google Cloud Run Service: Runs the containerized FastAPI backend and ReAct agent securely.
- Google Artifact Registry: Stores the compiled and optimized production Docker images.
- Google Cloud Storage (GCS) Bucket: Stores session events and file artifacts, enabling complete workspace state recovery and bypassing the Firestore 1,500-byte index limit for large fields.
- Google Firestore (Native Mode): Houses lightweight user authentication details and session metadata.
- Google Secret Manager: Securely stores the production
JWT_SECRETand any optional API keys. - Google Cloud Trace: Exports and monitors live traces (latency, LLM calls, sandbox steps) in real-time.
- Workload Identity Federation (WIF): Authorizes GitHub Actions workflows to build and deploy to GCP without storing long-lived credentials (like JSON service account keys) in repository secrets.
The infrastructure is declared in deployment/terraform/single-project. To provision or update these resources:
- Initialize Terraform:
terraform -chdir=deployment/terraform/single-project init
- Review plans and apply configuration (replace
<YOUR_PROJECT_ID>with your project):terraform -chdir=deployment/terraform/single-project apply -var="project_id=<YOUR_PROJECT_ID>"
Continuous integration and delivery is handled by .github/workflows/deploy-to-prod.yaml.
Whenever code is pushed to the main branch:
- Triggers: Runs on updates to app files, the Dockerfile, or dependencies.
- Authentication: Uses OIDC to login to GCP using the configured Workload Identity Provider.
- Build: Compiles a production Docker image using our multi-stage BuildKit optimizations.
- Register: Pushes the image to Google Artifact Registry.
- Deploy: Deploys the new container version using
google-agents-cli deployto Cloud Run.
If you want to deploy the application manually from your local terminal:
gcloud config set project <YOUR_PROJECT_ID>
uv run agents-cli deploy- Production URL: The live application is hosted on Google Cloud Run.
- Automated Environment Selectors: Accessing the production domain automatically locks the frontend's runtime selector to Deployed Agent (Cloud) and disables selection of the local subprocess runtime.
- Secure Session Handling: Conversations and large data summaries are saved as type-safe JSON objects directly inside GCS. Old files and sessions are automatically cleaned up after 7 days by the FastAPI background cleanup service.
- Cloud Observability: Requests, execution chains, and Vertex AI latency figures are visible under the GCP Trace Explorer portal.
This application was developed and optimized using the google-agents-cli framework and its associated developer skills. By leveraging the standardized workflow, scaffolding, and operational patterns, the project directly benefits from several key architectural choices.
The google-agents-cli framework provides a collection of curated, developer-centric skills that guide development from initial architecture through deployment and monitoring:
google-agents-cli-scaffold: Automates project creation, environment configuration, and dependency setup, establishing consistent module structures and evaluation frameworks.google-agents-cli-adk-code: Defines standard API patterns, callback contexts, tool registries, custom code execution hooks, and state persistence guidelines.google-agents-cli-eval: Establishes programmatic testing methodologies using LLM-as-judge configs to validate non-deterministic agent trajectories.google-agents-cli-deploy: Coordinates infrastructure provisioning (Terraform) and GitOps CI/CD pipelines targeting Google Cloud (Cloud Run, Artifact Registry, Secret Manager).google-agents-cli-observability: Guides distributed OpenTelemetry tracing and prompt-response logging integration.
The application’s codebase incorporates several design decisions inspired directly by these skills:
- Skill Reference:
google-agents-cli-adk-code&google-agents-cli-workflow - Implementation: In FileSavingLocalCodeExecutor, we set the property
optimize_data_file = True. - How it Works: When a new CSV file is uploaded, the ADK framework intercepts the request and automatically triggers a localized profiling script (
explore_df) in the executor environment before the first LLM request. It runs pandas inspection operations (schema, column types, row counts, unique value samples) and injects this structure directly into the model's system context. This allows the Gemini model to write syntactically correct code blocks on the very first turn without having to query the file structure manually, saving round-trip latencies. - Caching & Separation: Within a session, profiling is run exactly once and cached inside FirestoreSessionService's
_code_executor_input_files. Submissions in a new session or thread enforce isolated directory states, triggering a fresh profiling run for data privacy.
- Skill Reference:
google-agents-cli-adk-code - Implementation: To support Plotly graphics generation and local file outputs, we bypassed ADK's restricted
BuiltInCodeExecutorin favor of a custom FileSavingLocalCodeExecutor. This executor executes code in a separate Pythonspawnprocess context on the server, redirectingstdoutand capturing newly generated workspace files. Because a subprocess itself does not prevent malicious actions on the host, sandbox security is achieved at the containerization layer (using Docker for local runs, and Google Cloud Run for production) to fully isolate and protect host systems.
- Skill Reference:
google-agents-cli-adk-code - Implementation: This skill covers writing custom code executors, creating callbacks (like our history sanitization). In app/agent.py, the clean_history_callback function acts as an interceptor before each LLM call. It parses executable code calls and code execution results, reformats them as standard markdown blocks, and strips out
thoughtSignatureparameters. This prevents Gemini API key authorization errors caused by mutating cryptographic signatures in multi-turn chat sessions.
- Skill Reference:
google-agents-cli-eval - Implementation: Standard local web requests initialize the frontend artifact services automatically. However, offline operations (like
agents-cli eval generate) run without a web context. We implemented init_agent_callback to detect empty contexts and injectInMemoryArtifactServiceon-the-fly, preventing evaluation crashes.
- Skill Reference:
google-agents-cli-eval - Implementation: Rather than asserting model text output structure inside flaky pytest test cases, we maintain a programmatic evaluation suite under tests/eval/eval_config.yaml. Traces generated from standard dataset runs are graded using customizable LLM-as-judge functions, scoring criteria (e.g. response quality, chart accuracy), and providing regression comparisons in HTML format.
- Skill Reference:
google-agents-cli-observability - Implementation: The setup_telemetry function sets up OpenTelemetry (OTel) parameters, exporting spans for fast API requests, agent runs, LLM calls, and code execution. It also configures prompt-response logging metadata to export logs directly to a designated GCP Storage Bucket, allowing monitoring inside the Google Cloud Trace Portal.
