@convex-dev/agent 0.0.16 → 0.0.17-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/README.md +159 -98
  2. package/dist/commonjs/client/index.d.ts +806 -189
  3. package/dist/commonjs/client/index.d.ts.map +1 -1
  4. package/dist/commonjs/client/index.js +178 -28
  5. package/dist/commonjs/client/index.js.map +1 -1
  6. package/dist/commonjs/client/playground.d.ts +609 -0
  7. package/dist/commonjs/client/playground.d.ts.map +1 -0
  8. package/dist/commonjs/client/playground.js +200 -0
  9. package/dist/commonjs/client/playground.js.map +1 -0
  10. package/dist/commonjs/component/apiKeys.d.ts +11 -0
  11. package/dist/commonjs/component/apiKeys.d.ts.map +1 -0
  12. package/dist/commonjs/component/apiKeys.js +69 -0
  13. package/dist/commonjs/component/apiKeys.js.map +1 -0
  14. package/dist/commonjs/component/files.d.ts +31 -0
  15. package/dist/commonjs/component/files.d.ts.map +1 -0
  16. package/dist/commonjs/component/files.js +61 -0
  17. package/dist/commonjs/component/files.js.map +1 -0
  18. package/dist/commonjs/component/messages.d.ts +720 -676
  19. package/dist/commonjs/component/messages.d.ts.map +1 -1
  20. package/dist/commonjs/component/messages.js +99 -287
  21. package/dist/commonjs/component/messages.js.map +1 -1
  22. package/dist/commonjs/component/schema.d.ts +1124 -1324
  23. package/dist/commonjs/component/schema.d.ts.map +1 -1
  24. package/dist/commonjs/component/schema.js +26 -14
  25. package/dist/commonjs/component/schema.js.map +1 -1
  26. package/dist/commonjs/component/threads.d.ts +95 -0
  27. package/dist/commonjs/component/threads.d.ts.map +1 -0
  28. package/dist/commonjs/component/threads.js +151 -0
  29. package/dist/commonjs/component/threads.js.map +1 -0
  30. package/dist/commonjs/component/users.d.ts +37 -0
  31. package/dist/commonjs/component/users.d.ts.map +1 -0
  32. package/dist/commonjs/component/users.js +118 -0
  33. package/dist/commonjs/component/users.js.map +1 -0
  34. package/dist/commonjs/component/vector/index.d.ts.map +1 -1
  35. package/dist/commonjs/component/vector/index.js +4 -6
  36. package/dist/commonjs/component/vector/index.js.map +1 -1
  37. package/dist/commonjs/component/vector/tables.d.ts +10 -10
  38. package/dist/commonjs/component/vector/tables.d.ts.map +1 -1
  39. package/dist/commonjs/component/vector/tables.js.map +1 -1
  40. package/dist/commonjs/mapping.d.ts +7 -1
  41. package/dist/commonjs/mapping.d.ts.map +1 -1
  42. package/dist/commonjs/mapping.js +39 -18
  43. package/dist/commonjs/mapping.js.map +1 -1
  44. package/dist/commonjs/validators.d.ts +1669 -2340
  45. package/dist/commonjs/validators.d.ts.map +1 -1
  46. package/dist/commonjs/validators.js +35 -26
  47. package/dist/commonjs/validators.js.map +1 -1
  48. package/dist/esm/client/index.d.ts +806 -189
  49. package/dist/esm/client/index.d.ts.map +1 -1
  50. package/dist/esm/client/index.js +178 -28
  51. package/dist/esm/client/index.js.map +1 -1
  52. package/dist/esm/client/playground.d.ts +609 -0
  53. package/dist/esm/client/playground.d.ts.map +1 -0
  54. package/dist/esm/client/playground.js +200 -0
  55. package/dist/esm/client/playground.js.map +1 -0
  56. package/dist/esm/component/apiKeys.d.ts +11 -0
  57. package/dist/esm/component/apiKeys.d.ts.map +1 -0
  58. package/dist/esm/component/apiKeys.js +69 -0
  59. package/dist/esm/component/apiKeys.js.map +1 -0
  60. package/dist/esm/component/files.d.ts +31 -0
  61. package/dist/esm/component/files.d.ts.map +1 -0
  62. package/dist/esm/component/files.js +61 -0
  63. package/dist/esm/component/files.js.map +1 -0
  64. package/dist/esm/component/messages.d.ts +720 -676
  65. package/dist/esm/component/messages.d.ts.map +1 -1
  66. package/dist/esm/component/messages.js +99 -287
  67. package/dist/esm/component/messages.js.map +1 -1
  68. package/dist/esm/component/schema.d.ts +1124 -1324
  69. package/dist/esm/component/schema.d.ts.map +1 -1
  70. package/dist/esm/component/schema.js +26 -14
  71. package/dist/esm/component/schema.js.map +1 -1
  72. package/dist/esm/component/threads.d.ts +95 -0
  73. package/dist/esm/component/threads.d.ts.map +1 -0
  74. package/dist/esm/component/threads.js +151 -0
  75. package/dist/esm/component/threads.js.map +1 -0
  76. package/dist/esm/component/users.d.ts +37 -0
  77. package/dist/esm/component/users.d.ts.map +1 -0
  78. package/dist/esm/component/users.js +118 -0
  79. package/dist/esm/component/users.js.map +1 -0
  80. package/dist/esm/component/vector/index.d.ts.map +1 -1
  81. package/dist/esm/component/vector/index.js +4 -6
  82. package/dist/esm/component/vector/index.js.map +1 -1
  83. package/dist/esm/component/vector/tables.d.ts +10 -10
  84. package/dist/esm/component/vector/tables.d.ts.map +1 -1
  85. package/dist/esm/component/vector/tables.js.map +1 -1
  86. package/dist/esm/mapping.d.ts +7 -1
  87. package/dist/esm/mapping.d.ts.map +1 -1
  88. package/dist/esm/mapping.js +39 -18
  89. package/dist/esm/mapping.js.map +1 -1
  90. package/dist/esm/validators.d.ts +1669 -2340
  91. package/dist/esm/validators.d.ts.map +1 -1
  92. package/dist/esm/validators.js +35 -26
  93. package/dist/esm/validators.js.map +1 -1
  94. package/package.json +8 -1
  95. package/src/client/index.ts +220 -59
  96. package/src/client/playground.ts +257 -0
  97. package/src/component/_generated/api.d.ts +601 -400
  98. package/src/component/apiKeys.ts +74 -0
  99. package/src/component/files.ts +72 -0
  100. package/src/component/messages.test.ts +23 -0
  101. package/src/component/messages.ts +127 -341
  102. package/src/component/schema.ts +32 -13
  103. package/src/component/threads.ts +184 -0
  104. package/src/component/users.ts +145 -0
  105. package/src/component/vector/index.ts +5 -6
  106. package/src/component/vector/tables.ts +15 -15
  107. package/src/mapping.ts +65 -32
  108. package/src/validators.ts +47 -28
package/README.md CHANGED
@@ -111,7 +111,7 @@ export default app;
111
111
 
112
112
  ## Usage
113
113
 
114
- ### Configuring the agent
114
+ ### Creating the agent
115
115
 
116
116
  ```ts
117
117
  import { tool } from "ai";
@@ -124,8 +124,6 @@ import { components } from "./_generated/api";
124
124
  const supportAgent = new Agent(components.agent, {
125
125
  // The chat completions model to use for the agent.
126
126
  chat: openai.chat("gpt-4o-mini"),
127
- // Embedding model to power vector search of message history (RAG).
128
- textEmbedding: openai.embedding("text-embedding-3-small"),
129
127
  // The default system prompt if not overriden.
130
128
  instructions: "You are a helpful assistant.",
131
129
  tools: {
@@ -135,57 +133,26 @@ const supportAgent = new Agent(components.agent, {
135
133
  myConvexTool: createTool({
136
134
  description: "My Convex tool",
137
135
  args: z.object({...}),
138
- handler: async (ctx, args) => {
136
+ // Note: annotate the return type of the handler to avoid type cycles.
137
+ handler: async (ctx, args): Promise<string> => {
139
138
  return "Hello, world!";
140
139
  },
141
140
  }),
142
141
  },
143
- // Used for fetching context messages. Values shown are the defaults.
144
- contextOptions: {
145
- // Whether to include tool messages in the context.
146
- includeToolCalls: false,
147
- // How many recent messages to include. These are added after the search
148
- // messages, and do not count against the search limit.
149
- recentMessages: 100,
150
- // Options for searching messages via text and/or vector search.
151
- searchOptions: {
152
- limit: 10, // The maximum number of messages to fetch.
153
- textSearch: false, // Whether to use text search to find messages.
154
- vectorSearch: false, // Whether to use vector search to find messages.
155
- // Note, this is after the limit is applied.
156
- // E.g. this will quadruple the number of messages fetched.
157
- // (two before, and one after each message found in the search)
158
- messageRange: { before: 2, after: 1 },
159
- },
160
- // Whether to search across other threads for relevant messages.
161
- // By default, only the current thread is searched.
162
- searchOtherThreads: false,
163
- },
164
- // Used for storing messages.
165
- storageOptions: {
166
- // When false, allows you to pass in arbitrary context that will
167
- // be in addition to automatically fetched content.
168
- // Pass true to have all input messages saved to the thread history.
169
- saveAllInputMessages: false,
170
- // By default it saves the input message, or the last message if multiple are provided.
171
- saveAnyInputMessages: true,
172
- // Save the generated messages to the thread history.
173
- saveOutputMessages: true,
174
- },
142
+ // Embedding model to power vector search of message history (RAG).
143
+ textEmbedding: openai.embedding("text-embedding-3-small"),
144
+ // Used for fetching context messages. See [below](#configuring-the-context-of-messages)
145
+ contextOptions,
146
+ // Used for storing messages. See [below](#configuring-the-storage-of-messages)
147
+ storageOptions,
175
148
  // Used for limiting the number of steps when tool calls are involved.
149
+ // NOTE: if you want tool calls to happen automatically with a single call,
150
+ // you need to set this to something greater than 1 (the default).
176
151
  maxSteps: 1,
177
- // Used for limiting the number of retries when a tool call fails.
152
+ // Used for limiting the number of retries when a tool call fails. Default: 3.
178
153
  maxRetries: 3,
179
- // Used for tracking token usage.
180
- usageHandler: async (ctx, args) => {
181
- const {
182
- // Who used the tokens
183
- userId, threadId, agentName,
184
- // What LLM was used
185
- model, provider,
186
- // How many tokens were used (extra info is available in providerMetadata)
187
- usage, providerMetadata
188
- } = args;
154
+ // Used for tracking token usage. See [below](#tracking-token-usage)
155
+ usageHandler: async (ctx, { model, usage }) => {
189
156
  // ... log, save usage to your database, etc.
190
157
  },
191
158
  });
@@ -230,28 +197,87 @@ export const continueThread = action({
230
197
  });
231
198
  ```
232
199
 
233
- ### Sending a message with configurable message history context
200
+ ### Generating text
201
+
202
+ The arguments to `generateText` are the same as the AI SDK, except you don't
203
+ have to provide a model. By default it will use the agent's chat model.
204
+
205
+ ```ts
206
+ const { thread } = await supportAgent.createThread(ctx, { userId });
207
+ const result = await thread.generateText({ prompt });
208
+ ```
209
+
210
+ ### Generating an object
211
+
212
+ Similar to the AI SDK, you can generate or streaman object.
213
+ The same arguments apply, except you don't have to provide a model.
214
+ It will use the agent's default chat model.
215
+
216
+ ```ts
217
+ import { z } from "zod";
218
+
219
+ const result = await thread.generateObject({
220
+ prompt: "Generate a plan based on the conversation so far",
221
+ schema: z.object({...}),
222
+ });
223
+ ```
224
+
225
+
226
+ ### Configuring the context of messages
234
227
 
235
228
  You can customize what history is included per-message via `contextOptions`.
236
- See the [configuring the agent](#configuring-the-agent) section for details.
229
+ These options can be provided to the Agent constructor, or per-message.
237
230
 
238
231
  ```ts
239
- const result = await thread.generateText({ prompt }, { contextOptions });
232
+ const result = await thread.generateText({ prompt }, {
233
+ // Values shown are the defaults.
234
+ contextOptions: {
235
+ // Whether to include tool messages in the context.
236
+ includeToolCalls: false,
237
+ // How many recent messages to include. These are added after the search
238
+ // messages, and do not count against the search limit.
239
+ recentMessages: 100,
240
+ // Options for searching messages via text and/or vector search.
241
+ searchOptions: {
242
+ limit: 10, // The maximum number of messages to fetch.
243
+ textSearch: false, // Whether to use text search to find messages.
244
+ vectorSearch: false, // Whether to use vector search to find messages.
245
+ // Note, this is after the limit is applied.
246
+ // E.g. this will quadruple the number of messages fetched.
247
+ // (two before, and one after each message found in the search)
248
+ messageRange: { before: 2, after: 1 },
249
+ },
250
+ // Whether to search across other threads for relevant messages.
251
+ // By default, only the current thread is searched.
252
+ searchOtherThreads: false,
253
+ },
240
254
  ```
241
255
 
242
256
  ### Configuring the storage of messages
243
257
 
244
- See the [configuring the agent](#configuring-the-agent) section for details.
245
258
  Generally the defaults are fine, but if you want to pass in multiple messages
246
259
  and have them all saved (vs. just the last one), or avoid saving any input
247
- or output messages, you can pass in a `storageOptions` object.
260
+ or output messages, you can pass in a `storageOptions` object, either to the
261
+ Agent constructor or per-message.
248
262
 
249
263
  The usecase for passing multiple messages is if you want to include some extra
250
264
  messages for context to the LLM, but only the last message is the user's actual
251
265
  request. e.g. `messages = [...messagesFromRag, messageFromUser]`.
252
266
 
253
267
  ```ts
254
- const result = await thread.generateText({ messages }, { storageOptions });
268
+ const result = await thread.generateText({ messages }, {
269
+ // The default values are shown below.
270
+ storageOptions: {
271
+ // When false, allows you to pass in arbitrary context that will
272
+ // be in addition to automatically fetched content.
273
+ // Pass true to have all input messages saved to the thread history.
274
+ saveAllInputMessages: false,
275
+ // By default it saves the input message, or the last message if multiple are provided.
276
+ saveAnyInputMessages: true,
277
+ // Save the generated messages to the thread history.
278
+ saveOutputMessages: true,
279
+ },
280
+ });
255
281
  ```
256
282
 
257
283
  ### Creating a tool with Convex context
@@ -299,6 +325,73 @@ Specifying tools at each layer will overwrite the defaults.
299
325
  The tools will be `args.tools ?? thread.tools ?? agent.options.tools`.
300
326
  This allows you to create tools in a context that is convenient.
301
327
 
328
+ ### Fetching thread history
329
+
330
+ Fetch the full messages directly. These will include things like usage, etc.
331
+
332
+ ```ts
333
+ import type { MessageDoc } from "@convex-dev/agent";
334
+
335
+ const messages: MessageDoc[] = await ctx.runQuery(
336
+ components.agent.messages.listMessagesByThreadId, {
337
+ threadId,
338
+ order: "desc",
339
+ paginationOpts: { cursor: null, numItems: 10 }
340
+ });
341
+ ```
342
+
343
+ ### Search for messages
344
+
345
+ This is what the agent does automatically, but it can be useful to do manually, e.g. to find custom context to include.
346
+
347
+ Fetch Messages for a user and/or thread.
348
+ Accepts ContextOptions, e.g. includeToolCalls, searchOptions, etc.
349
+ If you provide a `beforeMessageId`, it will only fetch messages from before that message.
350
+
351
+ ```ts
352
+ import type { MessageDoc } from "@convex-dev/agent";
353
+
354
+ const messages: MessageDoc[] = await supportAgent.fetchContextMessages(ctx, {
355
+ threadId, messages: [{ role, content }], contextOptions
356
+ });
357
+ ```
358
+
359
+ ### Get and update thread information
360
+
361
+ List threads for a user:
362
+
363
+ ```ts
364
+ const threads = await ctx.runQuery(components.agent.threads.listThreadsByUserId, {
365
+ userId,
366
+ order: "desc",
367
+ paginationOpts: { cursor: null, numItems: 10 }
368
+ });
369
+ ```
370
+
371
+ Get a thread by id:
372
+
373
+ ```ts
374
+ const thread = await ctx.runQuery(components.agent.threads.getThread, {
375
+ threadId,
376
+ });
377
+ ```
378
+
379
+ Update a thread's metadata:
380
+
381
+ ```ts
382
+ await ctx.runMutation(components.agent.threads.updateThread, {
383
+ threadId,
384
+ { title, summary, status }
385
+ });
386
+ ```
387
+
388
+ ## Using the Workflow component for long-lived durable workflows
389
+
390
+ The [Workflow component](https://convex.dev/components/workflow) is a great way to build long-lived, durable workflows.
391
+ It handles retries and guarantees of eventually completing, surviving server restarts, and more.
392
+ Read more about durable workflows in [this Stack post](https://stack.convex.dev/durable-workflows-and-strong-guarantees).
393
+
394
+
302
395
  ### Exposing the agent as Convex actions
303
396
 
304
397
  You can expose the agent as a Convex internal action.
@@ -358,14 +451,7 @@ export const supportAgentWorkflow = workflow.define({
358
451
 
359
452
  See another example in [example.ts](./example/convex/example.ts#L120).
360
453
 
361
- ### Fetching thread history
362
-
363
- ```ts
364
- const messages = await ctx.runQuery(
365
- components.agent.messages.getThreadMessages,
366
- { threadId }
367
- );
368
- ```
454
+ ## Extra control: how to do more things yourself
369
455
 
370
456
  ### Generating text for a user without an associated thread
371
457
 
@@ -373,26 +459,7 @@ const messages = await ctx.runQuery(
373
459
  const result = await supportAgent.generateText(ctx, { userId }, { prompt });
374
460
  ```
375
461
 
376
- ### Manually managing messages
377
-
378
- Fetch the full messages directly. These will include things like usage, etc.
379
-
380
- ```ts
381
- const messages = await ctx.runQuery(
382
- components.agent.messages.getThreadMessages,
383
- { threadId, order: "desc", paginationOpts: { cursor: null, numItems: 10 } }
384
- );
385
- ```
386
-
387
- Fetch CoreMessages (e.g. `{ role, content }`) for a user and/or thread.
388
- Accepts ContextOptions, e.g. includeToolCalls, searchOptions, etc.
389
- If you provide a parentMessageId, it will only fetch messages from before that message.
390
-
391
- ```ts
392
- const coreMessages = await supportAgent.fetchContextMessages(ctx, {
393
- threadId, messages: [{ role, content }], contextOptions
394
- });
395
- ```
462
+ ### Saving messages manually
396
463
 
397
464
  Save messages to the database.
398
465
 
@@ -468,27 +535,21 @@ See an example in
468
535
  [this demo](https://github.com/ianmacartney/ai-agent-chat/blob/main/convex/chat.ts)
469
536
  that captures usage to a table, then scans it to generate per-user invoices.
470
537
 
538
+ You can provide a `usageHandler` to the agent, per-thread, or per-message.
539
+
471
540
  ```ts
472
541
  const supportAgent = new Agent(components.agent, {
473
542
  ...
474
543
  usageHandler: async (ctx, args) => {
475
- const { userId, threadId, agentName } = args;
476
- const { model, provider, usage, providerMetadata } = args;
477
- // ... save usage to your database, etc.
478
- },
479
- });
480
- // or when creating/continuing a thread:
481
- const { thread } = await supportAgent.createThread(ctx, {
482
- ...
483
- usageHandler: async (ctx, args) => {
484
- // ...
485
- },
486
- });
487
- // or when generating text:
488
- const result = await thread.generateText({
489
- ...
490
- usageHandler: async (ctx, args) => {
491
- // ...
544
+ const {
545
+ // Who used the tokens
546
+ userId, threadId, agentName,
547
+ // What LLM was used
548
+ model, provider,
549
+ // How many tokens were used (extra info is available in providerMetadata)
550
+ usage, providerMetadata
551
+ } = args;
552
+ // ... log, save usage to your database, etc.
492
553
  },
493
554
  });
494
555
  ```