Gemini 3 API Tutorial: Automating Data Analysis With Gemini 3 Pro and LangGraph
Build a multi‑agent workflow powered by Gemini 3 API to take a dataset, analyze it, generate insights, and produce a complete PDF report automatically.
Gemini 3 Pro is the state-of-the-art AI model we have all been waiting for, featuring a massive one-million-token context window that effortlessly handles datasets, documents, videos, and codebases in a single pass. It delivers PhD-level reasoning while excelling at multimodal processing of text, images, audio, and video for seamless creative workflows.
In this project-based tutorial, I will show you how to use the Gemini 3 API to build multi-agent applications that use a CSV dataset provided by the user and perform deep data analytics.
In short, the multi-agent app will perform:
Simple analytics: Quickly explore the dataset structure and basics.
Code generation: Use Gemini 3 Pro to create advanced analysis code with visualizations.
Secure execution: Run the code in a sandboxed environment and save results.
Intelligent reasoning: Analyze and interpret findings for key insights.
PDF report compilation: Generate a polished PDF with visuals and clear explanations, insights graspable in seconds.
google-generativeai: Access Gemini 3 Pro via the official API.
langgraph: Orchestrate multi-agent AI workflows with ease.
langsmith: Track runs, monitor performance, and debug with interactive dashboards.
grandalf: Visualize agent graphs as clean ASCII diagrams.
pydantic: Manage shared graph states with robust data validation.
pandas: Perform quick dataset exploration and analysis.
matplotlib: Generate stunning data visualizations.
markdown2: Convert Markdown to HTML for rich report formatting.
weasyprint: Transform HTML/CSS into professional PDF reports.
markdown-it-py: Advanced Markdown parser for complex formatting.
mdit-py-plugins: Extend markdown-it-py with plugins for tables, footnotes, and more.
Note: We are using Jupyter Notebook to build this project.
2. Go to Google AI Studio and generate your API key. Make sure you have billing set up on your account, as the Gemini 3 Pro model is not available in the free tier.
3. Next, create a free LangSmith account and generate the API key.
4. Save both API keys as environment variables in your local system. Set LANGSMITH_API_KEY and GEMINI_API_KEY.
5. Import all the necessary Python packages in your notebook:
from google import genai
from google.genai import types
from pydantic import BaseModel
from langgraph.graph import StateGraph, END
import os, json, textwrap, traceback
from pathlib import Path
import pandas as pd
import markdown2
import weasyprint
In this section, we will set up a Gemini API client and wrap calls to the model so they can be traced and logged in LangSmith. Additionally, we will extract token usage metadata and return it in a LangSmith-friendly format.
First, we will initialize the Gemini GenAI client by providing the API key:
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
MODEL ="gemini-3-pro-preview"
Next, we will write a small wrapper around a Gemini model call to enable automatic tracing by LangSmith. Using the @traceable decorator, we register the function as an LLM run.
Within this function, the code will send the prompt to Gemini and extract token usage details, which are essential for accurate LangSmith tracking, following the tracing guidelines.
Finally, the function will return the model’s text output along with token statistics and the raw response in the format that LangSmith expects, ensuring that the run is displayed accurately in the UI.
3. Building Tools for the Multi-Agent Gemini 3 Workflow
We will now create tools that provide dataset inspection, safe Python execution, and Markdown‑to‑PDF report generation that will be used inside an AI agent workflow.
Tool 1: Load dataset
This tool takes a file path, reads the CSV into a pandas DataFrame using, and then builds a summary containing the dataset shape, column names, each column’s data type, missing‑value percentages, the first five rows, and full descriptive statistics. It returns this summary so an agent can quickly understand the dataset.
defload_dataset(path:str):
df = pd.read_csv(path)
summary ={"shape": df.shape,"columns":list(df.columns),"dtypes":{c:str(t)for c, t in df.dtypes.items()},"missing_pct": df.isna().mean().to_dict(),"head": df.head(5).to_dict(orient="records"),"describe": df.describe(include="all").fillna("").to_dict()}return summary
This tool safely runs dynamically generated Python code inside a restricted environment. It prepares a small local environment, then executes the provided code with exec.
The executed code is expected to return artifact paths (like saved plots) and metadata.
defrun_python(code:str):"""
Generated code MUST:
- save plots to ARTIFACTS_DIR
- collect paths in _artifacts (list[str])
- collect meta in _charts_meta (list[dict])
- optionally set _stdout (string)
"""
local_env ={"ARTIFACTS_DIR": ARTIFACTS_DIR}try:exec(textwrap.dedent(code),{}, local_env)return{"ok":True,"stdout": local_env.get("_stdout",""),"artifacts": local_env.get("_artifacts",[]),"charts_meta": local_env.get("_charts_meta",[]),}except Exception:return{"ok":False,"traceback": traceback.format_exc()}
This tool converts Markdown into a nicely formatted PDF. It first builds a markdown parser that supports tables, lists, task lists, and footnotes.
Then render_pdf converts the markdown text into HTML, wraps it in a custom CSS‑styled template (controlling fonts, table appearance, image sizing, etc.), and uses WeasyPrint to generate a PDF file.
Finally, it saves the PDF into the artifacts folder and returns the path.
This class defines a shared state object that holds everything the agent workflow produces: like the dataset path, profiling info, generated plan, code, execution results, insights, and final report, plus retry limits and error messages to prevent infinite loops.
We will now create AI agents that will work together to profile the dataset, write and execute analysis code, generate insights, and produce a final PDF report.
Agent 1: Data profiler and planner
This agent is responsible for understanding the dataset and creating a structured analysis plan. It first loads the dataset using the load_dataset tool, which gives it a summary containing shapes, missing values, column types, descriptive stats, and example rows.
Then it sends this dataset summary to the LLM with very explicit instructions: identify the task type, select a target column if applicable, decide what exploratory steps should be taken, propose the charts that should be generated, and outline any modeling steps if the dataset suggests classification or regression.
The LLM returns a JSON structure representing this plan, and the agent parses it, falling back to storing raw text if JSON parsing fails.
Finally, it saves both the dataset profile and the generated plan into the shared state so the next agents have all the information they need.
@traceable(name="profiler_agent")defprofiler_agent(state: State):
profile = load_dataset(state.dataset_path)
prompt =f"""
You are the Data Profiler Agent.
Produce a JSON analysis plan with:
- task_type: "classification"|"regression"|"eda_only"
- target_column (if any)
- eda_steps (list)
- charts_to_make (list) # 5-10 max, most informative
- baseline_model_steps (list if modeling)
- risks_or_data_issues (list)
Dataset profile:
{json.dumps(profile, indent=2)}
"""
resp = gemini_call(prompt, thinking_level="high")
text = resp["generations"][0]["text"]try:
plan = json.loads(text)except:
plan ={"raw_plan": text}
state.profile = profile
state.plan = plan
return state
This agent converts the analysis plan into executable Python code. It receives the dataset profile, the plan, and any previous execution error. Using all that context, it asks the LLM to output only Python code.
The prompt includes strict requirements: load the dataset, follow the plan exactly, generate each specified chart, save plots into ARTIFACTS_DIR, track paths and chart metadata, capture console output, close figures after saving, and optionally compute modeling metrics.
This ensures the code is reproducible and safe in the sandbox. The result is stored in state.code, ready for the executor to run.
@traceable(name="code_writer_agent")defcode_writer_agent(state: State):
prompt =f"""
You are the Code Writer Agent.
Write Python code ONLY (no markdown).
Previous error to fix (if any):
{state.last_error}
HARD REQUIREMENTS:
1. Load dataset from: {state.dataset_path}
2. Follow the plan exactly.
3. Create ALL charts in charts_to_make.
4. Save every chart in ARTIFACTS_DIR with filenames like:
ARTIFACTS_DIR / "chart_01_<short_name>.png"
5. Track saved plot paths in _artifacts (list[str]).
6. Track chart metadata in _charts_meta (list[dict]) with:
{{
"title": "<human readable chart title>",
"filename": "artifacts/chart_01_x.png",
"description": "<what this plot shows (1-2 sentences)>",
"one_liner": "<ONE line insight from the chart>"
}}
The one_liner MUST be a single sentence, max ~20 words.
7. Store useful console output in _stdout.
IMPORTANT:
- import matplotlib.pyplot as plt
- plt.close() after saving each plot
- ensure _artifacts and _charts_meta exist even if empty
- if modeling, add baseline metrics to _stdout
Dataset profile:
{json.dumps(state.profile, indent=2)}
Analysis plan:
{json.dumps(state.plan, indent=2)}
Return ONLY executable python code.
"""
resp = gemini_call(prompt, thinking_level="high")
state.code = resp["generations"][0]["text"]return state
This agent runs the Python code produced by the Code Writer using the isolated run_python sandbox. It captures execution results, chart metadata, standard output, and any artifacts created.
If the code runs successfully, the results are stored and the workflow proceeds normally. If it fails, the agent increments the retry counter and stores the traceback so the Code Writer agent can fix the error on the next attempt.
With MAX_RETRIES limiting the loop, this agent prevents infinite cycling and provides the feedback signals needed for self‑correction.
@traceable(name="executor_agent")defexecutor_agent(state: State):
result = run_python(state.code)
state.exec_result = result
state.charts_meta = result.get("charts_meta",[])ifnot result["ok"]:
state.retry_count +=1
state.last_error = result.get("traceback","Unknown error")return state
This agent interprets the entire analysis. It takes the dataset profile, execution output, and the chart metadata, and produces human‑readable analytical insights.
It instructs the LLM to generate structured insights: for each chart, produce two takeaways and one risk, then generate a limited set of overall insights.
The agent must ensure no empty bullets, no repeated points, and insights must be specific to the dataset, not generic.
The resulting insight report is stored in state.insights, becoming an input for the final reporting stage.
@traceable(name="insights_agent")definsights_agent(state: State):
prompt =f"""
You are the Insights Agent.
HARD REQUIREMENTS:
- No empty bullets.
- No repeated bullets.
- Be specific to this dataset and these charts.
- Output format:
### Chart Insights
For each chart in charts_meta:
- **<title>**
- Takeaway 1 (one sentence)
- Takeaway 2 (one sentence)
- Caveat/Risk (one sentence)
### Overall Insights
- 3-5 bullets max, each one sentence.
Inputs:
Profile:
{json.dumps(state.profile, indent=2)}
Execution result:
{json.dumps(state.exec_result, indent=2)}
Charts meta:
{json.dumps(state.charts_meta, indent=2)}
"""
resp = gemini_call(prompt, thinking_level="high")
state.insights = resp["generations"][0]["text"]return state
This is the final synthesis agent. It uses the complete pipeline outputs: profile, insights, chart metadata, execution logs, and crafts a full, clean Markdown report.
The prompt forces strict formatting rules: no repeated titles, consistent spacing, every chart displayed exactly once in a standardized HTML block, and insights integrated cleanly.
Once the Markdown is produced, the agent calls render_pdf to convert it into a polished PDF using WeasyPrint. Both the Markdown and the PDF path are stored in the shared state, completing the analysis workflow.
@traceable(name="report_agent")defreport_agent(state: State):
prompt =f"""
You are the Report Agent.
Create a neat Markdown report (HTML allowed).
HARD REQUIREMENTS:
- Do NOT repeat section titles or chart titles.
- Do NOT output empty bullet points. If a bullet would be empty, skip it.
- Keep spacing consistent: one blank line between sections.
- Use charts_meta as the ONLY source of charts.
- Include EVERY chart, exactly once, in the same order as charts_meta.
- For each chart output EXACTLY this block:
<div class="chart-block">
<h3>Chart {{i}}: {{title}}</h3>
<img src="{{filename}}" alt="{{title}}">
<p><b>What it shows:</b> {{one_liner}}</p>
</div>
Where:
- title, filename, one_liner come from charts_meta
- one_liner must be ONE sentence, max ~20 words.
Sections:
1. Dataset Overview (short)
2. Data Quality Notes (bullets)
3. Exploratory Analysis (chart-by-chart blocks only, no extra chart titles)
4. Modeling Results (if any; use a markdown table)
5. Key Insights (use insights text)
6. Recommendations / Next Steps (bullets)
Inputs:
Profile: {json.dumps(state.profile, indent=2)}
Exec stdout: {state.exec_result.get("stdout","")}
Exec ok: {state.exec_result.get("ok")}
Traceback (if any): {state.exec_result.get("traceback","")}
Charts meta:
{json.dumps(state.charts_meta, indent=2)}
Insights:
{state.insights}
Return ONLY the Markdown report.
"""
resp = gemini_call(prompt, thinking_level="low")
state.report_md = resp["generations"][0]["text"]
state.report_pdf = render_pdf(state.report_md)return state
This final step involves constructing the complete multi-agent workflow by assembling all agents into a state-driven graph.
A StateGraph is created using a shared State model, ensuring that every agent interacts with the same evolving state object as the workflow progresses. Each component, such as the profiler, code writer, executor, insights writer, and report builder, is added to the graph as a distinct node, representing a specific stage in the pipeline.
The workflow always starts with the profiler agent, which is designated as the entry point. This ensures that the process begins with a thorough understanding of the dataset and the generation of an analysis plan.
Edges are established to define the flow of the process. After profiling, the output is directed to the code writer, which then feeds into the executor. The key logic lies in the conditional routing from the executor.
A helper function, retry_or_continue, examines the execution result. If the code executes successfully, the workflow proceeds to the insights agent.
If it fails but still has retries available, it loops back to the code writer for automatic correction.
If there are no retries left, it bypasses further analysis and moves directly to the report generator, ensuring that the system does not enter an endless loop. The conditional edges are incorporated into the executor node so that the workflow can adapt based on the success or failure of execution.
Finally, the graph connects the insights stage to the report stage, and from the report stage to the conclusion of the workflow. The graph is then compiled into an executable structure, and an ASCII diagram is generated to visualize the flow.
This multi-agent graph orchestrates the entire adaptive analysis pipeline, enabling error recovery, step-by-step coordination, and smooth transitions between agents.
7. Running the Full Gemini 3 API Data Analysis Pipeline
To run the full pipeline, you simply provide a dataset path, create an initial State object, and invoke the compiled graph. In our case, we are providing it with the Boston Housing dataset.
DATASET_PATH ="/work/housing.csv"# <-- change this
state = State(dataset_path=DATASET_PATH)
out = graph.invoke(state)
Once invoked, the multi‑agent system automatically performs the entire analysis: profiling the dataset, generating a plan, writing and executing Python code, extracting insights, and producing both a Markdown and a PDF report.
--- Modeling Baseline Results ---
Dataset Shape:(489,4)
Linear Regression -> RMSE:82,395.54, R2:0.6911
Random Forest -> RMSE:56,931.38, R2:0.8525
Observations: Random Forest typically outperforms Linear Regression due to capturing non-linear relationships (e.g., LSTAT).
After the run finishes, you can open your LangSmith dashboard and navigate to the “autolab-gemini3pro” project. Every agent run appears there.
Clicking on the recent run and switching to the Waterfall view displays the timeline of each step: how long the agents took and which tools they used.
You can click into any agent to inspect:
The prompt it received
The exact model generation
Tool execution details
Returned artifacts, charts, and traces
LangSmith was instrumental in improving the entire workflow. What you see is the final version, but it took many tries to get this project right, and Langsmith helped me debug the issues in the agents.
8. Display Report Markdown and PDF
Once the multi‑agent workflow completes, you can directly inspect the generated Markdown report inside your notebook.
The Markdown version is useful for quickly reviewing the analysis, reading insights, and examining the report structure without leaving your workspace.
# Housing Price Analysis Report## 1. Dataset Overview
The dataset consists of **489 records**and**4 features** focusing on housing metrics. The target variable is `MEDV` (Median Value of owner-occupied homes). The features include `RM` (average number of rooms), `LSTAT.............ขับเคลื่อนโดย
In addition to the Markdown, the workflow also produces a polished PDF report. The PDF is saved automatically in the artifacts folder, and you can view the path like this:
The generated PDF is perfect and contains all key components of the analysis: narrative explanations, visually rendered charts, chart interpretations, modeling summaries, and final recommendations.
This makes it ideal for sharing with teammates, supervisors, or clients, especially when you want a clean, presentation-ready version of the results.
Final Thoughts
Working on this project made it clear just how far modern AI models and graph‑based agent workflows have evolved. Not long ago, building even a single agent with multiple tools required days of tuning, debugging, and dealing with unpredictable behaviors.
Today, with models like Gemini 3 Pro, the system can understand the dataset, generate accurate code, run analyses, interpret visualizations, and assemble a polished report with remarkable reliability.
In this project, we have built a complete multi‑agent data‑analysis application capable of taking any CSV dataset, performing end‑to‑end exploratory analysis, running baseline models, generating insights, and producing a fully formatted PDF report.
This project uses five coordinated agents: profiling & planning, code generation, execution with retries, insights generation, and reporting, and three core tools for dataset loading, safe code execution, and Markdown‑to‑PDF rendering.
The result is a clean, automated analysis flow that produces a professional, narrative‑driven report supported by visualizations.
Gemini 3 API FAQs
What is the context window size of the Gemini 3 API?⌄
The Gemini 3 API supports a context window of up to approximately one million tokens, enabling it to process large datasets, long documents or full codebases in a single call. Monitoring token usage is still recommended to control cost and avoid truncation.
How does the thinking_level parameter affect Gemini 3 API performance?⌄
The thinking_level parameter controls reasoning depth versus speed and cost in the Gemini 3 API. Setting it to high triggers more thorough reasoning (ideal for complex workflows), while low prioritises faster responses and lower token consumption.
What are the pricing and rate limit details for the Gemini 3 API?⌄
Gemini 3 Pro uses token-based billing: you pay for both input and output tokens. Larger prompts or multimodal inputs raise token counts and cost more. Rate limits vary by account tier, so tracking usage and setting alerts is essential for production environments.
Which input formats are supported by the Gemini 3 API?⌄
The Gemini 3 API supports multiple input formats—text, images, audio, and video—enabling true multimodal reasoning. You can mix formats (for example, a dataset plus a chart image), but non-text inputs typically consume more tokens, so plan accordingly.
What are the key limitations of the Gemini 3 API and how should I manage them?⌄
While the Gemini 3 API is very capable, it still faces practical limits: large contexts can increase latency and cost, and model outputs may require human validation. Sensitive data should not be sent without compliance checks, and generated code or analyses should be sandboxed before deployment.
As a certified data scientist, I am passionate about leveraging cutting-edge technology to create innovative machine learning applications. With a strong background in speech recognition, data analysis and reporting, MLOps, conversational AI, and NLP, I have honed my skills in developing intelligent systems that can make a real impact. In addition to my technical expertise, I am also a skilled communicator with a talent for distilling complex concepts into clear and concise language. As a result, I have become a sought-after blogger on data science, sharing my insights and experiences with a growing community of fellow data professionals. Currently, I am focusing on content creation and editing, working with large language models to develop powerful and engaging content that can help businesses and individuals alike make the most of their data.
Build a production-ready app with Gemini 3.1 Pro and master the Gemini CLI, custom skills, context and memory control, testing, and Vercel deployment step by step.
Google's Managed Agents let you deploy autonomous agents with a single API call. Learn how to build one that analyzes data, runs Python, and generates charts.
Discover how Google's newest specialized reasoning model can accelerate your data science workflows, interpret complex datasets, and write robust code.
Learn how to automate data extraction from emails and PDFs using Google Apps Script and the Gemini API. Build a serverless pipeline to Google Sheets today.
Gemini 3 Pro is the state-of-the-art AI model we have all been waiting for, featuring a massive one-million-token context window that effortlessly handles datasets, documents, videos, and codebases in a single pass. It delivers PhD-level reasoning while excelling at multimodal processing of text, images, audio, and video for seamless creative workflows.
In this project-based tutorial, I will show you how to use the Gemini 3 API to build multi-agent applications that use a CSV dataset provided by the user and perform deep data analytics.
In short, the multi-agent app will perform:
If you're keen to learn more about building agentic AI workflows, I recommend checking out our guide to Google Antigravity, Gemini 3 Flash tutorial, and the AI Agent Fundamentals skill track.
1. Setting Up the Gemini 3 API Environment
1. Run this command to install all required packages for our multi-agent app:
Package Breakdown:
Note: We are using Jupyter Notebook to build this project.
2. Go to Google AI Studio and generate your API key. Make sure you have billing set up on your account, as the Gemini 3 Pro model is not available in the free tier.
3. Next, create a free LangSmith account and generate the API key.
4. Save both API keys as environment variables in your local system. Set
LANGSMITH_API_KEYandGEMINI_API_KEY.5. Import all the necessary Python packages in your notebook:
6. Set the environment variables to specify the LangSmith project name and enable LangSmith tracking:
7. Create the folder where all the images and PDFs will be saved:
2. How to Initialize the Gemini 3 API Client
In this section, we will set up a Gemini API client and wrap calls to the model so they can be traced and logged in LangSmith. Additionally, we will extract token usage metadata and return it in a LangSmith-friendly format.
First, we will initialize the Gemini GenAI client by providing the API key:
Next, we will write a small wrapper around a Gemini model call to enable automatic tracing by LangSmith. Using the
@traceabledecorator, we register the function as an LLM run.Within this function, the code will send the prompt to Gemini and extract token usage details, which are essential for accurate LangSmith tracking, following the tracing guidelines.
Finally, the function will return the model’s text output along with token statistics and the raw response in the format that LangSmith expects, ensuring that the run is displayed accurately in the UI.
3. Building Tools for the Multi-Agent Gemini 3 Workflow
We will now create tools that provide dataset inspection, safe Python execution, and Markdown‑to‑PDF report generation that will be used inside an AI agent workflow.
Tool 1: Load dataset
This tool takes a file path, reads the CSV into a pandas DataFrame using, and then builds a summary containing the dataset shape, column names, each column’s data type, missing‑value percentages, the first five rows, and full descriptive statistics. It returns this summary so an agent can quickly understand the dataset.
Tool 2: Run Python code safely (simple sandbox)
This tool safely runs dynamically generated Python code inside a restricted environment. It prepares a small local environment, then executes the provided code with exec.
The executed code is expected to return artifact paths (like saved plots) and metadata.
Tool 3: Render PDF from Markdown
This tool converts Markdown into a nicely formatted PDF. It first builds a markdown parser that supports tables, lists, task lists, and footnotes.
Then
render_pdfconverts the markdown text into HTML, wraps it in a custom CSS‑styled template (controlling fonts, table appearance, image sizing, etc.), and uses WeasyPrint to generate a PDF file.Finally, it saves the PDF into the artifacts folder and returns the path.
This simply registers all three functions as available tools for the agent to use.
4. Shared Graph State
This class defines a shared
stateobject that holds everything the agent workflow produces: like the dataset path, profiling info, generated plan, code, execution results, insights, and final report, plus retry limits and error messages to prevent infinite loops.5. Creating Gemini 3 API Agents for Data Analysis
We will now create AI agents that will work together to profile the dataset, write and execute analysis code, generate insights, and produce a final PDF report.
Agent 1: Data profiler and planner
This agent is responsible for understanding the dataset and creating a structured analysis plan. It first loads the dataset using the
load_datasettool, which gives it a summary containing shapes, missing values, column types, descriptive stats, and example rows.Then it sends this dataset summary to the LLM with very explicit instructions: identify the task type, select a target column if applicable, decide what exploratory steps should be taken, propose the charts that should be generated, and outline any modeling steps if the dataset suggests classification or regression.
The LLM returns a JSON structure representing this plan, and the agent parses it, falling back to storing raw text if JSON parsing fails.
Finally, it saves both the dataset profile and the generated plan into the shared state so the next agents have all the information they need.
Agent 2: Code writer
This agent converts the analysis plan into executable Python code. It receives the dataset profile, the plan, and any previous execution error. Using all that context, it asks the LLM to output only Python code.
The prompt includes strict requirements: load the dataset, follow the plan exactly, generate each specified chart, save plots into
ARTIFACTS_DIR, track paths and chart metadata, capture console output, close figures after saving, and optionally compute modeling metrics.This ensures the code is reproducible and safe in the sandbox. The result is stored in
state.code, ready for the executor to run.Agent 3: Executor (with auto-retry)
This agent runs the Python code produced by the Code Writer using the isolated
run_pythonsandbox. It captures execution results, chart metadata, standard output, and any artifacts created.If the code runs successfully, the results are stored and the workflow proceeds normally. If it fails, the agent increments the retry counter and stores the traceback so the Code Writer agent can fix the error on the next attempt.
With
MAX_RETRIESlimiting the loop, this agent prevents infinite cycling and provides the feedback signals needed for self‑correction.Agent 4: Insights writer
This agent interprets the entire analysis. It takes the dataset profile, execution output, and the chart metadata, and produces human‑readable analytical insights.
It instructs the LLM to generate structured insights: for each chart, produce two takeaways and one risk, then generate a limited set of overall insights.
The agent must ensure no empty bullets, no repeated points, and insights must be specific to the dataset, not generic.
The resulting insight report is stored in
state.insights, becoming an input for the final reporting stage.Agent 5: Report builder → PDF
This is the final synthesis agent. It uses the complete pipeline outputs: profile, insights, chart metadata, execution logs, and crafts a full, clean Markdown report.
The prompt forces strict formatting rules: no repeated titles, consistent spacing, every chart displayed exactly once in a standardized HTML block, and insights integrated cleanly.
Once the Markdown is produced, the agent calls
render_pdfto convert it into a polished PDF using WeasyPrint. Both the Markdown and the PDF path are stored in the shared state, completing the analysis workflow.6. Build the Multi-Agent Graph
This final step involves constructing the complete multi-agent workflow by assembling all agents into a state-driven graph.
A StateGraph is created using a shared State model, ensuring that every agent interacts with the same evolving state object as the workflow progresses. Each component, such as the profiler, code writer, executor, insights writer, and report builder, is added to the graph as a distinct node, representing a specific stage in the pipeline.
The workflow always starts with the profiler agent, which is designated as the entry point. This ensures that the process begins with a thorough understanding of the dataset and the generation of an analysis plan.
Edges are established to define the flow of the process. After profiling, the output is directed to the code writer, which then feeds into the executor. The key logic lies in the conditional routing from the executor.
A helper function,
retry_or_continue, examines the execution result. If the code executes successfully, the workflow proceeds to the insights agent.If it fails but still has retries available, it loops back to the code writer for automatic correction.
If there are no retries left, it bypasses further analysis and moves directly to the report generator, ensuring that the system does not enter an endless loop. The conditional edges are incorporated into the executor node so that the workflow can adapt based on the success or failure of execution.
Finally, the graph connects the insights stage to the report stage, and from the report stage to the conclusion of the workflow. The graph is then compiled into an executable structure, and an ASCII diagram is generated to visualize the flow.
This multi-agent graph orchestrates the entire adaptive analysis pipeline, enabling error recovery, step-by-step coordination, and smooth transitions between agents.
7. Running the Full Gemini 3 API Data Analysis Pipeline
To run the full pipeline, you simply provide a dataset path, create an initial State object, and invoke the compiled graph. In our case, we are providing it with the Boston Housing dataset.
Once invoked, the multi‑agent system automatically performs the entire analysis: profiling the dataset, generating a plan, writing and executing Python code, extracting insights, and producing both a Markdown and a PDF report.
After the run finishes, you can open your LangSmith dashboard and navigate to the “autolab-gemini3pro” project. Every agent run appears there.
Clicking on the recent run and switching to the Waterfall view displays the timeline of each step: how long the agents took and which tools they used.
You can click into any agent to inspect:
LangSmith was instrumental in improving the entire workflow. What you see is the final version, but it took many tries to get this project right, and Langsmith helped me debug the issues in the agents.
8. Display Report Markdown and PDF
Once the multi‑agent workflow completes, you can directly inspect the generated Markdown report inside your notebook.
The Markdown version is useful for quickly reviewing the analysis, reading insights, and examining the report structure without leaving your workspace.
In addition to the Markdown, the workflow also produces a polished PDF report. The PDF is saved automatically in the artifacts folder, and you can view the path like this:
The generated PDF is perfect and contains all key components of the analysis: narrative explanations, visually rendered charts, chart interpretations, modeling summaries, and final recommendations.
This makes it ideal for sharing with teammates, supervisors, or clients, especially when you want a clean, presentation-ready version of the results.
Final Thoughts
Working on this project made it clear just how far modern AI models and graph‑based agent workflows have evolved. Not long ago, building even a single agent with multiple tools required days of tuning, debugging, and dealing with unpredictable behaviors.
Today, with models like Gemini 3 Pro, the system can understand the dataset, generate accurate code, run analyses, interpret visualizations, and assemble a polished report with remarkable reliability.
In this project, we have built a complete multi‑agent data‑analysis application capable of taking any CSV dataset, performing end‑to‑end exploratory analysis, running baseline models, generating insights, and producing a fully formatted PDF report.
This project uses five coordinated agents: profiling & planning, code generation, execution with retries, insights generation, and reporting, and three core tools for dataset loading, safe code execution, and Markdown‑to‑PDF rendering.
The result is a clean, automated analysis flow that produces a professional, narrative‑driven report supported by visualizations.