ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

eve Chat Template 部署实战:从一键 Starter 到 Vercel 生产模式的完整配置指南

eve Chat Template 部署实战:从一键 Starter 到 Vercel 生产模式的完整配置指南
  • 人工智能
  • AI Agent
  • Agent 框架
  • 后端
  • 工具调用

【免费下载链接】eve

The Open Framework for Building Agents

项目地址:https://gitcode.com/gh_mirrors/eve28/eve
点击查看免费下载

本文基于apps/templates/eve-chat-template模板的部署文档 setup-and-deploy.md,系统讲解 eve Chat Template 的三种运行模式(Starter / Production / Local development)、一键部署流程、长期记忆接入、Sign in with Vercel 配置、数据库迁移与常见故障排查。读完后,你可以把该模板从零部署为一个可多用户访问、具备持久化聊天历史与按用户隔离记忆的 Next.js 聊天应用,并能对照仓库源码理解每个环境变量的实际作用。

模板的三种运行模式

该模板是一个 Next.js 聊天应用,浏览器通过同源的/eve/v1/*路由与 eve agent 通信。模板刻意设计为"同一份代码库、三种运行模式",模式的选取完全由环境变量决定。README 给出的模式判定表如下:

模式触发条件认证方式聊天持久化长期记忆
Starter配置了EVE_CHAT_PASSWORD共享密码 + 安全会话 Cookie浏览器 localStorage配置 Blob 后为共享 Vercel Blob 文档
Production配置了 Neon、Upstash 及全部 Sign in with Vercel 变量Sign in with VercelNeon 数据库按用户隔离的 Vercel Blob 文档
Local development以上均未配置且本地运行next dev本地开发身份浏览器 localStorage进程内,重启即重置

生产模式的完整环境变量清单(缺一不可):

DATABASE_URL= BETTER_AUTH_SECRET= NEXT_PUBLIC_VERCEL_APP_CLIENT_ID= VERCEL_APP_CLIENT_SECRET= UPSTASH_REDIS_REST_URL= UPSTASH_REDIS_REST_TOKEN= KV_REST_API_URL= KV_REST_API_TOKEN=

可选变量包括BETTER_AUTH_URL(自定义生产域名覆盖)以及SLACK_CONNECTOR、LINEAR_CONNECTOR、NOTION_CONNECTOR、SENTRY_CONNECTOR(启用 Vercel Connect 集成)。

从源码结构看,模式判定逻辑集中在 setup.ts:fullEnvironmentReady = databaseConfigured && isAuthConfigured() && isRateLimitConfigured(),其中isAuthConfigured要求BETTER_AUTH_SECRET、NEXT_PUBLIC_VERCEL_APP_CLIENT_ID、VERCEL_APP_CLIENT_SECRET三者齐全;isRateLimitConfigured接受UPSTASH_REDIS_REST_URL/TOKEN或KV_REST_API_URL/TOKEN任一组。三组都就绪时返回authMode: "vercel"、storageMode: "database";仅密码就绪时返回authMode: "password"、storageMode: "browser";两者皆无则appReady: false——这就是文档所说"生产部署中若两种模式都未配置,应用 fail closed、拒绝聊天请求"的实现依据。

前置条件

  • Node.js 24 或更新版本(setup.sh 会检查process.versions.node,低于 24 直接退出)
  • 通过 Corepack 管理的 pnpm(package.json 声明了packageManager: pnpm@11.25.0)
  • Vercel 账号
  • Vercel CLI:全局安装,或用pnpm dlx按需运行
corepack enable pnpm install pnpm dlx vercel@latest login

后续命令统一使用vercel前缀;若没有全局安装,把vercel替换为pnpm dlx vercel@latest即可。

一键部署 Starter 模式

README 中的 Deploy with Vercel 按钮可以直接创建一个可用的 Starter 部署——不预置任何 Marketplace 存储产品,也不执行数据库迁移。部署表单只会询问一个变量:

EVE_CHAT_PASSWORD=

使用强密码,官方建议 16 位以上。这个密码的工作机制在 password-auth.ts 中实现:登录成功后服务端用该密码作为 HMAC-SHA256 密钥签名一个带过期时间的 token(有效期 30 天),写入名为eve_chat_session的安全会话 Cookie;每次校验都通过timingSafeEqual做恒定时间比较,避免时序攻击。

Starter 模式有两个重要边界:

  1. 聊天历史留在浏览器。会话和 eve session 游标存储在localStorage(见 local-store.ts,存储上限 50 个聊天),因此历史不会跟随用户迁移到另一台浏览器或另一台设备。
  2. Starter 面向单一受信操作者。所有知道密码的人共享同一个 eve principal(eve-auth.ts 中passwordEveAuth固定返回principalId: "eve-chat-user"),进而共享所有用户级连接授权。在向独立用户开放访问之前,必须升级到 Production 模式。

另外,部署按钮流程不会为长期记忆预置存储:agent 可正常运行,但在完成下文"长期记忆"步骤之前,Vercel 上的记忆功能是关闭的。

长期记忆(Long-Term Memory)

记忆能力由 agent/memory/profile.ts 定义:

export default defineMemory({ description: "Remember stable facts and preferences about the caller.", provider: fileMemory(), scope(context) { // Do not expose memory tools until the deployed app has durable storage. if (process.env.VERCEL && !hasMemoryBlobStorage()) { return null; } return byPrincipal(context); }, });

要点:

  • fileMemory()让 agent 维护一份小的、按 principal 隔离的持久事实文档。Starter 模式下所有密码持有者共享一份文档;生产模式下每个登录用户各有一份。
  • 部署在 Vercel 上(process.env.VERCEL存在)时,只有检测到EVE_MEMORY_BLOB_STORE_ID或EVE_MEMORY_BLOB_READ_WRITE_TOKEN环境变量,scope才返回byPrincipal(context);否则返回null,agent 完全不具备记忆工具。所有模式下记忆都是可选的。
  • 模板只认EVE_MEMORY_BLOB_*命名空间。如果你手工挂载的 Blob 用的是通用BLOB_*变量,会被显式忽略——这是刻意的隔离,防止记忆悄悄接管应用自己的 Blob 存储。
  • 本地开发时 eve 把记忆保存在进程内,dev server 重启即重置。

在 Vercel 上启用记忆的完整步骤:先完成 下文 的项目关联,然后运行:

pnpm exec eve integration setup file-memory --yes

该命令会创建或复用一个私有 Vercel Blob store,以 OIDC 方式将其连接到 Production、Preview 和 Development,并把EVE_MEMORY_BLOB_*变量拉取到.env.local。Blob 用量可能产生费用。执行后需要重新部署——环境变量变更只对新部署生效。模板的一键脚本 setup.sh 中执行的是同一条命令,且做了幂等处理:若EVE_MEMORY_BLOB_STORE_ID已存在则跳过,失败也只告警不阻断后续 Neon/Upstash/OAuth 步骤。

生产持久化升级

配置好 Vercel Blob、Neon、Upstash 和 Sign in with Vercel 后,同一份代码库就切换为生产模式:Vercel 身份认证、私有 Blob 中的按用户长期记忆、数据库支撑的按用户聊天历史,以及分布式速率限制。

模板提供了自动化脚本:

./scripts/setup.sh # 或:./scripts/setup.sh --scope <team-slug>

setup.sh 的完整执行链路(要求vercel、node、pnpm、openssl四个命令齐备,Node 主版本 ≥ 24):

  1. pnpm install安装依赖;
  2. 若不存在.vercel/project.json则执行vercel link(可选--scope指定团队),并解析出projectId/ 团队 slug;
  3. 私有文件记忆:运行pnpm exec eve integration setup file-memory --yes(已配置则跳过);
  4. Neon:以DATABASE_URL为就绪标记,缺失时执行vercel integration add neon;
  5. Upstash Redis:以KV_REST_API_URL为就绪标记,缺失时执行vercel integration add upstash-kv;
  6. BETTER_AUTH_SECRET:用openssl rand -base64 32生成,通过 Vercel API 以 encrypted 类型写入 production/preview/development 三个环境;
  7. Sign in with Vercel OAuth 应用:通过 Vercel API 注册 OAuth 应用(scopes 为openid、email、profile、offline_access,注册http://localhost:3000/api/auth/callback/vercel及项目生产/预览域名回调),自动生成 client secret,并写入NEXT_PUBLIC_VERCEL_APP_CLIENT_ID/VERCEL_APP_CLIENT_SECRET;API 不可用时回退到交互式 dashboard 引导;
  8. BETTER_AUTH_URL:从项目的域名列表解析出生产域名(优先.vercel.app后缀)并写入 production/preview;
  9. 交互式询问是否创建 Slack 及 Notion/Linear/Sentry 四个可选连接器;
  10. vercel env pull .env.local --yes拉取变量到本地;若.env.local缺少BETTER_AUTH_URL则补写http://localhost:3000;
  11. 若.env.local中存在DATABASE_URL,加载环境变量后运行pnpm db:migrate;否则提示跳过。

脚本全程幂等:每一步都以"对应环境变量是否已存在"为跳过条件,中断后重跑即可续传。注意 Neon 通过 Marketplace 导入时DATABASE_URL通常标记为 sensitive 且只应用于 Production/Preview,本地迁移需要额外处理(见下文迁移章节)。

一旦全部生产环境变量就绪,生产模式优先于EVE_CHAT_PASSWORD生效。首次生产部署之后需要运行迁移:

vercel env run -e production -- pnpm db:migrate

本地关联 Vercel 项目

创建或选择承载该模板的 Vercel 项目:

vercel link

团队协作时传入团队 scope:

vercel link --scope <team-slug>

关联后本地会生成.vercel/project.json,脚本与后续所有vercel api调用都基于它解析项目与团队上下文。

生产存储配置

setup 脚本会预置所需的全部存储(包括长期记忆所需的 Blob store)。其中 Neon 和 Upstash Redis 仅生产模式需要。手动配置方式:

# 预置 Neon Postgres vercel integration add neon # 预置 Upstash Redis vercel integration add upstash

按提示将两个资源连接到已关联的项目即可。

关于 Neon 的DATABASE_URL:通过导入流程创建时它通常被标记为 sensitive 并应用于 Production 和 Preview——这对vercel env run执行部署迁移没有影响;只有当你希望把它拉进.env.local供本地开发使用时,才需要为 Development 环境单独勾选。本地运行应用时拉取环境变量:

vercel env pull .env.local --yes

Upstash 的变量用于分布式速率限制。rate-limit.ts 优先读取UPSTASH_REDIS_REST_URL/TOKEN,回退到KV_REST_API_URL/TOKEN;采用固定时间窗计数器(incr+expire),超限抛出携带retryAfter的RateLimitError。若两组变量都不存在,getRedis()返回空,限流被静默跳过——这正是模式判定要求限流变量齐备才进入生产模式的原因。

BETTER_AUTH_SECRET

Better Auth 是生产模式下 Sign in with Vercel 的会话层(见 auth.ts,它基于 Drizzle 适配器与 Neon 中的user/session/account/verification表工作)。为生产环境生成安全密钥:

openssl rand -base64 32

写入所有 Vercel 环境:

printf '%s' "<generated-secret>" | vercel env add BETTER_AUTH_SECRET production,preview,development

本地需要时拉取:

vercel env pull .env.local --yes

auth.ts中有一个兜底 secret(eve-chat-template-unconfigured-secret),但那只是未配置状态的占位,生产环境必须使用自己生成的随机值。

Sign in with Vercel

在生产者账号或团队下创建一个 Vercel App(OAuth 客户端)。必需的 scopes 为:

openid email profile

在 Vercel App 的 scopes/permissions 设置里把三项全部打开——这些是 Vercel App 权限,不是环境变量。

email scope 是强制项。缺少时 Better Auth 会重定向到:

/auth/error?error=email_not_found

为每个要使用的 origin 添加回调 URL:

http://localhost:3000/api/auth/callback/vercel http://localhost:3001/api/auth/callback/vercel https://<your-project-production-domain>/api/auth/callback/vercel https://<your-custom-domain>/api/auth/callback/vercel

只有当本地开发跑在 3001 端口时才需要 3001 那条回调;自定义域名的回调在确定域名后再加。

复制 client ID 和 client secret 后写入环境变量:

printf '%s' "<client-id>" | vercel env add NEXT_PUBLIC_VERCEL_APP_CLIENT_ID production,preview,development printf '%s' "<client-secret>" | vercel env add VERCEL_APP_CLIENT_SECRET production,preview,development

拉取到本地:

vercel env pull .env.local --yes

其中NEXT_PUBLIC_VERCEL_APP_CLIENT_ID是刻意公开的;VERCEL_APP_CLIENT_SECRET和BETTER_AUTH_SECRET必须保持机密。

也可以用 CLI 直接创建 OAuth 应用:

vercel oauth-apps register \ --name "eve Chat Template" \ --slug "eve-chat-template" \ --redirect-uri "https://<your-project-production-domain>/api/auth/callback/vercel"

用 CLI 创建后,上线前请在 Vercel dashboard 核对 scopes 与 client secret。源码侧与之对应:auth.ts 仅在 secret、client ID、client secret 三者齐备时才注册vercelsocial provider,且请求的 scope 固定为["openid", "email", "profile"],OAuth token 会加密落库(encryptOAuthTokens: true)并允许账号关联。

App URL 推导顺序

应用按以下优先级确定认证 origin:

BETTER_AUTH_URL -> VERCEL_PROJECT_PRODUCTION_URL -> VERCEL_URL -> http://localhost:3000

auth-url.ts 中的getEffectiveAppUrl()完全实现了这条链,并对取值做归一化:无协议的输入自动补https://,去掉 path/query/hash 与尾斜杠,无效 URL 直接视为未配置。

首次 Vercel 部署通常不需要显式设置BETTER_AUTH_URL(setup 脚本会自动解析生产域名并写入);当你使用自定义生产域名时才需要显式设置:

printf '%s' "https://<your-custom-domain>" | vercel env add BETTER_AUTH_URL production,preview,development

VERCEL_PROJECT_PRODUCTION_URL与VERCEL_URL是 Vercel 系统注入的环境变量,无需手工维护。

数据库迁移

生产迁移应在首次部署后以及任何 schema 变更后执行:

vercel env run -e production -- pnpm db:migrate

package.json 中也内置了对等脚本:

pnpm db:migrate:production # 等价于 vercel env run -e production -- pnpm db:migrate

本地开发需要先加载.env.local再运行 Drizzle(drizzle.config.ts 从process.env.DATABASE_URL取连接串,schema 指向apps/web/lib/db/schema.ts,迁移产物输出到apps/web/lib/db/migrations/):

set -a source .env.local set +a pnpm db:migrate

仅本地原型阶段也可以直接推 schema:

set -a source .env.local set +a pnpm db:push

从源码结构看,db/client.ts 的isDatabaseSchemaReady()会检查六张表是否齐备:account、chat、chat_event、session、user、verification——这与 schema.ts 中定义的 Drizzle 表一一对应(Better Auth 的四张表加上模板自有的chat/chat_event两张持久化表,chat.eve_session以 jsonb 保存 eveClientSessionState,chat_event按eventIndex唯一索引保存MessageStreamEvent事件流)。setup 状态检查正是以这六张表齐备作为"数据库就绪"的标准,这也是故障排查中missing: ["database migrations"]提示的由来。

本地运行

启动 Web 应用:

pnpm dev

或者指定 3001 端口(注意:Vercel App 中必须存在对应的 3001 回调 URL):

PORT=3001 pnpm dev

以 Vercel 服务图的方式同时运行 Web 应用和 eve peer 服务(无需关联 Vercel 项目):

pnpm dev:all # 即 vercel dev --local

服务图的声明位于 vercel.ts:通过withEve包装,services.web指向 Next.js 应用(root 为apps/web),所有路由默认转发到该服务。打开对应的本地 URL,并确认 Vercel App 中包含同样的回调 URL 即可。本地模式下(NODE_ENV === "development"且VERCEL !== "1")应用自动使用本地开发身份,无需任何环境变量。

可选的 Vercel Connect 集成

Slack、Notion、Linear、Sentry 均为可选项,不在部署按钮的必需流程中。

创建需要的连接器:

# Slack 频道 vercel connect create slack --name eve-chat-template --triggers vercel connect attach <slack-connector-uid> --triggers --trigger-path /eve/v1/slack --yes # MCP 连接 vercel connect create mcp.notion.com --name notion vercel connect create https://mcp.linear.app/mcp --name linear vercel connect create https://mcp.sentry.dev/mcp --name sentry

如需把连接器挂到已关联的 Vercel 项目:

vercel connect attach <connector-uid> --yes

把对应 UID 写入环境变量:

printf '%s' "<slack-connector-uid>" | vercel env add SLACK_CONNECTOR production,preview,development printf '%s' "<connector-uid>" | vercel env add NOTION_CONNECTOR production,preview,development printf '%s' "<connector-uid>" | vercel env add LINEAR_CONNECTOR production,preview,development printf '%s' "<connector-uid>" | vercel env add SENTRY_CONNECTOR production,preview,development vercel env pull .env.local --yes

本地开发时,连接配置会回退到固定名称slack/eve-chat-template、notion、linear、sentry——这与 agent/connections/notion.ts 中的process.env.NOTION_CONNECTOR ?? "notion"以及 agent/channels/slack.ts 中的process.env.SLACK_CONNECTOR ?? "slack/eve-chat-template"一致,因此按上述名称创建的本地连接器无需修改agent/下任何文件即可生效。Slack 走的是slackChannel频道,触发路径为/eve/v1/slack。

交互层面的联动:composer 只有在至少配置了一个 MCP 连接器环境变量时才显示连接菜单(LINEAR_CONNECTOR、NOTION_CONNECTOR、SENTRY_CONNECTOR任一存在即可,见 setup.ts 中CONNECTION_ENV_KEYS的检查逻辑);纯密码的 Starter 部署因此不显示菜单,并告知 eve 没有可用的外部连接。若某次聊天需要 MCP 授权,使用聊天 UI 中的 Connect 卡片完成;若要直接管理连接器,打开 Vercel 项目的 integrations/settings 页面查找对应 connector。

部署

部署前先本地构建:

pnpm build # 等价于 pnpm build:eve(eve build)+ pnpm build:web(next build --turbopack apps/web)

部署到生产:

vercel --prod

在修改环境变量、存储产品或 Connect 连接器之后,务必重新部署,让生产环境使用最新的 project 配置。

故障排查

  • 聊天被禁用并提示需要配置:查看界面 tooltip。缺少迁移会显示为database migrations,此时运行vercel env run -e production -- pnpm db:migrate。
  • 登录重定向到/auth/error?error=email_not_found:在 Vercel App 中启用 email scope。
  • 登录重定向到/auth/error?error=invalid_scope:确认 Vercel App 已开启openid、email、profile三项 scope。
  • OAuth 授权页之后仍报 auth 错误:核对回调 URL 是否与浏览器 origin 完全一致,包括端口和/api/auth/callback/vercel路径。
  • pnpm db:migrate报缺少DATABASE_URL:生产环境改用vercel env run -e production -- pnpm db:migrate;本地开发则把 Development scope 的 Neon 变量拉进.env.local(或手工粘贴连接串)。
  • 限流配置缺失:预置 Upstash Redis 后重新拉取环境变量。
  • Notion 工具调用失败:确认 Vercel 中已设置NOTION_CONNECTOR、连接器已挂到项目、且本地环境变量已重新拉取。

环境变量速查

变量作用适用模式机密级别
EVE_CHAT_PASSWORDStarter 密码,16 位以上建议Starter / 本地机密
EVE_MEMORY_BLOB_STORE_ID/EVE_MEMORY_BLOB_READ_WRITE_TOKEN启用 Vercel 私有 Blob 长期记忆Starter / Production机密
DATABASE_URLNeon 连接串(迁移与生产持久化)Production / 本地迁移机密
BETTER_AUTH_SECRETBetter Auth 会话密钥Production机密
NEXT_PUBLIC_VERCEL_APP_CLIENT_IDVercel App client IDProduction公开
VERCEL_APP_CLIENT_SECRETVercel App client secretProduction机密
BETTER_AUTH_URL自定义生产域名的 auth origin 覆盖Production / 本地非机密
UPSTASH_REDIS_REST_URL/UPSTASH_REDIS_REST_TOKEN(或KV_REST_API_URL/KV_REST_API_TOKEN)分布式速率限制Production机密
SLACK_CONNECTOR/NOTION_CONNECTOR/LINEAR_CONNECTOR/SENTRY_CONNECTORVercel Connect 连接器 UID可选机密

配套源码位置:agent 定义见 agent/agent.ts(含 instructions.md 行为指令、agent/tools/工具与agent/channels/、agent/connections/集成);运行模式与流式架构的深入原理见同目录的 how-the-chatbot-works.md。

  • 人工智能
  • AI Agent
  • Agent 框架
  • 后端
  • 工具调用

【免费下载链接】eve

The Open Framework for Building Agents

项目地址:https://gitcode.com/gh_mirrors/eve28/eve
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进