- Fix streaming UI message dedupe (#281)
- chore(deltas): delete legacy TextStreamPart streaming path (#275)
- fix(react): Fix O(n²) lag streaming long tool-input deltas (#190) (#270)
- fix(mapping): preserve tool messages in multi-step history (#200) (#272)
- fix: Stops a cleanup task from canceling itself (#285)
- Update types for
ctxargs to be more compatible with convex 1.41
- fix: persist final step when saveStreamDeltas.returnImmediately is true (#266)
- fix: handle tool validation errors in stopWhen and willContinue (#241)
- Fix bundled package
- Tool approval support:
needsApprovalincreateTool,agent.approveToolCall(),agent.denyToolCall() - Auto-deny unresolved tool approvals when a new generation starts
- Fix unhandled rejection in DeltaStreamer on transaction teardown
Note on versioning: This release jumps from 0.3.2 to 0.6.0, skipping
versions 0.4.0 and 0.5.0. This is intentional and aligns the @convex-dev/agent
package version with the AI SDK v6 major version for clearer compatibility
signaling. Going forward, the minor version of this package will track the AI
SDK major version to make it easier for developers to identify which version of
the AI SDK is supported.
- Breaking: Requires AI SDK v6 and drops support for AI SDK v5. Projects pinned to v5 must upgrade their AI SDK dependencies before updating to this version.
- Aligns this package's message and tool invocation types with the AI SDK v6 APIs to reduce casting/adapter code when integrating with the core SDK.
- Updates internal helpers to use the AI SDK v6 request/response shapes and error handling semantics.
- Migration from 0.3.x:
- Update your AI SDK dependency to v6 in
package.jsonand reinstall dependencies. - Rebuild and run your type checker to surface any call sites that depend on the old AI SDK v5 types or message shapes.
- Review any custom integrations that relied on deprecated v5-only helpers and update them to the new AI SDK v6-compatible APIs.
- See Vercel's v6 migration guide for details on AI SDK changes.
- Update your AI SDK dependency to v6 in
- Fix deleteByOrder spanning many messages
- Avoid JSON.stringify in the render path for logging in useUIMessages.
- Ensures input messages are saved associated with promptMessageId. This generally happens by default, but if the promptMessageId wasn't latest, it would have previously saved them as the newest messages.
- Adds /test and /_generated/component.js entrypoints
- Drops commonjs support
- Improves source mapping for generated files
- Changes to a statically generated component API
- Capture tool errors in the message
- Filters out empty content arrays when prompting the LLM.
- Fixes combining sequential user messages in useUIMessages
- Breaking: now joins all text parts with a space delimiter instead of strict concatenation. This improves text search and is unlikely to look worse, as text parts aren't meant to be deltas.
- Exports a
docsToModelMessagesto convert MessageDoc to ModelMessage taking into account omitting missing messages or empty content. - Fixes playground UI showing follow-up messages.
- Adds a /test entrypoint to make adding tests with the agent easier.
- Simplifies the types for generating object & text to more closely match the AI SDK.
- Allows passing a
promptMessageIdtosaveMessageto matchsaveMessages.
- Support models that return no content ([])
- Breaking bug fix: we were returning output in UIMessages with extra { type: "json", value: ... } instead of the value itself. Now we return the output directly.
- Add documentation for new behavior and export new functions.
- Deprecation: Renames deserializeMessage to toModelMessage.
- Fix: Pass provider metadata through more consistently in message parts.
- Adds useUIMessages and useUIStreamingMessages for UIMessage-first client usage. These have more metadata around reasoning streaming status, and provide support for metadata and custom data parts.
- Adds a
listUIMessagesakin tolistMessagesconverted to UIMessages. - Uses the UIMessageChunk stream when streaming text, which fixes many bugs which stemmed from the AI SDK's onChunk callback.
- Enables having streaming hooks skip streamIds so you can stream via HTTP for some clients and have others get the deltas.
- Compresses the deltas saved to the DB - combining text deltas & reasoning
deltas that come from the same part
id. optimisticallySendMessagewill set fields for both MessageDoc and UIMessage, so it should transparently work for either hook strategy, though you may see more fields than you expect.- Defaults
texttoundefinedif it's empty (no text chunks) mockModelcan now simulate responses for multi-step generation, by passing acontentStepsarray to its constructor. Each element is an array of content for that step.createToolsupports async iteration.- Add
experimental_downloadtype togenerateObject - Adds
structuredClonepolyfill for ReactNative UIMessages.
- Updates types to match the latest
aipackage types - note: you should update theaipackage to 5.0.29 or above.
- Splits out the
startfunction from the Agent, along with other utilities that can be used without the Agent, e.g. tosaveInputMessagesand fetch context messages combined with input messages. - Adds a
contextHandleroption to the Agent, which is a function to modify the context messages before they are passed to the LLM. - Adds a
fromUIMessagefunction to convert UIMessage[] to MessageDoc[]. - Fixes asObjectAction being generic on the wrong DataModel.
- Using
mockModelworks better now for streaming. - Search text will use the last message, prompt, or promptMessage string.
- Fixes the
stepOrderbeing off when streaming with tool calls. - More readable MessageDoc type.
- The output of a tool result is now saved differently from the
resultand matches the ModelMessage expected format. This also coerces the previousresultformat into the newoutputdata format. - cachedInputTokens is now saved in the usage field
- The global default for providerOptions is supplied correctly, however lmk if you actually want it, otherwise it's deprecated and may be removed.
- Fix: useSmoothText starts streaming even if no text update happens.
- The DeltaStreamer class is now generic on the type of part to save, and decoupled to make it easier to use on its own.
- Running agent-playground works on windows (credit: yahyasamet)
- The setup script works interactively (credit: kfiroo)
- Playground assistant messages CSS fix (credit: jamieday)
- Fix: promptMessageId is back on the generate/streamObject args type
- omit fileIds in saveMessages when none present (credit:mlshv)
- Add source as a first-class content type for assistants (unstable)
- Adds a
mockModelutility for testing (that works in the default Convex runtime). - Fixes async abort saving of messages.
- No longer saves the final delta when aborting a stream async.
- No longer fails previous messages by default when generating without a promptMessageId
- Fixes double-submitting the user prompt when using promptMessageId
- Reintroduces the
maxStepsconfig for Agents / global config. This becomes the default whenstopWhenis not provided. - Supports a tool response in an assistant message
- Correctly handles providerOptions vs. providerMetadata in ser/de
- Fix up reasoning state (breaking but shouldn't be present anywhere)
- You can now pass
argsdirectly tolistMessagesinstead of passing threadId & paginationOpts manually. - useSmoothText is even smoother
- toUIMessage is much better - works in both directions with any ordering
- Only embeds the first 10k of characters for vector search.
- Add _creationTime to UIMessage (number) to replace v4's createdAt
- Improves the playground debugging by enabling streaming
- Fixes .text in UIMessages when
textwasn't set already - Fixes skipping failed agent tool calls in toUIMessages
- Assume no stop when means only one step
- Defaults to consuming the stream when saving deltas, so you don't have to do
result.consumeStream(). You can passreturnImmediately: trueif you want to save deltas and also process the stream yourself. - Agent name is now required.
- You can specify default
providerOptions at the Agent level. - The
agentparam inToolCtxis now optional to make it easier to manually wrap tools before the agent is defined.
Adds support for the AI SDK v5, and associated versions of LLM providers. This involves some breaking changes associated with the changes to the UI, but the data at rest is backwards compatible.
- Supports LanguageModel: a string for gateway or LanguageModelV2.
- No longer returns lastMessageId when saving message, instead it returns all the messages it saved with all metadata.
- All saved messages are returned when generating / streaming text / objects. Not just the prompt message ID / order.
- Adds a
SmoothTextcomponent that can be used to render streaming text. - Generating / streaming will return a
promptMessageIdfield, which is the message ID of the last message that was used as the prompt. This replaces themessageIdfield, which was confusing. - There's a
.startfunction you can use to call the AI SDK directly and still get all the message management benefits. - More functions are supported without using an Agent class.
- The UIMessage is now based on the v5 UIMessage, and the MessageDoc is based on the ModelMessage. The data at rest has not changed - backwards compatible.
- Add a
.textfield to the toUIMessages return value (this is the UIMessage exported by the Agent library) to replace thecontentfield. - The
idis no longer used / configurable when saving messages. Reach out if you were using it - the normal message ID should suffice. maxRetriesoption has been moved into a generalcallSettingsconfig on Agent, and in general has been renamed tostopWhenin v5.- Saving pending messages now requires passing status: "pending" instead of a top-level pending: true. Most people don't use this feature currently.
- A pending message is now created by default when generating / streaming text / objects, representing the message that is being generated. It will attempt to only create pending messages when it anticipates generating a response.
- On failure / abort, the pending message is updated with streaming contents.
- Breaking: the
threadreturn value fromcontinueThreadno longer allows overriding the tools or usage handler at the thread level. You can still override the agent defaults at the call-site.
- definePlaygroundAPI uses the new interface functions
- Add generic types on UIMessages (credit: ethan-huo)
- Deleting returns the order range (credit: ethan-huo)
- Allow specifying a custom
ctxtype for use in tools created withcreateTool - Fix resolution of
definePlaygroundApi - Fix: ReactNative can do optimistic updates even if it has crypto defined
- Fix: getMessageByIds correctly serializes non-user messages
- Fix: usage handler won't be overwritten with undefined.
- Importing
definePlaygroundAPIfrom @convex-dev/agent directly - Supports adding a file to the message history from an httpAction
- Fix: enforce storageOptions "none" in streamText (credit: fvaldes33)
- It's possible to call many agent functions directly from a workflow.
- Support calling generate/stream with the same
promptMessageIdmultiple times and have it continue the generation, e.g. when maxSteps is 1. asTextActionandasObjectActionnow returnorderandwarnings.- generating embeddings asynchronously is more efficient
- Deprecated: dropped long-deprecated args like
isTool, and somestorageOptions.save*options that have been replaced with alternatives. - Breaking:
.idontoUIMessagesis now always the message's_id, not any custom id provided from the AI SDK. Shouldn't affect ~anyone. - Fix embedding/vector argument to search messages
- Fix handling of
undefinedin streaming text - Return the last agent name to the playground UI
- Validate the playground backend less frantically
- Allow passing null for userId arguments
- Agents can be dynamically created for the playground
- You can abort streaming messages by ID or message
order - You can request that
syncStreamsreturn aborted streamed messages, if you want to show those in your UI. - They will have
msg.streaming === falseif they were aborted. - Factored out functions so you don't have to have an agent to call:
saveMessages,getThreadMetadata,createThread,fetchContextMessages,listMessages,syncStreams - Improved the
ctxtype for the raw request handler and exposed more types - Add
agentNametoUIMessage - Saving messages returns the
orderof the last message saved. - Fix: stream deletion is idempotent and cleanup is canceled if it's already deleted.
- Show reasoning before text in UI messages
- List un-named agents in the playground
- Expose delete functions for messages & threads on the Agent class
- Expose updating messages on the Agent class
- Expose the types for ThreadQuery, StreamArgs, and SyncStreamsReturnValue
- Fix thread title text search
- Fix loading state of pagination (peer bump)
- Fix user messages going from pending-> failed when using prompt with generateText repeatedly in a thread.
- Allow updating a thread's userId
- Auth is available in the
createToolctx. - Add text search on thread titles.
- Add RAG example & docs
- Pass the final model & provider when storing messages, in case it was overriden at the thread/callsite level.
- Supports passing both a promptMessageId and messages, so you can pass context messages while also generating the propt message ahead of time in a mutation.
- Now includes an example of RAG using the Memory component.
- Fix object serialization
- Sources will be populated to non-tool results
- Deleting files will return the files actually deleted
- Agents without names will warn if used in the playground
- More graceful deletion of streams
- You can abort a stream asynchronously and have it stop writing deltas smoothly.
- The timeout for streaming deltas with no sign of life has been increased to 10 minutes.
- Delete stream deltas automatically 5 min after the stream finishes.
- Fix: deleting threads asynchronously will clean up deltas.
- Fix: update the reasoning in the top-level message when streaming
- Support images in localhost by loading them locally and passing them to the LLM as raw data. (author: @julionav)
- Add
updateMessageto the raw components.agent.messages API for patching existing message contents, status, and error details. (author: @julionav) - Add extensions to support NodeNext bundling
- Fix: paginating over all users now works for more than one page
- Fix: streams are now deleted when deleting threads / user data
- Image and file handling! It now auto-saves large input messages, and has an API to save and get metadata about files, as well as automatic reference counting for files being used in messages, so you can vacuum unused files. Check out examples/files-images, which also includes an example generating an image and saving it in messages one-shot.
- Adds a
rawRequestResponseHandlerargument to the Agent that is a good spot to log or save all raw request/responses if you're trying to debug model behavior, headers, etc. - Centralizes the example model usage so you can swap models in one place.
- StorageOptions now takes a better argument name
saveMessages?: "all" | "none" | "promptAndOutput";, deprecatingsave{All,Any}InputMessagesandsaveOutputMessages. - Add
rawRequestResponseHandlerto the Agent definition, so you can log the raw request and response from the LLM.
- The
filesfield is deprecated in favor offileIdsin the message metadata. This wasn't really used before but it was possible folks discovered how to set it.
- The
stepstable is now gone. It will still be around in your backend, where you can inspect or clear it if you want, but it will not be written to, and the low-level APIs around saving steps alongside messages are gone. To get debug information, you can use therawRequestResponseHandlerand dump the request and response to your own debug table. Maybe conditional on some environment variable so you can turn it on/off for debugging.
- Fix pagination for the Agent messages when loading more
- Allow using useSmoothText in Next.js
- Fix: re-export
ToolCtxin@convex-dev/agent/react
- APIs to get and update thread metadata on the agent / thread objects.
- Support generating embeddings asynchronously to save messages in mutations.
- Allow embedding generation to be done lazily by default.
- Build the project so it's compatible with composite and verbatim module syntax
useSmoothTextis even smoother- Fix handling of file messages to include
filenameanddatafield instead offile. - Fix bundling of api.d.ts to fix the
AgentComponenttype beingany. - More examples in the examples/ directory, that you can access from the root example
- Improve scripts for running the examples. See README.
- Starting to unify model definitions for examples so you only have to change it in one place to e.g. use grok.
- Better import hygiene for folks using
verbatimModuleSyntax.
- Automatically pulls in the thread's userId when no userId is specified.
- Fixes bugs around duplicate content when streaming / using toUIMessages.
useSmoothTextis now even smoother with a stream rate that auto-adjusts.- Defaults streaming chunks to sentence instead of word.
- The
userIdassociated with the thread will automatically be associated with messages and tool calls, if no userId is passed at thread continuation or call-site. This is likely what you want, but in case you didn't, consider not setting a default userId for the thread and passing it in only when continuing the thread. - The
searchMessageandtextSearchfunctions now take the more explicit parametersearchAllMessagesForUserIdinstead ofuserId.
- Allows you to pass
promptMessageIdtoagent.streamText. This parameter allows you to create a message ahead of time and then generate the response separately, responding to that message.
- Added text delta streaming with
useThreadMessagesanduseStreamingThreadMessagesReact hooks. See examples/chat-streaming for example usage. - Also includes a
useSmoothTexthook andoptimisticallySendMessageto get smooth streaming UI and immediate feedback when a user sends a msg. - Adds a UIMessage type that is an AI SDK UIMessage with some extra fields for convenience, e.g. a stable key, order/stepOrder, streaming status.
- Allow listing threads without an associated userId in the playground.
- make stepOrder always increasing, for more predictable sorting of failed + non-failed messages.
- A reference to the agent is now passed to tool calls using the
createToolutility. - In more places, we aren't storing the AI SDK
idunless explicitly passed in, and favoring the built-in Convex ID instead. - The examples/ folder will become a better resource with more specific examples. For now, there's an index page when running the examples, that points to the text streaming and weather demos.
- There's now
listMessagessaveMessage, andasSaveMessagesMutationon the Agent.listMessagesis compliant with the normal pagination API.
components.agent.messages.listMessagesByThreadIdis nowascending by default! It'll have a type error to help you out. While you're at it, you can use the new.listMessageson the agent itself!addStepnow returns the messages it created instead of a step. This is not likely to be called by clients directly. It's mostly used internally.toUIMessageshas been moved to the@convex-dev/agent/reactimport entrypoint.
- The file api has been improved to allow for upserting files more correctly.
You can use it to track images and files in messages, and have a cron that
queries for images that can be safely deleted. When adding it to a message,
call
addFile,useExistingFile, orcopyFileto get thefileIdand add it to the message metadata. When the message is deleted, it will delete the file (if it has the last reference to it). - Added an example for passing in images to LLMs.
- Embeddings of length 1408 are now supported.
- UI Playground, to host locally or embed into your app.
- On the left panel it has a dropdown to select a users, then lists the user's treads
- In the middle you can see the thread's messages and tool calls, as well as
send new messages in the thread:
- Configurable context & message saving options
- Play with the system prompt for rapid prototyping.
- On the right you can see the selected message's details, as well as fetch contextual messages to investigate what messages would get fetched for that message, with configurable ContextOptions.
- Use the hosted version or run it
locally with
npx @convex-dev/agent-playground- uses Vite internally for now. - API key management (to authenticate into the UI Playground)
- The
orderandstepOrderis now well defined: each call to something likegenerateTextwill be on the next "order" and each message generated from it will have increasing "subOrder" indexes. - Adds a function to turn MessageDoc[] into UIMessage[].
- Eliminates an index to reduce storage cost per-message.
- The README is a better resource.
agent.fetchContextMessagesnow returnsMessageDocinstead of aCoreMessageobjects.isToolconfiguration for context has been changed toexcludeToolMessages- wherefalse/undefinedis the default and includes tool messages, andtruewill only return user/assistant messages.- Reorganization of API (split
agent.messages.*intoagent.threads.*,agent.messages.*,agent.files.*, andagent.users.*. - Parameters like
parentMessageIdhave generally been renamed topromptMessageIdorbeforeMessageIdorupToAndIncludingMessageIdto better clarify their use for things like using an existing message as a prompt or searching context from before a message, or fetching messages up to and including a given message. Thegenerate*/stream*functions can take apromptMessageIdinstead of aprompt/messagesarg now. - Calls to steps and objects now take a parentMessageId instead of messageId parameter, as this is the true meaning of parent message (the message being responded to).
- The
stepstable is going away, to be replaced with a callback where you can dump your own comprehensive debug information if/when you want to. As such, thestepIdfield isn't returned on messages. - The
parentMessageIdfield is no longer exposed. Its purpose is now filled by the order & stepOrder fields: each message with the same order is a child of the message at stepOrder 0.
- Fixes a bug with providing out-of-order tool messages in the prompt context. (author: @apostolisCodpal)
-
You can pass tools at the agent definition, thread definition, or per-message call, making it easier to define tools at runtime with runtime context.
-
README improvements
getEmbeddingshas been renamed togenerateEmbeddings
- Passing
ConfigOptionsandStorageOptionsshould now be passed as separate parameters viaconfigOptionsandstorageOptions. e.g. forgenerateText{ prompt }, { contextOptions: { recentMessages: 10 } }instead of{ prompt, recentMessages: 10 }
-
There is now a usageHandler you can specify on the Agent definition, thread, or per-message that can log or save token usage history.
-
The model and provider are being stored on the messages table, along with usage, warnings, and other fields previously hidden away in the steps table.
- The agent name is now correctly propagating to the messages table for non-user messages.
- parentThreadIds is deprecated, as it wasn't merging histories and the desire to do so should have a message as its parent to make the history behavior clear.