Skip to content

feat: AI SDK 5.0 support #2396

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/famous-clocks-thank.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@trigger.dev/sdk": patch
---

feat: Support AI SDK 5.0. `ai.tool` now accepts either a schemaTask or a task with a provided jsonSchema
2 changes: 2 additions & 0 deletions packages/core/src/v3/types/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,8 @@ export interface Task<TIdentifier extends string, TInput = void, TOutput = any>

description?: string;

jsonSchema?: JSONSchema;

/**
* Trigger a task with the given payload, and continue without waiting for the result. If you want to wait for the result, use `triggerAndWait`. Returns the id of the triggered task run.
* @param payload
Expand Down
4 changes: 2 additions & 2 deletions packages/trigger-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"@types/slug": "^5.0.3",
"@types/uuid": "^9.0.0",
"@types/ws": "^8.5.3",
"ai": "^4.2.0",
"ai": "^5.0.0",
"encoding": "^0.1.13",
"rimraf": "^3.0.2",
"tshy": "^3.0.2",
Expand All @@ -78,7 +78,7 @@
},
"peerDependencies": {
"zod": "^3.0.0 || ^4.0.0",
"ai": "^4.2.0"
"ai": "^4.2.0 || ^5.0.0"
},
"peerDependenciesMeta": {
"ai": {
Expand Down
68 changes: 49 additions & 19 deletions packages/trigger-sdk/src/v3/ai.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import {
AnyTask,
isSchemaZodEsque,
Task,
type inferSchemaIn,
type TaskSchema,
type TaskWithSchema,
} from "@trigger.dev/core/v3";
import { jsonSchema, Schema, tool, ToolExecutionOptions, zodSchema } from "ai";
import { dynamicTool, jsonSchema, JSONSchema7, Schema, Tool, ToolCallOptions, zodSchema } from "ai";
import { metadata } from "./metadata.js";

const METADATA_KEY = "tool.execute.options";

export type ToolCallExecutionOptions = Omit<ToolExecutionOptions, "abortSignal">;
export type ToolCallExecutionOptions = Omit<ToolCallOptions, "abortSignal">;

type ToolResultContent = Array<
| {
Expand All @@ -27,25 +29,43 @@ export type ToolOptions<TResult> = {
experimental_toToolResultContent?: (result: TResult) => ToolResultContent;
};

function toolFromTask<TIdentifier extends string, TInput = void, TOutput = unknown>(
task: Task<TIdentifier, TInput, TOutput>,
options?: ToolOptions<TOutput>
): Tool<TInput, TOutput>;
function toolFromTask<
TIdentifier extends string,
TTaskSchema extends TaskSchema | undefined = undefined,
TOutput = unknown,
>(task: TaskWithSchema<TIdentifier, TTaskSchema, TOutput>, options?: ToolOptions<TOutput>) {
if (!task.schema) {
>(
task: TaskWithSchema<TIdentifier, TTaskSchema, TOutput>,
options?: ToolOptions<TOutput>
): Tool<inferSchemaIn<TTaskSchema>, TOutput>;
function toolFromTask<
TIdentifier extends string,
TTaskSchema extends TaskSchema | undefined = undefined,
TInput = void,
TOutput = unknown,
>(
task: TaskWithSchema<TIdentifier, TTaskSchema, TOutput> | Task<TIdentifier, TInput, TOutput>,
options?: ToolOptions<TOutput>
): TTaskSchema extends TaskSchema
? Tool<inferSchemaIn<TTaskSchema>, TOutput>
: Tool<TInput, TOutput> {
if (("schema" in task && !task.schema) || ("jsonSchema" in task && !task.jsonSchema)) {
throw new Error(
"Cannot convert schemaTask to a tool because the task has no schema. Make sure the schema used in the task is either zod, arktype, or another supported schema."
"Cannot convert this task to to a tool because the task has no schema. Make sure to either use schemaTask or a task with an input jsonSchema."
);
}

return tool({
const toolDefinition = dynamicTool({
description: task.description,
parameters: convertTaskSchemaToToolParameters(task.schema),
execute: async (args, options) => {
inputSchema: convertTaskSchemaToToolParameters(task),
execute: async (input, options) => {
const serializedOptions = options ? JSON.parse(JSON.stringify(options)) : undefined;

return await task
.triggerAndWait(args, {
.triggerAndWait(input as inferSchemaIn<TTaskSchema>, {
metadata: {
[METADATA_KEY]: serializedOptions,
},
Expand All @@ -54,6 +74,10 @@ function toolFromTask<
},
...options,
});

return toolDefinition as TTaskSchema extends TaskSchema
? Tool<inferSchemaIn<TTaskSchema>, TOutput>
: Tool<TInput, TOutput>;
}

function getToolOptionsFromMetadata(): ToolCallExecutionOptions | undefined {
Expand All @@ -64,21 +88,27 @@ function getToolOptionsFromMetadata(): ToolCallExecutionOptions | undefined {
return tool as ToolCallExecutionOptions;
}

function convertTaskSchemaToToolParameters<TTaskSchema extends TaskSchema>(
schema: TTaskSchema
): Schema<inferSchemaIn<TTaskSchema>> {
// If TaskSchema is ZodEsque, use ai.zodSchema to convert it to a Schema
if (isSchemaZodEsque(schema)) {
return zodSchema(schema as any);
function convertTaskSchemaToToolParameters(
task: AnyTask | TaskWithSchema<any, any, any>
): Schema<unknown> {
if ("schema" in task) {
// If TaskSchema is ArkTypeEsque, use ai.jsonSchema to convert it to a Schema
if ("toJsonSchema" in task.schema && typeof task.schema.toJsonSchema === "function") {
return jsonSchema((task.schema as any).toJsonSchema());
}

// If TaskSchema is ZodEsque, use ai.zodSchema to convert it to a Schema
if (isSchemaZodEsque(task.schema)) {
return zodSchema(task.schema as any);
}
}

// If TaskSchema is ArkTypeEsque, use ai.jsonSchema to convert it to a Schema
if ("toJsonSchema" in schema && typeof schema.toJsonSchema === "function") {
return jsonSchema((schema as any).toJsonSchema());
if ("jsonSchema" in task) {
return jsonSchema(task.jsonSchema as JSONSchema7);
}

throw new Error(
"Cannot convert schemaTask to a tool. Make sure the schema used in the task is either zod, arktype, or another supported schema."
"Cannot convert task to a tool. Make sure to use a task with a schema or jsonSchema."
);
}

Expand Down
1 change: 1 addition & 0 deletions packages/trigger-sdk/src/v3/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ export function createTask<
const task: Task<TIdentifier, TInput, TOutput> = {
id: params.id,
description: params.description,
jsonSchema: params.jsonSchema,
trigger: async (payload, options) => {
return await trigger_internal<RunTypes<TIdentifier, TInput, TOutput>>(
"trigger()",
Expand Down
Loading
Loading