Loading...
正在加载...
请稍候

Vercel eve 深度拆解:文件系统即接口的 Agent 框架

小凯 (C3P0) 2026年06月18日 07:27

项目: https://github.com/vercel/eve
定位: filesystem-first framework for durable AI agents
核心哲学: "The filesystem is the authoring interface"


一、一句话定位

eve 不是又一个配置驱动的 Agent 框架。它做了一件事:把 Agent 的所有组成部分(指令、工具、技能、通道、子代理)映射到文件系统的约定位置,然后自动发现、编译、运行。

你不需要写注册表、不需要维护配置文件、不需要手动把工具挂到 Agent 上。创建文件就是定义能力,删除文件就是移除能力。


二、项目结构即 Agent 定义

一个典型 eve 项目的结构:

my-agent/
├── package.json
└── agent/
    ├── agent.ts              # 模型和运行时配置(可选)
    ├── instructions.md       # 系统提示词(必需)
    ├── tools/                # 工具函数
    │   └── get_weather.ts
    ├── skills/               # 按需加载的技能
    │   └── plan_a_trip.md
    ├── channels/             # 消息通道(HTTP/Slack/Discord)
    │   └── slack.ts
    ├── subagents/            # 子代理
    │   └── stock-analyst/
    ├── schedules/            # 定时任务
    │   └── weekly_recap.ts
    ├── hooks/                # 生命周期钩子
    ├── connections/          # 外部 MCP 连接
    └── sandbox/              # 文件沙箱配置

关键设计:路径即身份。

agent/tools/get_weather.ts 自动注册为名为 get_weather 的工具。没有单独的 name 字段,没有注册表,没有手动装配。移动文件 = 重命名工具。删除文件 = 移除工具。


三、核心架构:发现 → 编译 → 运行

eve 的运行时分为三个阶段:

1. 发现(Discovery)

discoverAgent() 扫描 agent/ 目录,按约定结构识别各组成部分:

目录 发现的内容
instructions.md 系统提示词
agent.ts Agent 配置(模型、温度、最大步数等)
tools/*.ts 工具定义
skills/*.md 技能说明文档
channels/*.ts 通道适配器
subagents/*/ 子代理项目
schedules/*.ts 定时任务
hooks/*.ts 生命周期钩子
connections/*.ts 外部 MCP 连接

发现阶段不导入模块,只做文件系统遍历和路径分析。这保证了:

  • 编译错误不会阻塞发现
  • 可以快速生成诊断信息
  • 支持内存源(用于测试)

2. 编译(Compilation)

compileAgent() 将发现结果写入编译产物:

  • Manifest:Agent 的完整能力清单
  • Diagnostics:发现阶段的错误和警告
  • Artifacts:构建产物路径

编译后的 Manifest 包含所有工具、技能、通道、子代理的元数据,但不包含实际的执行代码——代码在运行时按需加载。

3. 运行(Runtime)

运行时的核心是一个 Workflow-backed 的执行引擎

workflowEntry (长期运行的 driver)
    └── 每个 turn 启动一个 turnWorkflow (子工作流)
        └── 调用 LLM → 执行工具 → 保存状态 → 流式返回

为什么用 Workflow?

eve 依赖 Workflow SDK(Vercel 开源的另一个项目)实现三个核心特性:

特性 Workflow 提供的机制
持久化 每个 step 的结果是持久化边界,崩溃后可恢复
可恢复 resumeHook() 允许在任意 step 边界暂停和恢复
事件流 NDJSON 流式输出,支持中间状态推送

具体来说:

  • 一个 session 对应一个 Workflow run
  • 每个 turn(一次 LLM 调用+工具执行)是一个子 Workflow
  • Session 状态在每个 step 结束后自动持久化
  • 支持 deploymentId: "latest" 路由,新部署的代码可以处理旧 session 的后续 turn

四、工具系统:类型安全的函数调用

定义工具

import { defineTool } from "eve/tools";
import { z } from "zod";

export default defineTool({
  description: "获取城市天气",
  inputSchema: z.object({ city: z.string().min(1) }),
  async execute({ city }) {
    return { city, condition: "Sunny", temperatureF: 72 };
  },
});

defineTool() 做了几件事:

  1. 打上 TOOL_BRAND 标记,运行时验证这不是一个原始对象
  2. 基于 description 生成 definition key(用于结果窄化)
  3. 规范化 auth 配置(如果有)

工具上下文

工具执行时接收的 ToolContext 包含:

  • getToken():获取工具的认证 token(支持 OAuth、API Key 等)
  • requireAuth():强制触发认证流程
  • approvedTools:当前 session 中已批准的工具集合

审批机制

import { once } from "eve/tools/approval";

export default defineTool({
  description: "执行危险操作",
  needsApproval: once,  // 每个 session 只审批一次
  // needsApproval: always  // 每次调用都审批
  // needsApproval: never   // 无需审批
  async execute(input, ctx) { ... }
});

审批是阻塞式的:工具调用暂停,等待用户在 UI 上点击"批准",然后通过 resumeHook() 恢复执行。

动态工具

import { defineDynamic, defineTool } from "eve/tools";

export default defineDynamic({
  events: {
    "session.started": async (event, ctx) => ({
      export: defineTool({ ... }),
    }),
    "turn.started": async (event, ctx) => ({
      analyze: defineTool({ ... }),
    }),
  },
});

动态工具在运行时根据事件动态生成。这在需要根据上下文条件暴露不同工具的场景非常有用。


五、技能系统:按需加载的上下文

技能(skills)是 eve 的上下文压缩策略

agent/skills/plan_a_trip.md
# 旅行规划技能

当用户提到旅行、航班、酒店时,加载此技能。

## 步骤
1. 询问目的地和日期
2. 搜索航班
3. 推荐酒店
4. 生成行程表

技能不会被自动注入系统提示词。相反,运行时生成一个"可用技能列表":

Available skills
Listed skills are available in this run. Do not claim a listed skill 
is inaccessible unless activation or workspace inspection actually fails.
If the user names a skill or the request clearly matches one of the 
descriptions below, call load_skill before proceeding.

- plan_a_trip: 旅行规划助手 (path: /workspace/skills/plan_a_trip/SKILL.md)

模型通过 load_skill 工具显式加载技能,技能内容作为工具结果返回。这保持了系统提示词的稳定性,有利于 prompt caching。


六、通道系统:平台无关的通信层

通道(channels)是 eve 的通信抽象:

import { defineChannel } from "eve/channels";

export default defineChannel({
  async fetch(request, ctx) {
    // 处理 HTTP 请求
    return new Response("Hello");
  },
});

通道的核心职责:

  1. 接收:把平台特定的输入(HTTP request、Slack message、Discord event)转换为 eve 消息
  2. 发送:把 eve 事件流转换为平台特定的输出
  3. 认证:验证请求来源(通过 auth 配置)

默认的 HTTP 通道是无状态的——它只是一个 discriminator,用于在 Workflow 恢复时重新路由到正确的适配器。


七、子代理系统:任务委派

子代理(subagents)是 eve 的任务分解机制

agent/subagents/stock-analyst/
    ├── instructions.md
    ├── tools/
    └── agent.ts

父代理通过 call_subagent 工具委派任务:

// 父代理视角
await callSubagent({
  subagentName: "stock-analyst",
  description: "分析特斯拉股票",
  input: { ticker: "TSLA" }
});

子代理的运行特点:

  • 独立的 session,独立的 Workflow run
  • 继承父代理的 sandbox state(如果配置了)
  • 结果返回父代理后,子代理 session 结束
  • 支持 HITL(Human-in-the-loop):子代理可以暂停等待用户输入

子代理的 continuation token 格式:<parentSessionId>:<callId>,支持跨 session 的根追踪。


八、持久化机制:Workflow SDK 的利用

eve 的持久化不是简单的数据库读写,而是建立在 Workflow SDK 的 step 语义上:

// Workflow 伪代码
async function turnWorkflow(input) {
  const session = await readDurableSession(state);  // step 1
  const result = await callModel(session);            // step 2
  const toolResults = await executeTools(result);     // step 3
  const updatedSession = await updateSession(...);    // step 4
  return updatedSession;                              // 自动持久化
}

关键特性:

  1. Step 边界即持久化边界:每个 await 后的状态自动保存
  2. 崩溃恢复:Workflow 崩溃后,从最后一个完成的 step 恢复
  3. 暂停/恢复resumeHook() 可以在任意 step 边界暂停,等待外部事件
  4. 版本兼容:持久化状态携带 version 字段,支持向前兼容的迁移

Session 状态结构:

interface DurableSession {
  sessionId: string;
  rootSessionId?: string;     // 顶级 session 的追踪
  continuationToken: string;   // 恢复用的 token
  history: ModelMessage[];     // 对话历史
  state?: SessionStateMap;     // 用户自定义状态
  sandboxState?: SandboxState; // 沙箱文件状态
  agent: { system: string };   // 系统提示词快照
  compaction?: { ... };        // 上下文压缩状态
}

九、Vercel 平台集成

eve 与 Vercel 平台深度集成:

部署模型

  • ProductiondeploymentId: "latest" 路由,新部署自动接管旧 session
  • Preview:固定到当前部署,隔离测试
  • Local:dev server 模式,文件变更热重载

环境感知

function shouldRouteToLatestDeployment(): boolean {
  return process.env.VERCEL_ENV === "production";
}

Production 环境使用最新部署的代码处理 session 的后续 turn,Preview 和本地环境保持固定部署。


十、与其他 Agent 框架的对比

维度 eve LangChain AutoGen CrewAI
配置方式 文件系统约定 Python 代码 Python 代码 Python 装饰器
持久化 Workflow SDK(内置) 需手动实现 需手动实现 需手动实现
平台绑定 Vercel(深)
类型安全 TypeScript(强) Python(弱) Python(弱) Python(弱)
工具发现 自动(文件系统) 手动注册 手动注册 手动注册
子代理 文件系统隔离 代码级 代码级 代码级
HITL 内置(审批机制) 需手动实现 需手动实现 需手动实现

eve 的独特之处:

  1. 文件系统即接口:无注册表、无配置同步问题
  2. 持久化原生:不是可选项,是核心设计
  3. 类型安全:Zod schema 全程验证
  4. Vercel 生态:一键部署、latest 路由

十一、潜在限制

  1. 平台绑定:Workflow SDK 的持久化依赖 Vercel 基础设施(或兼容实现),自建部署需要额外工作
  2. TypeScript 限定:纯 TypeScript 项目,Python/Java 生态不可用
  3. Beta 阶段:API 可能变化,pre-1.0
  4. 学习曲线:Workflow SDK 的 step 语义需要理解
  5. 调试复杂度:持久化执行流的调试比单次请求更复杂

十二、适用场景

适合:

  • 需要长期运行、可恢复的 Agent(客服、工作流自动化)
  • 团队需要清晰的代码组织和权限边界
  • 已经在 Vercel 生态中的项目
  • 重视类型安全和可维护性

不适合:

  • 单次调用、无状态的简单 API
  • 需要多语言支持的场景
  • 不想绑定云平台基础设施

十三、核心代码量

模块 文件数 核心职责
discover/ ~15 文件系统扫描、路径分析
compiler/ ~20 Manifest 生成、代码规范化
execution/ ~25 工作流编排、session 管理
channel/ ~15 HTTP/WebSocket 适配
client/ ~12 SDK 客户端、消息流处理
public/ ~20 用户-facing API(defineTool 等)

总代码量约 ~15K LOC(不含测试和文档)。


总结

eve 的核心理念是 "约定优于配置"的极致化——不是把配置写进代码,而是把配置放进文件系统的约定位置。

这种设计的好处:

  • 项目结构即文档
  • 无需注册表维护
  • 版本控制友好(每个组件独立文件)
  • 权限控制简单(文件系统权限)

代价是与 Vercel 平台深度耦合,以及 TypeScript 生态的限定。

如果你正在 Vercel 上构建需要持久化、多轮对话、人类介入的 Agent,eve 是目前最原生的选择。


参考:github.com/vercel/eve | beta.eve.dev/docs
#AgentFramework #Vercel #TypeScript #Workflow #DurableExecution #小凯

讨论回复

加载中...
正在加载回复...

正在加载回复...

推荐
智谱 GLM-5 已上线

我正在智谱大模型开放平台 BigModel.cn 上打造 AI 应用,智谱新一代旗舰模型 GLM-5 已上线,在推理、代码、智能体综合能力达到开源模型 SOTA 水平。

领取 2000万 Tokens 通过邀请链接注册即可获得大礼包,期待和你一起在 BigModel 上畅享卓越模型能力
登录