mcpField
I
inngest-agents

inngest-agents

github.com/inngestAgent 工作流29674 次安装4 周前更新
代码仓库

关于 inngest-agents

inngest-agents 是用于构建、迁移和调试 AI Agent 及多步工作流的技能,基于 Inngest AgentKit。重点涵盖持久执行、工具副作用处理、人工审批和实时进度。

主要功能

  1. 01通过 Inngest 函数运行持久 AgentKit 任务
  2. 02使用 step.ai 重试并缓存模型调用
  3. 03持久处理工具副作用
  4. 04等待人工审批和外部回调
  5. 05发布工作流实时进度
  6. 06提供 Agent 评估指导

适用场景

  1. 01构建支持或研究 Agent
  2. 02将现有 Agent 迁移到持久工作流
  3. 03为 Agent 操作加入人工审批
  4. 04排查重试及重复副作用

MCP 相关

该技能涵盖调用 MCP 服务的 Agent,并建议将有副作用的工具封装在 Inngest 持久步骤中。

安装

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

$npx skills add https://github.com/inngest/inngest-skills --skill inngest-agents

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

详细介绍

Inngest 智能体

当用户希望构建、迁移或调试 AI Agent、多步骤 AI 工作流、工具调用循环、客服 Agent、研究 Agent、人机协同审核流程或实时 Agent UI 时,请使用此技能。

Inngest 的 AgentKit 使用 createAgent 定义 Agent;当 AgentKit 运行由 Inngest 函数负责时,模型调用会使用 Inngest step.ai,从而持久地重试并缓存模型结果。使用 Agent 周围更底层的 Inngest 步骤原语来处理数据库读写、工具副作用、等待、审批、实时进度和流程控制。

官方参考资料:

可复制示例

从头开始构建持久化客服或工具调用 Agent 时,请查看配套示例 ../../examples/durable-agent。它展示了以 Agent 为先的预期结构:快速 HTTP 触发器、类型化事件、Inngest 函数内的 AgentKit、步骤级上下文加载、使用 step.waitForEvent 进行人工审批,以及审批后的持久化副作用。

何时使用 Inngest 构建 Agent

适用场景:

  • Agent 的运行时间可能超过单个 HTTP 请求。
  • Agent 会调用工具、API、数据库、浏览器、沙箱或 MCP 服务。
  • Agent 需要在部署、崩溃、无服务器超时或模型/API 故障后继续运行。
  • Agent 可能需要等待人工审批、外部回调、定时后续操作或用户输入。
  • Agent 进度应通过持久化工作流流式传输到 UI。
  • 模型/提供商调用需要并发或节流限制。
  • 重复发送、收费、写入或模型调用会造成高昂成本。

通常不值得使用:

  • 单次简短的只读模型调用,没有副作用,也不需要持久化进度。
  • 允许丢失请求的纯 UI 自动补全。

架构

除非代码库已有更完善的既定模式,否则请采用以下结构:

  1. HTTP/服务端操作层验证身份验证,在需要时存储用户意图,使用稳定的 id 发出事件,并快速返回。
  2. Inngest 函数负责 Agent 运行。
  3. 在 step.run 内加载状态和外部上下文。
  4. 在函数内创建 AgentKit Agent,或导入 Agent/网络工厂。
  5. 通过 AgentKit / step.ai 执行模型推理;使用 step.run 封装非模型工具的副作用。
  6. 使用 step.waitForEvent 或 step.waitForSignal 处理人工审批和外部回调。
  7. 使用原生实时功能发布持久化进度。
  8. 当 Agent 结果需要后续评估时,添加会话和评分。
  9. 在函数级别实施流程控制,以限制提供商和租户的用量。

基本 AgentKit 函数

请先采用精简的类型化函数;确认单 Agent 流程可行后,再添加网络和其他工具。

import { createAgent, openai } from "@inngest/agent-kit";
import { inngest } from "@/inngest/client";

export const summarizeTicket = inngest.createFunction(
  {
    id: "summarize-ticket",
    triggers: [{ event: "support/ticket.created" }],
    concurrency: [{ key: "event.data.accountId", limit: 2 }]
  },
  async ({ event, step }) => {
    const ticket = await step.run("load-ticket", () => {
      return getTicket(event.data.ticketId);
    });

    const writer = createAgent({
      name: "support-summary-writer",
      system: "Write a concise support-ticket summary with next actions.",
      model: openai({ model: "gpt-4o" })
    });

    const { output } = await writer.run(JSON.stringify(ticket));

    await step.run("save-summary", () => {
      return saveTicketSummary(event.data.ticketId, output);
    });

    return { ticketId: event.data.ticketId };
  }
);

工具调用

可以使用 AgentKit 定义工具,但适用于 Agent 的工具仍应遵循持久化规则:

  • 只读工具调用可以作为 Agent 的一部分运行,只要重放不会造成问题。
  • 外部副作用应使用稳定 ID 和 step.run 边界隔离,或实现为使用所提供 step 的工具处理程序。
  • 工具输出应足够小,以符合步骤状态限制。
  • 使用架构验证工具参数;绝不要信任模型提供的参数。
  • 使用来自经过身份验证的事件数据的租户/用户 ID,而不只是模型文本中的 ID。

工具副作用检查清单:

- What external state can this tool change?
- What idempotency key prevents duplicate writes?
- What should happen if the model calls the same tool twice?
- Is the output safe to store in function run state?
- Does the tool need provider-specific concurrency or throttle limits?

人机协同

请使用持久化等待,而不是轮询数据库或将状态保留在内存中。

const approval = await step.waitForEvent("wait-for-approval", {
  event: "support/reply.approved",
  timeout: "3d",
  match: "data.ticketId"
});

if (!approval) {
  await step.run("mark-review-timeout", () => {
    return markTicketNeedsManualReview(event.data.ticketId);
  });
  return { status: "timed_out" };
}

await step.run("send-reply", () => {
  return sendSupportReply({
    ticketId: event.data.ticketId,
    approvalId: approval.data.approvalId
  });
});

实时进度

对于 v4 原生实时功能:

  • 在步骤之间使用 step.realtime.publish。
  • 在现有的 step.run 内使用 inngest.realtime.publish。
  • v4 项目不要安装 v3 的 @inngest/realtime 包。
  • 不要仅将进程本地 WebSocket 作为持久函数的进度唯一来源。

对于 AgentKit 专用的 UI 钩子,在接入 useAgent 或 useChat 前,先检查已安装的 @inngest/agent-kit 版本和当前文档。

Agent 评估

当用户要求为 Agent 评分、比较提示词或模型、跟踪用户反馈、按对话/工单对运行进行分组,或长期排查 Agent 质量问题时,使用 inngest-agent-evals。在持久化 Agent 工作流中,在启动或连接用户流程的事件上添加 meta.sessions;对于运行期间已知的信号,使用直接评分;对于稍后才会出现的产品结果,使用延迟评分器。

流量控制与成本

Agent 工作负载通常需要提供商和租户限流:

  • 为模型提供商使用账户范围的并发或节流键。
  • 在公平性很重要时,按租户或账户设置键。
  • 使用确定性事件 ID,避免重复的用户操作触发重复的高成本运行。
  • 将成功的模型/工具结果保留在步骤中,这样后续失败重试时就不会再次为之前的模型调用付费。

示例:

{
  id: "support-agent-run",
  triggers: [{ event: "support/agent.requested" }],
  throttle: {
    limit: 120,
    period: "1m",
    key: `"openai"`
  },
  concurrency: [
    { key: "event.data.accountId", limit: 3 }
  ]
}

既有项目迁移

迁移现有 Agent 时:

  1. 搜索模型调用、工具循环、内存状态、流式处理程序、审批轮询和外部副作用。
  2. 首先保持提示词/工具行为稳定。
  3. 将触发器移至事件和 Inngest 函数中。
  4. 将模型调用移至 AgentKit / step.ai。
  5. 将有副作用的工具移至 step.run 或持久化工具处理程序中。
  6. 使用 step.waitForEvent 或 step.waitForSignal 替换进程本地等待。
  7. 在持久化运行正常工作后再添加实时功能。

如果代码库中有多个可能的工作流,且用户尚未选定其中一个,请先使用 inngest-brownfield-audit。

反模式

  • Agent 循环状态仅保存在内存中。
  • 用一个巨大的 try/catch 包住所有模型和工具调用。
  • 一次工具失败就重试整个 Agent。
  • 后续步骤失败后,重复为已成功的模型调用付费。
  • 使用 setTimeout、cron 轮询或 Redis TTL 作为人工审核机制。
  • 有副作用的工具没有幂等键。
  • 从可能会退出的服务端进程流式传输进度,而持久化工作却在其他地方继续运行。
  • 添加 AgentKit,却没有注册外围 Inngest 函数。

验证

  • 对 Agent、工具架构和事件负载进行类型检查。
  • 将工具处理程序与模型行为分开进行单元测试。
  • 测试 HTTP 入口是否只发送一个确定性事件并快速返回。
  • 测试重复的事件 ID 是否不会导致最终副作用重复执行。
  • 如有可能,运行 Inngest 开发服务器并检查 Agent 步骤/追踪记录。

评论

支持 Markdown