@convex-dev/agent 0.0.1-alpha.0 → 0.0.1-alpha.2

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 (70) hide show
  1. package/README.md +297 -6
  2. package/dist/commonjs/client/index.d.ts +521 -62
  3. package/dist/commonjs/client/index.d.ts.map +1 -1
  4. package/dist/commonjs/client/index.js +230 -118
  5. package/dist/commonjs/client/index.js.map +1 -1
  6. package/dist/commonjs/client/types.d.ts +3 -0
  7. package/dist/commonjs/client/types.d.ts.map +1 -1
  8. package/dist/commonjs/component/messages.d.ts +22 -17
  9. package/dist/commonjs/component/messages.d.ts.map +1 -1
  10. package/dist/commonjs/component/messages.js +107 -47
  11. package/dist/commonjs/component/messages.js.map +1 -1
  12. package/dist/commonjs/component/schema.d.ts +16 -12
  13. package/dist/commonjs/component/schema.d.ts.map +1 -1
  14. package/dist/commonjs/component/schema.js +10 -3
  15. package/dist/commonjs/component/schema.js.map +1 -1
  16. package/dist/commonjs/component/vector/index.d.ts +41 -0
  17. package/dist/commonjs/component/vector/index.d.ts.map +1 -0
  18. package/dist/commonjs/component/vector/index.js +120 -0
  19. package/dist/commonjs/component/vector/index.js.map +1 -0
  20. package/dist/commonjs/component/vector/tables.d.ts.map +1 -1
  21. package/dist/commonjs/component/vector/tables.js +4 -2
  22. package/dist/commonjs/component/vector/tables.js.map +1 -1
  23. package/dist/commonjs/mapping.d.ts +6 -1
  24. package/dist/commonjs/mapping.d.ts.map +1 -1
  25. package/dist/commonjs/mapping.js +25 -0
  26. package/dist/commonjs/mapping.js.map +1 -1
  27. package/dist/commonjs/validators.d.ts +1375 -0
  28. package/dist/commonjs/validators.d.ts.map +1 -1
  29. package/dist/commonjs/validators.js +27 -0
  30. package/dist/commonjs/validators.js.map +1 -1
  31. package/dist/esm/client/index.d.ts +521 -62
  32. package/dist/esm/client/index.d.ts.map +1 -1
  33. package/dist/esm/client/index.js +230 -118
  34. package/dist/esm/client/index.js.map +1 -1
  35. package/dist/esm/client/types.d.ts +3 -0
  36. package/dist/esm/client/types.d.ts.map +1 -1
  37. package/dist/esm/component/messages.d.ts +22 -17
  38. package/dist/esm/component/messages.d.ts.map +1 -1
  39. package/dist/esm/component/messages.js +107 -47
  40. package/dist/esm/component/messages.js.map +1 -1
  41. package/dist/esm/component/schema.d.ts +16 -12
  42. package/dist/esm/component/schema.d.ts.map +1 -1
  43. package/dist/esm/component/schema.js +10 -3
  44. package/dist/esm/component/schema.js.map +1 -1
  45. package/dist/esm/component/vector/index.d.ts +41 -0
  46. package/dist/esm/component/vector/index.d.ts.map +1 -0
  47. package/dist/esm/component/vector/index.js +120 -0
  48. package/dist/esm/component/vector/index.js.map +1 -0
  49. package/dist/esm/component/vector/tables.d.ts.map +1 -1
  50. package/dist/esm/component/vector/tables.js +4 -2
  51. package/dist/esm/component/vector/tables.js.map +1 -1
  52. package/dist/esm/mapping.d.ts +6 -1
  53. package/dist/esm/mapping.d.ts.map +1 -1
  54. package/dist/esm/mapping.js +25 -0
  55. package/dist/esm/mapping.js.map +1 -1
  56. package/dist/esm/validators.d.ts +1375 -0
  57. package/dist/esm/validators.d.ts.map +1 -1
  58. package/dist/esm/validators.js +27 -0
  59. package/dist/esm/validators.js.map +1 -1
  60. package/package.json +2 -2
  61. package/src/client/index.ts +428 -232
  62. package/src/client/types.ts +4 -0
  63. package/src/component/_generated/api.d.ts +138 -11
  64. package/src/component/messages.ts +136 -66
  65. package/src/component/schema.ts +10 -3
  66. package/src/component/vector/index.ts +144 -0
  67. package/src/component/vector/tables.ts +7 -5
  68. package/src/mapping.ts +46 -11
  69. package/src/validators.test.ts +9 -0
  70. package/src/validators.ts +32 -0
package/README.md CHANGED
@@ -4,9 +4,77 @@
4
4
 
5
5
  <!-- START: Include on https://convex.dev/components -->
6
6
 
7
- - [ ] What is some compelling syntax as a hook?
8
- - [ ] Why should you use this component?
9
- - [ ] Links to Stack / other resources?
7
+ AI Agent framework built on Convex.
8
+
9
+ - Automatic storage of chat history, per-user or per-chat.
10
+ - RAG for chat context, via hybrid text & vector search, with configuration options.
11
+ Or use the API to query the history yourself and do it your way.
12
+ - Opt-in search for messages from other chats (for the same specifieduser).
13
+ - Tool calls via the AI SDK, along with Convex-specific helpers.
14
+ - Easy workflow integration with the [Workflow component](https://convex.dev/components/workflow).
15
+ - Reactive & realtime updates to asynchronous chats.
16
+ - Support for streaming text and storing the result in the database.
17
+ - Optionally filter tool calls out of the chat history.
18
+
19
+ Example usage:
20
+
21
+ ```ts
22
+ // Define an agent similarly to the AI SDK
23
+ const supportAgent = new Agent(components.agent, {
24
+ chat: openai.chat("gpt-4o-mini"),
25
+ textEmbedding: openai.embedding("text-embedding-3-small"),
26
+ instructions: "You are a helpful assistant.",
27
+ tools: { accountLookup, fileTicket, sendEmail },
28
+ });
29
+
30
+ // Use the agent from within a normal action:
31
+ export const createChatting = action({
32
+ args: { prompt: v.string(), userId: v.string() },
33
+ handler: async (ctx, { prompt, userId }): Promise<{ chatId: string; initialResponse: string }> => {
34
+ // Start a new chat for the user.
35
+ const { chatId, chat } = await supportAgent.createChat(ctx, { userId });
36
+ const result = await chat.generateText({ prompt });
37
+ return { chatId, initialResponse: result.text };
38
+ },
39
+ });
40
+
41
+ // Pick up where you left off:
42
+ export const continueChat = action({
43
+ args: { prompt: v.string(), chatId: v.string() },
44
+ handler: async (ctx, { prompt, chatId }): Promise<string> => {
45
+ // This includes previous message history from the chat automatically.
46
+ const { chat } = await supportAgent.continueChat(ctx, { chatId });
47
+ const result = await chat.generateText({ prompt });
48
+ return result.text;
49
+ },
50
+ });
51
+
52
+ // Or use it within a workflow:
53
+ export const supportAgentStep = supportAgent.asAction({ maxSteps: 10 });
54
+
55
+ const workflow = new WorkflowManager(components.workflow);
56
+ const s = internal.example; // where steps are defined
57
+
58
+ export const supportAgentWorkflow = workflow.define({
59
+ args: { prompt: v.string(), userId: v.string(), chatId: v.string() },
60
+ handler: async (step, { prompt, userId, chatId }) => {
61
+ const suggestion = await step.runAction(s.supportAgentStep, {
62
+ chatId, generateText: { prompt },
63
+ });
64
+ const polished = await step.runAction(s.adaptSuggestionForUser, {
65
+ suggestion, userId,
66
+ });
67
+ await step.runMutation(s.sendUserMessage, { userId, message: polished.message });
68
+ },
69
+ });
70
+ ```
71
+
72
+ Also see the [Stack article](https://stack.convex.dev/ai-agent).
73
+
74
+ Coming soon:
75
+
76
+ - Generate and stream objects
77
+ - Nested agent configuration, with agents as tools to other agents.
10
78
 
11
79
  Found a bug? Feature request? [File it here](https://github.com/get-convex/agent/issues).
12
80
 
@@ -41,15 +109,238 @@ export default app;
41
109
 
42
110
  ## Usage
43
111
 
112
+ ### Configuring the agent
113
+
44
114
  ```ts
45
115
  import { components } from "./_generated/api";
46
116
  import { Agent } from "@convex-dev/agent";
47
117
 
48
- const agent = new Agent(components.agent, {
49
- ...options,
118
+ // Define an agent similarly to the AI SDK
119
+ const supportAgent = new Agent(components.agent, {
120
+ // Note: all of these are optional.
121
+ chat: openai.chat("gpt-4o-mini"),
122
+ // Used for vector search (RAG).
123
+ textEmbedding: openai.embedding("text-embedding-3-small"),
124
+ // Will be the default system prompt if not overriden.
125
+ instructions: "You are a helpful assistant.",
126
+ tools: {
127
+ // Standard AI SDK tool
128
+ myTool: tool({ description, parameters, execute: () => {}}),
129
+ // Convex tool
130
+ myConvexTool: createTool({
131
+ description: "My Convex tool",
132
+ args: v.object({...}),
133
+ handler: async (ctx, args) => {
134
+ return "Hello, world!";
135
+ },
136
+ }),
137
+ },
138
+ // Used for fetching context messages.
139
+ contextOptions: {
140
+ // Whether to include tool messages in the context.
141
+ includeToolCalls: true,
142
+ // How many recent messages to include. These are added after the search
143
+ // messages, and do not count against the search limit.
144
+ recentMessages: 10,
145
+ // Whether to search across other chats for relevant messages.
146
+ // By default, only the current chat is searched.
147
+ searchOtherChats: true,
148
+ // Options for searching messages.
149
+ searchOptions: {
150
+ // The maximum number of messages to fetch.
151
+ limit: 100,
152
+ // Whether to use text search to find messages.
153
+ textSearch: true,
154
+ // Whether to use vector search to find messages.
155
+ vectorSearch: true,
156
+ // Note, this is after the limit is applied.
157
+ // E.g. this will quadruple the number of messages fetched.
158
+ // (two before, and one after each message found in the search)
159
+ messageRange: { before: 2, after: 1 },
160
+ },
161
+ },
162
+ // Used for storing messages.
163
+ storageOptions: {
164
+ // Defaults to false, allowing you to pass in arbitrary context that will
165
+ // be in addition to automatically fetched content.
166
+ // Pass true to have all input messages saved to the chat history.
167
+ saveAllInputMessages: true,
168
+ // Defaults to true
169
+ saveOutputMessages: true,
170
+ },
171
+ // Used for limiting the number of steps when tool calls are involved.
172
+ maxSteps: 10,
173
+ // Used for limiting the number of retries when a tool call fails.
174
+ maxRetries: 3,
175
+ });
176
+ ```
177
+
178
+ ### Starting a chat
179
+
180
+ You can start a chat from either an action or a mutation.
181
+ If it's in an action, you can also start sending messages.
182
+ The chatId allows you to resume later and maintain message history.
183
+
184
+ ```ts
185
+ // Use the agent from within a normal action:
186
+ export const createChatting = action({
187
+ args: { prompt: v.string(), userId: v.string() },
188
+ handler: async (ctx, { prompt, userId }): Promise<{ chatId: string; initialResponse: string }> => {
189
+ // Start a new chat for the user.
190
+ const { chatId, chat } = await supportAgent.createChat(ctx, { userId });
191
+ const result = await chat.generateText({ prompt });
192
+ return { chatId, initialResponse: result.text };
193
+ },
194
+ });
195
+ ```
196
+
197
+ ### Continuing a chat
198
+
199
+ ```ts
200
+ // Pick up where you left off:
201
+ export const continueChat = action({
202
+ args: { prompt: v.string(), chatId: v.string() },
203
+ handler: async (ctx, { prompt, chatId }): Promise<string> => {
204
+ // This includes previous message history from the chat automatically.
205
+ const { chat } = await supportAgent.continueChat(ctx, { chatId });
206
+ const result = await chat.generateText({ prompt });
207
+ return result.text;
208
+ },
209
+ });
210
+ ```
211
+
212
+ ### Exposing the agent as a Convex action
213
+
214
+ ```ts
215
+ export const supportAgentStep = supportAgent.asAction({ maxSteps: 10 });
216
+
217
+ // Then from within another action:
218
+ export const callSupportAgent = action({
219
+ args: { prompt: v.string(), userId: v.string(), chatId: v.string() },
220
+ handler: async (step, { prompt, userId, chatId }) => {
221
+ const suggestion = await step.runAction(s.supportAgentStep, {
222
+ chatId, userId, generateText: { prompt },
223
+ });
224
+ },
225
+ });
226
+ ```
227
+
228
+ ### Using the agent within a workflow
229
+
230
+ You can use the [Workflow component](https://convex.dev/components/workflow)
231
+ to run, with retries and guarantees of eventually completing, surviving server restarts,
232
+ and more. Read more about durable workflows
233
+ [in this Stack post](https://stack.convex.dev/durable-workflows-and-strong-guarantees).
234
+
235
+ ```ts
236
+ const workflow = new WorkflowManager(components.workflow);
237
+ const s = internal.example; // where steps are defined
238
+
239
+ export const supportAgentWorkflow = workflow.define({
240
+ args: { prompt: v.string(), userId: v.string(), chatId: v.string() },
241
+ handler: async (step, { prompt, userId, chatId }) => {
242
+ const suggestion = await step.runAction(s.supportAgentStep, {
243
+ chatId,
244
+ generateText: { prompt },
245
+ });
246
+ const polished = await step.runAction(s.adaptSuggestionForUser, {
247
+ userId,
248
+ generateText: { prompt: suggestion },
249
+ });
250
+ await step.runMutation(s.sendUserMessage, { userId, message: polished.message });
251
+ },
50
252
  });
51
253
  ```
52
254
 
53
- See more example usage in [example.ts](./example/convex/example.ts).
255
+ ### Fetching chat history
256
+
257
+ ```ts
258
+ const messages = await ctx.runQuery(components.agent.messages.getChatMessages, {
259
+ chatId,
260
+ });
261
+ ```
262
+
263
+ ### Manually managing messages
264
+
265
+ ```ts
266
+ const messages = await ctx.runQuery(components.agent.messages.getChatMessages, {
267
+ chatId,
268
+ {...searchOptions}
269
+ });
270
+ ```
271
+
272
+ ```ts
273
+ const messages = await agent.saveMessages(ctx, { chatId, userId, messages });
274
+ ```
275
+
276
+ ```ts
277
+ const messages = await agent.saveSteps(ctx, { chatId, userId, step });
278
+ ```
279
+
280
+ // Update the message from pending to complete, along with any associated steps.
281
+ ```ts
282
+ const messages = await agent.completeMessage(ctx, { chatId, userId, messageId });
283
+ ```
284
+
285
+ ### Manage embeddings
286
+
287
+ ```ts
288
+ const messages = await ctx.runQuery(components.agent.embeddings.paginate, {
289
+ vectorDimension: 1536,
290
+ targetModel: "gpt-4o-mini",
291
+ cursor: null,
292
+ limit: 10,
293
+ });
294
+ ```
295
+
296
+ ```ts
297
+ const messages = await ctx.runQuery(components.agent.embeddings.deleteBatchForChat, {
298
+ vectorDimension: 1536,
299
+ targetModel: "gpt-4o-mini",
300
+ chatId: "123",
301
+ cursor: null,
302
+ limit: 10,
303
+ });
304
+ ```
305
+
306
+ ```ts
307
+ const messages = await ctx.runQuery(components.agent.embeddings.insertBatch, {
308
+ vectorDimension: 1536,
309
+ vectors: [
310
+ {
311
+ model: "gpt-4o-mini",
312
+ kind: "chat",
313
+ userId: "123",
314
+ chatId: "123",
315
+ vector: embedding,
316
+ },
317
+ ],
318
+ });
319
+ ```
320
+
321
+ ```ts
322
+ const messages = await ctx.runQuery(components.agent.embeddings.updateBatch, {
323
+ vectors: [
324
+ {
325
+ model: "gpt-4o-mini",
326
+ id: "123", // message's embeddingId
327
+ vector: embedding,
328
+ },
329
+ ],
330
+ });
331
+ ```
332
+
333
+ ```ts
334
+ const messages = await ctx.runQuery(components.agent.embeddings.deleteBatch, {
335
+ ids: ["123", "456"],
336
+ });
337
+ ```
338
+
339
+ See example usage in [example.ts](./example/convex/example.ts).
340
+ Read more in [this Stack post](https://stack.convex.dev/ai-agent).
341
+
342
+ ```sh
343
+ npm i @convex-dev/agent
344
+ ```
54
345
 
55
346
  <!-- END: Include on https://convex.dev/components -->