☰
Personal Agent Template 开发指南:基于 Eve 与 Nuxt 构建跨渠道持久化个人 AI 助手
2026/10/14 3:04:57 网站建设 项目流程
  • 人工智能
  • AI Agent
  • Agent 框架
  • 后端
  • 工具调用

【免费下载链接】eve

The Open Framework for Building Agents

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

本指南面向希望在 Eve 生态中快速搭建"持久化个人 AI 助手"的开发者,以仓库内apps/templates/personal-agent-template模板(下称 Personal Agent Template)为研究对象,系统讲解其双服务架构、环境变量配置、内部 API 通信模式、长期记忆流程以及自定义与部署全流程。读完本文后,你将掌握该模板从本地启动、接入 Slack / iMessage / Linear 到定制自己的 Agent 与记忆体系的一整套实战方案,并能读懂其源码级实现细节。

模板是什么

Personal Agent Template 是一个由 Eve 与 Nuxt 4 驱动的开源个人 AI 助手模板,定位为"durable personal AI assistant"。它的核心卖点是:Web 聊天、Slack、iMessage 三种交互表面共享同一个 Agent、同一份长期记忆,且所有记忆写入都必须经过用户显式批准。模板默认以V作为示例 persona,你可直接 fork 后按需改造。

在仓库中,模板的入口文档apps/templates/personal-agent-template/CLAUDE.md以@AGENTS.md的方式引入其配套的 AI 编码助手速查文档,后者汇总了全部开发要点:命令速查、目录结构、文档索引、内部 API 调用模式、记忆流程与自定义检查清单。本文将沿这条主线展开,并结合 docs/ARCHITECTURE.md、docs/ENVIRONMENT.md、docs/CUSTOMIZATION.md 三份文档及源码做深度扩充。

快速参考:常用命令一览

在开始之前,先熟悉模板的构建与开发命令(定义见 package.json):

命令作用
pnpm install安装依赖
pnpm dev启动 Nuxt Web 应用(本地http://localhost:3000)
pnpm dev:all通过 Vercel CLI 启动本地双服务图(Nuxt + Eve agent 对等服务)
pnpm build生产构建(内部为eve build+nuxt build两步)
pnpm typecheckTypeScript 类型检查
pnpm db:generate生成 Drizzle 迁移文件
pnpm db:migrate应用数据库迁移

需要说明的是,模板要求 Node.js 24+ 与 pnpm(engines.node: ">=24"、packageManager: pnpm@11.25.0)。

项目结构:三层各司其职

personal-agent-template/ ├── agent/ # Eve agent(channels、tools、skills、connections) ├── apps/web/ # Nuxt UI、Nitro API、共享应用代码 ├── lib/ # 跨层共享类型与常量(agent 与 web 共用) ├── vercel.ts # Vercel 对等服务编排 └── docs/ # 架构、环境变量、自定义指南

关键子目录职责如下:

  • agent/:Eve Agent 的全部逻辑,包括agent.ts(模型配置)、channels/(eve、slack、sendblue三个渠道)、tools/(weather、save_memory、github)、skills/(如daily-summary.md)、connections/(Linear MCP)、lib/(基础指令、内存/ Slack/ 电话内部 API 客户端)、instructions.ts(session.started钩子,用于记忆注入)。
  • apps/web/:Nuxt 前端(app/)、Nitro 服务端(server/,含/api/*、/api/internal/*、数据库 schema 与迁移、Better Auth)以及跨层共享代码(shared/)。
  • lib/:Agent 与 Web 两端共享的常量与类型,例如lib/agent.ts(品牌信息)、lib/types/memory.ts(记忆类别)、lib/connect.ts(Vercel Connect connector UID)。

#号 import 别名("#*": "./agent/*")让 agent 目录内的文件可以以#agent/xxx形式被 Web 侧引用,这是模板刻意设计的共享通道。

系统架构:Vercel 上的对等双服务

模板在 Vercel 上以两个协作服务运行,vercel.ts通过withEve在构建期编排这两个对等服务:

Vercel 服务入口职责
web/Nuxt UI + Nitro API
eve/_eve_internal/eveEve agent 运行时
// apps/templates/personal-agent-template/vercel.ts import { withEve } from "eve/vercel"; export default await withEve({ services: { web: { framework: "nuxt", root: "apps/web" }, }, routes: [{ src: "^(.*)$", destination: { type: "service", service: "web" } }], });

整体数据流为:

用户表面(Web 聊天 · Slack DM/提及 · iMessage/Sendblue) │ ▼ Eve agent(channels: eve · slack · sendblue / tools: weather · save_memory / connections: Linear MCP) │ HTTP + Authorization: Bearer <INTERNAL_API_SECRET> ▼ Nuxt 应用(/api/* 公开 API · /api/internal/* agent 专用 · Better Auth · NuxtHub SQLite) │ ▼ Vercel Connect(Linear · Slack 等集成)

也就是说:用户从任意渠道发消息,都由 Eve Agent 处理;Agent 需要读写业务数据时,通过带 Bearer 密钥的内部 API 回调 Nuxt;Nuxt 负责认证、数据库与集成授权。这种"Agent 无状态、数据收敛在 Web 服务"的设计,是模板实现跨渠道持久化的基石。

内部 API 模式:Agent 与 Nuxt 的通信契约

模板中最值得复用的工程模式是"Agent 侧客户端 →/api/internal/*→server/utils/*"这一 HTTP 调用链:

agent/lib/*-internal.ts → /api/internal/* → server/utils/*

所有/api/internal/*路由都要求请求头携带Authorization: Bearer <INTERNAL_API_SECRET>,校验逻辑集中在 apps/web/server/utils/internal-api.ts:

export function requireInternalRequest(event: H3Event) { const secret = process.env.INTERNAL_API_SECRET?.trim(); if (!secret) { throw createError({ statusCode: 503, statusMessage: "Internal API is not configured" }); } const authorization = getRequestHeader(event, "authorization"); if (authorization !== `Bearer ${secret}`) { throw createError({ statusCode: 401, statusMessage: "Unauthorized" }); } }

Agent 侧的调用封装在 agent/lib/internal-api.ts:appOrigin()依次取BETTER_AUTH_URL→VERCEL_URL→ 默认http://localhost:3000,internalHeaders()则拼装Bearer头并强制要求INTERNAL_API_SECRET已配置。

现有内部路由清单:

路由用途
GET /api/internal/memory拉取用户记忆,用于会话注入
POST /api/internal/memory由 Agent 工具保存记忆
GET /api/internal/phone/link根据电话号码解析 App 用户(Sendblue/iMessage)
GET /api/internal/slack/link/member根据 Slack 用户解析 App 用户
POST /api/internal/slack/link/consume消费 Slack 链接码

例如 apps/web/server/api/internal/memory.get.ts 内部会并行调用getOrCreateProfileForUser与listMemoryForUser,返回{ profile, memory };而memory.post.ts用 zod 校验{ userId, category, content, source }后调用setMemoryForCategory落库。这组路由被以下 Agent 侧客户端消费:

  • agent/lib/memory-internal.ts—fetchUserContext(GET)与saveMemoryRemote(POST);
  • agent/lib/phone-internal.ts/agent/lib/slack-internal.ts— 渠道身份绑定。

环境变量:从本地三件套到生产全量

最小启动集(本地开发只需这三个)

变量获取方式
BETTER_AUTH_SECRET执行openssl rand -base64 32
BETTER_AUTH_URL本地为http://localhost:3000,生产为你的线上 URL
INTERNAL_API_SECRET执行openssl rand -base64 32(web 与 eve 两个服务必须一致)
cp .env.example .env

这三个变量足以支撑本地开发。上 Vercel 时需在web 与 eve 两个服务上都配置,并额外准备数据库。

数据库:本地 SQLite 与线上 Turso

本地开发时,NuxtHub(hub.db: "sqlite")直接使用.data/db/sqlite.db文件,无需任何配置。但在 Vercel 等 serverless 平台无法创建本地文件,若不配置托管数据库,每个请求都会报错:

Error: ConnectionFailed("Unable to open connection to local database .../.data/db/sqlite.db: 14")

解决方案是从 Vercel Marketplace 开通 Turso 数据库(README 中的 Deploy 按钮会自动附带,也可以对已有项目执行vercel integration add turso)。这会为项目注入TURSO_DATABASE_URL与TURSO_AUTH_TOKEN;NuxtHub 在构建期检测到这两个变量后自动从本地文件切换到远端 libSQL,因此配置后需要重新部署。随后拉取环境并迁移:

vercel env pull .env --yes pnpm db:migrate

可选变量NUXT_PUBLIC_SITE_URL用于 SEO 规范化 URL(Open Graph、Twitter card、canonical),缺省时回退到请求源地址。

认证与内部密钥

  • BETTER_AUTH_SECRET(必需):Better Auth 用于签名会话与令牌的随机密钥。
  • BETTER_AUTH_URL(必需):Nuxt 应用的公开 URL,既用于认证回调,也作为 Agent → Nuxt 内部 API 调用的基础 URL。
  • INTERNAL_API_SECRET(必需):Eve agent 服务与 Nuxt 内部 API 共享的 Bearer 令牌,用于记忆读写、Slack 账号绑定、iMessage 电话绑定。两个服务必须完全一致;缺失或不一致时,记忆注入、Slack 绑定、iMessage 认证会静默失败或返回 401。

Sendblue(iMessage,可选)

以下变量设置在eve服务上(BETTER_AUTH_URL则两个服务都要设,以便 Agent 解析电话绑定):

变量必填说明
SENDBLUE_API_KEY是Sendblue 控制台的 API key ID
SENDBLUE_API_SECRET是API 密钥
SENDBLUE_FROM_NUMBER是你的 Sendblue 号码(E.164 格式,如+15551234567)
SENDBLUE_WEBHOOK_SECRET是通过sb-signing-secret头校验的共享密钥
SENDBLUE_STATUS_CALLBACK_URL否外发消息的送达状态回调
SENDBLUE_ALLOWED_SERVICES否逗号分隔的服务白名单,默认仅iMessage,设为iMessage,SMS,RCS可全部接受

AI 模型

模板不在.env.example中定义 AI 密钥,默认模型在 agent/agent.ts 中:

export default defineAgent({ model: "anthropic/claude-sonnet-4.6", modelOptions: { providerOptions: { anthropic: { thinking: { type: "enabled", budgetTokens: 2048 }, }, }, }, });

在 Vercel 上由 Eve 平台负责 provider 配置;本地开发时按 Eve 文档为你选择的 provider 配置环境。

本地勿提交的文件

.env(本地密钥)、.data/(NuxtHub SQLite)、.eve/(Eve 开发缓存)、.vercel/(Vercel CLI 链接元数据)均已被 gitignore。重置本地数据库:

rm -rf .data/db && pnpm db:migrate

长期记忆:从注入到保存的完整闭环

记忆是模板的灵魂功能,其数据流可分为三个环节:

1. 会话注入(session.started)

agent/instructions.ts 监听session.started事件:先取ctx.session.auth.current?.principalId,若用户已认证则调用fetchUserContext(userId)拉取GET /api/internal/memory返回的{ profile, memory },再经buildUserContextPrompt拼装成"关于用户 + 记忆"的提示段落,追加到BASE_INSTRUCTIONS之后注入本会话。

提示段落的结构(agent/lib/memory-internal.ts):

  • # About this user:bio(如有)、时区、首选语言;
  • # Memory:按类别逐个输出## <类别名>+ 该类别完整内容。

注意:注入发生在会话建立时,因此导入或修改记忆后必须新开一个聊天,Agent 才会拾取最新上下文。

2. Agent 保存(save_memory工具 + Web 审批 UI)

agent/tools/save_memory.ts 用defineTool定义,关键特征:

  • 输入 schema 用 zod 约束:reason(保存理由)+updates(1~5 条),每条{ category, content },其中content必须是该类别整段替换文本而非增量;
  • approval: always()— 每次保存都必须经过用户审批(Web 端由ToolSaveMemory.vue渲染审批 UI);
  • execute中逐条调用saveMemoryRemote(POST/api/internal/memory,source: "agent"),服务端由 apps/web/server/api/internal/memory.post.ts 落库。

3. 档案管理 UI(Settings → Profile)

用户可在设置页对记忆执行导入、查看、编辑、删除。记忆类别固定为 5 个(见 lib/types/memory.ts):

类别枚举UI 标签导入解析别名
work_contextWork Contextwork context
personal_contextPersonal Contextpersonal context
active_focusActive Focusactive focus/active context
instructions_preferencesInstructions & Preferencesinstructions & preferences/instructions and preferences
project_historyProject Historyproject history

每类只保存一段散文文本,保存时整块替换(setMemoryForCategory会清空该类别旧行再写入新行)。对应的 Drizzle 表user_memory定义于 apps/web/server/db/schema/memory.ts,含user_id + category联合索引。此外模板还提供 Raycast 风格的 ChatGPT 导出粘贴导入解析器(apps/web/server/utils/memory-import.ts)。

渠道接入:Slack 与 iMessage 的实战实现

Slack:账号绑定与上下文注入

agent/channels/slack.ts 基于slackChannel实现:

  • 凭据来自 Vercel Connect:connectSlackCredentials("slack/v")(自定义 fork 时替换 slug);
  • 消息到达后先尝试解析link <code>命令(调用consumeSlackLinkCodeRemote消费 Web 端生成的链接码),成功则回复绑定完成;
  • 未绑定的 Slack 用户会收到指引:打开集成页生成链接码,再在 DM 中发送link <code>;
  • 已绑定用户通过fetchSlackLinkForMember查到 App 用户,用buildAppSessionAuth构造会话认证,使 Slack 会话复用与 Web 相同的身份、记忆与集成授权;
  • 同时把发送者的 display name、username、email 及"最近线程消息"注入上下文,让 Agent 知道是谁在说话、上文说了什么。

iMessage / Sendblue:纯文本世界的审批降级

agent/channels/sendblue.ts 实现了完整的 Sendblue 渠道,值得注意的设计点:

  • Webhook 路由为POST /eve/v1/sendblue/webhook,先校验sb-signing-secret头、跳过 typing 事件与is_outbound/非RECEIVED消息、默认拒绝群聊;
  • 入站消息按 E.164 号码通过GET /api/internal/phone/link解析 App 用户,未绑定号码会收到"去 Settings → Profile 添加号码"的指引;
  • 由于 iMessage 没有浏览器审批 UI,工具审批被降级为纯文本 YES/NO 回复:input.requested事件把 pending 工具请求记录到pendingInputByThread,用户回复yes/y/ok/approve或no/n/skip/deny触发source.respond;
  • save_memory在 iMessage 上被特殊处理:模板明确告知用户记忆保存需在 Web 档案中完成(Memory saves are not available in iMessage…),避免在无 UI 渠道上执行记忆写入。

Linear:MCP 连接即工具

agent/connections/linear.ts 使用defineMcpClientConnection连接https://mcp.linear.app/mcp,凭据通过 Vercel Connect(mcp.linear.app/linear)按用户维度下发;completeAuthorization还带 0/500/1000/2000ms 的重试退避。连接成功后,Agent 即可直接调用 Linear 的 issues/projects/cycles 等工具。基础指令(agent/lib/base-instructions.ts)为此内置了强约束:"Always call the tools first,绝不用state: "open"(Linear 没有该状态),总结时输出 identifier/title/status/priority"——这些规则直接避免了大模型"凭记忆作答"和无效查询。

自定义清单:把 V 变成你的 Agent

模板以V为示例 persona,fork 后按以下清单逐项替换:

  • lib/agent.ts — 品牌信息(name/slug/tagline/description/avatar.icon);
  • agent/lib/base-instructions.ts — persona、语气、工具使用与记忆行为规则;
  • agent/channels/slack.ts —connectSlackCredentials("slack/你的slug");
  • agent/agent.ts — AI 模型与 provider 选项。

同时需要同步更新的还有:apps/web/app/app.config.ts中的站点元数据(site.name/title/description/tagline)、apps/web/public/下的banner.png/og.png/favicon.ico品牌素材,以及发布 fork 时的package.json元信息。

扩展点:新工具、新技能、新集成

  • 新增工具:在agent/tools/创建defineTool(参考 agent/tools/weather.ts 与 agent/tools/save_memory.ts);如需自定义渲染,在apps/web/app/components/chat/tool/添加组件并挂到MessageContentEve.vue。工具目录按约定自动发现(具体以 Eve 文档为准)。
  • 新增技能:在agent/skills/写 Markdown 即可,参考 agent/skills/daily-summary.md(晨间简报:从注入的记忆取 active focus → 查 Linear 未完成 issues → 输出 Today/Linear/Suggested next 三段式),并在首页快捷操作中引用。
  • GitHub 集成:通过 Vercel Connect OAuth +@github-tools/sdk/eve,connector UID 在 lib/connect.ts(GITHUB_CONNECTOR = "github/personal-agent",与server/connectors.ts保持同步),工具在session.started时按用户 token 动态装配(agent/tools/github.ts)。创建命令:vercel connect create github --name personal-agent与vercel connect attach github/personal-agent。
  • Linear / Slack 集成:均走 Vercel Connect;Linear 无需改代码(connector 固定为mcp.linear.app/linear),Slack 需把 slug 换成自己的。

数据库模型一览

SQLite 经由 NuxtHub,schema 定义在 apps/web/server/db/schema/(迁移文件在server/db/migrations/)。核心表:

表用途
user/session/accountBetter Auth 认证
threads聊天线程
user_profile姓名、时区、电话
user_memory按类别的长期记忆
phone_links电话 ↔ App 用户映射(Sendblue/iMessage)
slack_linksSlack ↔ App 用户映射
slack_link_codes临时链接码

迁移流程为pnpm db:generate→pnpm db:migrate。

本地开发与 Vercel 部署

本地自托管

pnpm install cp .env.example .env pnpm db:migrate pnpm dev

打开http://localhost:3000,注册账号即可开始聊天。如需同时跑起 Agent 侧,使用pnpm dev:all(Vercel CLI 本地模式同时运行 Nuxt 与 eve 对等服务)。

部署 fork

核心注意事项:

  1. 双服务:web+eve由 vercel.ts 编排;
  2. 两侧环境变量一致:尤其是INTERNAL_API_SECRET与BETTER_AUTH_URL;
  3. 生产数据库:开通 Turso 后vercel env pull .env --yes && pnpm db:migrate应用迁移;
  4. 生产迁移在部署后执行,不要在构建期依赖本地 SQLite 文件。

小结:这套模板的工程价值

从源码与文档可以看出,Personal Agent Template 的工程要点可以归纳为四点:Eve 与 Nuxt 双服务对等部署、Bearer 密钥保护的内部 API 作为 Agent ↔ 业务数据通道、按类别整块替换的长期记忆模型(注入 + 审批保存 + UI 管理三段式)、多渠道(Web/Slack/iMessage)共享同一身份与记忆的绑定机制。无论你是想 fork 它直接产出个人助手,还是研究 Eve 框架下"Agent + 全栈 Web 服务"的协作范式,这份模板都提供了完整且可运行的最佳实践参考。深入源码的入口包括 agent/、apps/web/server/ 与 docs/ 三处,配合仓库根目录的 AGENTS.md 可快速建立全局认知。

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

【免费下载链接】eve

The Open Framework for Building Agents

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

相关推荐

上一篇:Loop:完全免费的 macOS 窗口管理工具,用径向菜单告别拖拽窗口
下一篇:Liger-Kernel 模型适配决策矩阵:为 HuggingFace 模型自动补丁的 12 个架构判定

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询