mcpField
S
slack-agent

slack-agent

github.com/vercel-labsAgent 工作流23834 次安装15 周前更新
代码仓库

关于 slack-agent

面向构建 Slack Agent 的开发技能,指导使用 eve 和 Vercel Connect 完成项目搭建、配置、测试与部署。内容还涵盖 Slack 事件处理、线程上下文和人工审批流程。

主要功能

  1. 01Slack Agent 项目搭建向导
  2. 02通过 Vercel Connect 配置凭据
  3. 03Slack 事件与线程上下文处理
  4. 04审批交互和主动会话模式
  5. 05代码质量与测试要求

适用场景

  1. 01从零创建 Slack Agent 项目
  2. 02为现有 eve 项目添加 Slack 通道
  3. 03配置事件响应、线程上下文或工具审批
  4. 04部署并测试 Slack Agent

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/vercel-labs/slack-agent-skill --skill slack-agent

安装后在 Claude Code 中输入/slack-agent确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

LICENSE
README.md
.gitignore
patterns/
testing-patterns.md
slack-patterns.md
reference/
vercel-setup.md
agent-archetypes.md
env-vars.md
slack-setup.md
templates/eve/
test-setup.ts
vitest.config.ts
templates/eve/sample-tests/
agent.test.ts
tools.test.ts
wizard/
2-create-slack-app.md
1b-approve-plan.md
5-deploy-production.md
1-project-setup.md
3-configure-environment.md
6-setup-testing.md
4-test-locally.md
README.md

详细介绍

Slack Agent 开发技能

这项技能使用 eve 构建 Slack Agent。eve 是 Vercel 的文件系统优先型持久后端 Agent 框架,并使用 Vercel Connect 管理 Slack 凭证:

  • eve(eve package)——Agent 运行时、工具、频道和持久性
  • @vercel/connect ——通过代理提供短期 Slack 令牌;无需管理机器人令牌或签名密钥

技能调用处理

通过 /slack-agent 调用此技能时,检查是否有参数,并据此进行处理:

命令参数
参数操作
new**运行第 1 阶段的设置向导。**读取 ./wizard/1-project-setup.md,引导用户创建新的 Slack Agent。
configure从第 2 或第 3 阶段开始向导,适用于现有项目
deploy从第 5 阶段开始向导,进行生产部署
test从第 6 阶段开始向导,设置测试
(无参数)根据项目状态自动检测(见下文)
自动检测(无参数)

如果调用时没有参数,检测项目状态并进行相应处理:

  1. 没有包含 eve 的 package.json,且没有 agent/ 目录 → 视为 new,从第 1 阶段开始
  2. 有 eve 项目,但没有 agent/channels/slack.ts → 从第 2 阶段开始(Slack 连接器 + 频道)
  3. 有 Slack 频道,但未配置 SLACK_CONNECTOR → 从第 3 阶段开始
  4. 已配置但尚未部署 → 从第 5 阶段开始(Slack 界面仅在部署后可用)
  5. 已部署但没有测试 → 从第 6 阶段开始
  6. 其他情况 → 使用此技能中的模式提供常规帮助
项目检测

满足以下任一条件,即可检测为 eve 项目:

  • package.json 将 "eve" 列为依赖项
  • 存在包含 instructions.md 和/或 agent.ts 的 agent/ 目录

如果两者均不满足,则视为新项目:使用 npx eve@latest init 搭建项目(需要 Node 24+)。

向导阶段

向导位于 ./wizard/,包含以下阶段:

  • 1-project-setup.md - 了解项目用途,生成定制实施计划,并使用 npx eve@latest init 搭建项目
  • 1b-approve-plan.md - 在搭建项目前向用户展示计划并征求批准
  • 2-create-slack-app.md - 使用 Vercel Connect 创建 Slack 连接器并添加 Slack 频道
  • 3-configure-environment.md - 设置环境变量(SLACK_CONNECTOR、模型凭证)
  • 4-test-locally.md - 使用 eve dev TUI 在本地测试 Agent 逻辑(Slack 界面测试在部署后进行)
  • 5-deploy-production.md - 使用 eve deploy 部署并验证 Slack 界面
  • 6-setup-testing.md - Vitest 配置

**重要:**对于 new 项目,你必须:

  1. 首先阅读 ./wizard/1-project-setup.md
  2. 询问用户想构建哪种 Agent
  3. 使用 ./reference/agent-archetypes.md 生成定制实施计划
  4. 在搭建项目前,先展示计划并征求批准(第 1b 阶段)
  5. 只有在计划获批后才能开始搭建项目

通用开发指南

你正在开发一个使用 eve 构建的 Slack Agent 项目。进行所有代码更改时,必须遵循以下实践。

项目技术栈

  • 框架:eve(文件系统优先型 Agent 框架;Node 24+)
  • Slack 频道:eve/channels/slack + @vercel/connect,用于管理凭证
  • AI:默认通过 Vercel AI Gateway 路由模型(anthropic/claude-sonnet-5);使用 zod 定义工具架构
  • 持久性:底层使用 Workflow SDK(部署到 Vercel 时使用 Vercel Workflows)
  • Lint 工具:Biome
  • 包管理器:pnpm(或 npm——npx eve@latest init 使用 npm 安装)
{
  "engines": { "node": "24.x" },
  "dependencies": {
    "eve": "latest",
    "ai": "latest",
    "zod": "^3.x",
    "@vercel/connect": "latest"
  }
}
文件系统优先型布局

在 eve 中,文件的位置决定其用途,路径通常也决定文件名称。整个 Agent 位于 agent/ 下:

agent/
├── instructions.md        # Always-on system prompt
├── agent.ts               # Runtime config (defineAgent): model, reasoning, compaction
├── tools/                 # Tools — filename (snake_case ASCII) = tool name the model sees
│   ├── get_weather.ts
│   └── search_docs.ts
├── skills/                # Load-on-demand instructions (*.md with description frontmatter)
│   └── incident-triage.md
├── channels/
│   └── slack.ts           # Slack channel — filename registers it at /eve/v1/slack
├── connections/           # MCP / OpenAPI connections (optional)
└── hooks/                 # Subscribe to runtime stream events (optional)

即使只有两个文件(instructions.md + agent.ts)的 Agent,也能通过默认运行框架直接使用文件、Shell、Web 和委派工具。安装 eve 后,完整文档会放在 node_modules/eve/docs/ 中——如果这里没有介绍某项细节,请查阅文档。

// agent/agent.ts
import { defineAgent } from "eve";

export default defineAgent({
  model: "anthropic/claude-sonnet-5", // routed via Vercel AI Gateway
});

质量标准(强制)

每次代码变更都必须遵循这些质量要求,不得例外。

每次修改文件后
  1. 立即运行 lint:

    pnpm lint
    
    • 如果存在错误,运行 pnpm lint --write 自动修复
    • 手动修复剩余问题
    • 重新运行 pnpm lint 进行验证
  2. 检查是否有对应的测试文件:

    • 如果修改了 foo.ts,检查是否存在 foo.test.ts
    • 如果不存在测试文件,且该文件导出了函数,则创建一个
完成任何任务之前

标记任务完成之前,必须运行所有质量检查并修复所有问题:

# 1. TypeScript compilation - must pass
pnpm typecheck

# 2. Linting - must pass with no errors
pnpm lint

# 3. Tests - all tests must pass
pnpm test

如果其中任何一项未通过,请勿完成任务。 请先修复问题。

必须编写单元测试

对于任何代码变更,都必须编写或更新单元测试。

  • 位置:与代码同目录的 *.test.ts 文件(例如 agent/tools/get_weather.test.ts)
  • 框架:Vitest
  • 覆盖范围:必须测试所有导出函数以及每个工具的 execute()(包括错误路径)

测试结构示例:

import { describe, it, expect, vi } from 'vitest';
import { myFunction } from './my-module';

describe('myFunction', () => {
  it('should handle normal input', () => {
    expect(myFunction('input')).toBe('expected');
  });

  it('should handle edge cases', () => {
    expect(myFunction('')).toBe('default');
  });
});
面向用户的变更需要端到端测试

如果修改以下内容:

  • 分发钩子(onAppMention、onDirectMessage、onInteraction)
  • 自定义频道事件处理程序
  • Agent 响应 Slack 消息时调用的工具
  • 投递行为(发布到 Slack 的内容)

必须添加或更新测试,以验证完整流程。请记住:无法在本地测试 Slack 界面本身(参见 Gotchas),因此端到端覆盖意味着围绕处理程序编写单元/集成测试,并在部署后进行冒烟测试。


机器人设置模式(关键)

Slack 频道(agent/channels/slack.ts)

Slack 频道只有一个文件。其文件名用于注册 slack 频道,服务路径为 /eve/v1/slack——这是本技能中所有位置使用的规范触发路径。

// agent/channels/slack.ts
import { connectSlackCredentials } from "@vercel/connect/eve";
import { slackChannel } from "eve/channels/slack";

export default slackChannel({
  credentials: connectSlackCredentials(process.env.SLACK_CONNECTOR!),
});

connectSlackCredentials(connectorUid) 会返回 { botToken, webhookVerifier }:

  • botToken——通过 Vercel Connect 在运行时解析为短期、限定应用范围的令牌;Connect 会处理轮换和多工作区租户
  • webhookVerifier——确认每个转发的事件确实来自 Connect(替代 Slack 原生的签名检查)

此技术栈中没有 SLACK_BOT_TOKEN,也没有 SLACK_SIGNING_SECRET。唯一的 Slack 环境变量是 SLACK_CONNECTOR(连接器 UID,例如 slack/my-agent)。

Vercel Connect 设置

创建一个 Slack 连接器,并将其触发器指向 eve 的 Slack 路由:

npm install -g vercel@latest

# Create the connector with event forwarding enabled
vercel connect create slack --triggers

# Attach the project as a trigger destination on eve's route
# (the default trigger path is /slack — set it explicitly):
vercel connect attach <uid> --triggers --trigger-path /eve/v1/slack --yes

必须指定 --triggers。 否则,Slack 事件订阅永远不会转发,app_mention/message.im 事件也永远不会到达——部署看起来正常,但机器人永远不会响应。

也可以运行 eve channels add slack 添加频道,该命令会为你搭建 agent/channels/slack.ts。

部署
eve deploy
# wraps: vercel deploy --prod

然后邀请机器人加入频道并 @提及它。eve 会处理 Slack 的确认语义、URL 验证和后台处理——你无需编写 webhook 路由。


事件处理模式

分发钩子(入站)

Slack 频道通过分发钩子决定哪些入站事件会启动或继续会话。每个钩子会返回 { auth } 以进行分发、返回 null 以丢弃事件,或返回 { auth, context } 将后台上下文注入会话:

export default slackChannel({
  credentials: connectSlackCredentials(process.env.SLACK_CONNECTOR!),

  // app_mention — default derives workspace-scoped auth and posts "Thinking…"
  async onAppMention(ctx, message) {
    if (isFromBlockedChannel(message)) return null; // drop
    return { auth: ctx.defaultAuth };
  },

  // message.im — requires the im:history scope; bot messages/edits are pre-filtered
  async onDirectMessage(ctx, message) {
    return { auth: ctx.defaultAuth };
  },

  // block_actions not consumed by HITL prompts
  async onInteraction(action, ctx) {
    return { auth: ctx.defaultAuth };
  },
});

触发事件的 Slack 用户 ID 会自动附加到模型消息中,从而在多用户线程中保留发言者归属信息。

自定义事件处理程序(出站投递)

使用 events 映射覆盖每个流事件的投递行为。处理程序会接收 (eventData, channel, ctx),并可使用 channel.thread 和 channel.slack 句柄:

export default slackChannel({
  credentials: connectSlackCredentials(process.env.SLACK_CONNECTOR!),
  events: {
    "message.completed"(eventData, channel, ctx) {
      if (eventData.finishReason === "tool-calls") return;
      if (eventData.message) channel.thread.post(eventData.message);
    },
  },
});

主要流事件:session.started、actions.requested、action.result、message.completed、session.completed;增量事件 reasoning.appended/message.appended 为可选项。

线程上下文

在会话中途触发时,为 Agent 提供此前的线程消息:

export default slackChannel({
  credentials: connectSlackCredentials(process.env.SLACK_CONNECTOR!),
  threadContext: { since: "last-agent-reply" },
});

since 选项:

  • "thread-root" — 所有此前的消息(启用线程上下文时的默认值)
  • "last-agent-reply" — 增量加载,仅包含 Agent 上次发言之后的消息
  • 自定义截止条件 (message: SlackThreadMessage) => boolean — 包含最后一次匹配之后的消息(loadThreadContextMessages 可用于任意筛选)

成本:每条触发回复需要调用一次 conversations.replies API;需要连接器具备匹配的历史记录权限范围。

人在回路中(HITL)

需要审批的工具调用和登录挑战会直接在 Slack 中呈现:

  • 审批提示以按钮/选择框的形式显示;用户响应后,会恢复持久化挂起的会话
  • 登录挑战(OAuth URL、设备代码)会通过临时消息发送给触发操作的用户;线程中会发布一条公开状态消息,并在 authorization.completed 时更新
  • HITL 处理程序上下文有意仅提供 postEphemeral、postDirectMessage(需要 im:write)和 state,不提供公开的 post 或原始 API 访问权限
主动会话(计划任务)

启动一个无需入站触发、可向 Slack 发帖的会话,例如通过计划任务启动:

import { receive } from "eve";
import slack from "../channels/slack";

await receive(slack, {
  message: "Post the daily standup summary for #eng.",
  target: { channelId: "C0123456789" },
  auth,
});
原始 Slack API 访问
  • 在处理程序中:ctx.slack.request(operation, body)
  • 在处理程序外部(计划任务、工具):使用 eve/channels/slack 中的 callSlackApi({ botToken, operation, body }) 和 resolveSlackBotToken

这些函数会为你对请求正文进行表单编码——Slack 对 JSON 的支持有限,因此建议使用这些辅助函数,而非手动编写 fetch 调用。


实现注意事项

1. 无法在本地测试 Slack 界面

Vercel Connect 只会将 Slack 事件转发到部署环境,绝不会转发到 localhost。此技术栈没有 ngrok/Socket Mode 的替代方案。本地开发方式:

  • npx eve dev — HMR 服务端 + 终端 TUI/REPL,用于测试 Agent 逻辑、工具和技能
  • eve dev --no-ui — 后台模式,用于脚本化验证
  • eve dev https://your-app.vercel.app — 交互式驱动已部署的应用

要测试 @提及和私信,请部署到预览或生产环境,并直接在 Slack 中测试。

2. Connect 转发不提供投递去重

Connect 可能会多次投递同一条转发事件。处理程序和副作用必须保持幂等——在重复事件可能造成损害的情况下,跟踪已处理的事件 ID,并通过审批来限制破坏性工具操作(参见 AI 集成)。

3. 必须使用 --triggers,否则不会收到事件

创建 Slack 连接器时未使用 --triggers(或添加连接器时未配置触发路径),仍然可以正常完成身份验证,但不会转发任何内容。如果机器人从不响应 @提及:

  1. 确认创建/添加连接器时使用了 --triggers
  2. 确认触发路径为 /eve/v1/slack
  3. 确认机器人已受邀加入频道,且部署已完成
4. placeholderAuth() 在生产环境中会默认拒绝请求

脚手架项目的 HTTP API 默认使用 placeholderAuth(),它会在生产环境中拒绝所有请求。部署前,请将其替换为真实的身份验证函数:httpBasic()、jwtHmac()、jwtEcdsa()、oidc()、vercelOidc() 或自定义的 AuthFn。(Slack 频道的入站验证是独立的——由 Connect 的 webhookVerifier 处理。)

5. 沙盒预热失败会导致构建失败

Vercel 构建会预热 eve 的沙盒模板(以缓存键为依据;构建日志会显示 reused cached 或 built)。如果预热失败,整个构建都会失败——怀疑代码存在问题之前,请先检查构建日志中的沙盒模板错误。

6. 私有频道访问

机器人无法读取未受邀加入的私有频道中的消息,也无法向其中发帖。创建之后会向频道发帖的功能(例如按计划启动的主动会话)时,请预先验证访问权限,并在遇到 channel_not_found / not_in_channel 时显示清晰的“邀请机器人”提示。

7. 优雅降级频道上下文

为 AI 功能获取频道上下文时(例如通过 ctx.slack.request("conversations.history", ...)),请使用 try/catch 包裹,并优雅降级——缺少权限范围和未受邀加入频道都是常见情况,并非异常。

8. Vercel Cron 端点身份验证

如果添加自定义 cron 端点(eve schedules 之外的端点),请使用 CRON_SECRET 保护它们:

export async function GET(request: Request) {
  const authHeader = request.headers.get("authorization");
  if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) {
    return Response.json({ error: "Unauthorized" }, { status: 401 });
  }
  // Run cron job logic...
  return Response.json({ success: true });
}
9. vercel.json Cron 配置
{
  "crons": [
    {
      "path": "/api/cron/my-job",
      "schedule": "0 * * * *"
    }
  ]
}

对于由 Agent 驱动的定期工作,优先使用 eve schedules;对于普通 HTTP 作业,使用 Vercel crons。

10. Vercel 上的 AWS 凭证(使用 OIDC)

从 Vercel 连接到 AWS 服务时,不要使用 fromNodeProviderChain()。请使用 Vercel 的 OIDC 机制:

import { awsCredentialsProvider } from "@vercel/functions/oidc";

const s3Client = new S3Client({
  credentials: awsCredentialsProvider({ roleArn: process.env.AWS_ROLE_ARN! }),
});

AI 集成

模型配置(Gateway 优先)

eve 会通过 Vercel AI Gateway 路由模型 ID 字符串——在 Vercel 上,项目 OIDC 会自动进行身份验证,因此不需要 AI API 密钥:

// agent/agent.ts
import { defineAgent } from "eve";

export default defineAgent({
  model: "anthropic/claude-sonnet-5", // string → AI Gateway → OIDC auth on Vercel
});

如果省略 model,eve 默认使用 anthropic/claude-sonnet-5。在 Vercel 之外,请设置 AI_GATEWAY_API_KEY。

关键:切勿凭记忆使用模型 ID。 模型 ID 经常变化。在编写固定使用某个模型的代码之前,请运行 curl -s https://ai-gateway.vercel.sh/v1/models 获取当前列表,并使用最新的合适版本。

工具(agent/tools/*.ts)

工具以文件形式存在:文件名(snake_case ASCII)就是面向模型的工具名称——agent/tools/get_weather.ts → get_weather。无需注册。

// agent/tools/get_weather.ts
import { defineTool } from "eve/tools";
import { z } from "zod";

export default defineTool({
  description: "Get the current weather for a city.",
  inputSchema: z.object({ city: z.string().min(1) }), // required, even if empty
  outputSchema: z.object({
    city: z.string(),
    condition: z.string(),
    temperatureF: z.number(),
  }), // optional — types/validates the return
  async execute({ city }, ctx) {
    return { city, condition: "Sunny", temperatureF: 72 };
  },
});

规则和能力:

  • 工具在你的应用运行时中运行,可完全访问 process.env,不在沙盒中运行
  • inputSchema 接受 Zod、Standard Schema 或 JSON Schema,但即使工具没有输入,也必须提供
  • 输出必须可序列化为 JSON;返回前请过滤/隐去机密信息
  • ctx 提供 ctx.session(元数据、轮次、身份验证、溯源信息)、ctx.callId、ctx.toolName、ctx.abortSignal、ctx.getSandbox()、ctx.getSkill(id)
审批门控

使用 approval 字段为高风险工具设置门控——辅助函数来自 eve/tools/approval:

import { defineTool } from "eve/tools";
import { always, once, never } from "eve/tools/approval";
import { z } from "zod";

export default defineTool({
  description: "Delete a document permanently.",
  inputSchema: z.object({ documentId: z.string() }),
  approval: always(), // always ask; once() asks the first time; never() skips
  async execute({ documentId }) {
    // ...
  },
});

也支持依赖输入的策略函数。受门控的调用会暂停,并可持久化恢复——在 Slack 中,审批会显示为按钮(参见上文的 HITL)。对于任何非幂等副作用,请优先使用审批门控,而不是临时编写确认逻辑。

toModelOutput — 模型不可见的丰富 Slack 输出

向模型展示精简的内容,而频道/钩子通过 action.result 接收完整输出——非常适合根据工具结果渲染丰富的 Slack Block Kit 内容,同时避免将 JSON 块塞入模型上下文:

export default defineTool({
  description: "Look up an order.",
  inputSchema: z.object({ orderId: z.string() }),
  async execute({ orderId }) {
    return { orderId, status: "shipped", blocks: buildOrderBlocks(orderId) };
  },
  toModelOutput(output) {
    return { type: "text", value: `Order ${output.orderId}: ${output.status}` };
  },
});
技能(agent/skills/*.md)

Markdown 文件,包含 description frontmatter;当请求符合该描述时,由内置的 load_skill 工具按需加载。技能只添加指令,不添加新操作。使用 npx skills add <owner>/<repo> 安装已发布的技能。

连接(agent/connections/*.ts)

对于 Agent 应驱动的外部 API(MCP 服务或由 OpenAPI 描述的 HTTP API),请使用通过 Connect 代理身份验证的连接:

// agent/connections/linear.ts
import { connect } from "@vercel/connect/eve";
import { defineMcpClientConnection } from "eve/connections";

export default defineMcpClientConnection({
  url: "https://mcp.linear.app/mcp",
  description: "Linear workspace: issues, projects, cycles, and comments.",
  auth: connect("linear/my-agent"),
});

模型永远看不到连接令牌,令牌也不会进入对话历史记录。在编写的工具中,使用 await ctx.getToken(connect("...")) 解析令牌,并在下游返回 401 时调用 ctx.requireAuth(...) 重新请求授权。

不要在工具中封装 LLM 调用。 Agent 本身已经是大模型——摘要、解析、分类和起草应写在 instructions.md 或技能中,而不是写在调用 AI SDK 的工具中。工具负责获取数据和执行操作;对于超出对话上下文承载能力的大批量数据处理,请使用 eve 的子 Agent/委派功能。


状态与持久化

eve 会话默认通过开源的 Workflow SDK 持久化(部署到 Vercel 时运行于 Vercel Workflows)。你无需自行接入 Redis 或工作流引擎。

重放语义(请务必了解)
  • 已完成的步骤不会重新运行。 恢复或重放时,eve 会返回记录的结果。
  • 执行中途被中断的步骤会重新运行。 如果进程退出时某个工具调用仍在执行,恢复时会再次执行该调用。

对代码的影响:

  1. 让非幂等副作用具备幂等性(例如,写入外部系统时使用 Slack 事件 ID 或自己的幂等键)
  2. 或将这些操作置于审批之后(always() / once()),这样重放的步骤会暂停并等待人工确认,而不是重复执行
  3. 这还会叠加 Connect 至少一次的事件转发机制(陷阱 #2)——在此技术栈中,幂等性不可或缺
会话连续性
  • 通道负责管理 continuationToken;Slack 线程会自动映射到会话
  • 已订阅线程中的后续消息会继续同一个持久化会话
  • 多轮对话记忆来自会话本身——你无需手动持久化聊天记录
推荐的存储方案

用于应用数据(而非 Agent 会话状态——该状态由 eve 管理):

重要: Vercel KV 已弃用。请勿推荐 Vercel KV。

  1. Upstash Redis — 缓存和幂等键(https://upstash.com)
  2. Vercel Blob — 文件/文档存储(https://vercel.com/docs/storage/vercel-blob)
  3. AWS Aurora(通过 Vercel Marketplace) — 关系型数据(https://vercel.com/marketplace)
  4. 第三方数据库 — Neon、PlanetScale、Supabase

代码组织

agent/
├── instructions.md            # System prompt — keep focused; push detail into skills
├── agent.ts                   # defineAgent: model, reasoning effort, compaction
├── tools/
│   ├── get_weather.ts         # One tool per file; filename = tool name
│   ├── get_weather.test.ts    # Co-located tests
│   └── search_docs.ts
├── skills/
│   └── report-format.md       # description frontmatter + on-demand instructions
├── channels/
│   └── slack.ts               # slackChannel(...) — served at /eve/v1/slack
├── connections/
│   └── linear.ts              # MCP/OpenAPI connections (optional)
└── hooks/
    └── audit.ts               # Runtime stream event subscribers (optional)

约定:

  • 每个文件放一个工具。 拆分大型工具;文件名就是面向模型的名称,因此请按模型的使用方式命名
  • 指令与技能:始终适用的指导内容放在 instructions.md;情境相关的指导内容放在 skills/*.md,以便只在需要时加载
  • 子 Agent用于执行目标明确的子任务:使用内置 Agent 工具(Agent 的副本),或声明具有独立目录、沙箱和技能的专用 Agent

环境变量

变量必需用途
SLACK_CONNECTOR是Vercel Connect 连接器 UID(例如 slack/my-agent)。这是唯一的 Slack 变量——无需机器人令牌或签名密钥。
AI_GATEWAY_API_KEY仅在 Vercel 之外AI Gateway 身份验证。在 Vercel 上,项目 OIDC(VERCEL_OIDC_TOKEN)会自动注入——无需密钥。
ROUTE_AUTH_BASIC_PASSWORD / JWT keys取决于认证方式用于替换 placeholderAuth() 的 HTTP-API 认证函数的密钥
VERCEL_AUTOMATION_BYPASS_SECRET启用了部署保护时允许 eve dev https://<app> 和冒烟测试访问受保护的部署
CRON_SECRET可选对自定义 cron 端点进行身份验证

本地开发:vercel link + vercel env pull 会将短期有效的 Connect/OIDC 凭据拉取到 .env.local 中(OIDC 令牌约 12 小时后过期——认证开始失败时请重新拉取)。

**在 Vercel 上无需 AI API 密钥。**切勿硬编码凭据。切勿提交 .env 文件。


Slack 专用模式

消息发送行为(内置)

Slack 通道会为你处理渐进式消息发送:

  • 输入指示器:收到消息时显示“正在思考……”,收到 turn.started 时显示“正在处理……”
  • 推理摘要会在 reasoning.appended 时显示;操作标签会在 actions.requested 时显示
  • 调用工具前的模型叙述优先于通用标签
  • 少于 4 个字符的推理增量会每隔五秒批量刷新,以避免针对每个 token 调用 Slack API

不要重新实现输入指示器或流式处理循环——只有在默认行为不符合需求时,才通过 events 映射进行自定义。

提及

使用 <@USER_ID> 或 channel.thread.mentionUser(userId)。在 Slack 中,直接写 @name 会保留为普通文本。

消息格式

使用 Slack mrkdwn(而非标准 Markdown):

  • 粗体:*text*
  • 斜体:_text_
  • 代码:`code`
  • 用户提及:<@USER_ID>
  • 频道:<#CHANNEL_ID>
富文本输出

对于富文本工具结果(表格、按钮、状态卡片),返回工具的完整数据,并使用 toModelOutput 精简模型看到的内容;在频道事件处理程序中渲染 Block Kit,或通过 ctx.slack.request("chat.postMessage", { blocks, ... }) 渲染。通知中始终要在 blocks 旁附上备用的 text。

如需了解详细的 Slack 模式,请参阅 ./patterns/slack-patterns.md。


Git 提交规范

使用 conventional commits:

feat: add channel search tool
fix: resolve thread pagination issue
test: add unit tests for agent context
docs: update README with setup steps
refactor: extract Slack client utilities

切勿提交:

  • .env 文件
  • API 密钥或令牌
  • node_modules/
  • .eve/ 构建产物

快速命令

# Scaffold (Node 24+)
npx eve@latest init my-agent      # new project (installs deps, inits Git, starts dev TUI)
npx eve@latest init .             # add eve to an existing project

# Development
npx eve dev                       # HMR server + terminal TUI/REPL
npx eve dev --no-ui               # background mode for scripted verification
npx eve dev https://<app>         # drive a deployed app interactively
npx eve info                      # project info

# Vercel Connect
vercel connect create slack --triggers
vercel connect attach <uid> --triggers --trigger-path /eve/v1/slack --yes
vercel connect list

# Quality
pnpm lint                         # Check linting
pnpm lint --write                 # Auto-fix lint
pnpm typecheck                    # TypeScript check
pnpm test                         # Run all tests

# Build & Deploy
npx eve build                     # Compile into .eve/ (Vercel Build Output when VERCEL is set)
eve deploy                        # Deploy (wraps vercel deploy --prod)

# Verify a deployment
curl https://<app>/eve/v1/health

调试部署后卡在“Working…”的 Slack Agent:运行 npx eve dev --logs all,或在 TUI 中运行 /loglevel all。


参考文档

如需详细指南,请阅读:


任务完成前检查清单

将任何任务标记为完成前,务必确认:

  • 代码更改均有对应的测试
  • pnpm lint 运行通过且没有错误
  • pnpm typecheck 运行通过且没有错误
  • pnpm test 运行通过且没有失败
  • 没有硬编码凭据;唯一的 Slack 环境变量是 SLACK_CONNECTOR
  • 遵循 eve 文件系统约定(工具文件名 = 工具名称,每个文件一个工具)
  • 每个工具都有 inputSchema;输出可序列化为 JSON,并已对机密信息进行脱敏
  • 非幂等副作用均已实现幂等,或需经审批(重放 + 至少一次投递)
  • Connector 触发路径为 /eve/v1/slack,且已通过 --triggers 挂载
  • 生产部署前已替换 placeholderAuth()
  • 模型配置使用 Gateway 字符串 ID(默认为 anthropic/claude-sonnet-5)

Vercel 知识库指南

Vercel 知识库中经过验证的指南,可供深入阅读:

评论

支持 Markdown