Menu

← All posts

How it works · part one

How a Traid assistant works

June 14, 2026

An assistant answers from what you wrote, and when an answer needs to be interactive it builds a small app on the spot. This is the first in a series on how that works. We start with the overall architecture. Later posts go deep on the sandbox.

Two kinds of agents

One assistant, two ways to respond.

Every assistant is made of agents, and there are two kinds. Conversational agents answer in text. They read your notes and reply like a colleague who has studied them: summaries, lookups, recommendations, anything where the right answer is a sentence or a paragraph.

Toolchain agents do something different. Instead of replying with words, they build an interactive mini app, a planner, a calculator, a checklist, and hand it back to you inside the conversation. Same knowledge base, different output. An assistant can have several of each.

Routing: deciding how to respond

A small classifier picks the right agent for each message.

When you send a message, a router model reads it alongside short descriptions of the assistant's agents and any apps you've already saved. It returns a routing decision as JSON: run an existing app, hand off to a conversational agent, or hand off to a toolchain agent to build something new.

routing decision

{
  "type": "agent",
  "selectedAgent": "Recipe Planner",
  "reason": "User asked to plan meals, which the planner handles"
}

Because routing is its own step, the assistant stays focused. A request to "open my budget app" launches the app; a request to "change the budget app to show weekly totals" goes to an agent that can edit it. The router decides which, every turn.

Apps are generated on demand

A toolchain agent writes a small program in a Lisp DSL.

When a toolchain agent is chosen, it generates a short program in a Lisp dialect modeled on Clojure. The agent is prompted to return one code block describing a UI tree, which Traid parses out of the response and runs. Nothing is pre-built. The app is written fresh, from your request and your notes, each time.

a generated mini app

(def quotes
  (list {:text "Stay hungry" :by "Jobs"}
        {:text "Less is more" :by "Rohe"}
        {:text "Know thyself" :by "Socrates"}))

(defn quote-card [q]
  (div :class "flex-col gap-1 p-3 rounded-lg border"
    (p :class "text-lg" (:text q))
    (p :class "text-sm" (:by q))))

(defn quote-list []
  (->> quotes
       (sort-by :by)
       (map quote-card)))

(defn main []
  (div :class "flex-col gap-3 p-4"
    (h2 "Quotes")
    (quote-list)))

(main)

The functions you see here, div, h2, map, sort-by, are the entire vocabulary the program has. That detail turns out to be the foundation of the safety story.

Why this is safer to run

Sandboxed by construction, not by scanning.

Most "AI builds an app" tools generate real JavaScript and run it in your browser. That code can do anything your browser can: call out to the network, read storage, touch other pages. Vetting it means scanning generated code for bad behavior, and scanners miss things.

Traid takes a different path. A generated app is never executed as code. It's interpreted: Traid reads the program and evaluates it step by step against a fixed set of building blocks. An app can only call functions that have been explicitly registered with the interpreter, and the only ones registered are safe UI and data builders. There is no fetch, no eval, no file or network access in scope, because those were never added to its vocabulary in the first place.

On top of that, every run is bounded. An app that loops forever or runs too long is stopped automatically, so a bad program can't freeze your browser. The result is a sandbox by construction. The attack surface is far smaller, not because we try to catch the dangerous parts, but because the dangerous parts don't exist in the language it's allowed to speak. No approach is a silver bullet, but there is much less here to target in the first place.

Designed to self correct

Generated, checked, and repaired before you see it.

Generated programs can still have ordinary mistakes. Before an app reaches you, Traid lints it and runs it. If something fails, the exact error is fed back to the agent with a request to fix that specific problem, and it tries again, a few times if needed. You only see an app once it runs cleanly, or a clear message and a retry if it truly can't. We'll cover this loop in its own post.

Save once, reuse free

Generation has a cost. Reuse doesn't.

Building an app spends a small amount in tokens, since a model writes it. Save one to Quick Launch and it runs free from then on, no model call required. When someone saves an app you made, they pay the price you set and get unlimited free reuse, and you earn the credits.

Next in the series: a closer look at the sandbox.