Vercel Eve vs Mastra vs Flue 2.0: How Eve Works and Where They Differ
If you have been following the agent framework space, you know the pattern: a new framework lands every few months, and every one says durable, production-ready, and model-agnostic. Vercel's entry is called eve, and it is the first one that made me stop and re-read the architecture docs instead of skimming the marketing.
I have been running servers far longer than I have been building agents, so my questions are operational ones: where does my code actually run, what survives a crash, and what does a deploy look like? This post answers those for eve, then does the comparison the title promises: how eve, Mastra, and Flue 2.0 differ, building on the Mastra vs Flue 2.0 comparison we published earlier this month.
The short version
- Eve is filesystem-first. The agent/ directory is the contract. Paths are identity: a file at agent/tools/get_weather.ts is a tool named get_weather. No name fields, no central registry.
- Eve is durable by default. Sessions, turns, and steps run on a durable workflow runtime. Crash the process or redeploy mid-turn and the run resumes from the last completed step, with nothing to configure.
- Tool code runs in the app runtime; only the sandbox runs model-controlled code. Secrets live in the app runtime via process.env. The sandbox gets an isolated /workspace, no environment, and egress controlled by a network policy, with credential brokering at the firewall.
- The sandbox has real backends. Vercel Sandbox, Docker, a local microsandbox VM, or a pure-JS bash simulator, chosen by availability (Vercel Sandbox is only auto-selected when
process.env.VERCELis set) and pinned per agent when you want. - Deployment is Vercel-first but self-hostable. eve build produces a Nitro Node server under .output/ that runs anywhere, or .vercel/output for Vercel with Vercel Workflow and Vercel Sandbox.
- The differences with Mastra and Flue are structural, not cosmetic. Eve is a filesystem contract with a durable runtime; Mastra is a batteries-included application framework; Flue is a durable harness with a hooks API. Where code runs, who owns durability, and how much you bring yourself are the real axes.
- eve (npm)
0.37.1 - @mastra/core
1.55.0 - @flue/runtime
2.0.3 - Node.js
24 required by eve
Checked 2026-08-14 against the eve.dev docs (getting started, execution model and durability, sandbox, security model, connections, channels, subagents, CLI, deployment), the vercel/eve GitHub repo, and the npm registry. Mastra and Flue versions are carried from our earlier Mastra vs Flue 2.0 post (checked 2026-08-05); both projects move fast, so re-check before you rely on them.
What Vercel Eve actually is
Eve is Vercel's open-source framework for building durable AI agents. The npm package is named eve, the CLI binary is eve, and the docs open with a strong claim: the filesystem is the authoring interface. You write markdown for the parts a human reads like a spec, and TypeScript for the parts that need real types and runtime behavior.
The default scaffold routes model traffic through the Vercel AI Gateway: you set AI_GATEWAY_API_KEY, or link a Vercel project and use VERCEL_OIDC_TOKEN. If you do not want the gateway, install the AI SDK provider package for your model and pass the provider's LanguageModel directly. Eve requires Node.js 24 or newer.
The filesystem is the authoring interface
A minimal project looks like this:
my-agent/
├── package.json
├── tsconfig.json
└── agent/
├── agent.ts # optional: model and runtime config
├── instructions.md # required: always-on system prompt
├── tools/ # typed functions the model can call
├── skills/ # procedures loaded on demand
├── channels/ # HTTP and messaging entry points
├── connections/ # MCP and OpenAPI services
├── hooks/ # lifecycle and stream-event subscribers
├── lib/ # shared authored code, import-only
├── sandbox/ # optional override, plus workspace seeds
├── schedules/ # recurring jobs
└── subagents/ # specialist child agents
evals/ # lives beside agent/, not inside itIdentity comes from the path. You never write a name or id field on a define call:
Path | Resolves to |
|---|---|
agent/tools/get_weather.ts | tool get_weather |
agent/connections/linear.ts | connection linear |
agent/skills/summarize.md | skill summarize |
agent/subagents/researcher/agent.ts | subagent researcher |
root agent name from package.json name | root agent |
The root agent takes its name from package.json; a subagent takes its name from its directory. Files under agent/sandbox/workspace/ are seeded into /workspace when a session starts, skill files land under $HOME/.agents/skills/, and lib/ stays import-only source code.
Hands-on: first Eve project
The fastest way to feel the difference is to scaffold one:
$ npx eve@latest init my-agent
# creates my-agent/, installs dependencies, initializes Git
# and offers to start the dev server
$ cd my-agent && npm run dev
# the TUI sends messages to your agent
# pick a model and reasoning effort up front
$ npx eve@latest init my-agent --model openai/gpt-5.6-terra --reasoning highTo add eve to a project that already has a package.json, run npx eve@latest init . from its root before you create any agent/ files. It adds the missing eve, ai, and zod dependencies without touching files the project already owns.
The default model when no agent.ts exists is zai/glm-5.2. Change it with eve set --model anthropic/claude-opus-4.8, or from the TUI with /model:
// agent/agent.ts
import { defineAgent } from "eve";
export default defineAgent({
model: "anthropic/claude-opus-4.8",
});A tool is a typed function the model can call. The filename is the name the model sees, and the execute function runs in the app runtime with full access to process.env, not in the sandbox:
// agent/tools/get_weather.ts
import { defineTool } from "eve/tools";
import { z } from "zod";
export default defineTool({
description: "Get the current weather for a city.",
inputSchema: z.object({ city: z.string().min(1) }),
async execute({ city }, ctx) {
return { city, condition: "Sunny", temperatureF: 72 };
},
});Tools can be gated on human approval with the always()/once()/never() helpers, and can project their output for the model with toModelOutput while channels and hooks still get the full result. When something is not discovered the way you expect, eve info prints the discovered surface and diagnostics, eve logs reads JSONL diagnostic logs, and eve traces shows local span trees.
How Eve runs under the hood
Work nests in three levels: a session is the whole durable conversation, a turn is one user message and everything it triggers, and a step is a durable checkpoint inside a turn, one model call plus the tool calls it makes. Every turn runs as a durable workflow on the open-source Workflow SDK. In local development and a self-hosted eve start process, workflow runs persist under .eve/.workflow-data; on Vercel, the same code runs against Vercel Workflow.
- Crash recovery: kill the process, hit a timeout, or redeploy mid-turn and the run resumes from the last completed step. Completed steps never re-run; eve replays the recorded result.
- Parked work: when a tool needs human approval, an OAuth sign-in needs a browser, or a subagent is still running, the turn parks durably. The workflow suspends and holds no compute until the input it is waiting on arrives, even if that is much later.
- Message steering: while a turn is active, new input is buffered durably and the active turn is cooperatively cancelled (turnPolicy steer, the default). Set turnPolicy to queue when every turn must finish before the next one starts.
The sandbox and the trust boundary
Eve spans two execution environments. The app runtime is the trusted side: your tool implementations, model calls, connections, hooks, and instrumentation run there with full Node.js access and process.env. The sandbox is the isolated side: it owns the per-session filesystem rooted at /workspace and runs shell commands, with no environment, no secrets, and no path back into the app runtime.
- The built-in bash, read_file, write_file, glob, and grep tools all target the sandbox, and they are implemented in the app runtime and proxy into it. The model drives the sandbox through tool calls, never by holding a credential.
- Authored tools reach the sandbox through ctx.getSandbox() when they need isolated file or process work, for example running a Python analysis script and returning its output.
- Sandbox backends: vercel() on Vercel Sandbox, docker() via the docker CLI with the ghcr.io/vercel/eve:latest image, microsandbox() in a local VM on Apple Silicon or Linux with KVM, and justbash(), a pure-JS bash simulator with no real binaries. The default picks Vercel, then Docker, then microsandbox, then just-bash, in that order.
- Network egress: the default policy is allow-all. Set deny-all or an explicit allow-list for anything sensitive. The Vercel and microsandbox backends support domain-level policies and credential brokering, which injects auth headers at the firewall so the secret never enters the sandbox process. The Docker backend only honors allow-all or deny-all.
Connections, channels, and subagents
Three capabilities that matter for real deployments:
- Connections: agent/connections/linear.ts wires in an MCP server or an OpenAPI document. The model discovers tools through connection_search and calls them by qualified names such as linear__list_issues. Tokens come from getToken or an OAuth flow, are cached per step, and never reach the model or land in durable state.
- Channels: the eve HTTP channel is enabled by default and is what the TUI and curl talk to. Platform channels for Slack, Discord, Teams, Telegram, Twilio, GitHub, Linear, and iMessage (via Photon) install from the registry with eve add channel/slack, and you can author custom channels with defineChannel. The file stem is the channel id.
- Subagents: a built-in agent tool delegates to a fresh copy of the root agent, and declared subagents under agent/subagents/ get their own instructions, tools, skills, sandbox, and state. Nothing crosses the boundary implicitly; each child starts with fresh durable state.
- Schedules: agent/schedules/*.ts defines recurring jobs as defineSchedule modules or markdown with cron frontmatter, and schedules are root-only.
Deploying Eve
The deployment strategy decides the build output, the workflow store, and the sandbox backend:
$ npx eve build
# compiles .eve/ artifacts and the host output
$ npx eve start
# serves .output/ locally; port $PORT, then 3000
$ curl https://your-agent.example.com/eve/v1/health
# on Vercel: link, then deploy to production
$ npx eve link
$ npx eve deploySelf-hosting, eve build writes a standard Nitro server under .output/ and eve start serves it. Two choices are yours: the workflow world (the local world persists under .eve/.workflow-data, and advanced setups can pin @workflow/world-postgres via experimental.workflow.world) and the sandbox backend (docker() or microsandbox() on your own hardware). Before accepting browser traffic, replace placeholderAuth() with a real policy: routes reject unauthenticated requests with 401 by default, and the scaffold intentionally ships closed.
The differences: Eve vs Mastra vs Flue 2.0
Now the comparison. We went deep on Mastra and Flue in the earlier post, so the table below is the whole field, followed by the sections that actually decide the choice: mental model, where code runs, durability, batteries, and business model.
Feature | Eve (0.37.x) | Mastra (1.55) | Flue 2.0 (2.0.x) |
|---|---|---|---|
Authoring model | Filesystem contract, paths are identity | Config objects + registry | Function + hooks, re-renders per turn |
Durable runtime | Yes, default: sessions, turns, steps on Workflow SDK | Workflows with suspend/resume, Inngest/Temporal runners | Yes: conversation runtime, step.do() checkpoints, Durable Objects on Cloudflare |
Code execution | App runtime + isolated sandbox, credentials brokered | App process; Code Mode in @mastra/isolated-vm | App runtime; sandbox opt-in, local() runs on your host |
Memory | None built in; defineState + bring your own | Four tiers: history, working, semantic, observational | None built in; usePersistentState + compaction |
RAG | Bring your own via tools/MCP | Built in: chunking, embeddings, vector stores, GraphRAG | Bring your own via tools/MCP |
Evals | evals/ directory, defineEval, eve eval | About 20 scorers, datasets, experiments, gates, CI | Vitest suites + vitest-evals |
Human-in-the-loop | Approval on tools/connections, parked turns | First-class approvals, workflow suspend/resume | No approval primitive; build via channels/SDK |
Channels | HTTP + Slack, Discord, Teams, Telegram, Twilio, GitHub, Linear, Photon | Slack, Teams, Discord, Telegram, WhatsApp, iMessage | Via blueprints/SDK, not first-class |
MCP | Consume MCP + OpenAPI via connections | Consume MCP + author MCP servers | Consume remote MCP via useMcpConnection |
Local tooling | TUI + CLI (info, logs, traces) + registry | Studio at localhost:4111, graph viz, evals UI | CLI only, no first-party UI |
Deployment | Vercel (Workflow + Sandbox) or self-hosted Nitro Node | Standalone server, adapters, Platform, Inngest/Temporal | Node (Vite + Hono) or Cloudflare Workers |
License | Apache-2.0; preview under Vercel beta terms | Apache-2.0 core + ee/ enterprise boundary; paid Platform | Apache-2.0, no hosted product |
The mental models are the real difference
Eve says the directory is the contract: markdown and TypeScript in conventional paths, identity from the filename. Mastra says configuration and graphs: new Agent({...}) objects and typed workflow steps. Flue says render-with-hooks, React for agents: the agent function runs fresh before every model call and its hooks declare what exists this turn. These are three different answers to where the source of truth lives, and they change how a new person reads your repo.
Where code runs decides the security story
Eve splits execution into a trusted app runtime and an isolated sandbox, with credentials brokered at the sandbox firewall. Mastra runs model-authored programs in Code Mode, backed by @mastra/isolated-vm, an in-process V8 isolate with no filesystem, network, or process access. Flue made sandboxes opt-in in 2.0, and the default local() backend executes commands on your host machine. That last point is a security decision, not a convenience: if you point Flue at real infrastructure, use a container or remote backend.
Durability is default, opt-in, or workflow-level
Eve and Flue both make the conversation itself durable: eve with the Workflow SDK and parked work, Flue with exactly-once message delivery and durable tools that checkpoint side effects. Mastra's durability story is at the workflow level, suspend and resume plus Inngest/Temporal runners, while the agent loop itself is less of a durable-execution claim. If your question is what happens when the process dies mid-task, Eve and Flue are the direct answers; Mastra is the answer when you need deterministic multi-step orchestration with human gates.
Batteries: Mastra brings them, Eve and Flue do not
Mastra ships memory, RAG, GraphRAG, evals with dozens of scorers, channels, and a local Studio, all in one repo, and it is the only one of the three with a hosted platform. Eve ships a registry (eve add channel/slack, eve add linear), first-class connections, evals, and instrumentation, but memory and RAG are yours to compose. Flue ships the harness and little else: persistent state, tools, skills, and the expectation that you bring the vector store. The less you want to assemble, the more Mastra's batteries matter; the more you want to own the stack, the less you need them.
Business model and maturity
Mastra is a venture-backed company (Kepler Software, about $35M raised) with an Apache-2.0 core, an ee/ enterprise boundary, and a paid Platform. Flue is the Astro team's open-source project, pure Apache-2.0, no hosted product. Eve is Vercel's open-source framework, Apache-2.0, currently a preview under the Vercel beta terms, with a Vercel-first deploy path. Maturity: Mastra ships weekly at 1.55; Flue went from beta to 2.0 in about two months and is on patch releases; eve is at 0.37.x with very active weekly downloads on npm. Version-pin all three and read the changelog before every upgrade.
Which should you pick?
- Choose Eve when: you want the filesystem contract and inspectable config, durable sessions by default without standing up an orchestrator, a sandbox with real backends and network policy, and a deploy path that works on Vercel or on your own Nitro Node server. Node 24 and the AI SDK ecosystem are the costs.
- Choose Mastra when: you want memory, RAG, evals, channels, and a Studio out of the box, deterministic workflows with human approvals, or you are adding agents to an existing TypeScript application and want framework adapters.
- Choose Flue 2.0 when: you are building autonomous, sandboxed coding agents, you want capabilities that change at runtime through hooks, or you deploy on Cloudflare Workers and want Durable Object durability. Pure Apache-2.0 with no hosted product.
- Consider neither when: the flow is fully deterministic (plain code, cron, Temporal, Inngest), your organization is Python-first, or you only need streaming chat, where the Vercel AI SDK alone is the honest answer.
I did not pick a winner in the Mastra vs Flue post, and I am not going to here. Build your real workflow, with a tool call, a failure path, an approval point, and something observable, in the framework that matches your mental model, and keep the other two in mind for the next project. The good news is that all three are TypeScript, all three are Apache-2.0 at the core, and all three will break your code if you ignore upgrades for a quarter.
Official sources
- eve docs, getting started: https://eve.dev/docs/getting-started
- eve execution model and durability: https://eve.dev/docs/concepts/execution-model-and-durability
- eve sandbox: https://eve.dev/docs/sandbox
- eve security model: https://eve.dev/docs/concepts/security-model
- eve CLI reference: https://eve.dev/docs/reference/cli
- vercel/eve on GitHub: https://github.com/vercel/eve
- eve on npm: https://www.npmjs.com/package/eve
- Our earlier comparison, Mastra vs Flue 2.0: https://systhoughts.com/posts/mastra-vs-flue-2-0-typescript-agent-frameworks
Are you running eve, Mastra, or Flue in production yet? Which one earned its keep, and which one bit you? Drop it in the comments.
Until next time, keep your systems thoughtful.

No comments yet