I’ve been on a kick lately, building small agents in TypeScript instead of Python. Two frameworks keep showing up in my browser tabs: Flue and Mastra. They’re both betting on the same thing: TypeScript is the right language to ship AI in. They just disagree about almost everything else.
That disagreement is the interesting part.
The harness vs the workflow
Flue’s pitch is one line: Agent = Model + Harness. The framework gives you a programmable harness. Sandbox, filesystem, bash, sessions, skills with structured output. You drop in a model. You get something that looks a lot like Claude Code or Codex, except you wrote it and you deploy it.
Here’s a Flue agent that triages a GitHub issue:
import type { FlueContext } from '@flue/sdk/client';
import * as v from 'valibot';
export default async function ({ init, payload }: FlueContext) {
const agent = await init({ model: 'anthropic/claude-opus-4-7' });
const session = await agent.session();
const triage = await session.skill('triage', {
args: { issueNumber: payload.issueNumber },
result: v.object({
severity: v.picklist(['low', 'medium', 'high', 'critical']),
reproducible: v.boolean(),
summary: v.string(),
}),
});
return triage;
}
The whole shape is: init the agent, open a session, call a skill, get a typed result back. The skill is a directory of prompts and tools that the harness orchestrates. Your code never has to babysit a tool-call loop. The framework is doing it.
Mastra goes the other way. The core abstractions are agents, workflows, and RAG. You compose them, evaluate them, and deploy them as APIs next to your Next.js or Hono app.
A roughly equivalent Mastra agent:
import { Agent } from '@mastra/core';
import { z } from 'zod';
export const triageAgent = new Agent({
name: 'issue-triage',
instructions: 'You triage GitHub issues. Be concise.',
model: { provider: 'ANTHROPIC', name: 'claude-opus-4-7' },
});
export async function triage(issueNumber: number) {
const result = await triageAgent.generate(
`Triage issue #${issueNumber}`,
{
output: z.object({
severity: z.enum(['low', 'medium', 'high', 'critical']),
reproducible: z.boolean(),
summary: z.string(),
}),
},
);
return result.object;
}
Different shape entirely. You declare the agent up front, you call .generate() with a structured output schema, you get an object back. There’s no harness loop driving sessions and skills. There’s just a model with tools, and you wire it into your app like any other service.
Where they diverge
| Flue | Mastra | |
|---|---|---|
| Mental model | Agent = Model + Harness | Agent = LLM with tools |
| Primitives | Sessions, skills, sandboxes | Agents, workflows, RAG |
| What you bring | Skill prompts and tools | Instructions, tools, eval suites |
| Deploy targets | Node, Cloudflare Workers, GitHub Actions | Anywhere TypeScript runs, plus Mastra Cloud |
| Replaces | Dosu, Greptile, CodeRabbit | Honestly, half of LangChain |
| Tagline | “Stop renting someone else’s agent” | “Python trains, TypeScript ships” |
If you’re building something that acts (writes files, runs commands, reads a repo, works through a task across many tool calls), Flue’s harness model is doing more for you. If you’re embedding an agent into an existing app and the bigger problem is glue, eval, and observability, Mastra has more of the production scaffolding ready to go.
I don’t think one is winning yet. They might both be right for different jobs.
The thing nobody’s saying out loud
Both of these projects assume something I would have laughed at five years ago: that TypeScript is a serious language for building AI infrastructure. Not a frontend duct tape. Not a glue layer. The actual substrate.
A couple weeks back, Microsoft shipped the TypeScript 7.0 beta, and the punchline is that the compiler is no longer written in TypeScript. It’s written in Go. Native code, shared memory parallelism, the whole thing. They’re claiming about 10x faster than 6.0 on real codebases. The language server, too. The editing experience is reportedly night and day.
Read that twice. The TypeScript team looked at the language they invented, decided it wasn’t fast enough to compile itself, and rewrote the toolchain in Go. That’s a remarkable thing to do.
It also reframes everything. If tsc is fast enough that incremental compiles feel like Go’s build times, the cost-of-iteration argument against TypeScript for serious systems work mostly evaporates. The other arguments (no real concurrency, GC pauses, V8 quirks) are runtime arguments, and most agent code is I/O bound on a model API anyway.
So you get a typed, npm-friendly, JIT’d runtime with a now-fast toolchain, and the LLM ecosystem has decided to publish first-class SDKs for it. That’s a pretty good place for a framework to land.
Flue and Mastra are both betting on it. They might both be right.
What I’d actually pick
For a coding agent, an issue triage bot, anything that needs to do work in a sandbox: Flue. The harness model is the right level of abstraction for that kind of work, and “drop your code in a Cloudflare Worker, point a webhook at it” is a stupidly nice deployment story.
For a chat-shaped assistant living inside a real product, with eval suites and traces and the whole observability story: Mastra. The framework gets out of your way and the tooling around it is more mature.
For everything else: keep an eye on both. The TypeScript-as-AI-substrate bet is going to play out fast, and a 10x faster compiler landing the same year is not a coincidence I would have predicted.