workflows.
The seventh time tasa runs read → grep → edit → test, it compiles that pattern into a single tool. Next time, one call does the work of seven — and the tool is small enough to read, easy to roll back.
;; v0.1 · powered by lisp
(defagent tasa :in 'lisp)
;; thesis
An agent that ships frozen is a program.
One that compounds is a species.
Every other agent is an npm install — a black box updated on someone else's cadence, with the same skills for you and every other user. Tasa ships as a living image. It watches how you work, keeps what earns its way in, and forgets what doesn't. Every change is typed. Every change is reversible. Every change is yours
;; join the waitlist
tasa is early. The base is stable — the evolution loop is landing next. One email, no drip, no tracking. We ping you when it's ready to try.
tasa (née tabula-rasa) is an evolving coding agent. The base is a small coding loop that reads, writes, runs shells, and calls the models you'd expect. The interesting part is what happens between sessions.
When a workflow repeats, tasa compiles it into a tool and offers it back. When a failure gets fixed, tasa turns the fix into a policy tied to that exact failure. When you correct it, the correction is scoped — this project, this user, this session — not silently global. Nothing lands in the live agent without earning its way there.
It's written in Lisp for a specific reason: Lisp is the language where code and data are the same shape. That means tasa can read, transform, and safely write its own building blocks — which is what evolving actually requires. Everything ships as one native binary. No Node, no npm, no lockfile drift.
;; the point is a coding agent that compounds — not another opaque assistant shipping frozen skills.
Four kinds of thing tasa learns as you work. Each one is small, checkable, and one keystroke to undo — earned across enough sessions to be worth trusting.
The seventh time tasa runs read → grep → edit → test, it compiles that pattern into a single tool. Next time, one call does the work of seven — and the tool is small enough to read, easy to roll back.
The migration fails with "needs --no-input"? You fix it once. The fix becomes a policy tied to that exact failure. The next time the same error signals, tasa handles it before you notice.
Facts about your project — style rules, deployment quirks, who owns what — stored with provenance and an expiry date. You told it, so it's true. A random web page told it, so it stays a hint.
Model settings, tone, project quirks. Each one is scoped: this session, this user, this project. Nothing goes silently global. Everything is one command to undo.
Every version of tasa's behavior is a numbered generation. New behavior is proposed as a candidate, tried in a sandbox, and — if it wins — swapped in without dropping your session. Rolling back is one command. There is a receipt for every change.
| gen | Δ | note |
|---|---|---|
| 000 | bootstrap | hand-written kernel. trusted. small on purpose. |
| 007 | + prompt-artifact | user pinned a style rule. scope=user. reversible. |
| 014 | + recovery-policy | tool/shell-nonzero → :retry-with-flag --no-input. 6/6 held-out. |
| 031 | + workflow-artifact | read→grep→edit→test collapsed into one typed closure. |
| 042 | swap | atomic pointer flip at safe point. in-flight turn finishes on gen 041. |
| 058 | − workflow-artifact | regressed on 2 held-out episodes. rolled back. archived to lineage. |
| 077 | + semantic-memory | project fact, provenance=user, valid-until=2026-12-31. |
| ∞ | candidate | in a child world. not yet earned. |
Self-evolving doesn't mean self-authorized. Every change carries a risk tier — some auto-activate, some wait for evaluation, some require a human, some are off-limits entirely. The kernel is small and the model can't touch it.
| risk | examples | default |
|---|---|---|
| R0 | Explicit user model, style, or scoped preference change | Auto-activate. Reversible. Session or user scope. |
| R1 | Workflow or recovery policy over already-approved capabilities | Auto-promote after ≥5 held-out replays, zero regressions, and one efficiency win. |
| R2 | Inferred memory, prompt/policy changes, shell or network workflows, non-kernel source patches | Human approval after world evaluation. |
| R3 | Kernel, compiler, promotion logic, trust boundary, capability expansion | Never self-promotable. |
;; and no Node.js, no TypeScript, no JavaScript runtime.
Metaprogramming is code that writes code. In tasa, a file that describes a tool is a tool — the same shape whether a human writes it, an extension writes it, or tasa learns to write it. That is why learning here means new tools, not just new prompts. Drop a file in, get a tool. The agent can read these files. The agent can write these files, inside a trust boundary you set. Draw your own conclusions.
(in-package #:tasa/extensions)
(define-command hello (arguments)
"Greet from the live Lisp image."
(format nil "Hello, ~A"
(if (zerop (length arguments)) "world" arguments)))
(define-extension-tool echo (arguments cwd)
(:description "Return a supplied value.")
(:schema
(tasa/util:json-object
"type" "object"
"properties" (tasa/util:json-object
"value" (tasa/util:json-object "type" "string"))
"required" (vector "value")))
(declare (ignore cwd))
(tasa/util:json-value arguments "value"))
;; Extensions that own resources can release them before shutdown.
(register-cleanup
(lambda () (format *trace-output* "extension stopped~%")))Lisp isn't just novelty here — it does real work. A few properties of the language map directly onto things tasa needs to do.
;; longer take → Lisp vs TypeScript for AI coding agents
$ bin/tasa --exploretasa 0.1 :: generation=042 provider=vertex model=gemini-3.1-protype /help, /why, /worlds, /learn, /quit> start the dev server→ shell npm run dev! signaled tool/shell-nonzero (EADDRINUSE :3000) policy recovery-policy/port-in-use (gen 042)→ shell lsof -ti:3000 | xargs kill -9→ shell npm run dev✓ ready on http://localhost:3000 (1.4s)> /why episode 0x9a2f ← recovery-policy/port-in-use learned after you killed :3000 by hand 4 times last week parents 6 episodes · held-out 6/6 · promoted gen 038→042> /worldscandidate workflow/rerun-flaky-test fitness ▲ 1 world running>