Research & engineering notes
Honest, technical writeups on how Zod Agent is built. No hype — just the architecture decisions behind a client-side agent runtime.
Read the notesThe client-side agent loop
Zod Agent runs a real multi-round function-calling loop entirely in the browser. When you send a message, it builds history from the current session, calls your configured provider with the full set of tool schemas, executes any requested tool calls locally, and feeds the results back — repeating up to six rounds. Everything from the request to the tool execution to the final streamed answer uses browser APIs only: fetch + ReadableStream for streaming, localStorage for persistence. Because there's no server, the same codebase ports cleanly to the Chrome extension and the desktop app — the entire platform surface is just the browser APIs the app already uses.
Structured output rendering
Instead of building a structured-output schema layer on top of the provider API, Zod takes a lighter approach: the default system prompt invites the model to optionally emit lightweight [section] markers, and a parser (parseLlmOutput) turns those into distinct UI cards — thinking steps, findings, suggestions, to-dos, code blocks, files, errors, security warnings, visualizations, and Approve/Reject confirmation plans. Plain text passes through untouched. This keeps rendering flexible across every OpenAI-compatible provider without depending on a specific tool-call output format. It's pragmatic: markers are a contract with the model, not a guarantee, which is why every renderer also handles their absence gracefully.
The aligned YAML formatter
One of Zod's signatures is a hand-rolled YAML formatter that re-emits every config document with all mapping colons aligned to a single global column. It parses with js-yaml, then chooses inline vs. block layout based on a live line budget measured from the editor width, and wraps long scalar values — like API keys — at the value column. The editor layer ("Socratic" line rendering) highlights keys, masks secrets unless toggled, makes booleans clickable, links URLs, and highlights $ENV variables. Each config section also gets an "ask AI" input that sends the current YAML to the provider and asks for a complete, valid replacement document. The same formatter powers the yaml_format tool, so what you see in the editor is what the agent produces.
The service-worker background scheduler
Scheduled work in a browser normally dies with the tab. Zod's scheduler doesn't: a classic service worker mirrors the app's localStorage document into an IndexedDB store on every save, ticks due crons every two seconds, and runs each one through the full agent loop — tools included, or a whole workflow harness if the task is wired to one — against your configured provider. Up to three cron runs execute concurrently. Results are pushed to an IndexedDB outbox that the page imports on reopen, so a run that completes while you're away shows up as a done task with its reply. The honest caveat is that a service worker only lives while the browser is open. Making it truly always-on — firing even when the browser is closed — is why the extension target plans to move the scheduler onto chrome.alarms; that's on the roadmap.
Deeper reading
Want the full picture? The changelog walks through how these pieces shipped, and the docs go into operational detail.