tasatasa  /  lispjoin

;; v0.1 · powered by lisp

tasa — a self-evolving Lisp coding agent

(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

Get tasa when the first generation ships.

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.

No newsletter, no drip, no tracking. One email when tasa is ready to try.

  learns your codebase  compounds every session  turns fixes into policies  writes its own tools  earns every upgrade  rollback in one command  explains every decision  lisp all the way down  learns your codebase  compounds every session  turns fixes into policies  writes its own tools  earns every upgrade  rollback in one command  explains every decision  lisp all the way down
;;01

what it is

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.

;;02

what it picks up

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.

01workflow

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.

02recovery policy

recovery policies.

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.

03memory

memory that knows where it came from.

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.

04prompt · config

prompts & configs.

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.

;;03

generations

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.

generations.logtail -f
genΔnote
000bootstraphand-written kernel. trusted. small on purpose.
007+ prompt-artifactuser pinned a style rule. scope=user. reversible.
014+ recovery-policytool/shell-nonzero → :retry-with-flag --no-input. 6/6 held-out.
031+ workflow-artifactread→grep→edit→test collapsed into one typed closure.
042swapatomic pointer flip at safe point. in-flight turn finishes on gen 041.
058− workflow-artifactregressed on 2 held-out episodes. rolled back. archived to lineage.
077+ semantic-memoryproject fact, provenance=user, valid-until=2026-12-31.
candidatein a child world. not yet earned.
;;04

safe by default

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.

promotion-policy.tabtiered autonomy
riskexamplesdefault
R0Explicit user model, style, or scoped preference changeAuto-activate. Reversible. Session or user scope.
R1Workflow or recovery policy over already-approved capabilitiesAuto-promote after ≥5 held-out replays, zero regressions, and one efficiency win.
R2Inferred memory, prompt/policy changes, shell or network workflows, non-kernel source patchesHuman approval after world evaluation.
R3Kernel, compiler, promotion logic, trust boundary, capability expansionNever self-promotable.
;; correctness and safety are hard gates. efficiency never compensates for a regression.
;;05

under the hood

;; and no Node.js, no TypeScript, no JavaScript runtime.

;;06

metaprogramming, in practice

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.

.lisp~/.tasa/agent/extensions/hello.lisp
(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~%")))
;;07

why lisp

Lisp isn't just novelty here — it does real work. A few properties of the language map directly onto things tasa needs to do.

Lisp thing
What you get
Live image
Fix it while it's running. No restart, no lost context. The agent you're using is the agent you can edit.
Code is data (metaprogramming)
Lisp programs read, transform, and write Lisp programs — the same way you would. That is why tasa can evolve its own tools instead of just memorizing prompts.
Restarts, not crashes
When something fails, the next step is a choice, not a stack trace. Choices that work become policies. This is a Lisp trick almost nothing else has.
One image, one language
Runtime, agent, and everything it learns live in the same editable place. Every change is inspectable, typed, and reversible.
Typed s-expressions
Learned behavior is a small, checkable shape. The agent can't smuggle in arbitrary code, and you can read every diff.
Single native binary
Ships as one file. No Node, no npm, no lockfile drift. It boots fast and stays boring.

;; longer take → Lisp vs TypeScript for AI coding agents

;;08

a session, elided