ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

eve 框架实战:以 filesystem-first 方式构建 durable 后端 AI Agent——Comp AI CRM 实践

eve 框架实战:以 filesystem-first 方式构建 durable 后端 AI Agent——Comp AI CRM 实践 后端前端CRM人工智能AI Agent【免费下载链接】crmComp AI CRM is an open source, CRM designed for AI agents. Agentic-first CRM.项目地址https://gitcode.com/gh_mirrors/crm48/crm点击查看免费下载本文以 Comp AI CRM 仓库中的 eve 技能文档.agents/skills/eve/SKILL.md为骨架结合apps/agent目录下的真实 eve 项目源码系统讲解 eve 框架的核心设计理念filesystem-first、Agent 即目录、编译运行、安装初始化流程以及 channels、schedules、hooks、sandbox、tools、instructions、subagents、evals 等可编程模块的实战用法。读完本文你将掌握如何用 eve 把一个后端 AI Agent 拆解为磁盘上的文件集合并让 eve 自动编译运行它。eve 是什么一个 filesystem-first 的 durable 后端 Agent 框架根据.agents/skills/eve/SKILL.md的定义eve 是一个 filesystem-first文件系统优先的框架用于构建 durable持久化、可恢复的后端 AI Agent。它的核心心智模型非常独特一个 Agent 就是磁盘上的一个目录——instructions指令、skills技能、tools工具、connections连接、channels通道、subagents子代理、schedules调度全部是文件——eve 负责编译并运行它。也就是说你不需要在内存中拼装一个 Agent 对象而是以目录 文件的形式声明 Agent 的全部组成部分eve 框架会在启动时读取这些文件、把它们编译成可运行的 Agent 运行时。这一设计在本仓库中得到了完整的印证apps/agent/agent目录就是一个Agent 即目录的活标本其子目录与 SKILL.md 中列出的组成要素一一对应SKILL.md 中的组成要素仓库中的实际目录/文件apps/agent/agent/instructionsinstructions.md、instructions/task.tsskillsskills/data-boundaries.md、skills/evidence.md、skills/identity-matching.md、skills/writing-a-brief.mdtoolstools/ 下 26 个*.ts文件search_crm、research_company、record_fact 等channelschannels/crm.ts、channels/eve.tssubagentssubagents/agent_builder/、subagents/agent_runner/schedulesschedules/dispatch.tshooksSKILL 未显式列出但属于同层级模块hooks/ 下 activity、audit、builder-delegation、telemetry 四个钩子每一个目录里的文件都是一个独立的、可被 eve 发现并注册的模块这正是filesystem-first的含义文件系统结构本身就是 Agent 的程序结构。权威文档从 node_modules/eve/docs/ 开始SKILL.md 强调了一个重要的工程实践eve 的完整文档随 eve 包本身一同发布位置在安装后的node_modules/eve/docs/并明确要求不要依赖这篇 skill 作为指导——始终阅读随包文档因为它与已安装的版本精确匹配。 阅读顺序上应从node_modules/eve/docs/README.md开始它包含完整的文档索引和推荐的阅读顺序在编写任何 eve 代码之前先阅读对应的指南。这条约定保证了文档与代码版本永远同步——apps/agent/package.json中声明了eve: ^0.29.4因此安装后该版本的 eve 文档即是^0.29.4对应版本不会出现文档与 API 错位的问题。安装与初始化npm install 与 npx eve initSKILL.md 给出了两个入口命令这是任何 eve 项目的第一步# 在已有项目中安装 eve 框架 npm install eve # 或脚手架生成一个全新的 eve Agent 项目 npx eve init agent-name执行npx eve init agent-name后eve 会生成一个标准化的 Agent 目录骨架随后即可通过node_modules/eve/docs/中的文档了解该骨架的每个目录的职责。在 Comp AI CRM 仓库中apps/agent/package.json展示了 eve 项目的标准命令集这些命令由scripts段定义{ scripts: { dev: eve dev, dev:headless: eve dev --no-ui, dispatch: curl -fsS -X POST \${AGENT_URL:-http://127.0.0.1:2000}/eve/v1/dev/schedules/dispatch\, build: eve build, start: bun scripts/start.ts, check-types: tsc --noEmit, test: CRM_TELEMETRY_DISABLED1 bun test, eval: CRM_TELEMETRY_DISABLED1 eve eval, lint: biome check ., clean: rm -rf .turbo .eve node_modules }, dependencies: { eve: ^0.29.4, context.dev: 2.10.0, zod: ^4.4.3, crm/db: workspace:*, crm/telemetry: workspace:*, crm/validation: workspace:* } }从中可以看出 eve 框架的核心 CLI 能力eve dev以开发模式运行 Agent并默认启动 UIdev:headless则通过--no-ui关闭界面适合无头环境eve build编译 Agent——这正是eve 编译并运行它中的编译环节把文件系统上的声明式配置与代码编译为可分发/可运行的产物eve eval运行 evals评测配合apps/agent/evals/evals.config.ts中的配置执行评估套件eve/v1/dev/schedules/dispatch开发环境下的调度触发端点用于手动触发 schedule。注意clean脚本会清理.eve目录这是 eve 的本地产物/缓存目录从侧面印证了 eve 具备编译产物这一中间状态。Agent 入口defineAgent 与动态模型选择每个 eve Agent 目录都有一个根级入口文件来声明 Agent 本身的配置。在 Comp AI CRM 中这个文件是 apps/agent/agent/agent.tsimport crm/env/load; import { DEFAULT_AGENT_MODEL } from crm/db/settings; import { defineAgent, defineDynamic } from eve; export default defineAgent({ model: defineDynamic({ fallback: DEFAULT_AGENT_MODEL.id, events: { session.started: () selectedModel() }, }), limits: { maxInputTokensPerSession: 500_000, maxOutputTokensPerSession: 50_000, sessionTimeoutMs: 30 * 24 * 60 * 60 * 1000, }, });几个关键点defineAgent是 eve 的 Agent 定义入口接收一个配置对象defineDynamic表示动态配置——model字段平时使用fallback兜底但在session.started事件发生时动态求值调用selectedModel()实现每个会话按需选择模型limits声明了会话级的硬性限制单会话最大输入 50 万 token、最大输出 5 万 token、会话超时 30 天。这类限制正是durable Agent的体现——会话是长期存活的实体因此必须有明确的资源边界。ChannelsAgent 与外部世界的进出通道channels 是 eve 中负责收发消息的模块相当于 Agent 的网络层。Comp AI CRM 定义了两种 channel自定义 HTTP channeldefineChannelapps/agent/agent/channels/crm.ts 使用defineChannel声明了一组 HTTP 路由与事件处理器负责接收 CRM 后端的调度请求、并向 CRM 发送 agent 产出import { defineChannel, GET, POST } from eve/channels; import { z } from zod; export default defineChannel({ routes: [ GET(/internal/crm/dispatch-health, async (request) { ... }), POST(/internal/crm/dispatch, async (request, { send, waitUntil }) { ... }), POST(/internal/crm/builder-dispatch, async (request, { send, waitUntil }) { ... }), POST(/internal/crm/agent-dispatch, async (request, { send, waitUntil }) { ... }), POST(/internal/crm/cancel-run, async (request, { cancel }) { ... }), POST(/internal/crm/slack/create-channel, async (request) { ... }), POST(/internal/crm/verify-key, async (request) { ... }), ], events: { async input.requested(data, channel, ctx) { ... }, async message.completed(data, channel) { ... }, async session.waiting(_data, channel) { ... }, async turn.failed(data, channel) { ... }, async session.completed(_data, channel) { ... }, async turn.cancelled(_data, channel) { ... }, async session.failed(data, channel) { ... }, }, async receive(input, { send }) { ... }, });route 处理器收到的{ send, waitUntil, cancel }等能力对象值得注意send向 Agent 会话发送消息并携带auth与continuationToken续接令牌是外部触发 Agent的通道waitUntil把异步任务挂到请求生命周期之外执行类似平台的后台任务语义POST /internal/crm/dispatch返回 202 后由waitUntil继续执行排空逻辑cancel通过continuationToken取消一个正在运行的会话continuationTokeneve 的 durable 机制核心——每个会话/任务都有一个不透明令牌本仓库中taskToken(task.id)、runToken(runId)、builderToken(conversationId)即其生成器外部系统可以凭它续接或取消会话这正是Agent 状态可持久恢复的接口证据。事件处理器则覆盖了会话/回合的完整生命周期input.requested请求用户输入、message.completed、session.waiting会话等待输入、turn.failed/turn.cancelled、session.completed/session.failed。Comp AI CRM 正是通过这些事件把 Agent 的运行状态回写到数据库例如agentConversation、agentRun、agentTask表实现前后端状态一致性。内置 eve channel认证组合apps/agent/agent/channels/eve.ts 展示了 eve 提供的开箱即用认证工具import { type AuthFn, extractBearerToken, localDev, vercelOidc, verifyJwtHmac, withAuthChallenges, } from eve/channels/auth; import { eveChannel } from eve/channels/eve; export function repFromCrm(secret: string): AuthFnRequest { return withAuthChallenges( async (request: Request) { const result await verifyJwtHmac( extractBearerToken(request.headers.get(authorization)), { algorithm: HS256, audiences: [BRIDGE_AUDIENCE], issuer: BRIDGE_ISSUER, secret, }, ); if (!result.ok) return null; // ... 提取 claims.subject 作为 principalId }, [{ scheme: Bearer }], ); } export default eveChannel({ auth: [...(secret ? [repFromCrm(secret)] : []), vercelOidc(), localDev()], });eveChannel是 eve 自带的 Web 通道auth数组可以组合多个认证器HMAC-JWT 校验CRM 桥接、vercelOidc()Vercel 平台 OIDC、localDev()本地开发免认证。withAuthChallenges负责在认证失败时返回标准的认证挑战响应。这套组合使同一通道在本地开发、生产部署、内部服务间调用三种场景下自动选择正确的认证策略。Schedulescron 驱动的后台调度eve 的 schedules 用defineSchedule声明 cron 表达式与对应执行逻辑。Comp AI CRM 的 apps/agent/agent/schedules/dispatch.ts 每分钟运行一次import { defineSchedule } from eve/schedules; import crm from ../channels/crm; export default defineSchedule({ cron: * * * * *, async run({ receive, waitUntil, appAuth }) { waitUntil( Promise.all([ sweepBlankFacts(), (async () { await reconcileStaleTasks(); await drainAll((task) receive(crm, { message: brief(task), target: { taskId: task.id }, auth: taskAuth(task, appAuth), }), ); await queueDueAgentRuns(); // ... 派发 builder submissions 与 agent runs })(), ]), ); }, });这里的核心 API 是receive(channel, { message, target, auth })——与 channel 的send相对schedule 通过receive把一条消息投递给指定 channel 的 Agent完成定时任务 → Agent 会话的桥接。appAuth是 eve 提供的应用级认证主体用于内部调度assertInternalDispatchAuth要求principalId eve:app。从apps/agent/package.json的dispatch脚本可见开发模式下可通过POST http://127.0.0.1:2000/eve/v1/dev/schedules/dispatch手动触发该 schedule。Hooks挂接会话生命周期事件hooks 让 Agent 可以在会话/回合事件发生时执行自定义逻辑。仓库中有四个 hook分布在 apps/agent/agent/hooks/activity.ts记录会话活动import { defineHook, type HookEvent } from eve/hooksaudit.ts审计日志telemetry.ts遥测数据上报builder-delegation.tsAgent Builder 委托逻辑。hooks 的典型形态如下以 apps/agent/agent/hooks/audit.ts 为例import { defineHook } from eve/hooks; export default defineHook({ ... });eve 会依据文件位置自动发现并注册这些 hook无需手动装配——这就是 filesystem-first 的体现你放一个defineHook文件在 hooks/ 目录下它就成了 Agent 的一部分。子代理subagent也可以拥有自己的 hooks例如 apps/agent/agent/subagents/agent_builder/hooks/execution-guard.ts 即为 agent_builder 子代理定义了执行守卫钩子。Sandbox默认拒绝网络的执行沙箱apps/agent/agent/sandbox/sandbox.ts 展示了 eve 对工具代码执行环境的隔离能力import { defaultBackend, defineSandbox } from eve/sandbox; export default defineSandbox({ backend: defaultBackend({ vercel: { networkPolicy: deny-all }, docker: { networkPolicy: deny-all }, microsandbox: { networkPolicy: deny-all }, }), });defineSandbox声明 Agent 工具执行所用的沙箱defaultBackendeve 根据部署平台自动选择后端Vercel / Docker / microsandbox这里对三者统一设置了networkPolicy: deny-all——即默认拒绝所有网络访问从源码结构看这意味该仓库的 Agent 工具默认在无网络沙箱中运行需要网络的能力如research_company必然在工具内部走专门的白名单网络通道或由 CRM 服务端代理体现了最小权限的安全原则。子代理同样可以配置独立的沙箱如 apps/agent/agent/subagents/agent_builder/sandbox/sandbox.ts。Tools用 zod 声明工具的输入输出契约tools 是 Agent 的能力单元。eve 的 tool 用defineTool定义且必须用 zod 声明输入 schema。以 apps/agent/agent/tools/search_crm.ts 为例import { defineTool } from eve/tools; import { z } from zod; import { searchCrm } from ../lib/lookup; export default defineTool({ description: Find contacts, companies and deals by name, email address, domain or deal name — the way a person would search. ..., inputSchema: z.object({ query: z.string().min(2).describe(A name, an email address, a domain, or part of one.), kinds: z .array(z.enum([contact, company, deal])) .optional() .describe(Narrow the search. Defaults to all three.), limit: z.number().int().min(1).max(25).default(10), }), async execute({ query, kinds, limit }) { const result await searchCrm(query, { kinds, limit }); return { ...result, note: /* 面向 Agent 的提示语 */ }; }, });关键实践description要面向模型写它会被注入模型上下文因此写的是the way a person would searchso you never have to ask a rep for one这类引导性描述而非面向人的注释inputSchema用 zod 声明类型、范围min(2)、max(25)、default(10)都成为模型生成参数的约束execute的返回值可附带note把结果为空也是一种答案等推理提示返回给模型改善 Agent 行为。tools/ 目录下 26 个工具archive_field、enrich_company、find_contact_socials、get_linkedin_profile、identify_contact、list_deals、record_fact、research_company、write_brief 等共同构成了这个 CRM Agent 的完整能力面。此外 eve 还提供disableToolapps/agent/agent/subagents/agent_builder/tools/bash.ts 中用于按上下文禁用工具和Approval类型apps/agent/agent/lib/approval.ts 中用于敏感操作审批等进阶工具能力。Instructions会话级动态指令eve 的 instructions 负责为会话生成系统提示词。Comp AI CRM 在 apps/agent/agent/instructions/task.ts 中把指令设计为随会话属性动态变化import { defineDynamic, defineInstructions } from eve/instructions; export default defineDynamic({ events: { session.started: async (_event, ctx) { const purpose purposeOf(ctx); if (purpose builder) return builderInstructions(ctx); if (purpose team-agent) { return defineInstructions({ markdown: This is one background run of a deployed team agent. ..., }); } // 解析 attributesbudget、taskKind、fieldKeys、contactId...后拼装指令 return defineInstructions({ markdown: ${RESEARCH_INSTRUCTIONS}\n\n${markdown} }); }, turn.started: (_event, ctx) { ... }, }, });配合根级静态指令 apps/agent/agent/instructions.mdNever invent a CRM record... Tools and persisted state are the authority形成了静态底线 动态上下文的双层指令体系静态文件声明不可违背的原则defineDynamic在session.started时按会话属性任务类型、预算、字段范围实时生成指令。defineInstructions与defineDynamic均来自eve/instructions模块。Subagents嵌套的专用子代理subagents 允许在一个 Agent 内部声明专用的子代理每个子代理又拥有自己完整的文件结构instructions、tools、hooks、sandbox、lib。仓库中有两个典型subagents/agent_builder/负责构建/编辑 Agent 的子代理含 17 个文件agent.ts、instructions.md、hooks/execution-guard.ts、sandbox/sandbox.ts、tools/ 下的 bash、glob、grep、read_file、save_agent_draft、todo、web_fetch、web_search 等以及 lib/draft-input.ts、lib/execution-state.tssubagents/agent_runner/负责执行已部署 Agent 的子代理19 个文件。从 apps/agent/agent/instructions/task.ts 中Call agent_runner exactly once and pass the run id from your user message. Do not call research tools or perform work yourself.这条指令可以看出子代理的协作模式父 Agent 负责编排与路由子代理负责专注执行某类专精任务二者通过会话消息交换结构化结果。子代理目录也遵循Agent 即目录的同一套约定形成了递归嵌套的 Agent 体系。EvalsAgent 的自动化评测eve 提供内置的评测框架通过eve eval命令运行。Comp AI CRM 的评测配置在 apps/agent/evals/evals.config.tsimport { defineEvalConfig } from eve/evals; export default defineEvalConfig({ maxConcurrency: 1, timeoutMs: 180_000, });maxConcurrency: 1串行执行评测避免并发评测间的资源竞争timeoutMs: 180_000单次评测超时 3 分钟。评测用例位于 apps/agent/evals/agent-builder.eval.ts覆盖了 agent_builder 子代理的核心行为。运行方式即package.json中的eval: CRM_TELEMETRY_DISABLED1 eve eval禁用遥测以隔离评测环境。从源码结构看eve 的 evals 与eve/dev开发服务器深度集成是先评测后上线的 Agent 开发流程中的关键一环。总结一套可照搬的 eve Agent 工程范式回顾 Comp AI CRM 的实践一个生产级 eve Agent 的标准形态是根级agent.ts用defineAgent声明模型与资源限制limitschannels/用defineChannel/eveChannel声明 HTTP 入口与认证用continuationToken支撑 durable 会话续接schedules/用defineSchedule cron 驱动定时后台任务hooks/用defineHook挂接会话生命周期做审计、遥测与状态回写tools/用defineTool zod 声明能力契约instructions/用defineInstructions/defineDynamic生成会话指令sandbox/用defineSandbox收紧执行环境默认 deny-all 网络subagents/声明专精子代理各自拥有完整文件结构evals/用defineEvalConfig配置自动化评测。这套范式与.agents/skills/eve/SKILL.md的定义完全一致Agent 是磁盘上的目录eve 编译并运行它。无论你从npx eve init agent-name起步还是像 Comp AI CRM 这样手工组织目录最终产物都是同一个声明式、可持久化、可评测的 durable 后端 Agent。动手之前请务必先阅读随包安装的node_modules/eve/docs/README.md——它与你安装的 eve 版本严格同步是最可靠的 API 与指南来源。赞分享后端前端CRM人工智能AI Agent【免费下载链接】crmComp AI CRM is an open source, CRM designed for AI agents. Agentic-first CRM.项目地址https://gitcode.com/gh_mirrors/crm48/crm点击查看免费下载相关推荐深入Comp AI CRM的AI Agent核心基于eve框架的18个工具与4大技能全解深入Comp AI CRM的AI Agent核心基于eve框架的18个工具与4大技能全解 Comp AI CRM 是一款开源的 AI 优先 CRM客户关系管后端前端CRM人工智能AI AgentAgent-First-Organization构建高效AI Agent的框架Agent First Organization构建高效AI Agent的框架 项目介绍 Agent First Organization 是一个开源项目旨开源Agentic CRM的崛起Comp AI CRM如何让AI Agent成为销售团队的幕后引擎开源Agentic CRM的崛起Comp AI CRM如何让AI Agent成为销售团队的幕后引擎 Comp AI CRM 是一款 开源的 Agentic C后端前端CRM人工智能AI Agent上一篇fully-local-pdf-chatbot安全更新策略安全加固与版本升级流程下一篇fully-local-pdf-chatbot技术债务管理可持续开发实践创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表