We recently teamed up with CoPilot Kit for a joint workshop on building agents that run entirely in the browser using TypeScript. Copilot Kit is an open-source framework for embedding AI copilots directly into your app UI, enabling them to perform real actions like submitting forms, triggering UI updates, and calling APIs. They bring the same rigor to frontend-agent interaction that Mastra brings to agent runtime.
Pairing Mastra with Copilot Kit lets JS engineers build full-stack AI agents that persist state, handle real inputs, and run directly in the browser, with no backend required.
This demo shows a real-world, multi-step workflow where a user-facing copilot could:
- Query backend APIs
- Parse and transform user data
- Trigger UI changes in response to reasoning steps
- Maintain session-aware memory across interactions
And all of it was handled in TypeScript-with no model lock-in, no proprietary DSL, and no backend roundtrips. A phrase that stuck with the workshop audience: "Shipping full-stack, production-ready agents—auth, context persistence, long-tails included."
Developers could step through the logic, tweak behavior live, and inspect memory without leaving the devtools. No special tooling like bespoke agent orchestration CLIs or closed-source SDKs. No custom language like YAML flows or internal DSLs. Just plain TypeScript—functions, promises, async flows—wired together with your own fetches, UI components, and toolchains. Code that runs in-browser, debugs in devtools, and integrates cleanly with your existing frontend stack.
Why Most Agent Stacks Break Down for JS Engineers
Building AI agents typically means hopping between languages and abstractions. You write your core logic in Python, use YAML or DSLs for orchestration, and try to glue it all into a JavaScript frontend. That’s cognitively expensive and brittle in practice.
Too many agent SDKs feel like this:
- You install a CLI that scaffolds a mystery box.
- You write YAML or a new DSL to describe flows.
- You pray it works, then backtrack to the frontend to wire up UI.
- It’s disjointed. Slow. Hard to debug.
"I changed the agent logic and saw the UI update without a single refresh or build step." —Harsh Makadia (Copilot Kit)
That's what happens when your agent runs in the browser. Mastra and Copilot Kit make it feel like just another TypeScript module.
What “Full-Stack TypeScript Agents” Actually Means
1. Single Language, Full Surface Area
TypeScript defines everything: agent logic, UI behaviors, execution steps, memory. No context switching. Just tsc
and go.
// Basic step definition
const steps = [
async () => await showForm({ fields: ["email", "intent"] }),
async (data) => await fetch(`/api/enrich?email=${data.email}`),
async (resp) => await showResult(resp)
];
2. In-Browser Execution
With WebAssembly
and SharedArrayBuffers
, agents run client-side. That means faster iteration, less latency, and fewer backend calls.
"This isn't just rendering UI in the browser—your agents live and think there too." —Harsh Makadia (Copilot Kit)
3. Composable Agent+UI Workflows
Agents can call await showForm(), await selectFromList()
, or trigger modals inline. Every UI interaction becomes a first-class step in the agent's reasoning loop.
await agent.run(async (ctx) => {
const userInput = await ctx.tools.showForm({ fields: ["searchTerm"] });
const results = await searchDocs(userInput.searchTerm);
return await ctx.tools.selectFromList(results);
});
4. Explicit State + Control
You own the agent plan, memory, and tools. No magic methods. No vendor lock-in. Just TypeScript functions and object literals. "It’s just TypeScript functions. No new DSL. No ceremony." —Shane Thomas (Mastra)
Production-Ready Means the Boring Stuff Works
"Production-ready" doesn’t mean perfect. It means predictable, testable, ship-fast-with-confidence.
- Auth flows: Your agents can securely track users, pass tokens, and restrict access.
- Context that persists: Memory survives across sessions, tabs, and reloads. CRM assistant? Agent-powered dashboard? All covered.
- Edge-case handling: Custom tools. API retries. User disambiguation. It all works because you own the control logic.
"Let’s stop romanticizing agents and start productizing them." —Shane Thomas (Mastra)
Why This Architecture Works for Engineering Leaders
If you're making architecture decisions, full-stack TypeScript agents solve a common pain: fragmentation between teams. When your ML logic is in Python, your UI is in React, and your workflow glue is in YAML, you get slower onboarding, more integration bugs, and hard-to-trace failures.
This model fixes that by collapsing logic and interface into a single, testable language.
-
One language = fewer silos
-
Runs in browser = easier onboarding
-
Devtools-native = faster debugging
-
Open-core = modifiable, forkable, inspectable
It’s about owning the whole experience, with tools your team already knows.
Thanks again to the CopilotKit crew for the joint workshop. Watch the full replay here