An agent workspace for data work
Put your agent on the record.
escrito runs the steps your agent takes on your data and records them as a DAG: every query, every transform, every chart, with its inputs and its result. Anyone can audit it, refresh it, or build on it.
One line in Claude Code, Codex, Cursor or anything that speaks MCP. The agent's SQL and Python run in escrito, next to your warehouse.
Publish
Show your work without doing any.
When the number checks out, it is ready to share. escrito already recorded every step your agent took to reach it. There is no script or notebook to materialize and no BI tool to push the analysis into. The handoff from a private agent session to a reusable artifact is a link, and it exists the moment the number does.
- exposures.sql0.4 KB
- orders_refunds.sql0.6 KB
- metrics_by_arm.sql0.5 KB
- readout_stats.py3.2 KB
- viz.py1.8 KB
- requirements.txt0.2 KB
- exposures.parquet9.4 MB
- orders_refunds.parquet1.2 MB
- metrics_by_arm.csv0.8 KB
- readout_chart.png142 KB
exposures · query
Everyone exposed to either arm since the start, one row per user, from the assignment table rather than the event stream.
SELECT user_id, arm, exposed_at FROM exposures WHERE experiment = 'ship_threshold'
312,406 rows · ran as maya@acme.com · 1.4 s
orders ⋈ refunds · query
Completed orders in the window with any refund netted off, so revenue is what was kept.
SELECT o.user_id, o.placed_at,
o.total - coalesce(r.amount, 0)
AS net
FROM orders o
LEFT JOIN refunds r
USING (order_id)
WHERE o.status = 'completed'
41,880 rows · ran as maya@acme.com · 0.9 s
metrics_by_arm · derive
One row per arm and metric. Conversion and refund rate over exposed users, the rest over orders.
SELECT e.arm, metric, value FROM exposures e LEFT JOIN net USING (user_id) GROUP BY e.arm, metric
14 rows · over the two nodes above · 0.3 s
readout_stats.py · transform
Welch on the means, bootstrap on the ratios: a rate needs per-user variance, and weekly means throw it away.
rng = np.random.default_rng(7)
draws = rng.choice(x, (10_000, n))
ci = np.percentile(nrpv(draws),
[2.5, 97.5], axis=0)
p = multipletests(welch(m).pvalue,
method="fdr_bh")[1]
7 rows · scipy 1.14.1, statsmodels 0.14.2 · 1.9 s
readout_chart · viz · published v1
Five intervals over readout_stats. Net revenue is the decision metric; its interval still crosses zero.
Vega-Lite · png preview · escrito.io/a/9k41d2xf7p
when another agent loads this link results cached · nothing re-queried · branch from any node
- link
- escrito.io/a/9k41d2xf7p
- carries
- the chart, the 4 nodes upstream of it, their code and inputs, the rows each returned, the packages pinned
- refresh
- re-runs the graph under the reader's permissions and says which nodes moved
- note
- "+1.9%, interval crosses zero, not a ship decision yet." Written for v1; the page says so on v2.
Reuse
Pick up from exactly where you left off. Skip the archaeology.
Old notebooks are rarely reopened, and their results are often hard for both humans and agents to reconstruct.
Every artifact your agent publishes with escrito carries a link to exactly the code that produced it and nothing else. Your next session, or someone else's, follows the link and branches from the node it needs. Nothing is re-queried and few tokens are wasted getting back to where the last session ended.
Sources
Every number gets a citation.
Not every number that moves a decision comes through a governed BI layer. A spreadsheet from Finance, an S3 dump from a vendor, a correction pasted into a chat: escrito records and versions every input the same way. The receipts assemble themselves.
Your agent
escrito is not an agent. You have one already.
Claude Code and Codex already talk to your database. escrito does not put a second agent between yours and the code it writes, and it does not narrow what that code can be. Your agent writes the code it needs, picks its own libraries, and runs it through one MCP server rather than somebody else's harness.
Bring your own semantic layer. Bring your own .md files. Your agent reads them in place; escrito never sees them.
Security
Your agent writes the query. It never holds a credential.
Authenticate with your warehouse over OAuth. escrito holds the grant, never your password. Your agent can ask escrito to run read-only SQL; it never touches the database itself.
Your agent's code runs in a sandbox that can reach the inputs escrito handed it, an object store for its outputs, and a package index. Nothing else.
| can | cannot | |
|---|---|---|
| your agent |
|
|
| escrito |
|
|
| the sandbox |
|
|
One email when it ships.
Nothing else. No newsletter.
Recorded. You are on the list.