ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Papermark 中的 Trigger.dev ai.tool 集成指南:将任务转化为 Vercel AI SDK 工具,让 LLM 自主调用

Papermark 中的 Trigger.dev ai.tool 集成指南:将任务转化为 Vercel AI SDK 工具,让 LLM 自主调用 后端前端企业应用【免费下载链接】papermarkPapermark is the open-source DocSend alternative and secure data rooms with built-in analytics and custom domains.项目地址https://gitcode.com/GitHub_Trending/pa/papermark点击查看免费下载ai.tool是 Trigger.dev SDK 提供的桥接能力它能把基于schemaTask定义的任务转换为符合 Vercel AI SDK 规范的tool对象从而让 GPT、Gemini 等大模型在generateText/streamText的推理过程中自主决定何时调用你已有的后台任务。本文以 Papermark 仓库中 ai-tool.md 为骨架结合 trigger.config.ts、lib/trigger/dataroom-change-notification.ts 等真实源码完整讲解从任务定义、Schema 约束、结果定制到多工具 Agent 编排的完整落地路径。读完本文你将能够在 Papermark或任何使用 Trigger.dev v4 的项目中把已有的持久化任务封装成 AI 工具构建具备多步工具调用的自主 Agent。核心概念为什么需要 ai.tool在传统做法中要让 LLM 调用你的业务能力你需要为每个能力手写tool的parametersJSON Schema、execute回调与错误处理。ai.tool把这条链路压缩成一行任务侧用schemaTask定义任务Zod Schema 会自动转成 AI SDK 工具声明所需的 JSON Schema转换侧ai.tool(myTask)返回一个标准的 Vercel AI SDKtool对象调用侧LLM 在generateText中发起工具调用任务以持久化、可重试、可观测的方式执行。这意味着你无需维护两份接口契约任务既能被triggerAndWait手动触发也能被 LLM 以工具形式自主触发同时保留 Trigger.dev 的重试、队列、日志与元数据能力。基本用法三步将任务接入 AI Agent以下完整示例来自 ai-tool.md 的 Basic Usage 一节可直接复制运行需安装trigger.dev/sdk、ai、ai-sdk/openai与zodPapermark 中对应版本为trigger.dev/sdk4.5.10、ai^6.0.191、ai-sdk/openai^3.0.65、zod^3.25.76见 package.jsonimport { schemaTask, ai } from trigger.dev/sdk; import { generateText } from ai; import { openai } from ai-sdk/openai; import { z } from zod; // 1. Define task with schema const lookupWeather schemaTask({ id: lookup-weather, schema: z.object({ location: z.string().describe(City name), units: z.enum([celsius, fahrenheit]).default(celsius), }), run: async ({ location, units }) { const weather await fetchWeather(location, units); return { temperature: weather.temp, conditions: weather.conditions }; }, }); // 2. Convert to AI tool const weatherTool ai.tool(lookupWeather); // 3. Use with AI SDK export const weatherAgent schemaTask({ id: weather-agent, schema: z.object({ question: z.string() }), run: async ({ question }) { const result await generateText({ model: openai(gpt-4o), prompt: question, tools: { lookupWeather: weatherTool, }, }); return { answer: result.text }; }, });执行链路weatherAgent被触发后generateText把lookupWeather的 JSON Schema 暴露给模型模型判定需要查询天气时返回工具调用请求AI SDK 转而执行lookupWeather任务其返回结果会作为 tool message 回传给模型最终模型的自然语言回答作为answer返回。Schema 要求必须使用 schemaTaskai.tool对任务类型有硬性约束任务必须用schemaTask并携带 Schema普通task无法转换。原因在于工具声明需要机器可读的参数定义而schemaTask的 Schema 正是这一声明的来源// ✅ Works - has schema const myTask schemaTask({ id: my-task, schema: z.object({ query: z.string(), }), run: async (payload) { ... }, }); // ❌ Wont work - no schema const myTask task({ id: my-task, run: async (payload: { query: string }) { ... }, });支持的 Schema 库Zodz.object({...})是首选也是 Papermark 中实际使用的方案ArkType类型安全校验器同样支持任何实现了.toJsonSchema()方法的 Schema 库只要能把 Schema 序列化为 JSON Schema 即可接入。从源码看Papermark 的 AI 相关任务大量采用 Zod Schema。例如 lib/trigger/dataroom-change-notification.ts 中的NotificationPayloadSchemaconst NotificationPayloadSchema z.object({ dataroomId: z.string().cuid(), dataroomDocumentIds: z.array(z.string().cuid()).min(1), senderUserId: z.string().cuid().nullable(), teamId: z.string().cuid(), excludeViewerId: z.string().cuid().optional(), }); export const sendDataroomChangeNotificationTask schemaTask({ id: send-dataroom-change-notification, schema: NotificationPayloadSchema, retry: { maxAttempts: 3 }, run: async (payload) { ... }, });这里可以看到schemaTask的完整形态id全局唯一标识任务schema定义入参z.string().cuid()约束 CUID 格式、z.array(...).min(1)约束非空数组、.optional()声明可选字段retry配置失败重试maxAttempts: 3run接收已解析且类型安全的 payload。这套 Schema 一旦接入ai.toolLLM 生成的参数也会经过同样的 Zod 校验类型安全贯穿LLM 输出 → 任务输入全链路。工具结果定制experimental_toToolResultContent默认情况下任务的返回值会被直接作为工具结果发给 LLM。当任务返回结构化数据如数据库行、嵌套对象时原始结构可能包含大量对模型无意义的字段。此时可用experimental_toToolResultContent定制发送给 LLM 的内容const searchTool ai.tool(searchDatabase, { experimental_toToolResultContent: (result) { // Return structured content for the LLM return [ { type: text, text: Found ${result.count} results:\n${result.items.map(i i.title).join(\n)}, }, ]; }, });返回值为 content part 数组如{ type: text, text: ... }这能让模型只看到精炼后的摘要减少 token 消耗并提升回答质量。该 API 带experimental_前缀说明其接口仍在演进中升级 SDK 时需留意变更。访问工具执行上下文ai.currentToolOptions()当任务以 AI 工具形式被调用时你可以在任务内部通过ai.currentToolOptions()获取 AI SDK 传入的执行选项const myToolTask schemaTask({ id: my-tool-task, schema: z.object({ input: z.string() }), run: async (payload) { // Access AI SDK tool execution options const toolOptions ai.currentToolOptions(); console.log(toolOptions); // { toolCallId: ..., messages: [...], ... } return processInput(payload.input); }, });toolCallId可用于将任务执行与某次 LLM 工具调用关联例如在消息流中定位、做幂等去重messages则提供了当前对话上下文。注意该能力仅在任务被ai.tool包装后以工具形式执行时可用任务被手动triggerAndWait触发时不存在工具调用上下文。多工具组合让 Agent 自由编排一个 Agent 通常需要多个能力。将多个任务转换为工具后统一注入tools并用maxSteps放开多轮工具调用的次数上限const searchTool ai.tool(searchDatabase); const calculateTool ai.tool(calculate); const summarizeTool ai.tool(summarize); export const agentTask schemaTask({ id: agent, schema: z.object({ task: z.string() }), run: async ({ task }) { const result await generateText({ model: openai(gpt-4o), prompt: task, tools: { search: searchTool, calculate: calculateTool, summarize: summarizeTool, }, maxSteps: 10, // Allow multiple tool calls }); return { result: result.text }; }, });maxSteps是构建复杂 Agent 的关键参数若不设置模型单轮推理后即停止设置为10后模型可以在搜索 → 计算 → 总结之间反复迭代直至产出最终答案。每个工具调用背后都是持久化的 Trigger.dev 任务天然获得重试与可观测性。强制工具调用toolChoice默认情况下模型自行决定是否调用工具。在需要强制使用某个工具的场景如用户明确要求查天气下可通过toolChoice控制const result await generateText({ model: openai(gpt-4o), prompt: Whats the weather in Tokyo?, tools: { weather: weatherTool, news: newsTool, }, toolChoice: required, // Force tool use // or: toolChoice: { type: tool, toolName: weather } });两种取值各有用途取值含义required强制模型至少调用一个工具由模型挑选{ type: tool, toolName: weather }强制调用指定名称的工具结合业务场景路由/分类 Agent 适合required必须走工具分流而只查天气这类明确意图适合指定toolName。从 Schema 生成描述让 LLM 更懂你的工具工具描述是 LLM 判断何时该用此工具的主要依据。schemaTask的description字段与字段级.describe()都会进入工具声明直接影响模型的工具选择质量const searchTask schemaTask({ id: search-database, description: Search the product database for items matching a query, schema: z.object({ query: z.string().describe(Search terms), limit: z.number().min(1).max(100).describe(Max results to return), category: z.enum([electronics, clothing, books]).optional() .describe(Filter by product category), }), run: async (payload) { ... }, });值得注意的细节z.number().min(1).max(100)这类 Zod 约束会转化为 JSON Schema 的minimum/maximum让模型在生成参数时自动收敛到合法区间.optional()与.describe()则共同引导模型生成合理的可选参数。工具越多、字段越复杂描述的作用越明显。常见模式Research Agent 完整实现以下组合网页搜索 网页读取两个任务的研究 Agent是文档给出的完整实战模式可视为多工具 maxSteps的最佳示范const webSearch schemaTask({ id: web-search, schema: z.object({ query: z.string(), maxResults: z.number().default(5), }), run: async ({ query, maxResults }) { return await searchWeb(query, maxResults); }, }); const readUrl schemaTask({ id: read-url, schema: z.object({ url: z.string().url(), }), run: async ({ url }) { return await fetchAndParse(url); }, }); export const researchAgent schemaTask({ id: research-agent, schema: z.object({ topic: z.string() }), run: async ({ topic }) { const result await generateText({ model: openai(gpt-4o), system: Research the topic thoroughly using available tools., prompt: topic, tools: { search: ai.tool(webSearch), read: ai.tool(readUrl), }, maxSteps: 20, }); return { research: result.text }; }, });z.string().url()会在 Zod 层校验 URL 格式z.number().default(5)为可选参数提供默认值——这些细节都在 JSON Schema 中有对应表达模型生成的非法参数会被任务层拦截。在 Papermark 仓库中的落地位置ai.tool能力属于 Trigger.dev v4Papermark 是使用该版本的典型仓库相关的工程配置可以直接对照任务目录与构建配置trigger.config.ts 中dirs: [./lib/trigger, ./ee/**/lib/trigger]声明了所有任务源码目录retries.default配置了全局重试策略maxAttempts: 3、指数退避factor: 2、抖动randomize: truebuild.extensions注入 Prisma 与 ffmpeg 等依赖。这意味着任务与普通 Next.js 路由分离部署具备独立的运行时环境。任务集中存放lib/trigger 目录下有automatic-unpause.ts、bulk-download.ts、convert-pdf-direct.ts、dataroom-change-notification.ts等 14 个任务文件涵盖通知、导出、文件转换等业务。真实 schemaTask 示例lib/trigger/dataroom-change-notification.ts 展示了生产级schemaTask的写法Zod 校验入参、retry: { maxAttempts: 3 }、logger.info/error结构化日志、以及触发内部 API 完成通知投递。AI SDK 的 generateText 实战ee/features/ai/lib/trigger/process-image-for-ai.ts 是Trigger.dev 任务 Vercel AI SDK协同的现成例子——任务内部用generateText调用vertex(gemini-3-flash-preview)分析图片再结合metadata.set()更新进度、putFileServer落盘、openai.files.create上传完整展示了把 AI 推理嵌入持久化任务管线的写法。使用要点速查Always use schemaTask—— 普通task无法被ai.tool转换Add descriptions—— 任务级description帮助 LLM 判断何时调用该工具Use.describe()—— 在 Schema 字段上补充参数语义提示提升参数生成质量Set maxSteps—— 复杂任务需要多轮工具调用务必放开步数上限Customize results—— 用experimental_toToolResultContent精简回传内容节省 token 并改善模型上下文。小结ai.tool将 Trigger.dev 的持久化执行能力与 Vercel AI SDK 的工具调用生态打通schemaTask的 Zod Schema 同时充当工具声明与运行时校验ai.tool()完成零成本转换maxSteps与toolChoice控制 Agent 的推理深度与调用倾向。结合 Papermark 仓库中 trigger.config.ts、lib/trigger 的既有工程实践你可以快速把现有的搜索、读取、通知、导出等任务升级为可被 LLM 自主调用的工具构建出具备多步推理能力且可重试、可观测的生产级 Agent。更完整的 Agent 编排并行化、路由、人机协同等模式可继续参阅 .agents/skills/trigger-agents/SKILL.md 及其 orchestration.md 等配套文档。赞分享后端前端企业应用【免费下载链接】papermarkPapermark is the open-source DocSend alternative and secure data rooms with built-in analytics and custom domains.项目地址https://gitcode.com/GitHub_Trending/pa/papermark点击查看免费下载相关推荐使用 mlflow/vercel 集成 MLflow Tracing 与 Vercel AI SDK自动追踪 TypeScript/JavaScript LLM 调用使用 mlflow/vercel 集成 MLflow Tracing 与 Vercel AI SDK自动追踪 TypeScript/JavaScript LMLOpsLLMOps人工智能大模型模型评测LLM 网关可观测性Papermark 中的 Trigger.dev 任务成本优化指南9 大策略与源码级实践Papermark 中的 Trigger.dev 任务成本优化指南9 大策略与源码级实践 本文基于仓库 .agents/skills/trigger cost后端前端企业应用Wechat Spellbook Mirror 模块使用指南快速定位微信内部类与方法Wechat Spellbook Mirror 模块使用指南快速定位微信内部类与方法 Wechat Spellbook 是一个使用 Kotlin 编写的开源微上一篇Translumo3 步用好的免费开源屏幕翻译工具游戏对白与硬字幕实时翻成中文下一篇VC 运行库缺失三步修复不再闪退创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表