01The big idea
A Quilt cell is a reactive value with a kind. It could be a number, a formula, a sensor, or a function. The same model extends to AI as a cell kind. An ai.llm cell has a prompt, a provider, a model, and a value (the model's response). It composes with everything else: it can be the input to a formula, the trigger of a listener, the body of a router.
Why is this the right abstraction? Because LLMs are slow, expensive, and nondeterministic. They need to be addressable (so you can reference them from formulas), cacheable (so you don't pay for the same prompt twice), and composable (so a model output can drive a router, which can fire another model, which can populate a sheet). The cell model is the only abstraction that gives you all three for free.
02The 4 providers
Quilt supports four AI providers out of the box. Each is a cell-level decision — you can mix and match in a single sheet.
⚡ z.ai
GLM 4.5 and AirX. Best for coding and reasoning. Strongest chain-of-thought. ~200ms latency.
🌙 Kimi (Moonshot)
Moonshot v1 8k/32k/128k. Best long-context. Web search built in. ~300ms.
🌊 DeepSeek
DeepSeek Chat (V3 Flash) + DeepSeek Reasoner (R1). Cheapest. Best for parallel workers. ~200ms.
☁️ Cloudflare Workers AI
Runs on Cloudflare's edge. Free tier 10k neurons/day. Llama 3.3, Mistral, BGE embeddings.
How to choose
| Use case | Best | Why |
|---|---|---|
| Code generation | z.ai GLM 4.5 | Strongest code, native CoT |
| Reasoning / math | DeepSeek R1 | Dedicated reasoning model |
| Long context (100k+) | Kimi 128k | Cheapest per token at scale |
| Concurrent fan-out (10+ calls) | DeepSeek Flash | Cheapest, fast |
| Embeddings (semantic search) | Cloudflare BGE | Free tier, on-edge, 768d |
| Vision (image → text) | Cloudflare Llama 3.2 Vision | On edge, no upload |
| Translation | Cloudflare M2M100 | 418 langs, free |
| Sentiment | Cloudflare DistilBERT | Fast, free |
03The 8 cell kinds
Every AI interaction in Quilt is one of 8 cell kinds. Each has a uniform interface: kind, provider, model, input (cell reference), and the cell's value is the result.
# 1. ai.llm — generic chat completion - id: ai.answer kind: ai.llm provider: zai model: glm-4.5 prompt: "{{input.question}}" # 2. ai.embed — text → vector - id: ai.embedding kind: ai.embed provider: cloudflare model: "@cf/baai/bge-base-en-v1.5" input: input.text # 3. ai.image — text → image (Stable Diffusion) - id: ai.art kind: ai.image provider: cloudflare model: "@cf/stabilityai/stable-diffusion-xl-base-1.0" prompt: "{{input.description}}" # 4. ai.translate — text → translated text - id: ai.french kind: ai.translate provider: cloudflare model: "@cf/meta/m2m100-1.2b" input: input.text target: fr # 5. ai.sentiment — text → label - id: ai.mood kind: ai.sentiment provider: cloudflare model: "@cf/huggingface/distilbert-sst-2-int8" input: review.text # 6. ai.summarize — long text → short text - id: ai.summary kind: ai.summarize provider: zai model: glm-4.5 input: doc.body max_words: 50 # 7. ai.code — description → code - id: ai.function kind: ai.code provider: zai model: glm-4.5 input: task.description language: rust # 8. ai.vision — image + text → text - id: ai.caption kind: ai.vision provider: cloudflare model: "@cf/llava-hf/llava-1.5-7b-hf" image: input.image prompt: "Describe this image"
04The execution model
When you set a value cell, the runtime does a topological sort of all dependent cells, then evaluates them in order. The same is true for AI cells — they propagate exactly like formulas. The only difference is they're async.
Input changes
A value cell is set (by user, by sensor, by API).
Dependents queue
The runtime queues all cells that depend on it.
Topological order
Cells are sorted by dependency. LLM cells go in the right place.
Evaluate
Value, formula, and sensor cells run sync. LLM cells run async.
Cache
If a cell's input is unchanged, the cached result is returned. No model call.
Propagate
New value cascades to the next level. Listeners fire.
input.text = "hello" twice, the model is only called once. This is critical when a formula or sensor updates a cell 10x/second.
05Security: API keys
API keys are sensitive. Quilt handles them in three layers, depending on where the cell runs.
Layer 1: Browser (Quilt Live)
The browser version uses CORS-enabled public endpoints. Keys are not embedded in the page. Instead, the page calls a proxy URL that you configure. The proxy holds the key.
In production, deploy a Cloudflare Worker that proxies to each provider. The browser makes a single call to your Worker, which fans out to the providers.
Layer 2: Cloudflare Worker (quilt-cloudflare)
Keys are set as Wrangler secrets. The Worker reads them with env.ZAI_API_KEY. Only the Worker has access. The browser sees nothing.
Layer 3: Local / server (TS / Rust)
Keys are read from environment variables. process.env.ZAI_API_KEY or std::env::var("ZAI_API_KEY"). Quilt never logs or persists them.
06Patterns
Six patterns that emerge naturally from the cell model.
1. Cascade (output → input)
Chain cells. The output of cell A is the input of cell B, which is the input of cell C. The cascade re-runs whenever any input changes.
- id: extract # cell 1: extract entities kind: ai.llm prompt: "Extract entities from: {{text}}" - id: classify # cell 2: classify kind: ai.llm prompt: "Classify sentiment of: {{extract}}" - id: route # cell 3: route kind: ai.llm prompt: "Where should we send this? {{classify}}"
2. Fan-out (parallel)
Three cells, same input, run in parallel. Then a synth cell takes all 3 and combines them.
- id: draft.zai kind: ai.llm provider: zai - id: draft.kimi kind: ai.llm provider: kimi - id: draft.deepseek kind: ai.llm provider: deepseek - id: best kind: ai.llm provider: zai prompt: "Pick the best of these 3: {{draft.zai}} {{draft.kimi}} {{draft.deepseek}}"
3. RAG (retrieve → augment → generate)
Embed the input. Search Vectorize for top-K. Pass the matches as context to the LLM cell.
- id: query.embed kind: ai.embed input: query.text - id: matches kind: vectorize.search vector: query.embed top_k: 5 - id: answer kind: ai.llm prompt: "Context: {{matches}}\nQuestion: {{query.text}}"
4. Agent (loop until done)
An agent cell that calls other cells in a loop. Memory is a value cell. Termination is a listener.
- id: agent.thought kind: ai.llm prompt: "Goal: {{goal}}\nStep {{step}}: what next?" - id: agent.action kind: router - id: agent.memory kind: value - id: agent.done kind: listener when: 'agent.thought contains "DONE"'
5. Memoize (cache by input)
Quilt caches by default. If you set input.text = "hello" once, the second set is a no-op. To force a re-run, use a version cell that the formula includes.
- id: input.version kind: value default: 0 - id: cache.key kind: formula value: 'input.text + ":" + input.version' - id: ai.answer kind: ai.llm prompt: "{{cache.key}}"
6. Cost control (budget)
Add a formula cell that estimates cost, a listener that checks the budget, and a router that picks a cheaper model when over.
- id: ai.cost kind: formula value: "ai.tokens * 0.001" - id: ai.over_budget kind: listener when: "ai.cost > budget.max" - id: ai.fallback kind: router routes: - when: "ai.cost > budget.max" then: "ai.deepseek" # cheaper
07Where it runs
| Runtime | AI support | Notes |
|---|---|---|
| quilt (TS) | ✓ all 8 kinds | OpenAI, Anthropic, z.ai, Kimi, DeepSeek, custom |
| quilt-rust | ✓ all 8 kinds | Same providers, sync + tokio async |
| quilt-cloudflare | ✓ 8 + Workers AI | Runs on edge, free tier available |
| quilt-live (browser) | ✓ via Worker proxy | Browser never holds keys |
| quilt-esp32 | ✓ local models only | 1.4 MB flash, 520 KB RAM |
| quilt-mesh | ✓ peer-to-peer | Each peer can be an AI node |
08What's next
The cell model absorbs AI. The next steps are obvious:
- Streaming cells (return chunks as they come)
- Multimodal cells (text + image + audio)
- Tool cells (model can call a function and get a result back)
- Persistent memory (memory that survives across sessions, encrypted)
- Agent cells (multi-step loop with self-critique)
- Federated cells (cells that run on the peer mesh)
- Self-improvement loops (try it · @quilt/evolve) — the system mutates itself based on LLM-generated adversarial inputs and LLM-judged feedback. RLAIF as a Quilt pattern. Hierarchical scopes: a cell, an organ, or a whole organism.
All of these are just new cell kinds. The runtime doesn't change.