Ask your data a question.
Get the answer your team means.
A data agent that reads the numbers with ChalkSQL and reads what they mean from Notion and Linear. It runs in a Chalk sandbox that can reach only those three services, using credentials it never sees.
One question, three sources
Nothing in the warehouse says which accounts are AI-native, which SKUs make up a product, or which accounts are internal tests. The agent finds that in the company's docs and tickets first, then writes one ChalkSQL query that applies every rule. This is a recorded run, replayed step by step; open any tool call to see what came back.
What is our revenue per product for enterprise customers split by whether or not they're "AI native"?
Fieldstone, its accounts, documents and tickets are fictional. The Notion and Linear APIs here are small stand-ins served from fixtures; the sandbox, the egress policy, ChalkSQL and the model router are real.
How it works
Text-to-SQL gets the syntax right and the business wrong. A useful data agent needs the definitions behind the numbers, and the access to read them, without the keys to everything else.
Context first
The agent looks up every term in the question in Notion: the product catalog, the AI-native definition, the revenue conventions. It follows their pointers into Linear, where two tickets record decisions the docs haven't caught up with.
Numbers from ChalkSQL
ChalkSQL queries the billing tables where they already live, in object storage, with joins, CTEs and CASE. The agent's final query encodes every rule it found, so the answer is reproducible.
Access on a leash
The sandbox can reach three hosts. Each token is bound to one of them and swapped in at egress, so the agent only ever holds placeholders, and every call it makes shows up in the apps' own logs.
Build it in three files
agent.py is a plain tool-calling loop with seven tools. run.py starts it in a sandbox with the access policy. deploy_workspace.py stands up the fake Notion and Linear.
To point it at your own workspace, swap two base URLs and two tokens. The tools use a handful of read endpoints, and the sandbox policy stays exactly the same.
chalk-ai/data-agentfrom chalkcompute import NetworkPolicy, Sandbox, Secret
sandbox = (
Sandbox(
image=image, # python + httpx + pyarrow + agent.py
lifetime="900s",
# An empty allowlist: the three hosts below are the only egress.
network_policy=NetworkPolicy(allowed_hosts=[]),
)
# Each token is bound to one host. Inside the sandbox, $NOTION_TOKEN is a random
# placeholder; the egress proxy swaps in the real token only on requests to Notion.
.add_credentials("api.chalk.ai", Secret.from_local_env("CHALK_API_TOKEN")) # router + ChalkSQL
.add_credentials("api.notion.com", Secret.from_local_env("NOTION_TOKEN"))
.add_credentials("api.linear.app", Secret.from_local_env("LINEAR_TOKEN"))
)
sandbox.run()
for event in sandbox.exec_stream("python3", "/app/agent.py", question, env=env):
print(event.stdout, end="") # the agent's trace, one JSON object per lineWhat Chalk handles
You write the agent. Chalk gives it data to query, a model to think with, and a boundary it can't talk its way out of.
Credentials it never sees
Secrets reach the network, not the agent. A prompt-injected agent can't leak a key it doesn't have, or spend the Notion token on another API.
Three hosts, nothing else
NetworkPolicy is an allowlist. Package indexes, paste sites and every other host fail to connect from inside the sandbox.
SQL where your data lives
ChalkSQL reads your data sources, the offline store and files in object storage. Nothing is copied into a store just for the agent.
Any model, one router
The agent calls an OpenAI-compatible endpoint on Chalk's model router. Switching models is one flag; the sandbox and tools stay the same.
A trace behind every answer
Each tool call, argument and result is recorded as JSON lines, and the answer cites the document each definition came from.
Checked against ground truth
The example ships a reference answer computed independently from the same data. The recorded run matches it to the cent.
Build agents that know your business
Analytics agents, support agents, or anything that needs your data and your definitions. Talk to an engineer about running them next to both.