Guide #9 Use Case — Data 20 min read March 2026

The AI Data Processing Pipeline: Clean, Transform, Analyze, Report

Hand the agent a CSV, a database export, or a URL to a web dashboard with no export button. It installs whatever packages it needs, cleans the data, runs analysis, generates charts, and delivers a finished report. Terminal for processing. Browser for extraction. GPU for inference. Cost: $0.10–2.00 per run.

The ad-hoc analysis bottleneck

Every company has data tasks that fall between "simple enough for a spreadsheet" and "complex enough for a data engineering team." Clean this CSV and deduplicate the entries. Join these two datasets and find the mismatches. Pull the numbers from a web dashboard that doesn't have an export button. Generate a monthly report with 6 charts. Run a sentiment analysis on 10,000 customer reviews.

These tasks land on a data analyst or a product manager who opens a Jupyter notebook, spends 2 hours wrangling pandas, and produces a result that's correct but not reproducible. Next month, they do it again from scratch. The notebook is in someone's personal folder. The dependencies aren't recorded. The logic is in a cell that was run out of order.

The Jupyter notebook pattern

  • 2–4 hours per ad-hoc analysis
  • Notebook lives on one person's laptop
  • Dependencies: "I think I pip installed something"
  • Cells run out of order, state is unclear
  • Charts are screenshots pasted into Google Docs
  • Not reproducible — next month, start over

The AI data agent pattern

  • 5–15 minutes from data to finished report
  • Runs in an isolated sandbox — clean every time
  • Agent installs its own dependencies explicitly
  • Linear execution, no hidden state
  • Charts exported as PNG/SVG, report as Markdown/PDF
  • Fully reproducible — same input, same output

The three data sources, three container types

Data comes from three places. Each needs a different container type:

Data sources
Files
(CSV, JSON, Excel)
APIs
(REST, database)
Web dashboards
(no export button)
Container types
Terminal sandbox
File + API processing
Browser container
Dashboard extraction
GPU sandbox
ML inference
Terminal sandbox: clean → transform → analyze → visualize → report

Pattern 1: File-based processing (terminal sandbox)

The simplest pattern. Upload a file to the sandbox, tell the agent what to do with it, download the result.

bash
# 1. Create sandbox
SANDBOX=$(curl -s -X POST "$SANDBOX_URL/api/sandboxes" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"data-pipeline","instance_type":"ab0t.medium","auto_stop_minutes":30}')
SID=$(echo "$SANDBOX" | jq -r '.sandbox_id')

# 2. Upload the dataset
curl -s -X POST "$SANDBOX_URL/api/sandboxes/$SID/upload" \
  -H "Authorization: Bearer $API_KEY" \
  -F "file=@sales_data_2025.csv"

# 3. Tell the agent what to do
curl -s -X POST "$SANDBOX_URL/api/sandboxes/$SID/execute" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "command": "cd /workspace && pip install pandas matplotlib seaborn && python -c \"\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\ndf = pd.read_csv(\"sales_data_2025.csv\")\n\n# Clean\ndf = df.dropna(subset=[\"amount\", \"date\"])\ndf[\"date\"] = pd.to_datetime(df[\"date\"])\ndf[\"amount\"] = pd.to_numeric(df[\"amount\"], errors=\"coerce\")\n\n# Analyze\nmonthly = df.groupby(df[\"date\"].dt.to_period(\"M\"))[\"amount\"].sum()\ntop_products = df.groupby(\"product\")[\"amount\"].sum().nlargest(10)\n\n# Visualize\nfig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 6))\nmonthly.plot(kind=\"bar\", ax=ax1, title=\"Monthly Revenue\")\ntop_products.plot(kind=\"barh\", ax=ax2, title=\"Top 10 Products\")\nplt.tight_layout()\nplt.savefig(\"charts.png\", dpi=150)\n\n# Report\nwith open(\"report.md\", \"w\") as f:\n    f.write(f\"# Sales Report 2025\\n\\n\")\n    f.write(f\"Total revenue: ${df[\"amount\"].sum():,.2f}\\n\\n\")\n    f.write(f\"Transactions: {len(df):,}\\n\\n\")\n    f.write(f\"## Monthly Breakdown\\n\\n\")\n    f.write(monthly.to_markdown())\nprint(\"Done.\")\""
  }'

# 4. Download results
curl -s "$SANDBOX_URL/api/sandboxes/$SID/download" \
  -H "Authorization: Bearer $API_KEY" \
  -o results.tar.gz

Pattern 2: Let Claude Code do the analysis

For exploratory analysis where you don't know what you're looking for, SSH into the sandbox and hand the task to Claude Code in plain English.

prompt to Claude Code (inside sandbox)
> I uploaded sales_data_2025.csv to /workspace. It has columns:
> date, product, region, amount, customer_id, channel.
>
> Analyze this dataset:
> 1. Clean: remove duplicates, handle missing values, fix date formats
> 2. Summary stats by region and by channel
> 3. Find the top 10 customers by total spend
> 4. Monthly revenue trend chart (line) with year-over-year comparison
> 5. Revenue by region (choropleth or bar chart)
> 6. Cohort analysis: when did each customer make their first purchase?
>    What % are still active 6 months later?
> 7. Save everything to /workspace/output/:
>    - report.md (narrative with embedded chart references)
>    - charts/ directory with PNGs
>    - cleaned_data.csv
>    - summary_stats.json

Claude Code reads the CSV, inspects the schema, installs dependencies (pandas, matplotlib, seaborn, geopandas if needed), writes and executes the analysis scripts, generates charts, and saves everything to /workspace/output/. You download the tarball when it's done.

Claude Code is the best tool for exploratory data work

When you don't know the schema, don't know the data quality, and don't know what questions to ask, Claude Code excels. It reads the first 100 rows, identifies data quality issues, proposes cleaning steps, and iterates. It's the equivalent of a senior data analyst's first hour with a new dataset, compressed into 3 minutes.

Pattern 3: Browser extraction for dashboard-trapped data

Some data lives in web dashboards with no export button. Google Analytics custom reports, Salesforce dashboards, Shopify analytics, internal admin panels. The data is right there on the screen but there's no API to get it out.

A browser container logs in, navigates to the dashboard, and extracts the data — either via DOM queries or Claude's vision.

python — extract_dashboard.py
async def extract_dashboard_data(cdp_url, dashboard_url, credentials):
    """Log into a web dashboard and extract the visible data."""
    async with async_playwright() as p:
        browser = await p.chromium.connect_over_cdp(cdp_url)
        page = await browser.contexts[0].new_page()

        # Login
        await page.goto(credentials["login_url"], wait_until="networkidle")
        await page.fill(credentials["username_field"], credentials["username"])
        await page.fill(credentials["password_field"], credentials["password"])
        await page.click(credentials["submit_button"])
        await page.wait_for_load_state("networkidle")

        # Navigate to dashboard
        await page.goto(dashboard_url, wait_until="networkidle")
        await page.wait_for_timeout(3000)

        # Try DOM extraction first
        table_data = await page.evaluate("""() => {
            const tables = document.querySelectorAll('table');
            return Array.from(tables).map(table => {
                const rows = table.querySelectorAll('tr');
                return Array.from(rows).map(row => {
                    const cells = row.querySelectorAll('td, th');
                    return Array.from(cells).map(c => c.innerText.trim());
                });
            });
        }""")

        if table_data and any(len(t) > 1 for t in table_data):
            return {"method": "dom", "tables": table_data}

        # Fallback: vision extraction
        screenshot = await page.screenshot(full_page=True)
        b64 = base64.b64encode(screenshot).decode()

        response = claude.messages.create(
            model="claude-sonnet-4-6-20250514",
            max_tokens=4096,
            messages=[{
                "role": "user",
                "content": [
                    {"type": "image", "source": {
                        "type": "base64", "media_type": "image/png", "data": b64}},
                    {"type": "text", "text": "Extract all data visible in this dashboard screenshot as a JSON array of objects. Include every number, label, and metric you can read."},
                ],
            }],
        )
        return {"method": "vision", "data": json.loads(response.content[0].text)}

Pattern 4: GPU sandboxes for ML inference

For tasks that need ML models — sentiment analysis, classification, embeddings, image recognition — create a GPU sandbox. The ab0t.gpu gives you a T4 GPU with 16 GB of VRAM.

bash
# Create a GPU sandbox for ML inference
curl -s -X POST "$SANDBOX_URL/api/sandboxes" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "ml-inference",
    "instance_type": "ab0t.gpu",
    "auto_stop_minutes": 30
  }'

# Cost: $0.526/hour — use for 30 min of inference, then stop
prompt to Claude Code (inside GPU sandbox)
> I uploaded customer_reviews.csv (10,000 rows, column: "review_text").
>
> Run sentiment analysis on every review:
> 1. Install transformers and torch
> 2. Load a sentiment model (distilbert-base-uncased-finetuned-sst-2-english)
> 3. Classify each review as positive/negative with a confidence score
> 4. Add sentiment and confidence columns to the CSV
> 5. Generate a sentiment distribution chart
> 6. Find the 20 most negative reviews for manual follow-up
> 7. Save: enriched_reviews.csv, sentiment_chart.png, negative_reviews.json

Putting it together: the complete pipeline

A real data processing task often combines all three patterns. Here's a monthly revenue reconciliation that uses browser extraction, file processing, and API calls.

python — monthly_reconciliation.py
async def monthly_reconciliation():
    async with httpx.AsyncClient(timeout=300) as client:

        # Step 1: Extract Stripe dashboard data (browser container)
        stripe_data = await extract_from_dashboard(
            client, "https://dashboard.stripe.com/reports/revenue",
            {"login_url": "https://dashboard.stripe.com/login", "...": "..."})

        # Step 2: Download internal sales data (API call in terminal)
        internal_data = await execute_on_sandbox(sandbox_id,
            "curl -s https://api.internal.com/sales?month=2026-03 -H 'Authorization: Bearer $INTERNAL_KEY' > /workspace/internal_sales.json")

        # Step 3: Upload partner revenue spreadsheet
        await upload_file(sandbox_id, "partner_revenue_march.xlsx")

        # Step 4: Reconcile everything (terminal sandbox)
        await execute_on_sandbox(sandbox_id, """
            cd /workspace && pip install pandas openpyxl && python -c "
            import pandas as pd, json

            # Load all three sources
            stripe = pd.DataFrame(json.load(open('stripe_data.json')))
            internal = pd.DataFrame(json.load(open('internal_sales.json')))
            partner = pd.read_excel('partner_revenue_march.xlsx')

            # Reconcile: match by transaction ID, flag discrepancies
            merged = internal.merge(stripe, on='transaction_id', how='outer', suffixes=('_internal', '_stripe'))
            discrepancies = merged[merged['amount_internal'] != merged['amount_stripe']]

            # Generate report
            discrepancies.to_csv('discrepancies.csv', index=False)
            print(f'Total discrepancies: {len(discrepancies)}')
            print(f'Total delta: ${(merged[\"amount_internal\"].sum() - merged[\"amount_stripe\"].sum()):,.2f}')
            "
        """)

        # Step 5: Download results
        await download_workspace(sandbox_id, "reconciliation_march.tar.gz")

Running pipelines on a schedule

Most data pipelines are recurring. The monthly report, the weekly KPI dashboard update, the daily data quality check. Wrap the pipeline in a cron-triggered script:

bash — daily-data-pipeline.sh (cron: 0 7 * * *)
#!/bin/bash
set -euo pipefail

# Create sandbox, run pipeline, download, cleanup
SID=$(curl -s -X POST "$SANDBOX_URL/api/sandboxes" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"daily-data","instance_type":"ab0t.small","auto_stop_minutes":15}' \
  | jq -r '.sandbox_id')

sleep 45  # Wait for boot

curl -s -X POST "$SANDBOX_URL/api/sandboxes/$SID/execute" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"command":"cd /workspace && git clone https://github.com/your-org/data-pipelines.git . && pip install -r requirements.txt && python daily_pipeline.py"}'

curl -s "$SANDBOX_URL/api/sandboxes/$SID/download" \
  -H "Authorization: Bearer $API_KEY" -o /tmp/daily-data.tar.gz

# Upload to S3 / email / Slack
aws s3 cp /tmp/daily-data.tar.gz s3://data-outputs/$(date +%Y-%m-%d).tar.gz

curl -s -X DELETE "$SANDBOX_URL/api/sandboxes/$SID" \
  -H "Authorization: Bearer $API_KEY"

What it costs

Task typeInstanceDurationCompute costModel costTotal
CSV cleaning + chartab0t.micro~5 min$0.001$0.05$0.05
Full analysis + reportab0t.medium~15 min$0.01$0.10$0.11
Dashboard extractionab0t.micro + 1 browser~5 min$0.003$0.02$0.02
ML inference (10K rows)ab0t.gpu~20 min$0.18$0.00$0.18
Monthly reconciliation (3 sources)ab0t.medium + 2 browsers~20 min$0.02$0.15$0.17

Production tips

Use ab0t.micro for everything that isn't ML

Pandas, matplotlib, and data cleaning run fine on 1 GB of RAM for datasets under 500 MB. Only upgrade to ab0t.medium (4 GB) for large joins or memory-heavy operations. GPU instances are only for model inference.

Upload data via the file API, not SSH

The POST /api/sandboxes/{id}/upload endpoint handles multipart uploads cleanly. For large datasets (>100 MB), upload to S3 first and have the sandbox download from there.

Version your pipeline scripts in git

Store your data processing scripts in a repo. The sandbox clones it on startup. When the business logic changes, you update the repo — the pipeline picks up the change on the next run.

Save intermediate outputs

Write the cleaned data, the analysis results, and the charts as separate files. When something looks wrong in the report, you can trace it back to the intermediate step without rerunning the whole pipeline.


What's next

Data in, report out

Upload a CSV. Describe the analysis. Download the result. Terminal, browser, and GPU — whatever the data needs.

Get Started Free