Daniel StoyanovPrismClaude Agent SDK · Python

Claude Agent SDK · Python · DuckDB · read-only

Prism

Plain English in, verified SQL and a chart out

A data analyst agent that turns a question into SQL, runs it in a sandbox, checks the result against the question it was asked, and renders a chart. If the query returns something implausible it re-queries instead of charting nonsense.

Take a look inside3 scenarios inside

What makes it special

  1. 01Read

    Reads the schema before it writes SQL

    Prism is told never to guess a column name, so it starts by pulling tables, types, row counts and the notes a type cannot carry, like refunds living on the order rather than the line. If a query still hits a missing column, the error comes back with a hint to re-read the schema, not to try another guess.

    describe_schema()agents/prism-analyst/prism/warehouse.py

  2. 02Run

    Read-only, three layers deep

    A parser refuses anything but a single SELECT before DuckDB sees it, and the connection itself is opened read-only in case that parser has a bug. The agent has no shell, file or web tools at all, so the only way to the data is one SELECT at a time.

    run_sql()agents/prism-analyst/prism/warehouse.pyagents/prism-analyst/prism/analyst.py

  3. 03Check

    Checks the answer against the question

    Every result comes back with computed warnings: a group key that never reaches the aggregate, a rate landing exactly on ½, a denominator under 25. That is how it catches a tidy 50% retention rate that is really 4,312 orders divided by 2,156 customers.

    inspect_result()agents/prism-analyst/prism/selfcheck.py

  4. 04Chart

    Won’t chart a number it doesn’t trust

    It is instructed to say so and re-query rather than plot a result it distrusts. The chart tool also refuses forms that mislead: a line across categories with no order, a donut with negative or more than six slices, a fourth series the validated palette has no colour for.

    render_chart()agents/prism-analyst/prism/charts.py

Inside the demo

  1. 01

    Revenue by channel, Q2

    Schema first, one readable query, then the chart the data shape asks for.

    question inrevenue by channel for Q2

  2. 02

    Self-check kills its own query

    The first query returns a clean-looking 50% - and cannot answer the question. Prism says so and re-queries.

    question inwhat is our 90-day retention for customers who frist ordered in Q1, split by channel?

  3. 03

    Query fails on a column that does not exist

    run_sql comes back ok:false with a binder error. Prism re-reads the schema instead of guessing a column name.

    question intop 5 products by refund rate last month

Under the hood

Architecture

stack
Claude Agent SDK · Python
pattern
Agent loop with sandboxed code execution
why this, and what it costs
Letting the model write and run code beats hand-built query tools the moment questions get compositional: you cannot pre-build a tool for every aggregation. The price is a sandbox you must actually isolate, and output you must validate before trusting.

Tools

3
  • describe_schemasafe

    Return tables, columns and types available to query.

  • run_sqlsafe

    Execute a read-only SQL query in the sandbox and return rows.

  • render_chartsafe

    Render a chart from a result set.

Source

runnable
real source
agents/prism-analyst/prism/analyst.py
packages
  • claude-agent-sdk
  • duckdb
  • pandas
written against
api_documentation/claude-agent-sdk-python.md

Watch it throw out its own 50%.

Inside, each question runs step by step: Prism reads the schema, each query lands with its rows and timing, and a result it rejects stays on screen, struck through, while the chart is drawn from the one that replaced it.

Take a look inside