Vercel Eve vs Mastra vs Flue 2.0: How Eve Works and Where They Differ

A hands-on, sysadmin-grade guide to Vercel Eve: how the filesystem-first agent framework works, from scaffolding and tools to durable sessions, sandbox backends, and deployment, plus a deep comparison of Eve, Mastra 1.55, and Flue 2.0.

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.VERCEL is 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.
Verified
  • eve (npm)0.37.1
  • @mastra/core1.55.0
  • @flue/runtime2.0.3
  • Node.js24 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 it

Identity 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:

first eve project
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 high

To 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:

build and deploy
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 deploy

Self-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