@convex-dev/agent 0.0.16 → 0.0.17-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.
- package/README.md +169 -98
- package/dist/commonjs/client/index.d.ts +806 -189
- package/dist/commonjs/client/index.d.ts.map +1 -1
- package/dist/commonjs/client/index.js +178 -28
- package/dist/commonjs/client/index.js.map +1 -1
- package/dist/commonjs/component/apiKeys.d.ts +11 -0
- package/dist/commonjs/component/apiKeys.d.ts.map +1 -0
- package/dist/commonjs/component/apiKeys.js +69 -0
- package/dist/commonjs/component/apiKeys.js.map +1 -0
- package/dist/commonjs/component/files.d.ts +31 -0
- package/dist/commonjs/component/files.d.ts.map +1 -0
- package/dist/commonjs/component/files.js +61 -0
- package/dist/commonjs/component/files.js.map +1 -0
- package/dist/commonjs/component/messages.d.ts +720 -676
- package/dist/commonjs/component/messages.d.ts.map +1 -1
- package/dist/commonjs/component/messages.js +99 -287
- package/dist/commonjs/component/messages.js.map +1 -1
- package/dist/commonjs/component/schema.d.ts +1124 -1324
- package/dist/commonjs/component/schema.d.ts.map +1 -1
- package/dist/commonjs/component/schema.js +26 -14
- package/dist/commonjs/component/schema.js.map +1 -1
- package/dist/commonjs/component/threads.d.ts +95 -0
- package/dist/commonjs/component/threads.d.ts.map +1 -0
- package/dist/commonjs/component/threads.js +151 -0
- package/dist/commonjs/component/threads.js.map +1 -0
- package/dist/commonjs/component/users.d.ts +37 -0
- package/dist/commonjs/component/users.d.ts.map +1 -0
- package/dist/commonjs/component/users.js +118 -0
- package/dist/commonjs/component/users.js.map +1 -0
- package/dist/commonjs/component/vector/index.d.ts.map +1 -1
- package/dist/commonjs/component/vector/index.js +4 -6
- package/dist/commonjs/component/vector/index.js.map +1 -1
- package/dist/commonjs/component/vector/tables.d.ts +10 -10
- package/dist/commonjs/component/vector/tables.d.ts.map +1 -1
- package/dist/commonjs/component/vector/tables.js.map +1 -1
- package/dist/commonjs/mapping.d.ts +7 -1
- package/dist/commonjs/mapping.d.ts.map +1 -1
- package/dist/commonjs/mapping.js +39 -18
- package/dist/commonjs/mapping.js.map +1 -1
- package/dist/commonjs/validators.d.ts +1669 -2340
- package/dist/commonjs/validators.d.ts.map +1 -1
- package/dist/commonjs/validators.js +35 -26
- package/dist/commonjs/validators.js.map +1 -1
- package/dist/esm/client/index.d.ts +806 -189
- package/dist/esm/client/index.d.ts.map +1 -1
- package/dist/esm/client/index.js +178 -28
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/component/apiKeys.d.ts +11 -0
- package/dist/esm/component/apiKeys.d.ts.map +1 -0
- package/dist/esm/component/apiKeys.js +69 -0
- package/dist/esm/component/apiKeys.js.map +1 -0
- package/dist/esm/component/files.d.ts +31 -0
- package/dist/esm/component/files.d.ts.map +1 -0
- package/dist/esm/component/files.js +61 -0
- package/dist/esm/component/files.js.map +1 -0
- package/dist/esm/component/messages.d.ts +720 -676
- package/dist/esm/component/messages.d.ts.map +1 -1
- package/dist/esm/component/messages.js +99 -287
- package/dist/esm/component/messages.js.map +1 -1
- package/dist/esm/component/schema.d.ts +1124 -1324
- package/dist/esm/component/schema.d.ts.map +1 -1
- package/dist/esm/component/schema.js +26 -14
- package/dist/esm/component/schema.js.map +1 -1
- package/dist/esm/component/threads.d.ts +95 -0
- package/dist/esm/component/threads.d.ts.map +1 -0
- package/dist/esm/component/threads.js +151 -0
- package/dist/esm/component/threads.js.map +1 -0
- package/dist/esm/component/users.d.ts +37 -0
- package/dist/esm/component/users.d.ts.map +1 -0
- package/dist/esm/component/users.js +118 -0
- package/dist/esm/component/users.js.map +1 -0
- package/dist/esm/component/vector/index.d.ts.map +1 -1
- package/dist/esm/component/vector/index.js +4 -6
- package/dist/esm/component/vector/index.js.map +1 -1
- package/dist/esm/component/vector/tables.d.ts +10 -10
- package/dist/esm/component/vector/tables.d.ts.map +1 -1
- package/dist/esm/component/vector/tables.js.map +1 -1
- package/dist/esm/mapping.d.ts +7 -1
- package/dist/esm/mapping.d.ts.map +1 -1
- package/dist/esm/mapping.js +39 -18
- package/dist/esm/mapping.js.map +1 -1
- package/dist/esm/validators.d.ts +1669 -2340
- package/dist/esm/validators.d.ts.map +1 -1
- package/dist/esm/validators.js +35 -26
- package/dist/esm/validators.js.map +1 -1
- package/package.json +1 -1
- package/src/client/index.ts +220 -59
- package/src/component/_generated/api.d.ts +601 -400
- package/src/component/apiKeys.ts +74 -0
- package/src/component/files.ts +72 -0
- package/src/component/messages.test.ts +23 -0
- package/src/component/messages.ts +127 -341
- package/src/component/schema.ts +32 -13
- package/src/component/threads.ts +184 -0
- package/src/component/users.ts +145 -0
- package/src/component/vector/index.ts +5 -6
- package/src/component/vector/tables.ts +15 -15
- package/src/mapping.ts +65 -32
- package/src/validators.ts +47 -28
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
AI Agent framework built on Convex.
|
|
8
8
|
|
|
9
9
|
- Automatic storage of chat history, per-user or per-thread, that can span multiple agents.
|
|
10
|
+
- Playground UI for testing, debugging, and development. See [playground/README.md](playground/README.md) for more.
|
|
10
11
|
- RAG for chat context, via hybrid text & vector search, with configuration options.
|
|
11
12
|
Use the API to query the history yourself and do it your way.
|
|
12
13
|
- Opt-in search for messages from other threads (for the same specified user).
|
|
@@ -111,7 +112,7 @@ export default app;
|
|
|
111
112
|
|
|
112
113
|
## Usage
|
|
113
114
|
|
|
114
|
-
###
|
|
115
|
+
### Creating the agent
|
|
115
116
|
|
|
116
117
|
```ts
|
|
117
118
|
import { tool } from "ai";
|
|
@@ -124,8 +125,6 @@ import { components } from "./_generated/api";
|
|
|
124
125
|
const supportAgent = new Agent(components.agent, {
|
|
125
126
|
// The chat completions model to use for the agent.
|
|
126
127
|
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
128
|
// The default system prompt if not overriden.
|
|
130
129
|
instructions: "You are a helpful assistant.",
|
|
131
130
|
tools: {
|
|
@@ -135,57 +134,26 @@ const supportAgent = new Agent(components.agent, {
|
|
|
135
134
|
myConvexTool: createTool({
|
|
136
135
|
description: "My Convex tool",
|
|
137
136
|
args: z.object({...}),
|
|
138
|
-
|
|
137
|
+
// Note: annotate the return type of the handler to avoid type cycles.
|
|
138
|
+
handler: async (ctx, args): Promise<string> => {
|
|
139
139
|
return "Hello, world!";
|
|
140
140
|
},
|
|
141
141
|
}),
|
|
142
142
|
},
|
|
143
|
-
//
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
-
},
|
|
143
|
+
// Embedding model to power vector search of message history (RAG).
|
|
144
|
+
textEmbedding: openai.embedding("text-embedding-3-small"),
|
|
145
|
+
// Used for fetching context messages. See [below](#configuring-the-context-of-messages)
|
|
146
|
+
contextOptions,
|
|
147
|
+
// Used for storing messages. See [below](#configuring-the-storage-of-messages)
|
|
148
|
+
storageOptions,
|
|
175
149
|
// Used for limiting the number of steps when tool calls are involved.
|
|
150
|
+
// NOTE: if you want tool calls to happen automatically with a single call,
|
|
151
|
+
// you need to set this to something greater than 1 (the default).
|
|
176
152
|
maxSteps: 1,
|
|
177
|
-
// Used for limiting the number of retries when a tool call fails.
|
|
153
|
+
// Used for limiting the number of retries when a tool call fails. Default: 3.
|
|
178
154
|
maxRetries: 3,
|
|
179
|
-
// Used for tracking token usage.
|
|
180
|
-
usageHandler: async (ctx,
|
|
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;
|
|
155
|
+
// Used for tracking token usage. See [below](#tracking-token-usage)
|
|
156
|
+
usageHandler: async (ctx, { model, usage }) => {
|
|
189
157
|
// ... log, save usage to your database, etc.
|
|
190
158
|
},
|
|
191
159
|
});
|
|
@@ -230,28 +198,87 @@ export const continueThread = action({
|
|
|
230
198
|
});
|
|
231
199
|
```
|
|
232
200
|
|
|
233
|
-
###
|
|
201
|
+
### Generating text
|
|
202
|
+
|
|
203
|
+
The arguments to `generateText` are the same as the AI SDK, except you don't
|
|
204
|
+
have to provide a model. By default it will use the agent's chat model.
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
const { thread } = await supportAgent.createThread(ctx, { userId });
|
|
208
|
+
const result = await thread.generateText({ prompt });
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Generating an object
|
|
212
|
+
|
|
213
|
+
Similar to the AI SDK, you can generate or streaman object.
|
|
214
|
+
The same arguments apply, except you don't have to provide a model.
|
|
215
|
+
It will use the agent's default chat model.
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
import { z } from "zod";
|
|
219
|
+
|
|
220
|
+
const result = await thread.generateObject({
|
|
221
|
+
prompt: "Generate a plan based on the conversation so far",
|
|
222
|
+
schema: z.object({...}),
|
|
223
|
+
});
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
### Configuring the context of messages
|
|
234
228
|
|
|
235
229
|
You can customize what history is included per-message via `contextOptions`.
|
|
236
|
-
|
|
230
|
+
These options can be provided to the Agent constructor, or per-message.
|
|
237
231
|
|
|
238
232
|
```ts
|
|
239
|
-
const result = await thread.generateText({ prompt }, {
|
|
233
|
+
const result = await thread.generateText({ prompt }, {
|
|
234
|
+
// Values shown are the defaults.
|
|
235
|
+
contextOptions: {
|
|
236
|
+
// Whether to include tool messages in the context.
|
|
237
|
+
includeToolCalls: false,
|
|
238
|
+
// How many recent messages to include. These are added after the search
|
|
239
|
+
// messages, and do not count against the search limit.
|
|
240
|
+
recentMessages: 100,
|
|
241
|
+
// Options for searching messages via text and/or vector search.
|
|
242
|
+
searchOptions: {
|
|
243
|
+
limit: 10, // The maximum number of messages to fetch.
|
|
244
|
+
textSearch: false, // Whether to use text search to find messages.
|
|
245
|
+
vectorSearch: false, // Whether to use vector search to find messages.
|
|
246
|
+
// Note, this is after the limit is applied.
|
|
247
|
+
// E.g. this will quadruple the number of messages fetched.
|
|
248
|
+
// (two before, and one after each message found in the search)
|
|
249
|
+
messageRange: { before: 2, after: 1 },
|
|
250
|
+
},
|
|
251
|
+
// Whether to search across other threads for relevant messages.
|
|
252
|
+
// By default, only the current thread is searched.
|
|
253
|
+
searchOtherThreads: false,
|
|
254
|
+
},
|
|
240
255
|
```
|
|
241
256
|
|
|
242
257
|
### Configuring the storage of messages
|
|
243
258
|
|
|
244
|
-
See the [configuring the agent](#configuring-the-agent) section for details.
|
|
245
259
|
Generally the defaults are fine, but if you want to pass in multiple messages
|
|
246
260
|
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
|
|
261
|
+
or output messages, you can pass in a `storageOptions` object, either to the
|
|
262
|
+
Agent constructor or per-message.
|
|
248
263
|
|
|
249
264
|
The usecase for passing multiple messages is if you want to include some extra
|
|
250
265
|
messages for context to the LLM, but only the last message is the user's actual
|
|
251
266
|
request. e.g. `messages = [...messagesFromRag, messageFromUser]`.
|
|
252
267
|
|
|
253
268
|
```ts
|
|
254
|
-
const result = await thread.generateText({ messages }, {
|
|
269
|
+
const result = await thread.generateText({ messages }, {
|
|
270
|
+
// The default values are shown below.
|
|
271
|
+
storageOptions: {
|
|
272
|
+
// When false, allows you to pass in arbitrary context that will
|
|
273
|
+
// be in addition to automatically fetched content.
|
|
274
|
+
// Pass true to have all input messages saved to the thread history.
|
|
275
|
+
saveAllInputMessages: false,
|
|
276
|
+
// By default it saves the input message, or the last message if multiple are provided.
|
|
277
|
+
saveAnyInputMessages: true,
|
|
278
|
+
// Save the generated messages to the thread history.
|
|
279
|
+
saveOutputMessages: true,
|
|
280
|
+
},
|
|
281
|
+
});
|
|
255
282
|
```
|
|
256
283
|
|
|
257
284
|
### Creating a tool with Convex context
|
|
@@ -299,6 +326,82 @@ Specifying tools at each layer will overwrite the defaults.
|
|
|
299
326
|
The tools will be `args.tools ?? thread.tools ?? agent.options.tools`.
|
|
300
327
|
This allows you to create tools in a context that is convenient.
|
|
301
328
|
|
|
329
|
+
### Fetching thread history
|
|
330
|
+
|
|
331
|
+
Fetch the full messages directly. These will include things like usage, etc.
|
|
332
|
+
|
|
333
|
+
```ts
|
|
334
|
+
import type { MessageDoc } from "@convex-dev/agent";
|
|
335
|
+
|
|
336
|
+
const messages: MessageDoc[] = await ctx.runQuery(
|
|
337
|
+
components.agent.messages.listMessagesByThreadId, {
|
|
338
|
+
threadId,
|
|
339
|
+
order: "desc",
|
|
340
|
+
paginationOpts: { cursor: null, numItems: 10 }
|
|
341
|
+
});
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Search for messages
|
|
345
|
+
|
|
346
|
+
This is what the agent does automatically, but it can be useful to do manually, e.g. to find custom context to include.
|
|
347
|
+
|
|
348
|
+
Fetch Messages for a user and/or thread.
|
|
349
|
+
Accepts ContextOptions, e.g. includeToolCalls, searchOptions, etc.
|
|
350
|
+
If you provide a `beforeMessageId`, it will only fetch messages from before that message.
|
|
351
|
+
|
|
352
|
+
```ts
|
|
353
|
+
import type { MessageDoc } from "@convex-dev/agent";
|
|
354
|
+
|
|
355
|
+
const messages: MessageDoc[] = await supportAgent.fetchContextMessages(ctx, {
|
|
356
|
+
threadId, messages: [{ role, content }], contextOptions
|
|
357
|
+
});
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### Get and update thread information
|
|
361
|
+
|
|
362
|
+
List threads for a user:
|
|
363
|
+
|
|
364
|
+
```ts
|
|
365
|
+
const threads = await ctx.runQuery(components.agent.threads.listThreadsByUserId, {
|
|
366
|
+
userId,
|
|
367
|
+
order: "desc",
|
|
368
|
+
paginationOpts: { cursor: null, numItems: 10 }
|
|
369
|
+
});
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Get a thread by id:
|
|
373
|
+
|
|
374
|
+
```ts
|
|
375
|
+
const thread = await ctx.runQuery(components.agent.threads.getThread, {
|
|
376
|
+
threadId,
|
|
377
|
+
});
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Update a thread's metadata:
|
|
381
|
+
|
|
382
|
+
```ts
|
|
383
|
+
await ctx.runMutation(components.agent.threads.updateThread, {
|
|
384
|
+
threadId,
|
|
385
|
+
{ title, summary, status }
|
|
386
|
+
});
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
## Using the Playground UI
|
|
390
|
+
|
|
391
|
+
The Playground UI is a simple way to test, debug, and develop with the agent.
|
|
392
|
+
- First configure it with instructions [here](./playground/README.md).
|
|
393
|
+
- Then you can use the [hosted version on GitHub pages](https://get-convex.github.io/agent/)
|
|
394
|
+
or run it locally with `npx @convex-dev/agent-playground`.
|
|
395
|
+
|
|
396
|
+
[Playground UI Screenshot](./playground/screenshot.png)
|
|
397
|
+
|
|
398
|
+
## Using the Workflow component for long-lived durable workflows
|
|
399
|
+
|
|
400
|
+
The [Workflow component](https://convex.dev/components/workflow) is a great way to build long-lived, durable workflows.
|
|
401
|
+
It handles retries and guarantees of eventually completing, surviving server restarts, and more.
|
|
402
|
+
Read more about durable workflows in [this Stack post](https://stack.convex.dev/durable-workflows-and-strong-guarantees).
|
|
403
|
+
|
|
404
|
+
|
|
302
405
|
### Exposing the agent as Convex actions
|
|
303
406
|
|
|
304
407
|
You can expose the agent as a Convex internal action.
|
|
@@ -358,14 +461,7 @@ export const supportAgentWorkflow = workflow.define({
|
|
|
358
461
|
|
|
359
462
|
See another example in [example.ts](./example/convex/example.ts#L120).
|
|
360
463
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
```ts
|
|
364
|
-
const messages = await ctx.runQuery(
|
|
365
|
-
components.agent.messages.getThreadMessages,
|
|
366
|
-
{ threadId }
|
|
367
|
-
);
|
|
368
|
-
```
|
|
464
|
+
## Extra control: how to do more things yourself
|
|
369
465
|
|
|
370
466
|
### Generating text for a user without an associated thread
|
|
371
467
|
|
|
@@ -373,26 +469,7 @@ const messages = await ctx.runQuery(
|
|
|
373
469
|
const result = await supportAgent.generateText(ctx, { userId }, { prompt });
|
|
374
470
|
```
|
|
375
471
|
|
|
376
|
-
###
|
|
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
|
-
```
|
|
472
|
+
### Saving messages manually
|
|
396
473
|
|
|
397
474
|
Save messages to the database.
|
|
398
475
|
|
|
@@ -468,27 +545,21 @@ See an example in
|
|
|
468
545
|
[this demo](https://github.com/ianmacartney/ai-agent-chat/blob/main/convex/chat.ts)
|
|
469
546
|
that captures usage to a table, then scans it to generate per-user invoices.
|
|
470
547
|
|
|
548
|
+
You can provide a `usageHandler` to the agent, per-thread, or per-message.
|
|
549
|
+
|
|
471
550
|
```ts
|
|
472
551
|
const supportAgent = new Agent(components.agent, {
|
|
473
552
|
...
|
|
474
553
|
usageHandler: async (ctx, args) => {
|
|
475
|
-
const {
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
//
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
// ...
|
|
485
|
-
},
|
|
486
|
-
});
|
|
487
|
-
// or when generating text:
|
|
488
|
-
const result = await thread.generateText({
|
|
489
|
-
...
|
|
490
|
-
usageHandler: async (ctx, args) => {
|
|
491
|
-
// ...
|
|
554
|
+
const {
|
|
555
|
+
// Who used the tokens
|
|
556
|
+
userId, threadId, agentName,
|
|
557
|
+
// What LLM was used
|
|
558
|
+
model, provider,
|
|
559
|
+
// How many tokens were used (extra info is available in providerMetadata)
|
|
560
|
+
usage, providerMetadata
|
|
561
|
+
} = args;
|
|
562
|
+
// ... log, save usage to your database, etc.
|
|
492
563
|
},
|
|
493
564
|
});
|
|
494
565
|
```
|