Introducing eve
TL;DR · AI 摘要
eve 是一个开源的智能代理框架,旨在简化代理的构建与运行,提供生产级功能如持久执行、沙箱计算等。
核心要点
- eve 提供了持久执行、沙箱计算等生产级功能,无需手动配置。
- 通过 agent.ts 和 instructions.md 文件,可以快速定义代理的模型和行为。
- eve 框架减少了代理开发中的重复工作,提升开发效率。
结构提纲
按章节快速跳转。
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- eve 框架
- 核心功能
- 持久执行
- 沙箱计算
- 人工审核
- 代理结构
- agent.ts
- instructions.md
- tools/
- skills/
- subagents/
- channels/
- schedules/
金句 / Highlights
值得收藏与分享的关键句。
eve is the framework that we build and run our own agents on.
Every agent starts with its definition.
You can just focus on what your agent does instead of how it does it.
介绍 eve - Vercel
今天,我们很自豪地推出 eve,这是一个用于构建、运行和扩展代理的开源代理框架。eve 的设计理念是构建代理应该意味着定义它要做什么,而不是组装它在生产环境中运行所需的所有组件。相反,eve 已经内置了生产环境所需的功能:
- 坚固的执行
- 沙盒计算
- 人机协作审批
- 子代理
- 评估
- 更多功能
eve 是我们构建和运行自己代理所使用的框架。
如今的代理,就像框架出现之前的网络一样,每个人都手动构建相同的基础设施,没有任何东西可以转移到下一个代理上。Next.js 结束了网络上的这种局面,而 eve 正在为代理做同样的事情。
代理是一个目录
这是一个 eve 代理。
agent/
agent.ts # 它运行的模型
instructions.md # 它是谁
tools/
run_sql.ts # 它能做什么
post_chart.ts
skills/
revenue-definitions.md # 它知道什么
subagents/
investigator/ # 它委托给谁
channels/
slack.ts # 它在哪里
schedules/
monday-summary.ts # 它何时自主行动一个数据分析师代理,一目了然
每个文件描述了代理的一个组件,因此只需一目了然,该目录就能告诉你代理是什么、做什么、在哪里以及何时自主行动。
几分钟内创建一个 eve 代理
每个代理都始于它的定义。
agent/agent.ts
1
import
{
defineAgent
}
from
"eve"
;
2
3
export
default
defineAgent
(
{
4
model
:
"anthropic/claude-opus-4.8"
,
5
}
)
;在一个文件中配置代理及其模型
agent.ts 文件是配置代理本身的地方。你可以用一行代码定义模型,通过 AI Gateway 支持提供者回退,压缩、模型选项和其他可选字段在你需要时都可用。
为你的代理赋予工作职责和个性,只需创建一个 instructions.md 文件,它作为 eve 在每次模型调用前插入的系统提示。
agent/instructions.md
你是一个高级数据分析师。你回答有关团队数据的问题。
-
优先使用精确数字而不是模糊的陈述。如果你可以计算,就计算。
-
说明你报告的任何数字背后的假设(日期范围、筛选条件、粒度)。
-
使用你可用的工具,而不是猜测。如果你无法从数据中回答,请明确说明。代理的身份和行为准则,前置在每次模型调用之前
你为你的代理创建文件,例如 post_chart.ts 和 revenue-definitions.md 用于工具和技能,eve 会将它们连接成一个可用的代理,无需任何样板代码或基础设施管理。你可以专注于你的代理做什么,而不是它如何做。
为什么我们构建了 eve
多年来,我们在 Vercel 构建了多个代理,包括 v0。但一旦编码代理使构建一个代理变得任何人都可以完成的事情,每个人都在做。我们发布了数百个代理和内部应用程序,看起来像是一场生产力革命。
但在这之下,每个团队在代理能做任何事情之前,都在重复构建相同的基础设施,而且没有任何东西可以从一个用例转移到下一个用例。每个代理都设计用于不同的任务,但它们都有相同的需求,相同的结构不断出现以满足这些需求。代理有其形状。
eve 的精髓在于将这种形状转化为一个框架。每当足够多的人以艰难的方式构建相同的东西时,每一代软件都会获得其抽象,而代理现在已经具备了这些能力。
链接到标题 Batteries included
代理在生产环境中所需的一切都随框架一起提供。
链接到标题 每次对话都有一个持久的会话
代理需要等待用户,调用缓慢的系统,并且可能运行数小时、数天或数周。在 eve 中,每次对话都是一个持久的工作流,每一步都会进行检查点记录,因此会话可以暂停、在崩溃或部署后继续运行,并且可以精确地从停止的地方恢复。这种持久性是基于开源的 Workflow SDK 构建的。
链接到标题 每个代理都有一个沙箱
代理所编写的代码应被视为不可信的,因此 eve 完全将代理生成的代码排除在应用程序运行时之外。每个代理都有自己的沙箱,这是一个用于 shell 命令、脚本以及文件读写操作的隔离环境,它与控制代理的运行环境在不同的安全上下文中运行。这个沙箱的后端是一个适配器。在部署时,它在 Vercel Sandbox 上运行。在本地,它可以在 Docker、microsandbox 或 just-bash 上运行,你还可以为其他任何提供者编写适配器。
链接到标题 人机协作审批
代理在真实系统上执行操作,其中一些操作需要人员的批准。在 eve 中,任何操作都可以配置为需要批准,代理会在那里暂停并等待,如果需要,可以无限期地等待,而不会消耗任何计算资源。一旦获得批准,eve 会从停止的地方继续执行任务。
链接到标题 安全连接到工具、数据和服务
代理需要连接到你的后端、数据和其他第三方服务。在 eve 中,连接是一个指向 MCP 服务器或任何具有兼容 OpenAPI 文档的 API 的文件。
agent/connections/linear.ts
1
import
{
defineMcpClientConnection
}
from
"eve/connections"
;
2
3
export
default
defineMcpClientConnection
(
{
4
url
:
"https://mcp.linear.app/sse"
,
5
description
:
"Linear workspace: issues, projects, cycles, and comments."
,
6
auth
:
{
7
getToken
:
async
(
)
=>
(
{
token
:
process
.
env
.
LINEAR_API_TOKEN
!
}
)
,
8
}
,
9
}
)
;一个文件连接到 MCP 服务器
eve 会发现远程工具,将其交给模型,并处理认证,模型永远不会看到连接的 URL 或凭据。Vercel Connect 处理交互式 OAuth,内置了同意和令牌刷新功能。在发布时,eve 代理可以连接到 Slack、GitHub、Snowflake、Salesforce、Notion 和 Linear,以及任何可以通过 OAuth、API 密钥或 MCP 服务器访问的工具。
连接你已经在使用的工具。
链接到标题 每个渠道使用相同的代理
大多数代理只存在于一个地方,因为每个新的表面都需要构建一个独立的集成。在 eve 中,同一个代理可以服务于每个表面,每个渠道只是一个小型的适配器文件。HTTP API 默认开启,包括 Slack、Discord、Teams、Telegram、Twilio、GitHub 和 Linear,defineChannel 覆盖自定义渠道。一个渠道也可以将任务转交给另一个渠道,因此一个事件的 Webhook 可以在 Slack 中打开一个调查线程。
链接到标题 内置追踪和评估
当代理出错时,第一个问题是代理实际做了什么。在 eve 中,每次运行都会生成一个追踪记录。每个模型调用和工具调用都按照顺序显示其输入和输出,包括代理在其沙箱中运行的命令,因此你可以重放运行过程,而不需要从日志中拼凑。
ai.eve.turn # 每个回合一个跨度
├── ai.streamText # 模型调用
│ └── ai.streamText.doStream
└── ai.toolCall # run_sql,包含输入和输出OpenTelemetry 跨度树,由单个回合生成
这些跨度是标准的 OpenTelemetry,并可以导出到你已经运行的任何追踪服务,无论是 Braintrust、Honeycomb、Datadog 还是 Jaeger。在 Vercel 上,它们会在 Observability 下的 Agent Runs 标签页中显示,给你一个统一的地方来查看每个会话,并深入查看任何运行。Evals 让你可以更进一步,通过可以本地运行或集成到 CI 的评分测试套件。
代理实际做了什么,一次一个回合
这剩下的是没有框架可以为你编写的部分:你的代理实际做了什么。
链接到标题 逐步扩展代理
最常见的赋予代理能力的方法是给予它工具,并教它如何通过技能来做事。今天这意味着构建工具、编写技能,然后将两者连接到运行代理循环的任何地方。使用 eve,一个工具是一个 TypeScript 文件,一个技能是一个 markdown 文件。
agent/tools/run_sql.ts
1
import
{
defineTool
}
from
"eve/tools"
;
2
import
{
z
}
from
"zod"
;
3
import
{
runReadOnlySql
}
from
"../lib/sample-db"
;
4
5
export
default
defineTool
(
{
6
description
:
"对 orders 和 customers 表运行只读 SQL 查询。"
,
7
inputSchema
:
z
.
object
(
{
8
sql
:
z
.
string
(
)
.
describe
(
"一个单独的只读 SELECT 语句。"
)
,
9
}
)
,
10
async
execute
(
{
sql
}
)
{
11
const
{
columns
,
rows
}
=
await
runReadOnlySql
(
sql
)
;
12
return
{
columns
,
rows
:
rows
.
slice
(
0
,
500
)
,
truncated
:
rows
.
length
>
500
}
;
13
}
,
14
}
)
;一个文件中的类型化工具,其中文件名成为工具名称
agent/skills/revenue-definitions.md
---
description
:
这个团队如何定义收入。在回答任何收入问题之前加载。
---
收入是在订阅期限内扣除退款后的收入。
周以周一为起点,使用 UTC 时间。
从每个数字中排除试用和内部账户。一个 markdown 文件中的技能,仅在相关主题出现时加载
注意缺少的部分。你不需要编写所有繁琐的代码来连接这些内容并将其注册到你的代理中,eve 会为你处理。
文件的名称和在树中的位置就是它的定义。eve 在构建时会自动获取工具和技能,将描述提供给模型,然后模型继续处理。就像 Next.js 通过控制路由将文件夹转换为路由一样,eve 通过控制代理循环将文件转换为能力。
链接到标题 添加人机协作的批准
要求对某个操作进行批准只需要在工具中添加一个字段。
1
export
default
defineTool
(
{
2
description
:
"对仓库运行只读 SQL 查询。"
,
3
inputSchema
:
z
.
object
(
{
sql
:
z
.
string
(
)
}
)
,
4
needsApproval
:
(
{
toolInput
}
)
=>
estimateScanGb
(
toolInput
.
sql
)
>
50
,
5
async
execute
(
{
sql
}
)
{
6
// 保持不变
7
}
,
8
}
)
;当查询扫描超过 50GB 时要求批准
现在你可以保护昂贵的查询、破坏性的写入,或者任何你不想在无人监督的情况下运行的内容。
链接到标题 让代理自己编写代码
你定义的工具并不是上限。eve 给你的代理提供了一台真正的计算机,带有 shell,因此它可以运行 bash、grep,以及你在终端中运行的任何其他命令。当一项工作需要尚未存在的代码时,代理会编写并运行它。
> 将上周的收入按地区分解并绘制图表
⦿ write_file analysis/by_region.py
⦿ bash
python analysis/by_region.py
6月1日当周按地区划分的收入:美洲210万美元,欧洲、中东和非洲160万美元,亚太地区50万美元。图表已保存至 analysis/by_region.png。代理在自己的沙箱中编写并运行自己的代码
你的代理可以在一个安全的沙箱中自行解决问题,重新塑造数据集、运行一次性分析,或者编写任何工作所需的代码,即使没有现有工具支持。
链接到标题 将工作委托给子代理
eve 代理也可以进行委托。子代理的结构与主代理相同,位于 subagents/ 目录中的一个子目录,拥有自己的指令、工具和沙箱。父代理调用子代理的方式与调用工具的方式相同。
agent/subagents/investigator/agent.ts
1
import
{
defineAgent
}
from
"eve"
;
2
3
export
default
defineAgent
(
{
4
description
:
"Investigates anomalies in the data before the analyst reports them."
,
5
model
:
"anthropic/claude-opus-4.8"
,
6
}
)
;分析师可以将工作交给的子代理
子代理从一个干净的上下文窗口开始,只拥有你赋予它的工具,完成工作后将结果返回给父代理。
链接到标题 启动并与你的代理进行交互
现在到了每个开发者都期待的部分:测试他们的代理。过去这意味着启动进程、提出问题并阅读日志,而没有简单的视图来查看使用了哪些工具、模型加载了什么,或者它为何以那种方式回答。你想要与你的代理交谈并观察它的工作,而你得到的只是 stdout。有了 eve,开发循环只需一条命令。
链接到标题 本地运行代理
要启动 eve 代理,你只需运行其开发服务器。
eve dev本地启动代理,带有与之交谈的终端用户界面
> 上周的收入是多少?
⦿ load_skill revenue-definitions
⦿ run_sql
SELECT date_trunc('week', created_at) ...
6月1日当周的收入为420万美元(扣除退款后),比前一周增长了6%。每次运行的每一步都实时可见
代理所做的每一步都可以在终端用户界面中看到。代理加载了技能,运行了查询,按照团队的规则进行了回答,而这些步骤都是持久会话中的检查点。终端用户界面只是一个客户端,代理通过 HTTP 提供相同的结构化事件,因此 curl、测试脚本或 CI 都可以驱动它并精确检查它做了什么。
链接到标题 使用评估测试代理
与代理交谈只能验证一次运行。评估以你测试其余软件的方式测试你的代理,通过在项目中其他文件中编写的评分检查。
evals/revenue.eval.ts
1
import
{
defineEval
}
from
"eve/evals"
;
2
import
{
includes
}
from
"eve/evals/expect"
;
3
4
export
default
defineEval
(
{
5
description
:
"The analyst answers revenue questions by the team's rules."
,
6
async
test
(
t
)
{
7
await
t
.
send
(
"What was revenue last week?"
)
;
8
t
.
completed
(
)
;
9
t
.
calledTool
(
"run_sql"
)
;
10
t
.
check
(
t
.
reply
,
includes
(
"net of refunds"
)
)
;
11
}
,
12
}
)
;一套用于检查分析师是否使用了其工具并遵循了团队定义的系统
你可以在本地运行 eve eval,也可以将其指向已部署的应用,这样,一次提示更改或模型切换就能让你在用户之前看到它造成了什么影响。
链接到标题 发布它
代理已经在你的笔记本电脑上运行了足够长的时间。通常,发布是代理工作结束、基础设施工作开始的步骤。使用 eve,无需进行任何配置,因为代理是一个普通的 Vercel 项目,它像其他任何前端或后端一样进行部署。
vercel deploy部署代理
当你部署代理时,代理本身没有任何变化,因为 eve 从一开始就以适配器为中心进行设计。发布时,eve 默认部署到 Vercel,其他平台的支持也在路上。生产环境中的同一目录与你在笔记本电脑上运行的一模一样。沙箱无需代码更改即可切换到 Vercel 沙箱,你在开发中交谈的代理现在可以通过一个公共 URL 访问。部署甚至不会中断代理;当你推送代码时,正在进行任务的会话会在它开始的版本上完成。
所有这些都不需要仪表板步骤。构建你代理的相同编码代理可以发布它并验证其工作。
但部署并不等于完成。在生产环境中,代理需要面对用户,并按照自己的时间表完成工作。
链接到标题 向你的团队介绍代理
过去,将代理引入 Slack 意味着首先构建一个 Slack 应用,包括应用配置、机器人令牌、事件订阅、Webhook 端点和签名密钥,所有这些都需要在代理说第一句话之前完成。使用 eve,添加一个频道只需一条命令。
eve channels
add
slack生成 Slack 频道文件
该命令会生成 channels/slack.ts 文件,这个文件像其他任何代码更改一样进行部署,你刚刚部署的代理现在可以在 Slack 中进行响应。频道带来了平台的特性,因此审批会以 Slack 按钮的形式呈现,问题会以选择菜单的形式呈现,代理在工作时会发布打字指示器。将凭证通过 Vercel Connect 传递,就不需要将机器人令牌复制到 .env 文件中。再次运行命令并使用 discord 或 teams,同一个代理也会出现在那里,每个频道对应一个文件。
频道是你的代理的用户界面,会话可以在它们之间移动。在 Slack 中提出的问题可以继续在网页上进行,而通过 HTTP 到达的事件 Webhook 可以在 Slack 中打开调查线程,并在团队已经存在的地方完成工作。
链接到标题 将代理安排到一个时间表上
周一的收入报告不应该等待有人去询问。一个时间表只需要一个文件,一个 cron 表达式和一个在代理自己的时钟上启动代理的处理程序。
agent/schedules/monday-summary.ts
1
import
{
defineSchedule
}
from
"eve/schedules"
;
2
import
slack
from
"../channels/slack.js"
;
3
4
export
default
defineSchedule
(
{
5
cron
:
"0 9 * * 1"
,
6
async
run
(
{
receive
,
waitUntil
,
appAuth
}
)
{
7
waitUntil
(
8
receive
(
slack
,
{
9
message
:
"Summarize last week's revenue and post it to the team channel."
,
10
target
:
{
channelId
:
"C0123ABC"
}
,
11
auth
:
appAuth
,
12
}
)
,
13
)
;
14
}
,
15
}
)
;通过 Slack 频道在 cron 安排下发布周一的收入报告
在 Vercel 上,每个时间表都部署为一个 Vercel 定时任务,因此报告每周一都会自动发布,无需有人记住它。
链接到标题 像其他软件一样运行代理
一个你的团队依赖的代理是生产软件,对其指令的更改可能会像更改其代码一样破坏它。由于 eve 代理是目录中的文件,它和你的其他代码一样存在于 Git 中,一个新的提示、工具或技能就是一个带有差异、审查和历史记录的提交。
将 eve eval 集成到 CI 中,你编写的测试套件就变成了部署门,对每个提交进行评分,这样回归问题会在 CI 中被拦截,而不是在生产环境中。
每个提交都会获得自己的预览部署,并且它会携带代理的频道。团队可以在它取代他们每天使用的版本之前,与下一个版本的 Slack 机器人进行交流。
当某个更改以 eve 无法检测到的方式出错时,你可以立即将生产环境回滚到之前的版本。
链接到标题 如何在 eve 上运行 Vercel
我们在 Vercel 的生产环境中运行了超过一百个代理,它们是公司日常运营的一部分,每个代理都在业务中承担着特定的角色。以下是一些例子。
链接到标题 数据分析师
Vercel 最常用的内部工具是一个代理,每月处理超过 30,000 个问题。任何人都可以在 Slack 中向 d0 提问,并得到仓库中的答案。每个查询都限定在提问者的权限范围内,因此 d0 永远不会向你展示你原本看不到的表格。
链接到标题 自主的 SDR
Lead Agent 全天候运行我们最优秀代表的剧本。它在新线索一出现时立即处理,并自行跟进,因此没有任何线索会在一夜之间变冷。它的年运行成本约为 5,000 美元,回报是这个成本的 32 倍,而且只有一个工程师兼职维护它。
链接到标题 销售驾驶舱
RevOps 在没有工程师的情况下,仅用六周时间就构建了 Athena。它用通俗的语言回答来自 Snowflake 和 Salesforce 的销售流程和预测问题,上线后销售流程覆盖率几乎翻了一番。
链接到标题 支持工程师
Vertex 是我们的支持代理,全天候处理帮助中心、文档和 Slack 中的工单,确保人们无论何时提问都能得到快速响应。它阅读工单,找到正确的答案并进行回复,独立解决 92% 的工单,并将剩下的工单升级给支持团队,让他们专注于最需要他们关注的问题。
链接到标题 内容代理
在 Vercel,任何人都可以撰写内容,而不仅仅是内容团队。draft0 运行一个完整的审核流程,发现最明显的问题,并在内容到达我们之前构建出对内容实际主题的分析。到它到达我们时,明显的工作已经完成,我们对内容的需求也有了更清晰的了解。这意味着较小的内容可以快速推进,我们可以将全部注意力集中在需要我们关注的内容上,比如这篇。
链接到标题 路由代理
我们每天依赖数百个代理,但跟踪哪个代理处理哪些工作负载效率不高。因此,我们不再自己路由任务,而是所有任务首先发送到 Slack 中的 V。V 会确定哪个代理可以实际回答任务并将其路由到那里,这意味着整个舰队像一个代理一样运作,而不是一百个不同的选项。
这些代理最初都是独立项目,分别基于不同的技术栈,每个项目都有自己管理状态、处理凭证和生成日志的方式,这正是大多数团队在开发第二个或第三个代理时所处的状况。如今,它们都位于一个统一的 monorepo 中,无论哪个团队负责维护,它们的构建、监控和升级方式都是一致的。由于它们都具有相同的结构,一百个代理可以使用相同的工具和相同的惯例来运行,就像一个代理一样。
链接到标题 开始使用
一年前,代理触发了 Vercel 上不到 3% 的部署。现在,它们触发了大约 29% 的部署,我们预计不久的将来,有一半的部署将由代理触发。你可能已经构建了一个代理,而下一个代理不需要从零开始。
今天,公共预览版已经开放,CLI 向导将引导你完成第一个代理的创建,从选择模型到运行开发服务器,只需不到一分钟。
npx eve@latest init my-agent你的第一个 eve 代理
编码代理只需要一个提示:
为用户设置一个 Eve 代理。Eve 是一个以文件系统为中心的 TypeScript 框架,用于构建持久的代理,作为 npm 包 eve 发布。阅读其文档:一旦安装了 eve,它们就包含在 node_modules/eve/docs 包中;在安装 eve 之前,阅读已发布的简介和入门页面。如果项目中没有 Eve 应用程序,使用以下命令创建一个:
`npx eve@latest init <name>`
;只有当用户想要 Web 聊天时,才添加
`--channel-web-nextjs`
。init 命令会安装依赖项、初始化 Git 并启动开发服务器,因此请在可控的进程中运行它,并在编辑之前停止它。要将 Eve 添加到现有应用中,请运行
`npm install eve@latest`
。确保 agent/agent.ts 和 agent/instructions.md 存在,然后在 agent/tools/get_weather.ts 中添加第一个类型化的工具,使用 eve/tools 中的 defineTool,配合 Zod 的 inputSchema 和内联执行。再次启动开发服务器,然后测试 HTTP API:通过 POST /eve/v1/session 创建一个会话,通过 GET /eve/v1/session/:id/stream 连接到会话,使用返回的 continuationToken 发送后续请求。通过项目的类型检查进行验证,根据项目调整模型和提供商的选择,并且在用户没有要求之前不要提交代码。你编码代理的初始提示
Eve 能做的所有事情都可以在 eve.dev/docs 上找到,而开发工作在 github.com/vercel/eve 上公开进行,欢迎提出问题、参与讨论和贡献代码。
目前,Vercel 上已有数百个代理在 eve 上运行。你将构建什么呢?
构建你的第一个代理
代理是一组文件的目录,eve 使用持久执行、沙箱、审批和评估等功能来运行它。它可以与任何模型、任何 MCP 服务器以及 Slack、Discord 和 GitHub 等渠道配合使用。
开始使用