Kern is a Lisp framework where the application itself is data — every resource, component, view, workflow, policy, translation, tenant customization, resident agent, and agent-written patch is a versioned, content-addressed row in the same Postgres that holds your business. The binary is a small evaluator that rarely changes. Deploying is a transaction. Rolling back is a WHERE clause. And an AI agent doesn't read your codebase through grep — it queries it, because the codebase has a schema.
For fifty years, software has governed its data with one discipline and its code with another. Your database gives every fact a transaction, a history, an audit trail, a permission model, and a query language. Your codebase gets a text repository, a build pipeline, an artifact registry, deploy gates, feature flags, and a rollback runbook — a hand-assembled, weaker imitation of the guarantees the database already provides. That divide was tolerable when humans wrote all the code, slowly. Now agents write code fast — and the code is the least governed artifact in the company.
Homoiconicity is the license: in a Lisp, code is s-expressions, s-expressions are data, and data has a home. The kernel — a reactor, an evaluator, a verifier suite, and a wire protocol — is the only compiled artifact, and it changes on the timescale of a database engine, not an application. It ships zero business logic: it is to your product what Postgres is to your rows.
New definitions are inserted, verified, catalogued, and compiled in one transaction — with their schema migration, if they carry one. Rejected code never becomes code. Atomic, fail-closed, no pipeline.
Admitted definitions compile native through SBCL at admission — compile is a core-language function, not a build system. Sandbox-tier code (tenants, agents) runs in kern's own interpreter, fuel-metered: exact step and allocation budgets per evaluation.
Workflows, UI sessions, and signalled conditions are serialized continuations — expression + environment, stored with a wake condition. Any node resumes any of them. Crash, deploy, or drain: nothing is lost, because nothing lived only in memory.
Every guarantee in this document has to know your schema — sync, policy, forms, history, the vault. So kern has one source of truth: the resource, a declaration the whole framework derives from. In a homoiconic language the idea reaches its native form: the DSL is just the language, and macroexpansion is the derivation pipeline. No DSL compiler, no code generation step — a defresource form expands into schema, migrations, history tables, sync horizons, policy checks, and form components, and the expansion is inspectable data, not compiler internals.
Because the declaration is itself a row, the catalog stops being generated documentation and becomes the storage format. Kern catalogues every definition — resources, functions, components, policies, workflows, prompts — because being in the catalog is what being code means. There is no definition an agent can see that the catalog doesn't describe, structurally, by construction.
And because code and schema live in the same database, they migrate in the same transaction. The handler that reads a new column and the migration that adds it commit together or not at all — the “deploy window” where code and schema disagree simply has no representation.
Durable-execution engines persist step results and re-execute deterministic code to recover position. It works — and it drags a constraint through everything: workflow code must be replay-safe, and versioning a workflow mid-flight is the problem that haunts the whole category. A Lisp interpreter can do the honest thing instead: serialize the actual continuation. The paused program is an expression plus an environment — which is to say, a row.
Versioning dissolves into the history tier: a paused workflow resumes against the exact code hashes it started with, because old definitions are immortal rows. “As-of” for code solves what replay-compatibility gymnastics never quite did. Steps that touch the database commit their effect and their checkpoint in one transaction — exactly-once, guaranteed by Postgres itself.
And the condition system — Lisp's resumable-error discipline — becomes the human-in-the-loop primitive. A failed step doesn't throw; it signals a durable condition whose restarts are data, presented in the operator plane (or to an agent) as choices. Pick one; the continuation resumes. “Workflow errored, an operator chooses a restart, work continues” is the true shape of SaaS operations, and no mainstream engine has it as a language feature.
Handlers never emit markup. Components are typed sexps drawn from a closed vocabulary of ~25 semantic components — page, form, table, card, badge, and kin — headless, themed by CSS variables, composed freely. A macro splits every component into static parts (sent once) and dynamic bindings (tracked) at expansion time; the server diffs and ships byte-sized patches over an owned wire protocol to a vendored ~15 KB client. The closed set is load-bearing: it is what makes derived forms, automatic PII masking, and a future native-renderer lane possible.
Then kern goes past diffing. Because every component's reads are analyzable forms against catalogued resources, the framework knows statically which fields each component depends on. A change to deal.stage invalidates exactly the components bound to it — no per-socket re-render-and-diff of everything in scope. Server-side diffing was always a clever recovery from not knowing dependencies; kern knows them.
And the session itself is a continuation. Hot state lives in the reactor's memory; on disconnect, deploy, or drain it checkpoints to a row — so any node resumes any session, and the reconnect storm that haunts stateful-socket frameworks becomes a rehydration, not a re-mount stampede. Serializable-continuation web serving has two decades of prior art; marrying it to server-diffed reactive UI and a database is the opening.
Grounding an agent on a catalog stops schema hallucination: a column that isn't in the catalog can't be referenced, because the reference fails verification. Kern takes grounding to its limit — admission. Agent-written code is data submitted to the database, and the verifier suite — catalog parity, capability audit, PII flow, contracts — runs inside the insert transaction. Rejected code never becomes code. And the grounding surface can't rot, because it is populated by the agent's own admitted work: being catalogued is what admission means.
Policy enforcement moves from checks to environments. Code runs in an environment where only its granted capabilities are bound — an unauthorized call isn't rejected, it's unnameable. There is no ambient authority to escalate, no forgotten middleware, no bypass path: the environment is the policy.
This closes the quiet failure mode of every hand-built framework: a policy that is declared, exported, documented — and wired into nothing. A permission model that no query path actually calls looks identical, in the source and in the demo, to one that holds; the gap only surfaces as a breach. Because kern's verifiers run at admission, “declared but unenforced” is a build failure, not a latent hole — a resource whose policy no admitted path consults fails catalog parity and never becomes code. The guarantee isn't that engineers wire enforcement correctly; it's that unwired enforcement can't be admitted.
One mechanism, not two: tenant customization and agent patches are the same primitive — governed evaluation. Sandboxed expressions, capability-scoped environments, fuel-metered, catalog-verified, audit-rowed. The customization ladder every serious SaaS eventually builds and the agent-in-the-loop every SaaS is about to need collapse into a single thing to secure.
And the framework ships its own MCP server: agents query the catalog, fetch definitions by hash, submit patches as sexps, and receive verifier verdicts as structured data. Today every coding agent reverse-engineers a codebase through file reads and grep; kern's answer is that the codebase is already a database with a schema. The IDE is an API.
The runtime-metadata products — Salesforce's config plane, Airtable, Twenty — proved something loud: users want to reshape live software. Custom objects, fields, views, and automations, created from Settings, live in seconds, no deploy. And every one of them is built the same way: a metadata engine interpreting rows at runtime, running beside a codebase that is still text shipped through CI. That seam is the product's ceiling — what Settings can't express needs a pull request, and the two substances version, audit, and migrate under different laws. Kern doesn't have the seam. Metadata was always code that lived in the database. In kern, all of it does.
So the no-code surface is not a second engine — it is a thin client of admission. Attributes draw from a closed vocabulary of semantic types — money, email, phone, address, select, relation, and kin — each carrying its validation, rendering, masking, and locale behavior. A Settings edit arrives as an extend-resource form and passes the same gate as everything else: verified, versioned, audit-rowed, live on commit. A trigger-action workflow drawn in the builder lands as the same defworkflow sexp an engineer would write. Roles are the same story — a role is a named bundle of capabilities, a row, grantable to a human, a key, or an agent alike. The Settings UI is an agent — a well-behaved one whose patches happen to be forms filled in by humans.
Tenant customization is the same mechanism, one column deeper. Scope is a column on the definition row — product, package, org, team, user — and the catalog resolves through the chain: a tenant sees the base product plus their org's overlay; a rep sees personal views above the team's. When an org admin adds a field to deal from Settings, the admitted form is scoped to their org — forms, views, policy, API, and history know it seconds later, and no other tenant's catalog moves at all. Extension needs no reserved prefixes and no hand-assigned “universal identifiers” to survive deploys — identity is the hash, and an extension references the exact base definition it extends. Who may edit is the same machinery one level up: schema-editing is a capability granted through roles, not a hardcoded admin flag. And because the overlay is code, the customization ladder has no cliff — a field today, a computed field tomorrow, a validation, a workflow, a component — the same substance throughout, priced in capability grants, not in “call us” tiers.
And the surface users shape most — views, layouts, dashboards — is rows by the same argument. A saved view is a catalogued query plus a projection: table, board, and calendar are three renderings of one form; filters, sorts, and groupings are data; a dashboard is widgets over the same queries; record pages compose the closed component vocabulary. Because views are definitions, they inherit the machinery unasked — dependency-exact invalidation, policy scoping, per-role sharing, as-of history. “Who changed the pipeline board” is the same query as “who changed the record.”
And here is what the substrate uniquely buys the builder: round-trip. Every visual builder ships with an eject cliff — the UI writes config until config runs out, someone drops to code, and the builder can never render that object again; from that day the product has a made-in-the-UI half and a made-by-engineers half, drifting. Kern's builders are projectional editors over the catalog: the workflow canvas, the form designer, and the view editor read and write the same sexps engineers do, and the canonical printer guarantees the rendering is one-to-one. Whatever the UI writes, an engineer can open in a buffer; whatever an engineer admits, the UI renders back as editable structure — a form the closed vocabulary can't express appears as an inline code node on the same canvas, not a locked door. Drafts are rows; activating one is admission; and because a running workflow is a continuation, the canvas can open a live run — showing which step it sleeps on, with a durable condition's restarts rendered as buttons an operator presses.
So make it official: the builder is a first-class object. Every kern product ships a workflow builder for its tenants not as a feature someone built but as a derived surface — the canvas, the palette, and the property panels are catalogued components like everything else: admitted, versioned, scoped, as-of queryable. Cash that out. The palette is a query — it offers exactly the step types the current user's capabilities can admit, so unnameable extends to the UI: a step you may not use is not greyed out, it is absent. A package that ships a new action ships its palette entry and property panel as fields on the same definition row — installed, it appears on every canvas allowed to name it, with no builder release. Property panels derive the way forms derive from resources, because def-forms are themselves typed, catalogued grammar — the builder is what happens when the derivation machinery is pointed at the language itself. And the fixed point holds: the builder's own definition opens on its own canvas. Smalltalk shipped its browser inside the image fifty years ago; kern ships its builder inside the catalog, where a product team, a tenant, or an agent can patch it — and roll it back — like any other rows.
An admitted resource is already an API. List, get, create, update, delete — over REST and the sexp wire — with filters and sorts drawn from the same query forms views use, executing inside capability environments so an endpoint cannot out-permission the application. The OpenAPI document is a query against the catalog: it can't drift from the schema because it is the schema, projected. Declare a resource and the endpoint exists seconds later — not a codegen pipeline, a SELECT. And API keys are capability grants — scoped, expiring, audit-rowed — not ambient tokens with a name.
Outbound crossings hold the same discipline. A webhook is a subscription row on the change stream — transactional with the write that caused it, durable, replayable from history when the receiver was down. An import is a governed transaction: a CSV maps onto resource forms, runs the same verifiers as every other write, dry-runs as a transaction that reports instead of committing — then lands whole or not at all, provenance on every row.
Translations complete the argument. Components emit meaning, not markup, so every human-visible string has one home: a label field on a catalogued definition. A translation is a row — (hash, locale) → string — bound at patch time, while the semantic types localize themselves: money, dates, and addresses format per locale from the type, not the template. A locale's coverage is a completeness query; an agent can translate the catalog overnight and the verifier reports exactly what's missing. No extraction pipeline, no .po files, no string that escaped them.
Strip the frameworks and an agent is embarrassingly small: a recursive function over a growing list of messages, whose one tool is eval, whose memory is JSON on a disk. Governed evaluation — the admission gate — already governs the code such an agent writes, treating it as an author standing at the seam. This is the other half, and the inversion: the agent itself becomes a resident object. Because every part it is made of already has a first-class home here — the loop is a continuation, the tool is governed evaluation, the memory is the catalog, the audit is the history tier — making it native is almost entirely reuse. The one new thing is a name for the composition: defagent.
The loop is a continuation. The accumulated message history is its environment, each model call is a step, and the whole conversation is a row — so it survives a deploy, parks for three days on a human's approval at zero cost, and resumes on any node. The article threads that state by hand and writes it to disk in twenty lines; the continuation store already holds workflows and sessions exactly this way, and the agent simply joins them. And the tool is admission. The article's most powerful move — one tool, eval — carries its one caveat: eval requires a sandbox, so the author runs it in Docker. Kern is that sandbox, as the storage format — reasoning-time evals run fuel-metered in the interpreter tier, where an ungranted capability is unnameable, not refused. There is no box to bolt on, because isolation is where the code already lives.
And the skills. Handed an API key mid-conversation, the article's agent writes a brave-search function into its running image — a real capability, invented at runtime — but it lives only in the transcript: a fresh session must re-read its own history and re-eval its own code to get it back. Capability is just a story the agent tells itself. Kern makes learning admission: a skill worth keeping passes the same gate as engineer code — catalog parity, capability audit, PII flow, contracts, inside the insert transaction — and becomes a content-addressed row, verified once, named by hash, scoped to its org, revocable, and live in every future session with no rehydration. The story it tells itself becomes a row it can query — and the transcript still holds the reasoning that built it, as provenance and an as-of trail of exactly how the skill was learned, not code that must be re-run to exist.
What is genuinely new is the identity. A defagent is a definition like a resource or a workflow — a row binding a catalogued prompt, a role (its capability bundle, and so its blast radius), a fuel budget, a model endpoint held as a metered capability, and a tool surface: the exact set of definitions it may name. It is content-addressed, scope-columned, versioned, as-of queryable, and delegable by attenuation — a user grants it a subset of their own capabilities and never more. So the agent is a principal, the same kind of row a human or an API key is, the same substance as the application it operates on; a role was already a named bundle of capabilities grantable to a human, a key, or an agent alike — this is the agent that phrase was always describing. Its self-authored skills stay sandbox-tier — metered, interpreted, capability-scoped — because admitted native code shares the kernel's heap; promotion to the native tier is a capability the agent does not hold, gated behind an operator's restart. Self-extension is real, and it is fenced exactly where the honest edges draw the line.
A (pii …) field never enters the history stream — it lives in a mutable, per-subject-keyed vault, with keys held in an external KMS outside the backup surface; everything downstream carries only a token. The derived components know what the schema knows, so a PII field renders masked by default — plaintext materializes only behind an explicit, expiring reveal grant, approved by a second party and written to a tamper-evident audit row. Erasure is crypto-shredding: destroy a subject's key and every copy of their personal data — live, replica, history, backup — becomes permanently undecryptable ciphertext, while the history itself still replays perfectly.
One deliberate exception to “nothing else”: the vault's cipher and the password hash bind to a vetted, audited implementation — never a hand-rolled one. The two primitives that actually guard secrets — authenticated symmetric encryption and the password KDF — are also the two whose subtle errors are invisible to ordinary tests: a broken cipher still round-trips, a wrong hash still verifies against itself. A vault is exactly where “from scratch” stops being a virtue, so kern uses an authenticated construction (AEAD, not unauthenticated CBC) from a reviewed library and treats the primitive as a dependency to pin and audit, not to write.
The operator plane derives from the same resources as the product: your support console, account views, and billing rollups are queries against the objects you already ship, not a second admin app built six months later. An operator impersonating a tenant sees the tenant's real UI with PII masked by default — support without disclosure, structurally.
And because code is rows, the audit story finally covers the whole system. Who changed this workflow, when, what did it look like before, who approved it — the questions a SOC 2 auditor calls “change management” and every other stack answers with screenshots of a CI dashboard — are, in kern, the same query as “who changed this record.” One audit machinery, both substances.
“World-class for AI” is a language-design spec, not a marketing line, and kern's dialect is built to it. Every definition is stored content-addressed — the idea Unison proved — so the hash is the identity and names are catalog pointers. Renames are metadata. Drift is impossible. An agent's patch references exact hashes; there is no “which status did it mean.”
One canonical printer. Exactly one rendering of every form — no formatting diffs, no style debates, minimal tokens. Structural diffs are the only diffs; the review UI shows semantic change or nothing. A deliberately small, boring core: no reader macros in the application dialect, a fixed special-form set, effects only through capabilities. Every constraint on human expressiveness is a gift to machine verifiability — and in this substrate, humans audit more than they type. Contracts, docstrings, and examples are machine-readable fields on the definition's row, not comments beside it — so the reference manual is a projection of the catalog, never stale, and because views and components are definitions too, its screenshots are live renders, not images that rot.
The host split is pragmatic: the kernel is Common Lisp on SBCL — a mature native compiler available at runtime, plus the condition system the workflow engine is built on. The application dialect is kern's own, CPS-transformed so continuations serialize, compiled through SBCL at admission for the hot path. The host provides an engine; the dialect is the product.
A world-class native compiler where compile is a core function — compile-on-admission is a language feature, not a build system. Conditions, restarts, and thirty years of image-based living systems.
LISTEN/NOTIFY as the bus, SKIP LOCKED queues, partitioned history, transactional DDL — pubsub, presence, cron, and the change stream are queries, not services. The database is the distribution layer.
The browser inside the image, content-addressed code, serializable-continuation web serving, the static/dynamic split, durable execution over rows, resource derivation, runtime-mutable metadata with APIs generated from it. Proven separately, elsewhere — kern is where they meet. Credits, not dependencies.
Kern's own dialect: CPS-transformed, capability-scoped environments, exact step and allocation budgets for sandbox tiers, native compilation for admitted code.
Verifiers in the insert transaction: catalog parity, capability audit, PII flow, contracts. The type system the dynamic dialect must earn — fail-closed, per transaction.
Workflows, sessions, and conditions serialized as rows with wake conditions — resumable by any node, versioned against exact code hashes.
Expansion-time static/dynamic split, dependency-exact invalidation derived from the catalog, byte patches on an owned wire, a closed ~25-component vocabulary.
Per-subject keyed PII vault, crypto-shred erasure, masked-by-default rendering, expiring reveal grants, and an operator plane derived from the same resources — trust as schema, not process.
Semantic field types, views · boards · dashboards as catalogued queries, a workflow canvas that is itself catalogued components, and a Settings client that submits admission transactions — no-code and code are one substance.
REST + OpenAPI projected from the catalog, API keys as capability grants, webhook subscription rows, per-locale translation rows bound at patch time.
A defagent binds a catalogued prompt, a role, a fuel budget, and a metered model endpoint — its loop a continuation, its learned skills admitted rows, its memory the history tier. Not a subsystem: a composition of the rows above.
Every box below is a thing most stacks deploy, version, secure, monitor, and pay for. In kern, each one is a table, a query, or the evaluator's normal behavior — inside the two things you already have. The last row is the unusual one: kern deletes the machinery of shipping software itself, because “ship” stopped being a concept the moment the code became rows.
→ postgres — queues, pubsub, and schedules are rows and NOTIFY, transactional with your data
→ continuations — durable execution is the evaluator's normal behavior, checkpoints are rows
→ rows — sessions are continuations; deploys and node loss don't drop them
→ a transaction — admit, don't ship; the verifiers are the gate, commit is the release
→ the history tier — every version of every definition, content-addressed, immortal
→ as-of — the previous application is a WHERE clause, not a runbook
→ as-of — paused workflows resume against the exact hashes they started with
→ gone — no bundler, no node_modules; a vendored ~15 KB patch applier
→ the resource — schema, queries, forms, policy, and the operator plane derive from declarations
→ the catalog — the codebase has a schema; agents query it over MCP
→ a projection — the repo is a deterministic view of the code tables; the image is truth
→ admission — capability environments + verifiers in the transaction; governance is the storage format
→ a resident — the loop is a continuation, skills are admitted rows, isolation is the storage format
→ the substrate — custom objects are resource forms; no second engine interpreting a second schema
→ the catalog — endpoints, OpenAPI, webhooks, and keys are projections and grants
→ rows — labels live on definitions; a locale is a coverage query, translating it is an agent's chore
A single well-provisioned Postgres sustains thousands of governed write-interactions per second; the median SaaS never sees one percent of that. B2B SaaS, vertical products, internal tools, and — above all — products where an AI agent does the work: an agent operating on live customer data needs a catalog it can't hallucinate off of, capabilities that bound what it may touch, a vault so it never lands a name in the clear, and an audit row for every action it takes. That is not a feature list to assemble; in kern it is the storage format.
Scale up by buying a bigger Postgres — the most boring, best-understood move in the industry. Scale out by adding identical stateless kernels: sessions are rows, so no node is special, none is sticky, and any node resumes anything. You will exit this envelope around the time you can afford a platform team to build the next one.
WHERE clause. But a granted egress — a webhook it may post, a mail it may send — crosses the seam and is gone; no clause un-sends it. That an action should have been taken is a guarantee no substrate can offer. Least-capability grants, the narrowest possible egress surface, and human escalation on high-consequence restarts are the mitigation; provable judgment is on offer from no one, and we won't pretend otherwise.