Declares
An operator DSL — a >> b chains, a | b forks — that builds the same
{ nodes, edges } blob the canvas produces. No network, no platform, no account.
Everything the Studio draws can be written in Python instead, and versioned there.
chatty-lab is the package that does it: a graph is declared with an operator DSL,
each version is named by its content, and a history of those versions travels between a
directory on your disk and a workspace on the platform.
pip install chatty-labOne wheel covers Python 3.10 and everything after it, and it brings both halves: the
library below, and a chatty command on your path.
Declares
An operator DSL — a >> b chains, a | b forks — that builds the same
{ nodes, edges } blob the canvas produces. No network, no platform, no account.
Names
A version is a digest of its content: the graph and every agent definition it pins. Commit the same graph twice and you get one version, not two.
Carries
push and pull move a branch between a .chatty directory and the platform,
working out what the far end is missing from digests alone.
Does not run
Nothing here executes a graph. Runs, trials and numbers live behind the platform’s
API — Platform.call is the
door to them.
import chatty_lab as clfrom chatty_lab import Input, Llm, Eval, Output, build
# 1 — declaregraph = build( Input() >> Llm("answer", model="NV:openai/gpt-oss-20b", prompt="Answer in one word:\n\n{{dataset_input}}") >> Eval("score", metrics=["exact_match"]) >> Output())
# 2 — name it, in a history kept in ./work/.chattyit = cl.Workdir(cl.Store.at("./work"), graph="3f47b2c8-…")done = it.commit(graph, message="one reader, one pass")done.version.n, done.version.digest.short # (1, 'a1b2c3d4e5f6')
# 3 — carry it to the platformlab = cl.Store.on("https://chatty-lab.com", token=TOKEN, graph="3f47b2c8-…")it.push(lab)Three moves, three pages: declaring, versioning, carrying.
What a version is — the canonical form of a graph, the digest that names it, where two
lines of work meet — is decided once, in Rust, and this package is one of three callers
of that decision. The other two are the chatty command and the platform itself.
Python 3.10 or later. The package ships py.typed, so your type checker reads
real types rather than Any.
A graph id, if you mean to push. It is the graph parameter in the Studio URL —
/studio?graph=3f47b2c8-… — or whatever POST /api/graphs handed back.
A token, likewise. The same Supabase access token the REST API takes. Three environment variables are read by name:
| Variable | What it is |
|---|---|
CHATTY_API | https://chatty-lab.com/api, or just the address of the site |
CHATTY_TOKEN | the bearer token |
CHATTY_WORKSPACE | the team workspace id — omit it for your personal one |
The package is Elastic License 2.0 — source-available, not open source. Read it, run it, change it, use it inside your own organisation. The one thing you may not do is offer it to other people as a hosted or managed service.