UNPKG

@convex-dev/agent

Version:

A agent component for Convex.

1,205 lines 55 kB
import type { EmbeddingModelV1, LanguageModelV1 } from "@ai-sdk/provider"; import type { CoreMessage, DeepPartial, GenerateObjectResult, GenerateTextResult, StepResult, StreamObjectResult, StreamTextResult, ToolSet } from "ai"; import { type PaginationOptions, type PaginationResult, type WithoutSystemFields } from "convex/server"; import type { MessageDoc, ThreadDoc } from "../component/schema.js"; import { type VectorDimension } from "../component/vector/tables.js"; import { type AIMessageWithoutId } from "../mapping.js"; import { extractText, isTool } from "../shared.js"; import { type MessageWithMetadata, type MessageStatus, type ProviderMetadata, type SearchOptions, type StreamArgs, type Usage } from "../validators.js"; import { createTool } from "./createTool.js"; import { type StreamingOptions } from "./streaming.js"; import type { AgentComponent, ContextOptions, GenerationOutputMetadata, Options, OurObjectArgs, OurStreamObjectArgs, RawRequestResponseHandler, RunActionCtx, RunMutationCtx, RunQueryCtx, ActionCtx, StorageOptions, StreamingTextArgs, SyncStreamsReturnValue, TextArgs, Thread, UsageHandler } from "./types.js"; export { storeFile, getFile } from "./files.js"; export { serializeDataOrUrl } from "../mapping.js"; export { vMessageDoc, vThreadDoc } from "../component/schema.js"; export { vAssistantMessage, vContextOptions, vMessage, vPaginationResult, vProviderMetadata, vStorageOptions, vStreamArgs, vSystemMessage, vToolMessage, vUsage, vUserMessage, } from "../validators.js"; export type { ToolCtx } from "./createTool.js"; export { createTool, extractText, isTool }; export type { AgentComponent, ContextOptions, MessageDoc, ProviderMetadata, StorageOptions, SyncStreamsReturnValue, Thread, ThreadDoc, Usage, UsageHandler, }; export declare class Agent<AgentTools extends ToolSet> { component: AgentComponent; options: { /** * The name for the agent. This will be attributed on each message * created by this agent. */ name?: string; /** * The LLM model to use for generating / streaming text and objects. * e.g. * import { openai } from "@ai-sdk/openai" * const myAgent = new Agent(components.agent, { * chat: openai.chat("gpt-4o-mini"), */ chat: LanguageModelV1; /** * The model to use for text embeddings. Optional. * If specified, it will use this for generating vector embeddings * of chats, and can opt-in to doing vector search for automatic context * on generateText, etc. * e.g. * import { openai } from "@ai-sdk/openai" * const myAgent = new Agent(components.agent, { * textEmbedding: openai.embedding("text-embedding-3-small") */ textEmbedding?: EmbeddingModelV1<string>; /** * The default system prompt to put in each request. * Override per-prompt by passing the "system" parameter. */ instructions?: string; /** * Tools that the agent can call out to and get responses from. * They can be AI SDK tools (import {tool} from "ai") * or tools that have Convex context * (import { createTool } from "@convex-dev/agent") */ tools?: AgentTools; /** * Options to determine what messages are included as context in message * generation. To disable any messages automatically being added, pass: * { recentMessages: 0 } */ contextOptions?: ContextOptions; /** * Determines whether messages are automatically stored when passed as * arguments or generated. */ storageOptions?: StorageOptions; /** * When generating or streaming text with tools available, this * determines the default max number of iterations. */ maxSteps?: number; /** * The maximum number of calls to make to an LLM in case it fails. * This can be overridden at each generate/stream callsite. */ maxRetries?: number; /** * The usage handler to use for this agent. */ usageHandler?: UsageHandler; /** * Called for each LLM request/response, so you can do things like * log the raw request body or response headers to a table, or logs. */ rawRequestResponseHandler?: RawRequestResponseHandler; }; constructor(component: AgentComponent, options: { /** * The name for the agent. This will be attributed on each message * created by this agent. */ name?: string; /** * The LLM model to use for generating / streaming text and objects. * e.g. * import { openai } from "@ai-sdk/openai" * const myAgent = new Agent(components.agent, { * chat: openai.chat("gpt-4o-mini"), */ chat: LanguageModelV1; /** * The model to use for text embeddings. Optional. * If specified, it will use this for generating vector embeddings * of chats, and can opt-in to doing vector search for automatic context * on generateText, etc. * e.g. * import { openai } from "@ai-sdk/openai" * const myAgent = new Agent(components.agent, { * textEmbedding: openai.embedding("text-embedding-3-small") */ textEmbedding?: EmbeddingModelV1<string>; /** * The default system prompt to put in each request. * Override per-prompt by passing the "system" parameter. */ instructions?: string; /** * Tools that the agent can call out to and get responses from. * They can be AI SDK tools (import {tool} from "ai") * or tools that have Convex context * (import { createTool } from "@convex-dev/agent") */ tools?: AgentTools; /** * Options to determine what messages are included as context in message * generation. To disable any messages automatically being added, pass: * { recentMessages: 0 } */ contextOptions?: ContextOptions; /** * Determines whether messages are automatically stored when passed as * arguments or generated. */ storageOptions?: StorageOptions; /** * When generating or streaming text with tools available, this * determines the default max number of iterations. */ maxSteps?: number; /** * The maximum number of calls to make to an LLM in case it fails. * This can be overridden at each generate/stream callsite. */ maxRetries?: number; /** * The usage handler to use for this agent. */ usageHandler?: UsageHandler; /** * Called for each LLM request/response, so you can do things like * log the raw request body or response headers to a table, or logs. */ rawRequestResponseHandler?: RawRequestResponseHandler; }); /** * Start a new thread with the agent. This will have a fresh history, though if * you pass in a userId you can have it search across other threads for relevant * messages as context for the LLM calls. * @param ctx The context of the Convex function. From an action, you can thread * with the agent. From a mutation, you can start a thread and save the threadId * to pass to continueThread later. * @param args The thread metadata. * @returns The threadId of the new thread and the thread object. */ createThread<ThreadTools extends ToolSet | undefined = undefined>(ctx: RunActionCtx, args?: { /** * The userId to associate with the thread. If not provided, the thread will be * anonymous. */ userId?: string; /** * The title of the thread. Not currently used for anything. */ title?: string; /** * The summary of the thread. Not currently used for anything. */ summary?: string; /** * The usage handler to use for this thread. Overrides any handler * set in the agent constructor. */ usageHandler?: UsageHandler; /** * The tools to use for this thread. * Overrides any tools passed in the agent constructor. */ tools?: ThreadTools; }): Promise<{ threadId: string; thread: Thread<ThreadTools extends undefined ? AgentTools : ThreadTools>; }>; /** * Start a new thread with the agent. This will have a fresh history, though if * you pass in a userId you can have it search across other threads for relevant * messages as context for the LLM calls. * @param ctx The context of the Convex function. From a mutation, you can * start a thread and save the threadId to pass to continueThread later. * @param args The thread metadata. * @returns The threadId of the new thread. */ createThread<ThreadTools extends ToolSet | undefined = undefined>(ctx: RunMutationCtx, args?: { /** * The userId to associate with the thread. If not provided, the thread will be * anonymous. */ userId?: string; /** * The title of the thread. Not currently used for anything. */ title?: string; /** * The summary of the thread. Not currently used for anything. */ summary?: string; /** * The usage handler to use for this thread. Overrides any handler * set in the agent constructor. */ usageHandler?: UsageHandler; /** * The tools to use for this thread. * Overrides any tools passed in the agent constructor. */ tools?: ThreadTools; }): Promise<{ threadId: string; }>; /** * Continues a thread using this agent. Note: threads can be continued * by different agents. This is a convenience around calling the various * generate and stream functions with explicit userId and threadId parameters. * @param ctx The ctx object passed to the action handler * @param { threadId, userId }: the thread and user to associate the messages with. * @returns Functions bound to the userId and threadId on a `{thread}` object. */ continueThread<ThreadTools extends ToolSet | undefined = undefined>(ctx: ActionCtx, args: { /** * The associated thread created by {@link createThread} */ threadId: string; /** * If supplied, the userId can be used to search across other threads for * relevant messages from the same user as context for the LLM calls. */ userId?: string; /** * The usage handler to use for this thread. Overrides any handler * set in the agent constructor. */ usageHandler?: UsageHandler; /** * The tools to use for this thread. * Overrides any tools passed in the agent constructor. */ tools?: ThreadTools; }): Promise<{ thread: Thread<ThreadTools extends undefined ? AgentTools : ThreadTools>; }>; /** * This behaves like {@link generateText} from the "ai" package except that * it add context based on the userId and threadId and saves the input and * resulting messages to the thread, if specified. * Use {@link continueThread} to get a version of this function already scoped * to a thread (and optionally userId). * @param ctx The context passed from the action function calling this. * @param { userId, threadId }: The user and thread to associate the message with * @param args The arguments to the generateText function, along with extra controls * for the {@link ContextOptions} and {@link StorageOptions}. * @returns The result of the generateText function. */ generateText<TOOLS extends ToolSet | undefined = undefined, OUTPUT = never, OUTPUT_PARTIAL = never>(ctx: ActionCtx, { userId: argsUserId, threadId, usageHandler, tools: threadTools, }: { userId?: string; threadId?: string; /** * The usage handler to use for this thread. Overrides any handler * set in the agent constructor. */ usageHandler?: UsageHandler; /** @deprecated Pass `tools` in the next parameter instead. This is only intended to pass through thread-default tools. */ tools?: ToolSet; }, args: TextArgs<AgentTools, TOOLS, OUTPUT, OUTPUT_PARTIAL>, options?: Options): Promise<GenerateTextResult<TOOLS extends undefined ? AgentTools : TOOLS, OUTPUT> & GenerationOutputMetadata>; /** * This behaves like {@link streamText} from the "ai" package except that * it add context based on the userId and threadId and saves the input and * resulting messages to the thread, if specified. * Use {@link continueThread} to get a version of this function already scoped * to a thread (and optionally userId). */ streamText<TOOLS extends ToolSet | undefined = undefined, OUTPUT = never, PARTIAL_OUTPUT = never>(ctx: ActionCtx, { userId: argsUserId, threadId, usageHandler, /** * @deprecated Pass `tools` in the next parameter instead. * This is only intended to pass through thread-default tools. */ tools: threadTools, }: { userId?: string; threadId?: string; usageHandler?: UsageHandler; tools?: ToolSet; }, /** * The arguments to the streamText function, similar to the ai `streamText` function. */ args: StreamingTextArgs<AgentTools, TOOLS, OUTPUT, PARTIAL_OUTPUT>, /** * The {@link ContextOptions} and {@link StorageOptions} * options to use for fetching contextual messages and saving input/output messages. */ options?: Options & { /** * Whether to save incremental data (deltas) from streaming responses. * Defaults to false. * If false, it will not save any deltas to the database. * If true, it will save deltas with {@link DEFAULT_STREAMING_OPTIONS}. * * Regardless of this option, when streaming you are able to use this * `streamText` function as you would with the "ai" package's version: * iterating over the text, streaming it over HTTP, etc. */ saveStreamDeltas?: boolean | StreamingOptions; }): Promise<StreamTextResult<TOOLS extends undefined ? AgentTools : TOOLS, PARTIAL_OUTPUT> & GenerationOutputMetadata>; /** * This behaves like {@link generateObject} from the "ai" package except that * it add context based on the userId and threadId and saves the input and * resulting messages to the thread, if specified. * Use {@link continueThread} to get a version of this function already scoped * to a thread (and optionally userId). */ generateObject<T>(ctx: RunActionCtx, { userId: argsUserId, threadId, usageHandler, }: { userId?: string; threadId?: string; usageHandler?: UsageHandler; }, /** * The arguments to the generateObject function, similar to the ai.generateObject function. */ args: OurObjectArgs<T>, /** * The {@link ContextOptions} and {@link StorageOptions} * options to use for fetching contextual messages and saving input/output messages. */ options?: Options): Promise<GenerateObjectResult<T> & GenerationOutputMetadata>; /** * This behaves like `streamObject` from the "ai" package except that * it add context based on the userId and threadId and saves the input and * resulting messages to the thread, if specified. * Use {@link continueThread} to get a version of this function already scoped * to a thread (and optionally userId). */ streamObject<T>(ctx: RunActionCtx, { userId: argsUserId, threadId, usageHandler, }: { userId?: string; threadId?: string; usageHandler?: UsageHandler; }, /** * The arguments to the streamObject function, similar to the ai `streamObject` function. */ args: OurStreamObjectArgs<T>, /** * The {@link ContextOptions} and {@link StorageOptions} * options to use for fetching contextual messages and saving input/output messages. */ options?: Options): Promise<StreamObjectResult<DeepPartial<T>, T, never> & GenerationOutputMetadata>; /** * Save a message to the thread. * @param ctx A ctx object from a mutation or action. * @param args The message and what to associate it with (user / thread) * You can pass extra metadata alongside the message, e.g. associated fileIds. * @returns The messageId of the saved message. */ saveMessage(ctx: RunMutationCtx, args: { threadId: string; userId?: string; /** * Metadata to save with the messages. Each element corresponds to the * message at the same index. */ metadata?: Omit<MessageWithMetadata, "message">; /** * If true, it will not generate embeddings for the message. * Useful if you're saving messages in a mutation where you can't run `fetch`. * You can generate them asynchronously by using the scheduler to run an * action later that calls `agent.generateAndSaveEmbeddings`. */ skipEmbeddings?: boolean; } & ({ prompt?: undefined; /** * The message to save. */ message: CoreMessage; } | { prompt: string; message?: undefined; })): Promise<{ messageId: string; message: { id?: string | undefined; userId?: string | undefined; embeddingId?: string | undefined; fileIds?: string[] | undefined; error?: string | undefined; agentName?: string | undefined; model?: string | undefined; provider?: string | undefined; providerOptions?: Record<string, Record<string, any>> | undefined; message?: { providerOptions?: Record<string, Record<string, any>> | undefined; role: "user"; content: string | ({ providerOptions?: Record<string, Record<string, any>> | undefined; type: "text"; text: string; } | { providerOptions?: Record<string, Record<string, any>> | undefined; mimeType?: string | undefined; type: "image"; image: string | ArrayBuffer; } | { providerOptions?: Record<string, Record<string, any>> | undefined; filename?: string | undefined; type: "file"; mimeType: string; data: string | ArrayBuffer; })[]; } | { providerOptions?: Record<string, Record<string, any>> | undefined; role: "assistant"; content: string | ({ providerOptions?: Record<string, Record<string, any>> | undefined; type: "text"; text: string; } | { providerOptions?: Record<string, Record<string, any>> | undefined; filename?: string | undefined; type: "file"; mimeType: string; data: string | ArrayBuffer; } | { providerOptions?: Record<string, Record<string, any>> | undefined; signature?: string | undefined; type: "reasoning"; text: string; } | { providerOptions?: Record<string, Record<string, any>> | undefined; type: "redacted-reasoning"; data: string; } | { providerOptions?: Record<string, Record<string, any>> | undefined; type: "tool-call"; toolCallId: string; toolName: string; args: any; })[]; } | { providerOptions?: Record<string, Record<string, any>> | undefined; role: "tool"; content: { providerOptions?: Record<string, Record<string, any>> | undefined; args?: any; experimental_content?: ({ type: "text"; text: string; } | { mimeType?: string | undefined; type: "image"; data: string; })[] | undefined; isError?: boolean | undefined; type: "tool-result"; toolCallId: string; toolName: string; result: any; }[]; } | { providerOptions?: Record<string, Record<string, any>> | undefined; role: "system"; content: string; } | undefined; text?: string | undefined; reasoning?: string | undefined; usage?: { promptTokens: number; completionTokens: number; totalTokens: number; } | undefined; providerMetadata?: Record<string, Record<string, any>> | undefined; sources?: { title?: string | undefined; providerOptions?: Record<string, Record<string, any>> | undefined; id: string; sourceType: "url"; url: string; }[] | undefined; reasoningDetails?: ({ signature?: string | undefined; type: "text"; text: string; } | { type: "redacted"; data: string; })[] | undefined; warnings?: ({ details?: string | undefined; type: "unsupported-setting"; setting: string; } | { details?: string | undefined; type: "unsupported-tool"; tool: any; } | { type: "other"; message: string; })[] | undefined; finishReason?: "length" | "error" | "other" | "stop" | "content-filter" | "tool-calls" | "unknown" | undefined; _id: string; _creationTime: number; status: "pending" | "success" | "failed"; order: number; threadId: string; stepOrder: number; tool: boolean; }; }>; /** * Explicitly save messages associated with the thread (& user if provided) * @param ctx The ctx parameter to a mutation or action. * @param args The messages and context to save * @returns */ saveMessages(ctx: RunMutationCtx | RunActionCtx, args: { threadId: string; userId?: string; /** * The message that these messages are in response to. They will be * the same "order" as this message, at increasing stepOrder(s). */ promptMessageId?: string; /** * The messages to save. */ messages: CoreMessageMaybeWithId[]; /** * Metadata to save with the messages. Each element corresponds to the * message at the same index. */ metadata?: Omit<MessageWithMetadata, "message">[]; /** * If false, it will "commit" the messages immediately. * If true, it will mark them as pending until the final step has finished. * Defaults to false. */ pending?: boolean; /** * If true, it will fail any pending steps. * Defaults to false. */ failPendingSteps?: boolean; /** * Skip generating embeddings for the messages. Useful if you're * saving messages in a mutation where you can't run `fetch`. * You can generate them asynchronously by using the scheduler to run an * action later that calls `agent.generateAndSaveEmbeddings`. */ skipEmbeddings?: boolean; }): Promise<{ lastMessageId: string; messages: MessageDoc[]; }>; /** * List messages from a thread. * @param ctx A ctx object from a query, mutation, or action. * @param args.threadId The thread to list messages from. * @param args.paginationOpts Pagination options (e.g. via usePaginatedQuery). * @param args.excludeToolMessages Whether to exclude tool messages. * False by default. * @param args.statuses What statuses to include. All by default. * @returns The MessageDoc's in a format compatible with usePaginatedQuery. */ listMessages(ctx: RunQueryCtx, args: { threadId: string; paginationOpts: PaginationOptions; excludeToolMessages?: boolean; statuses?: MessageStatus[]; }): Promise<PaginationResult<MessageDoc>>; /** * A function that handles fetching stream deltas, used with the React hooks * `useThreadMessages` or `useStreamingThreadMessages`. * @param ctx A ctx object from a query, mutation, or action. * @param args.threadId The thread to sync streams for. * @param args.streamArgs The stream arguments with per-stream cursors. * @returns The deltas for each stream from their existing cursor. */ syncStreams(ctx: RunQueryCtx, args: { threadId: string; streamArgs: StreamArgs | undefined; }): Promise<SyncStreamsReturnValue | undefined>; /** * Fetch the context messages for a thread. * @param ctx Either a query, mutation, or action ctx. * If it is not an action context, you can't do text or * vector search. * @param args The associated thread, user, message * @returns */ fetchContextMessages(ctx: RunQueryCtx | RunActionCtx, args: { userId: string | undefined; threadId: string | undefined; messages: CoreMessage[]; /** * If provided, it will search for messages up to and including this message. * Note: if this is far in the past, text and vector search results may be more * limited, as it's post-filtering the results. */ upToAndIncludingMessageId?: string; contextOptions: ContextOptions | undefined; }): Promise<MessageDoc[]>; /** * Get the metadata for a thread. * @param ctx A ctx object from a query, mutation, or action. * @param args.threadId The thread to get the metadata for. * @returns The metadata for the thread. */ getThreadMetadata(ctx: RunQueryCtx, args: { threadId: string; }): Promise<ThreadDoc>; /** * Update the metadata for a thread. * @param ctx A ctx object from a mutation or action. * @param args.threadId The thread to update the metadata for. * @param args.patch The patch to apply to the thread. * @returns The updated thread metadata. */ updateThreadMetadata(ctx: RunMutationCtx, args: { threadId: string; patch: Partial<WithoutSystemFields<ThreadDoc>>; }): Promise<ThreadDoc>; /** * Get the embeddings for a set of messages. * @param messages The messages to get the embeddings for. * @returns The embeddings for the messages. */ generateEmbeddings(ctx: RunActionCtx, { userId, threadId, }: { userId: string | undefined; threadId: string | undefined; }, messages: CoreMessage[]): Promise<{ vectors: (number[] | null)[]; dimension: VectorDimension; model: string; } | undefined>; /** * Generate embeddings for a set of messages, and save them to the database. * It will not generate or save embeddings for messages that already have an * embedding. * @param ctx The ctx parameter to an action. * @param args The messageIds to generate embeddings for. */ generateAndSaveEmbeddings(ctx: RunActionCtx, args: { messageIds: string[]; }): Promise<void>; /** * Explicitly save a "step" created by the AI SDK. * @param ctx The ctx argument to a mutation or action. * @param args The Step generated by the AI SDK. */ saveStep<TOOLS extends ToolSet>(ctx: ActionCtx, args: { userId?: string; threadId: string; /** * The message this step is in response to. */ promptMessageId: string; /** * The step to save, possibly including multiple tool calls. */ step: StepResult<TOOLS>; /** * The model used to generate the step. * Defaults to the chat model for the Agent. */ model?: string; /** * The provider of the model used to generate the step. * Defaults to the chat provider for the Agent. */ provider?: string; }): Promise<{ messages: MessageDoc[]; pending?: MessageDoc; }>; /** * Manually save the result of a generateObject call to the thread. * This happens automatically when using {@link generateObject} or {@link streamObject} * from the `thread` object created by {@link continueThread} or {@link createThread}. * @param ctx The context passed from the mutation or action function calling this. * @param args The arguments to the saveObject function. */ saveObject(ctx: RunActionCtx, args: { userId: string | undefined; threadId: string; promptMessageId: string; result: GenerateObjectResult<unknown>; metadata?: Omit<MessageWithMetadata, "message">; }): Promise<void>; /** * Commit or rollback a message that was pending. * This is done automatically when saving messages by default. * If creating pending messages, you can call this when the full "transaction" is done. * @param ctx The ctx argument to your mutation or action. * @param args What message to save. Generally the parent message sent into * the generateText call. */ completeMessage(ctx: RunMutationCtx, args: { threadId: string; messageId: string; result: { kind: "error"; error: string; } | { kind: "success"; }; }): Promise<void>; _saveMessagesAndFetchContext<T extends { id?: string; prompt?: string; messages?: CoreMessage[] | AIMessageWithoutId[]; system?: string; promptMessageId?: string; model?: LanguageModelV1; maxRetries?: number; }>(ctx: RunActionCtx, args: T, { userId: argsUserId, threadId, contextOptions, storageOptions, }: { userId: string | undefined; threadId: string | undefined; } & Options): Promise<{ args: T & { model: LanguageModelV1; }; userId: string | undefined; messageId: string | undefined; order: number | undefined; stepOrder: number | undefined; }>; _shouldSaveOutputMessages(storageOpts?: StorageOptions): boolean; _mergedContextOptions(opts: ContextOptions | undefined): ContextOptions; _searchOptionsWithEmbeddingAndDefaults(ctx: RunActionCtx, { userId, threadId }: { userId?: string; threadId?: string; }, contextOptions: ContextOptions, messages: CoreMessage[]): Promise<SearchOptions>; doEmbed(ctx: RunActionCtx, options: { userId: string | undefined; threadId: string | undefined; values: string[]; abortSignal?: AbortSignal; headers?: Record<string, string | undefined>; }): Promise<{ embeddings: number[][]; }>; /** * Process messages to inline file and image URLs that point to localhost * by converting them to base64. This solves the problem of LLMs not being * able to access localhost URLs. */ private _inlineMessagesFiles; /** * Check if a URL points to localhost */ private _isLocalhostUrl; /** * Download a file from a URL */ private _downloadFile; /** * WORKFLOW UTILITIES */ /** * Create a mutation that creates a thread so you can call it from a Workflow. * e.g. * ```ts * // in convex/foo.ts * export const createThread = weatherAgent.createThreadMutation(); * * const workflow = new WorkflowManager(components.workflow); * export const myWorkflow = workflow.define({ * args: {}, * handler: async (step) => { * const { threadId } = await step.runMutation(internal.foo.createThread); * // use the threadId to generate text, object, etc. * }, * }); * ``` * @returns A mutation that creates a thread. */ createThreadMutation(): import("convex/server").RegisteredMutation<"internal", { userId?: string | undefined; title?: string | undefined; summary?: string | undefined; }, Promise<{ threadId: string; }>>; /** * Create an action out of this agent so you can call it from workflows or other actions * without a wrapping function. * @param spec Configuration for the agent acting as an action, including * {@link ContextOptions}, {@link StorageOptions}, and maxSteps. */ asTextAction(spec?: { /** * The maximum number of steps to take in this action. * Defaults to the {@link Agent.maxSteps} option. */ maxSteps?: number; /** * The {@link ContextOptions} to use for fetching contextual messages and * saving input/output messages. * Defaults to the {@link Agent.contextOptions} option. */ contextOptions?: ContextOptions; /** * The {@link StorageOptions} to use for saving input/output messages. * Defaults to the {@link Agent.storageOptions} option. */ storageOptions?: StorageOptions; /** * Whether to stream the text. * If false, it will generate the text in a single call. (default) * If true or {@link StreamingOptions}, it will stream the text from the LLM * and save the chunks to the database with the options you specify, or the * defaults if you pass true. */ stream?: boolean | StreamingOptions; }): import("convex/server").RegisteredAction<"internal", { userId?: string | undefined; threadId?: string | undefined; providerOptions?: Record<string, Record<string, any>> | undefined; system?: string | undefined; messages?: ({ providerOptions?: Record<string, Record<string, any>> | undefined; role: "user"; content: string | ({ providerOptions?: Record<string, Record<string, any>> | undefined; type: "text"; text: string; } | { providerOptions?: Record<string, Record<string, any>> | undefined; mimeType?: string | undefined; type: "image"; image: string | ArrayBuffer; } | { providerOptions?: Record<string, Record<string, any>> | undefined; filename?: string | undefined; type: "file"; mimeType: string; data: string | ArrayBuffer; })[]; } | { providerOptions?: Record<string, Record<string, any>> | undefined; role: "assistant"; content: string | ({ providerOptions?: Record<string, Record<string, any>> | undefined; type: "text"; text: string; } | { providerOptions?: Record<string, Record<string, any>> | undefined; filename?: string | undefined; type: "file"; mimeType: string; data: string | ArrayBuffer; } | { providerOptions?: Record<string, Record<string, any>> | undefined; signature?: string | undefined; type: "reasoning"; text: string; } | { providerOptions?: Record<string, Record<string, any>> | undefined; type: "redacted-reasoning"; data: string; } | { providerOptions?: Record<string, Record<string, any>> | undefined; type: "tool-call"; toolCallId: string; toolName: string; args: any; })[]; } | { providerOptions?: Record<string, Record<string, any>> | undefined; role: "tool"; content: { providerOptions?: Record<string, Record<string, any>> | undefined; args?: any; experimental_content?: ({ type: "text"; text: string; } | { mimeType?: string | undefined; type: "image"; data: string; })[] | undefined; isError?: boolean | undefined; type: "tool-result"; toolCallId: string; toolName: string; result: any; }[]; } | { providerOptions?: Record<string, Record<string, any>> | undefined; role: "system"; content: string; })[] | undefined; headers?: Record<string, string> | undefined; maxTokens?: number | undefined; temperature?: number | undefined; topP?: number | undefined; topK?: number | undefined; presencePenalty?: number | undefined; frequencyPenalty?: number | undefined; seed?: number | undefined; maxRetries?: number | undefined; stream?: boolean | undefined; toolChoice?: "required" | "none" | "auto" | { type: "tool"; toolName: string; } | undefined; maxSteps?: number | undefined; experimental_continueSteps?: boolean | undefined; prompt?: string | undefined; promptMessageId?: string | undefined; contextOptions?: { excludeToolMessages?: boolean | undefined; recentMessages?: number | undefined; searchOptions?: { messageRange?: { before: number; after: number; } | undefined; textSearch?: boolean | undefined; vectorSearch?: boolean | undefined; limit: number; } | undefined; searchOtherThreads?: boolean | undefined; } | undefined; storageOptions?: { saveMessages?: "all" | "none" | "promptAndOutput"; saveAllInputMessages?: boolean; saveAnyInputMessages?: boolean; saveOutputMessages?: boolean; } | undefined; }, Promise<{ text: string; finishReason: import("@ai-sdk/provider").LanguageModelV1FinishReason; messageId: string | undefined; }>>; /** * Create an action that generates an object out of this agent so you can call * it from workflows or other actions without a wrapping function. * @param spec Configuration for the agent acting as an action, including * the normal parameters to {@link generateObject}, plus {@link ContextOptions} * and maxSteps. */ asObjectAction<T>(spec: OurObjectArgs<T> & { maxSteps?: number; }, options?: { contextOptions?: ContextOptions; storageOptions?: StorageOptions; }): import("convex/server").RegisteredAction<"internal", { userId?: string | undefined; threadId?: string | undefined; providerOptions?: Record<string, Record<string, any>> | undefined; system?: string | undefined; messages?: ({ providerOptions?: Record<string, Record<string, any>> | undefined; role: "user"; content: string | ({ providerOptions?: Record<string, Record<string, any>> | undefined; type: "text"; text: string; } | { providerOptions?: Record<string, Record<string, any>> | undefined; mimeType?: string | undefined; type: "image"; image: string | ArrayBuffer; } | { providerOptions?: Record<string, Record<string, any>> | undefined; filename?: string | undefined; type: "file"; mimeType: string; data: string | ArrayBuffer; })[]; } | { providerOptions?: Record<string, Record<string, any>> | undefined; role: "assistant"; content: string | ({ providerOptions?: Record<string, Record<string, any>> | undefined; type: "text"; text: string; } | { providerOptions?: Record<string, Record<string, any>> | undefined; filename?: string | undefined; type: "file"; mimeType: string; data: string | ArrayBuffer; } | { providerOptions?: Record<string, Record<string, any>> | undefined; signature?: string | undefined; type: "reasoning"; text: string; } | { providerOptions?: Record<string, Record<string, any>> | undefined; type: "redacted-reasoning"; data: string; } | { providerOptions?: Record<string, Record<string, any>> | undefined; type: "tool-call"; toolCallId: string; toolName: string; args: any; })[]; } | { providerOptions?: Record<string, Record<string, any>> | undefined; role: "tool"; content: { providerOptions?: Record<string, Record<string, any>> | undefined; args?: any; experimental_content?: ({ type: "text"; text: string; } | { mimeType?: string | undefined; type: "image"; data: string; })[] | undefined; isError?: boolean | undefined; type: "tool-result"; toolCallId: string; toolName: string; result: any; }[]; } | { providerOptions?: Record<string, Record<string, any>> | undefined; role: "system"; content: string; })[] | undefined; headers?: Record<string, string> | undefined; maxTokens?: number | undefined; temperature?: number | undefined; topP?: number | undefined; topK?: number | undefined; presencePenalty?: number | undefined; frequencyPenalty?: number | undefined; seed?: number | undefined; maxRetries?: number | undefined; prompt?: string | undefined; promptMessageId?: string | undefined; contextOptions?: { excludeToolMessages?: boolean | undefined; recentMessages?: number | undefined; searchOptions?: { messageRange?: { before: number; after: number; } | undefined; textSearch?: boolean | undefined; vectorSearch?: boolean | undefined; limit: number; } | undefined; searchOtherThreads?: boolean | undefined; } | undefined; storageOptions?: { saveMessages?: "all" | "none" | "promptAndOutput"; saveAllInputMessages?: boolean; saveAnyInputMessages?: boolean; saveOutputMessages?: boolean; } | undefined; }, Promise<{ object: T; }>>; /** * Save messages to the thread. * Useful as a step in Workflows, e.g. * ```ts * const saveMessages = agent.asSaveMessagesMutation(); * * const myWorkflow = workflow.define({ * args: {...}, * handler: async (step, args) => { * // do things to create (but not save)messages * const { messageIds } = await step.runMutation(internal.foo.saveMessages, { * threadId: args.threadId, * messages: args.messages, * }); * // ... * }, * }) * ``` * @returns A mutation that can be used to save messages to the thread. */ asSaveMessagesMutation(): import("convex/server").RegisteredMutation<"internal", { userId?: string | undefined; pending?: boolean | undefined; promptMessageId?: string | undefined; failPendingSteps?: boolean | undefined; threadId: string; messages: { id?: string | undefined; fileIds?: string[] | undefined; error?: string | undefined; model?: string | undefined; provider?: string | undefined; text?: string | undefined; reasoning?: string | undefined; usage?: { promptTokens: number; completionTokens: number; totalTokens: number; } | undefined; providerMetadata?: Record<string, Record<string, any>> | undefined; sources?: { title?: string | undefined; providerOptions?: Record<string, Record<string, any>> | undefined; id: string; sourceType: "url"; url: string; }[] | undefined; reasoningDetails?: ({ signature?: string | undefined; type: "text"; text: string; } | { type: "redacted"; data: string; })[] | undefined; warnings?: ({ details?: string | undefined; type: "unsupported-setting"; setting: string; } | { details?: string | undefined; type: "unsupported-tool"; tool: any; } | { type: "other"; message: string; })[] | undefined; finishReason?: "length" | "error" | "other" | "stop" | "content-filter" | "tool-calls" | "unknown" | undefined; message: { providerOptions?: Record<string, Record<string, any>> | undefined; role: "user"; content: string | ({ providerOptions?: Record<string, Record<string, any>> | undefined; type: "text"; text: string; } | { providerOptions?: Record<string, Record<string, any>> | undefined; mimeType?: string | undefined; type: "image"; image: string | ArrayBuffer; } | { providerOptions?: Record<string, Record<string, any>> | undefined; filename?: string | undefined; type: "file"; mimeType: string; data: string | ArrayBuffer; })[]; } | { providerOptions?: Record<string, Record<string, any>> | undefined; role: "assistant"; content: string | ({ providerOptions?: Record<string, Record<string, any>> | undefined; type: "text"; text: string; } | { providerOptions?: Record<string, Record<string, any>> | undefined; filename?: string | undefined; type: "file"; mimeType: string; data: string | ArrayBuffer; } | { providerOptions?: Record<string, Record<string, any>> | undefined; signature?: string | undefined; type: "reasoning"; text: string; } | { providerOptions?: Record<string, Record<string, any>> | undefined; type: "redacted-reasoning"; data: string; } | { providerOptions?: Record<string, Record<string, any>> | undefined; type: "tool-call"; toolCallId: string; toolName: string; args: any; })[]; } | { providerOptions?: Record<string, Record<string, any>> | undefined; role: "tool"; content: { providerOptions?: Record<string, Record<string, any>> | undefined; args?: any; experimental_content?: ({ type: "text"; text: string; } | { mimeType?: string | undefined; typ