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.

$ claude mcp add --transport http escrito https://app.escrito.io/mcp
Get on the waitlist

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.

Claude Code
Reply…⌘↵

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.

ship_threshold_readout/
  • 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
session 01M2… · ship_threshold readout5 nodes · 1 published
exposures
query · 312,406 rows

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 · 41,880 rows

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 · 7 metrics × 2 arms

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, bootstrap, BH

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

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

queryderivetransformvizpublishedhover a node for its code and result

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.

Claude Code · three months later

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.

Q3 board update · slide 7exported from escrito
Net revenue, Q3 2026, constant currency
$4.21M
+6.8% vs Q2 · 95% interval +4.1% to +9.4%
escrito.io/a/2f7kq9wd1crun 2026-10-024 nodesfx table from Finance, sha256:3e1f…
7
revenue
query · 54 rows
fx_rates_q3.csv
file · 84 rows · hashed
not in the warehouse
revenue_usd
derive · 9 rows
constant_ccy.py
transform · 1 row

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.

where escrito sitsone MCP server
YOUR DEFINITIONS dbt · Cube · Looker · CLAUDE.md YOUR WAREHOUSE connected as you, once YOUR AGENT writes the code Claude Code · Codex MCP escrito runs · records · keeps past the session THE ARTIFACT readout_chart · v2 the graph behind it escrito.io/a/9k41d2xf7p
not included: a chat boxa notebook UIa semantic modela model of our owna second pool of tokens

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.

who holds whatone grant · one sandbox
cancannot
your agent
  • ask escrito for a read-only query
  • send escrito code to run
  • see a credential
  • reach the warehouse
escrito
  • hold your OAuth grant
  • run read-only SQL, as you
  • hand code to the sandbox
  • run agent-written code
the sandbox
  • run the agent's code
  • reach package downloads and its inputs
  • reach the warehouse
  • reach escrito
  • see a credential

One email when it ships.

Nothing else. No newsletter.