@rudderjs/ai 1.17.3 → 1.18.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.
- package/README.md +19 -1274
- package/dist/budget-orm/index.d.ts +1 -95
- package/dist/budget-orm/index.d.ts.map +1 -1
- package/dist/budget-orm/index.js +4 -176
- package/dist/budget-orm/index.js.map +1 -1
- package/dist/chat-mentions.d.ts +1 -58
- package/dist/chat-mentions.d.ts.map +1 -1
- package/dist/chat-mentions.js +4 -80
- package/dist/chat-mentions.js.map +1 -1
- package/dist/commands/ai-eval.d.ts +1 -92
- package/dist/commands/ai-eval.d.ts.map +1 -1
- package/dist/commands/ai-eval.js +4 -377
- package/dist/commands/ai-eval.js.map +1 -1
- package/dist/commands/make-agent.d.ts +1 -2
- package/dist/commands/make-agent.d.ts.map +1 -1
- package/dist/commands/make-agent.js +4 -22
- package/dist/commands/make-agent.js.map +1 -1
- package/dist/computer-use/index.d.ts +1 -52
- package/dist/computer-use/index.d.ts.map +1 -1
- package/dist/computer-use/index.js +4 -50
- package/dist/computer-use/index.js.map +1 -1
- package/dist/conversation-orm/index.d.ts +1 -108
- package/dist/conversation-orm/index.d.ts.map +1 -1
- package/dist/conversation-orm/index.js +4 -214
- package/dist/conversation-orm/index.js.map +1 -1
- package/dist/doctor.d.ts +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +4 -65
- package/dist/doctor.js.map +1 -1
- package/dist/eval/index.d.ts +1 -270
- package/dist/eval/index.d.ts.map +1 -1
- package/dist/eval/index.js +4 -509
- package/dist/eval/index.js.map +1 -1
- package/dist/gateway/index.d.ts +1 -10
- package/dist/gateway/index.d.ts.map +1 -1
- package/dist/gateway/index.js +4 -10
- package/dist/gateway/index.js.map +1 -1
- package/dist/index.d.ts +1 -66
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -78
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.d.ts +1 -15
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +4 -14
- package/dist/mcp/index.js.map +1 -1
- package/dist/memory-embedding/index.d.ts +1 -120
- package/dist/memory-embedding/index.d.ts.map +1 -1
- package/dist/memory-embedding/index.js +4 -228
- package/dist/memory-embedding/index.js.map +1 -1
- package/dist/memory-orm/index.d.ts +1 -117
- package/dist/memory-orm/index.d.ts.map +1 -1
- package/dist/memory-orm/index.js +4 -186
- package/dist/memory-orm/index.js.map +1 -1
- package/dist/node/index.d.ts +1 -2
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +4 -2
- package/dist/node/index.js.map +1 -1
- package/dist/observers.d.ts +1 -129
- package/dist/observers.d.ts.map +1 -1
- package/dist/observers.js +4 -39
- package/dist/observers.js.map +1 -1
- package/dist/react/index.d.ts +1 -15
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +4 -15
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +4 -1
- package/dist/server/index.js.map +1 -1
- package/package.json +9 -13
- package/boost/guidelines.md +0 -260
- package/boost/skills/ai-agents/SKILL.md +0 -240
- package/boost/skills/ai-tools/SKILL.md +0 -260
- package/dist/agent-run-store.d.ts +0 -161
- package/dist/agent-run-store.d.ts.map +0 -1
- package/dist/agent-run-store.js +0 -98
- package/dist/agent-run-store.js.map +0 -1
- package/dist/agent-sse.d.ts +0 -153
- package/dist/agent-sse.d.ts.map +0 -1
- package/dist/agent-sse.js +0 -282
- package/dist/agent-sse.js.map +0 -1
- package/dist/agent.d.ts +0 -508
- package/dist/agent.d.ts.map +0 -1
- package/dist/agent.js +0 -1538
- package/dist/agent.js.map +0 -1
- package/dist/attachment.d.ts +0 -31
- package/dist/attachment.d.ts.map +0 -1
- package/dist/attachment.js +0 -89
- package/dist/attachment.js.map +0 -1
- package/dist/audio.d.ts +0 -45
- package/dist/audio.d.ts.map +0 -1
- package/dist/audio.js +0 -93
- package/dist/audio.js.map +0 -1
- package/dist/base64.d.ts +0 -7
- package/dist/base64.d.ts.map +0 -1
- package/dist/base64.js +0 -39
- package/dist/base64.js.map +0 -1
- package/dist/budget/pricing.d.ts +0 -124
- package/dist/budget/pricing.d.ts.map +0 -1
- package/dist/budget/pricing.js +0 -175
- package/dist/budget/pricing.js.map +0 -1
- package/dist/budget/storage.d.ts +0 -104
- package/dist/budget/storage.d.ts.map +0 -1
- package/dist/budget/storage.js +0 -0
- package/dist/budget/storage.js.map +0 -1
- package/dist/budget/with-budget.d.ts +0 -119
- package/dist/budget/with-budget.d.ts.map +0 -1
- package/dist/budget/with-budget.js +0 -175
- package/dist/budget/with-budget.js.map +0 -1
- package/dist/cached-embedding.d.ts +0 -14
- package/dist/cached-embedding.d.ts.map +0 -1
- package/dist/cached-embedding.js +0 -44
- package/dist/cached-embedding.js.map +0 -1
- package/dist/computer-use/actions.d.ts +0 -214
- package/dist/computer-use/actions.d.ts.map +0 -1
- package/dist/computer-use/actions.js +0 -48
- package/dist/computer-use/actions.js.map +0 -1
- package/dist/computer-use/errors.d.ts +0 -57
- package/dist/computer-use/errors.d.ts.map +0 -1
- package/dist/computer-use/errors.js +0 -76
- package/dist/computer-use/errors.js.map +0 -1
- package/dist/computer-use/playwright.d.ts +0 -76
- package/dist/computer-use/playwright.d.ts.map +0 -1
- package/dist/computer-use/playwright.js +0 -270
- package/dist/computer-use/playwright.js.map +0 -1
- package/dist/computer-use/tool.d.ts +0 -154
- package/dist/computer-use/tool.d.ts.map +0 -1
- package/dist/computer-use/tool.js +0 -210
- package/dist/computer-use/tool.js.map +0 -1
- package/dist/continuation-validation.d.ts +0 -85
- package/dist/continuation-validation.d.ts.map +0 -1
- package/dist/continuation-validation.js +0 -166
- package/dist/continuation-validation.js.map +0 -1
- package/dist/conversation-persistence.d.ts +0 -46
- package/dist/conversation-persistence.d.ts.map +0 -1
- package/dist/conversation-persistence.js +0 -176
- package/dist/conversation-persistence.js.map +0 -1
- package/dist/conversation.d.ts +0 -11
- package/dist/conversation.d.ts.map +0 -1
- package/dist/conversation.js +0 -55
- package/dist/conversation.js.map +0 -1
- package/dist/eval/fixtures.d.ts +0 -65
- package/dist/eval/fixtures.d.ts.map +0 -1
- package/dist/eval/fixtures.js +0 -110
- package/dist/eval/fixtures.js.map +0 -1
- package/dist/eval/html-reporter.d.ts +0 -25
- package/dist/eval/html-reporter.d.ts.map +0 -1
- package/dist/eval/html-reporter.js +0 -209
- package/dist/eval/html-reporter.js.map +0 -1
- package/dist/eval/json-reporter.d.ts +0 -43
- package/dist/eval/json-reporter.d.ts.map +0 -1
- package/dist/eval/json-reporter.js +0 -40
- package/dist/eval/json-reporter.js.map +0 -1
- package/dist/facade.d.ts +0 -96
- package/dist/facade.d.ts.map +0 -1
- package/dist/facade.js +0 -146
- package/dist/facade.js.map +0 -1
- package/dist/fake.d.ts +0 -201
- package/dist/fake.d.ts.map +0 -1
- package/dist/fake.js +0 -428
- package/dist/fake.js.map +0 -1
- package/dist/file-search.d.ts +0 -168
- package/dist/file-search.d.ts.map +0 -1
- package/dist/file-search.js +0 -158
- package/dist/file-search.js.map +0 -1
- package/dist/files.d.ts +0 -27
- package/dist/files.d.ts.map +0 -1
- package/dist/files.js +0 -44
- package/dist/files.js.map +0 -1
- package/dist/gateway/http-gateway-adapter.d.ts +0 -94
- package/dist/gateway/http-gateway-adapter.d.ts.map +0 -1
- package/dist/gateway/http-gateway-adapter.js +0 -106
- package/dist/gateway/http-gateway-adapter.js.map +0 -1
- package/dist/gateway/sse.d.ts +0 -28
- package/dist/gateway/sse.d.ts.map +0 -1
- package/dist/gateway/sse.js +0 -78
- package/dist/gateway/sse.js.map +0 -1
- package/dist/handoff.d.ts +0 -95
- package/dist/handoff.d.ts.map +0 -1
- package/dist/handoff.js +0 -78
- package/dist/handoff.js.map +0 -1
- package/dist/handoffs-driver.d.ts +0 -58
- package/dist/handoffs-driver.d.ts.map +0 -1
- package/dist/handoffs-driver.js +0 -103
- package/dist/handoffs-driver.js.map +0 -1
- package/dist/image.d.ts +0 -40
- package/dist/image.d.ts.map +0 -1
- package/dist/image.js +0 -109
- package/dist/image.js.map +0 -1
- package/dist/mcp/client-tools.d.ts +0 -39
- package/dist/mcp/client-tools.d.ts.map +0 -1
- package/dist/mcp/client-tools.js +0 -147
- package/dist/mcp/client-tools.js.map +0 -1
- package/dist/mcp/server-from-agent.d.ts +0 -24
- package/dist/mcp/server-from-agent.d.ts.map +0 -1
- package/dist/mcp/server-from-agent.js +0 -113
- package/dist/mcp/server-from-agent.js.map +0 -1
- package/dist/mcp/types.d.ts +0 -64
- package/dist/mcp/types.d.ts.map +0 -1
- package/dist/mcp/types.js +0 -6
- package/dist/mcp/types.js.map +0 -1
- package/dist/memory-extract.d.ts +0 -60
- package/dist/memory-extract.d.ts.map +0 -1
- package/dist/memory-extract.js +0 -163
- package/dist/memory-extract.js.map +0 -1
- package/dist/memory-inject.d.ts +0 -39
- package/dist/memory-inject.d.ts.map +0 -1
- package/dist/memory-inject.js +0 -135
- package/dist/memory-inject.js.map +0 -1
- package/dist/memory.d.ts +0 -55
- package/dist/memory.d.ts.map +0 -1
- package/dist/memory.js +0 -132
- package/dist/memory.js.map +0 -1
- package/dist/middleware.d.ts +0 -18
- package/dist/middleware.d.ts.map +0 -1
- package/dist/middleware.js +0 -72
- package/dist/middleware.js.map +0 -1
- package/dist/node/attachment.d.ts +0 -6
- package/dist/node/attachment.d.ts.map +0 -1
- package/dist/node/attachment.js +0 -35
- package/dist/node/attachment.js.map +0 -1
- package/dist/node/transcription.d.ts +0 -4
- package/dist/node/transcription.d.ts.map +0 -1
- package/dist/node/transcription.js +0 -8
- package/dist/node/transcription.js.map +0 -1
- package/dist/output.d.ts +0 -22
- package/dist/output.d.ts.map +0 -1
- package/dist/output.js +0 -60
- package/dist/output.js.map +0 -1
- package/dist/provider-tools.d.ts +0 -87
- package/dist/provider-tools.d.ts.map +0 -1
- package/dist/provider-tools.js +0 -189
- package/dist/provider-tools.js.map +0 -1
- package/dist/providers/anthropic.d.ts +0 -24
- package/dist/providers/anthropic.d.ts.map +0 -1
- package/dist/providers/anthropic.js +0 -405
- package/dist/providers/anthropic.js.map +0 -1
- package/dist/providers/azure.d.ts +0 -13
- package/dist/providers/azure.d.ts.map +0 -1
- package/dist/providers/azure.js +0 -15
- package/dist/providers/azure.js.map +0 -1
- package/dist/providers/bedrock.d.ts +0 -75
- package/dist/providers/bedrock.d.ts.map +0 -1
- package/dist/providers/bedrock.js +0 -181
- package/dist/providers/bedrock.js.map +0 -1
- package/dist/providers/cohere.d.ts +0 -13
- package/dist/providers/cohere.d.ts.map +0 -1
- package/dist/providers/cohere.js +0 -87
- package/dist/providers/cohere.js.map +0 -1
- package/dist/providers/deepseek.d.ts +0 -12
- package/dist/providers/deepseek.d.ts.map +0 -1
- package/dist/providers/deepseek.js +0 -15
- package/dist/providers/deepseek.js.map +0 -1
- package/dist/providers/elevenlabs.d.ts +0 -98
- package/dist/providers/elevenlabs.d.ts.map +0 -1
- package/dist/providers/elevenlabs.js +0 -229
- package/dist/providers/elevenlabs.js.map +0 -1
- package/dist/providers/google-cache-registry.d.ts +0 -132
- package/dist/providers/google-cache-registry.d.ts.map +0 -1
- package/dist/providers/google-cache-registry.js +0 -209
- package/dist/providers/google-cache-registry.js.map +0 -1
- package/dist/providers/google.d.ts +0 -38
- package/dist/providers/google.d.ts.map +0 -1
- package/dist/providers/google.js +0 -903
- package/dist/providers/google.js.map +0 -1
- package/dist/providers/groq.d.ts +0 -12
- package/dist/providers/groq.d.ts.map +0 -1
- package/dist/providers/groq.js +0 -15
- package/dist/providers/groq.js.map +0 -1
- package/dist/providers/jina.d.ts +0 -13
- package/dist/providers/jina.d.ts.map +0 -1
- package/dist/providers/jina.js +0 -90
- package/dist/providers/jina.js.map +0 -1
- package/dist/providers/mistral.d.ts +0 -13
- package/dist/providers/mistral.d.ts.map +0 -1
- package/dist/providers/mistral.js +0 -46
- package/dist/providers/mistral.js.map +0 -1
- package/dist/providers/ollama.d.ts +0 -11
- package/dist/providers/ollama.d.ts.map +0 -1
- package/dist/providers/ollama.js +0 -15
- package/dist/providers/ollama.js.map +0 -1
- package/dist/providers/openai.d.ts +0 -79
- package/dist/providers/openai.d.ts.map +0 -1
- package/dist/providers/openai.js +0 -792
- package/dist/providers/openai.js.map +0 -1
- package/dist/providers/openrouter.d.ts +0 -43
- package/dist/providers/openrouter.d.ts.map +0 -1
- package/dist/providers/openrouter.js +0 -21
- package/dist/providers/openrouter.js.map +0 -1
- package/dist/providers/voyage.d.ts +0 -91
- package/dist/providers/voyage.d.ts.map +0 -1
- package/dist/providers/voyage.js +0 -166
- package/dist/providers/voyage.js.map +0 -1
- package/dist/providers/xai.d.ts +0 -12
- package/dist/providers/xai.d.ts.map +0 -1
- package/dist/providers/xai.js +0 -15
- package/dist/providers/xai.js.map +0 -1
- package/dist/queue-job.d.ts +0 -100
- package/dist/queue-job.d.ts.map +0 -1
- package/dist/queue-job.js +0 -185
- package/dist/queue-job.js.map +0 -1
- package/dist/react/agent-run.d.ts +0 -111
- package/dist/react/agent-run.d.ts.map +0 -1
- package/dist/react/agent-run.js +0 -107
- package/dist/react/agent-run.js.map +0 -1
- package/dist/react/useAgentRun.d.ts +0 -68
- package/dist/react/useAgentRun.d.ts.map +0 -1
- package/dist/react/useAgentRun.js +0 -125
- package/dist/react/useAgentRun.js.map +0 -1
- package/dist/registry.d.ts +0 -45
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js +0 -131
- package/dist/registry.js.map +0 -1
- package/dist/rerank.d.ts +0 -20
- package/dist/rerank.d.ts.map +0 -1
- package/dist/rerank.js +0 -40
- package/dist/rerank.js.map +0 -1
- package/dist/resume-approval.d.ts +0 -30
- package/dist/resume-approval.d.ts.map +0 -1
- package/dist/resume-approval.js +0 -147
- package/dist/resume-approval.js.map +0 -1
- package/dist/sanitize-conversation.d.ts +0 -43
- package/dist/sanitize-conversation.d.ts.map +0 -1
- package/dist/sanitize-conversation.js +0 -85
- package/dist/sanitize-conversation.js.map +0 -1
- package/dist/scoped-tool.d.ts +0 -98
- package/dist/scoped-tool.d.ts.map +0 -1
- package/dist/scoped-tool.js +0 -174
- package/dist/scoped-tool.js.map +0 -1
- package/dist/server/provider.d.ts +0 -22
- package/dist/server/provider.d.ts.map +0 -1
- package/dist/server/provider.js +0 -194
- package/dist/server/provider.js.map +0 -1
- package/dist/similarity-search.d.ts +0 -163
- package/dist/similarity-search.d.ts.map +0 -1
- package/dist/similarity-search.js +0 -147
- package/dist/similarity-search.js.map +0 -1
- package/dist/sub-agent-run-store.d.ts +0 -157
- package/dist/sub-agent-run-store.d.ts.map +0 -1
- package/dist/sub-agent-run-store.js +0 -87
- package/dist/sub-agent-run-store.js.map +0 -1
- package/dist/tool-execution.d.ts +0 -16
- package/dist/tool-execution.d.ts.map +0 -1
- package/dist/tool-execution.js +0 -498
- package/dist/tool-execution.js.map +0 -1
- package/dist/tool-helpers.d.ts +0 -77
- package/dist/tool-helpers.d.ts.map +0 -1
- package/dist/tool-helpers.js +0 -117
- package/dist/tool-helpers.js.map +0 -1
- package/dist/tool.d.ts +0 -216
- package/dist/tool.d.ts.map +0 -1
- package/dist/tool.js +0 -175
- package/dist/tool.js.map +0 -1
- package/dist/transcription.d.ts +0 -42
- package/dist/transcription.d.ts.map +0 -1
- package/dist/transcription.js +0 -77
- package/dist/transcription.js.map +0 -1
- package/dist/types.d.ts +0 -1020
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/util/hash.d.ts +0 -11
- package/dist/util/hash.d.ts.map +0 -1
- package/dist/util/hash.js +0 -23
- package/dist/util/hash.js.map +0 -1
- package/dist/vector-stores/index.d.ts +0 -96
- package/dist/vector-stores/index.d.ts.map +0 -1
- package/dist/vector-stores/index.js +0 -153
- package/dist/vector-stores/index.js.map +0 -1
- package/dist/vercel-protocol.d.ts +0 -18
- package/dist/vercel-protocol.d.ts.map +0 -1
- package/dist/vercel-protocol.js +0 -75
- package/dist/vercel-protocol.js.map +0 -1
- package/dist/zod-to-json-schema.d.ts +0 -16
- package/dist/zod-to-json-schema.d.ts.map +0 -1
- package/dist/zod-to-json-schema.js +0 -17
- package/dist/zod-to-json-schema.js.map +0 -1
package/boost/guidelines.md
DELETED
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
# @rudderjs/ai
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
AI engine for Rudder providing a provider-agnostic agent framework with tool calling, streaming, middleware, attachments, conversation persistence, structured output, and queued execution. Supports Anthropic, OpenAI, Google, Ollama, DeepSeek, xAI, Groq, Mistral, and Azure OpenAI out of the box. Models are addressed via `provider/model` strings (e.g. `anthropic/claude-sonnet-4-5`), and the `AiRegistry` handles provider resolution and failover.
|
|
6
|
-
|
|
7
|
-
## Key Patterns
|
|
8
|
-
|
|
9
|
-
### Creating Agents
|
|
10
|
-
|
|
11
|
-
Extend the `Agent` class for reusable agents, or use `agent()` for inline one-offs:
|
|
12
|
-
|
|
13
|
-
```ts
|
|
14
|
-
class SearchAgent extends Agent implements HasTools, HasMiddleware {
|
|
15
|
-
instructions() { return 'You are a search assistant.' }
|
|
16
|
-
model() { return 'anthropic/claude-sonnet-4-5' }
|
|
17
|
-
tools() { return [searchTool] }
|
|
18
|
-
middleware() { return [loggingMiddleware] }
|
|
19
|
-
}
|
|
20
|
-
const response = await new SearchAgent().prompt('Find users named John')
|
|
21
|
-
|
|
22
|
-
// Inline agents
|
|
23
|
-
await agent({ instructions: 'You are helpful.', tools: [weatherTool] }).prompt('Hello')
|
|
24
|
-
await agent('You are helpful.').prompt('Hello') // simplest form
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
### Using Providers (Anthropic, OpenAI, Google, etc.)
|
|
28
|
-
|
|
29
|
-
Configure providers in `config/ai.ts`. The Node-only `AiProvider` lives at `@rudderjs/ai/server` (the main `@rudderjs/ai` entry is runtime-agnostic and has no provider class):
|
|
30
|
-
|
|
31
|
-
```ts
|
|
32
|
-
// config/ai.ts — providers: anthropic, openai, google, ollama, deepseek, xai, groq, mistral, azure, openrouter, bedrock
|
|
33
|
-
import type { AiConfig } from '@rudderjs/ai'
|
|
34
|
-
|
|
35
|
-
export default {
|
|
36
|
-
default: 'anthropic/claude-sonnet-4-5',
|
|
37
|
-
providers: {
|
|
38
|
-
anthropic: { apiKey: process.env.ANTHROPIC_API_KEY },
|
|
39
|
-
openai: { apiKey: process.env.OPENAI_API_KEY },
|
|
40
|
-
ollama: { driver: 'ollama', baseUrl: 'http://localhost:11434' },
|
|
41
|
-
},
|
|
42
|
-
} satisfies AiConfig
|
|
43
|
-
|
|
44
|
-
// bootstrap/providers.ts
|
|
45
|
-
import { AiProvider } from '@rudderjs/ai/server'
|
|
46
|
-
export default [AiProvider]
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
Provider auto-discovery (`defaultProviders()`) finds `AiProvider` automatically via the `rudderjs.providerSubpath` field in `@rudderjs/ai/package.json` — no manual subpath import needed when using auto-discovery.
|
|
50
|
-
|
|
51
|
-
Agents support failover: `failover() { return ['openai/gpt-4o'] }`. The same pattern is on the media generators: `ImageGenerator.of('...').model('openai/dall-e-3').failover('google/imagen-3').generate()` (also `AudioGenerator`, `Transcription`).
|
|
52
|
-
|
|
53
|
-
**Prompt caching.** Mark stable parts of the prompt as cacheable — providers translate to native primitives (Anthropic `cache_control`, OpenAI `prompt_cache_key`, Google `cachedContent`).
|
|
54
|
-
|
|
55
|
-
```ts
|
|
56
|
-
class SupportAgent extends Agent {
|
|
57
|
-
cacheable() { return { instructions: true, tools: true, messages: 2 } }
|
|
58
|
-
// ^ cache first 2 messages
|
|
59
|
-
}
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
Per-call override: `agent.prompt(input, { cache: false })` to disable; `{ cache: {...} }` to replace. All three big providers (Anthropic, OpenAI, Google) are wired up. The `ttl` field is Google-only and defaults to `'1h'`; Anthropic and OpenAI ignore it.
|
|
63
|
-
|
|
64
|
-
### Tools
|
|
65
|
-
|
|
66
|
-
Define tools with Zod schemas. Tools are either `server` (executed on backend) or `client` (forwarded to frontend):
|
|
67
|
-
|
|
68
|
-
```ts
|
|
69
|
-
const weatherTool = toolDefinition({
|
|
70
|
-
name: 'get_weather',
|
|
71
|
-
description: 'Get weather for a location',
|
|
72
|
-
inputSchema: z.object({ location: z.string() }),
|
|
73
|
-
}).server(async ({ location }) => ({ temp: 72, unit: 'F', location }))
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### Subagents (`agent.asTool()`)
|
|
77
|
-
|
|
78
|
-
Wrap one agent as a tool another agent can call. Defaults: `inputSchema = { prompt: string }`, `modelOutput = response.text`. Pass `inputSchema` + `prompt` for a typed schema.
|
|
79
|
-
|
|
80
|
-
```ts
|
|
81
|
-
class Planner extends Agent implements HasTools {
|
|
82
|
-
instructions() { return 'You break work into steps. Use `research` for facts.' }
|
|
83
|
-
tools() {
|
|
84
|
-
return [
|
|
85
|
-
new ResearchAgent().asTool({
|
|
86
|
-
name: 'research',
|
|
87
|
-
description: 'Research a topic in depth.',
|
|
88
|
-
}),
|
|
89
|
-
]
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
By default the subagent runs via `prompt()` (non-streaming). Pass `streaming: true` to surface inner progress as `tool-update` chunks (default projection emits `agent_start` / `tool_call` / `agent_done`, plus `agent_pending_approval` for inner approval gates); pass `(chunk) => SubAgentUpdate | null` for a custom projector. To propagate inner pauses upward through the parent loop, also pass `suspendable: { runStore }` (suspend without streaming throws at builder time) — `asTool` handles BOTH client-tool pauses AND approval pauses symmetrically, persisting a snapshot with a `pauseKind: 'client_tool' | 'approval'` discriminator. The host's continuation calls `Agent.resumeAsTool(subRunId, results, { runStore, agent })` for client-tool resumes, or `Agent.resumeAsTool(subRunId, [], { runStore, agent, approvedToolCallIds: [...] })` (or `rejectedToolCallIds`) for approval resumes. The returned `'paused'` variant carries `pauseKind` so the host can route the next round-trip correctly. `InMemorySubAgentRunStore` works for tests; `CachedSubAgentRunStore` plugs into `@rudderjs/cache` for multi-worker persistence.
|
|
95
|
-
|
|
96
|
-
### Middleware
|
|
97
|
-
|
|
98
|
-
Middleware hooks into the agent loop lifecycle. Hooks: `onConfig`, `onStart`, `onIteration`, `onChunk`, `onBeforeToolCall`, `onAfterToolCall`, `onToolPhaseComplete`, `onUsage`, `onAbort`, `onError`, `onFinish`.
|
|
99
|
-
|
|
100
|
-
```ts
|
|
101
|
-
const loggingMiddleware: AiMiddleware = {
|
|
102
|
-
onStart(ctx) { console.log(`[AI] Request ${ctx.requestId} started`) },
|
|
103
|
-
onUsage(ctx, usage) { console.log(`[AI] Tokens: ${usage.totalTokens}`) },
|
|
104
|
-
onBeforeToolCall(ctx, toolName, args) {
|
|
105
|
-
if (toolName === 'dangerous_tool') return { type: 'skip', result: 'Tool disabled' }
|
|
106
|
-
return undefined // continue normally
|
|
107
|
-
},
|
|
108
|
-
onChunk(ctx, chunk) { return chunk }, // transform or return null to drop
|
|
109
|
-
}
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### Attachments
|
|
113
|
-
|
|
114
|
-
Send images and documents alongside prompts. The main entry has runtime-agnostic factories (`fromBase64`, `fromUrl`, `fromString`); for path-based loading import from `@rudderjs/ai/node`:
|
|
115
|
-
|
|
116
|
-
```ts
|
|
117
|
-
import { Image, Document } from '@rudderjs/ai'
|
|
118
|
-
import { imageFromPath } from '@rudderjs/ai/node'
|
|
119
|
-
|
|
120
|
-
const img = await imageFromPath('./screenshot.png') // Node-only
|
|
121
|
-
const doc = await Document.fromUrl('https://example.com/report.pdf')
|
|
122
|
-
|
|
123
|
-
await myAgent.prompt('Describe this image and summarize the doc', {
|
|
124
|
-
attachments: [img.toAttachment(), doc.toAttachment()],
|
|
125
|
-
})
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### Conversations
|
|
129
|
-
|
|
130
|
-
Persist multi-turn conversations with `ConversationStore`. Register via `setConversationStore()` or pass `conversations` in AI config:
|
|
131
|
-
|
|
132
|
-
```ts
|
|
133
|
-
setConversationStore(new MemoryConversationStore())
|
|
134
|
-
const response = await myAgent.forUser('user-123').prompt('Hello') // creates conversation
|
|
135
|
-
const follow = await myAgent.continue(response.conversationId).prompt('Follow up')
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
For chat agents that should always auto-persist for the active user, override `conversational()` on the class — `agent.prompt(input)` then auto-loads + auto-saves without each caller passing the user id:
|
|
139
|
-
|
|
140
|
-
```ts
|
|
141
|
-
class ChatAgent extends Agent {
|
|
142
|
-
conversational() { return { user: Auth.user()?.id } } // null user → opt-out
|
|
143
|
-
}
|
|
144
|
-
await new ChatAgent().prompt('Hi') // auto-loads thread
|
|
145
|
-
await new ChatAgent().prompt('still you?') // resumes per (user, class)
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
Returning `false` (default) keeps the agent stateless. Optional `historyLimit: N` caps loaded messages. Per-call `{ conversation: false }` opts out; `forUser`/`continue` always win.
|
|
149
|
-
|
|
150
|
-
### Streaming
|
|
151
|
-
|
|
152
|
-
Use `.stream()` for real-time token delivery:
|
|
153
|
-
|
|
154
|
-
```ts
|
|
155
|
-
const { stream, response } = myAgent.stream('Write a story')
|
|
156
|
-
|
|
157
|
-
for await (const chunk of stream) {
|
|
158
|
-
if (chunk.type === 'text-delta') process.stdout.write(chunk.text ?? '')
|
|
159
|
-
if (chunk.type === 'tool-call') console.log('Tool called:', chunk.toolCall)
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const final = await response // full AgentResponse after stream ends
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
### MCP integration (`@rudderjs/ai/mcp`)
|
|
166
|
-
|
|
167
|
-
Bridge agents and Model Context Protocol servers in both directions. Optional peer: `@modelcontextprotocol/sdk`.
|
|
168
|
-
|
|
169
|
-
**Consume MCP tools in an agent:**
|
|
170
|
-
|
|
171
|
-
```ts
|
|
172
|
-
import { mcpClientTools } from '@rudderjs/ai/mcp'
|
|
173
|
-
|
|
174
|
-
const tools = await mcpClientTools('https://api.example.com/mcp')
|
|
175
|
-
// or: await mcpClientTools({ command: 'npx', args: ['some-mcp-server'] })
|
|
176
|
-
|
|
177
|
-
class ResearchAgent extends Agent {
|
|
178
|
-
instructions() { return 'You can call remote MCP tools.' }
|
|
179
|
-
tools() { return tools }
|
|
180
|
-
}
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
**Expose an agent as an MCP server** (callable from Claude Desktop, Cursor, etc.):
|
|
184
|
-
|
|
185
|
-
```ts
|
|
186
|
-
import { mcpServerFromAgent } from '@rudderjs/ai/mcp'
|
|
187
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
188
|
-
|
|
189
|
-
// Default: each agent.tools() entry becomes an MCP tool
|
|
190
|
-
const server = await mcpServerFromAgent(MyAgent)
|
|
191
|
-
|
|
192
|
-
// Or expose the whole agent as one prompt-tool
|
|
193
|
-
const promptServer = await mcpServerFromAgent(MyAgent, { expose: 'agent' })
|
|
194
|
-
|
|
195
|
-
await server.connect(new StdioServerTransport())
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
When mcpClientTools owns the underlying client (URL or stdio transport), the returned array exposes `close()` for shutdown — call it when the agent is done. With a caller-provided client, lifecycle stays with the caller.
|
|
199
|
-
|
|
200
|
-
### Queued prompts + live broadcast (`agent.queue().broadcast()`)
|
|
201
|
-
|
|
202
|
-
`agent.queue(input)` ships the run to the background queue (`@rudderjs/queue`). Add `.broadcast(channel)` to stream chunks to a `@rudderjs/broadcast` channel as the job runs — background AI work + live UI without polling.
|
|
203
|
-
|
|
204
|
-
```ts
|
|
205
|
-
import { agent } from '@rudderjs/ai'
|
|
206
|
-
|
|
207
|
-
// Plain queued — no live updates
|
|
208
|
-
await agent('You help with refunds.')
|
|
209
|
-
.queue('Process refund for order #1234')
|
|
210
|
-
.onQueue('ai')
|
|
211
|
-
.send()
|
|
212
|
-
|
|
213
|
-
// Stream chunks to the user's channel as they arrive
|
|
214
|
-
await new SupportAgent()
|
|
215
|
-
.queue('Help with refund request')
|
|
216
|
-
.broadcast(`user.${userId}.support`)
|
|
217
|
-
.send()
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
Subscribers on the channel receive `chunk` events (one per `StreamChunk`), then a `done` event with the final `AgentResponse`, or an `error` event on failure. Optional `eventPrefix` namespaces events: `.broadcast('chan', { eventPrefix: 'agent.' })` emits `agent.chunk` / `agent.done` / `agent.error`.
|
|
221
|
-
|
|
222
|
-
`@rudderjs/broadcast`'s in-process WS state is process-local — same-process web + `queue:work` works out of the box; a separate worker process needs a future pub/sub bridge.
|
|
223
|
-
|
|
224
|
-
### Structured Output
|
|
225
|
-
|
|
226
|
-
Use `Output` to constrain responses to typed schemas:
|
|
227
|
-
|
|
228
|
-
```ts
|
|
229
|
-
import { Output } from '@rudderjs/ai'
|
|
230
|
-
|
|
231
|
-
const sentiment = Output.choice({ options: ['positive', 'negative', 'neutral'] as const })
|
|
232
|
-
const extraction = Output.object({ schema: z.object({ name: z.string(), age: z.number() }) })
|
|
233
|
-
const items = Output.array({ element: z.object({ title: z.string() }) })
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
## Common Pitfalls
|
|
237
|
-
|
|
238
|
-
- **Model string format**: Always use `provider/model` (e.g. `anthropic/claude-sonnet-4-5`). A bare model name throws.
|
|
239
|
-
- **Optional SDK deps**: Provider SDKs (`@anthropic-ai/sdk`, `openai`, `@google/genai`) are optional dependencies. Install the ones you need.
|
|
240
|
-
- **ConversationStore required for `.forUser()`/`.continue()`**: Call `setConversationStore()` or pass `conversations` in the AI config. Without it, conversation methods throw.
|
|
241
|
-
- **Tool loop limits**: `maxSteps()` defaults to 20. If the agent hits the limit it stops silently. Increase it for complex multi-tool workflows.
|
|
242
|
-
- **Parallel tool execution**: when the model emits multiple tool calls in a single step, their `execute()` functions run concurrently by default. Streamed chunks still emit in tool-call order. Opt out via `prompt(..., { parallelTools: false })` or override `parallelTools()` on the agent class for tools with non-idempotent shared state.
|
|
243
|
-
- **Streaming response access**: `await response` only resolves after the stream is fully consumed. Always iterate the stream first.
|
|
244
|
-
- **Embeddings**: Only providers that implement `createEmbedding()` support `AI.embed()`. Currently OpenAI-compatible providers.
|
|
245
|
-
|
|
246
|
-
## Key Imports
|
|
247
|
-
|
|
248
|
-
```ts
|
|
249
|
-
import { AiProvider } from '@rudderjs/ai/server' // service provider (Node only)
|
|
250
|
-
import { Agent, agent, ConversableAgent } from '@rudderjs/ai' // agents
|
|
251
|
-
import { AI } from '@rudderjs/ai' // facade (AI.prompt, AI.agent, AI.embed)
|
|
252
|
-
import { toolDefinition } from '@rudderjs/ai' // tool builder
|
|
253
|
-
import { Image, Document } from '@rudderjs/ai' // attachments
|
|
254
|
-
import { MemoryConversationStore, setConversationStore } from '@rudderjs/ai'
|
|
255
|
-
import { Output } from '@rudderjs/ai' // structured output
|
|
256
|
-
import { AiRegistry } from '@rudderjs/ai' // provider registry
|
|
257
|
-
import { mcpClientTools, mcpServerFromAgent } from '@rudderjs/ai/mcp' // MCP bridge (Node)
|
|
258
|
-
import { stepCountIs, hasToolCall } from '@rudderjs/ai' // stop conditions
|
|
259
|
-
import type { AgentResponse, AiConfig, AiMiddleware, AnyTool, HasTools, HasMiddleware } from '@rudderjs/ai'
|
|
260
|
-
```
|
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: ai-agents
|
|
3
|
-
description: Building AI agents with tools, streaming, conversation memory, approval flows, and middleware in Rudder
|
|
4
|
-
license: MIT
|
|
5
|
-
appliesTo:
|
|
6
|
-
- '@rudderjs/ai'
|
|
7
|
-
trigger: building an `Agent` class, calling `Agent.prompt()`/`.stream()`, defining `tools()` or `middleware()`, or wiring conversations / failover
|
|
8
|
-
skip: writing a tool definition by itself — load `ai-tools` instead
|
|
9
|
-
metadata:
|
|
10
|
-
author: rudderjs
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
# AI Agents
|
|
14
|
-
|
|
15
|
-
## When to use this skill
|
|
16
|
-
|
|
17
|
-
Load this skill when you need to build an AI agent, run prompts with tool loops, stream responses, persist conversations, use approval gates, or queue agent work for background execution.
|
|
18
|
-
|
|
19
|
-
## Key concepts
|
|
20
|
-
|
|
21
|
-
- **Agent base class**: Extend `Agent` and implement `instructions()`. Optionally override `model()`, `tools()`, `maxSteps()`, `stopWhen()`, `temperature()`, `middleware()`.
|
|
22
|
-
- **Anonymous agents**: Use the `agent()` function for inline, one-off agents without a class.
|
|
23
|
-
- **Tool loop**: The agent runs a loop: prompt model -> execute tool calls -> feed results back -> repeat until stop condition.
|
|
24
|
-
- **Streaming**: `agent.stream()` returns `{ stream: AsyncIterable<StreamChunk>, response: Promise<AgentResponse> }`.
|
|
25
|
-
- **Conversations**: `agent.forUser(id).prompt()` or `agent.continue(conversationId).prompt()` for persistent memory.
|
|
26
|
-
- **Provider/model string**: Format is `'provider/model'` (e.g. `'anthropic/claude-sonnet-4-5'`, `'openai/gpt-4o'`).
|
|
27
|
-
- **Finish reasons**: `'stop'`, `'tool_calls'`, `'length'`, `'client_tool_calls'`, `'tool_approval_required'`.
|
|
28
|
-
|
|
29
|
-
## Step-by-step
|
|
30
|
-
|
|
31
|
-
### 1. Create an agent class
|
|
32
|
-
|
|
33
|
-
```ts
|
|
34
|
-
// app/Agents/ResearchAgent.ts
|
|
35
|
-
import { Agent } from '@rudderjs/ai'
|
|
36
|
-
import type { HasTools, AnyTool } from '@rudderjs/ai'
|
|
37
|
-
|
|
38
|
-
export class ResearchAgent extends Agent implements HasTools {
|
|
39
|
-
instructions(): string {
|
|
40
|
-
return `You are a research assistant. Use the search tool to find
|
|
41
|
-
information and summarize your findings clearly.`
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
model(): string {
|
|
45
|
-
return 'anthropic/claude-sonnet-4-5'
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
tools(): AnyTool[] {
|
|
49
|
-
return [searchTool, summarizeTool]
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
maxSteps(): number {
|
|
53
|
-
return 10
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### 2. Run a prompt (non-streaming)
|
|
59
|
-
|
|
60
|
-
```ts
|
|
61
|
-
const agent = new ResearchAgent()
|
|
62
|
-
|
|
63
|
-
const response = await agent.prompt('What is Rudder?')
|
|
64
|
-
console.log(response.text) // final text output
|
|
65
|
-
console.log(response.steps) // array of AgentStep
|
|
66
|
-
console.log(response.usage) // { promptTokens, completionTokens, totalTokens }
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
### 3. Stream a response
|
|
70
|
-
|
|
71
|
-
```ts
|
|
72
|
-
const { stream, response } = agent.stream('Explain TypeScript decorators')
|
|
73
|
-
|
|
74
|
-
for await (const chunk of stream) {
|
|
75
|
-
switch (chunk.type) {
|
|
76
|
-
case 'text-delta':
|
|
77
|
-
process.stdout.write(chunk.text ?? '')
|
|
78
|
-
break
|
|
79
|
-
case 'tool-call':
|
|
80
|
-
console.log(`Calling tool: ${chunk.toolCall?.name}`)
|
|
81
|
-
break
|
|
82
|
-
case 'tool-result':
|
|
83
|
-
console.log(`Tool result:`, chunk.result)
|
|
84
|
-
break
|
|
85
|
-
case 'tool-update':
|
|
86
|
-
console.log(`Progress:`, chunk.update)
|
|
87
|
-
break
|
|
88
|
-
case 'finish':
|
|
89
|
-
console.log(`Done: ${chunk.finishReason}`)
|
|
90
|
-
break
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const finalResponse = await response
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### 4. Use anonymous agents (inline)
|
|
98
|
-
|
|
99
|
-
```ts
|
|
100
|
-
import { agent } from '@rudderjs/ai'
|
|
101
|
-
|
|
102
|
-
// Simple string instructions
|
|
103
|
-
const response = await agent('You are a helpful assistant.').prompt('Hello')
|
|
104
|
-
|
|
105
|
-
// With tools and model
|
|
106
|
-
const response = await agent({
|
|
107
|
-
instructions: 'You are a search assistant.',
|
|
108
|
-
tools: [searchTool],
|
|
109
|
-
model: 'anthropic/claude-sonnet-4-5',
|
|
110
|
-
}).prompt('Find users named John')
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
### 5. Conversation persistence
|
|
114
|
-
|
|
115
|
-
```ts
|
|
116
|
-
const myAgent = new ResearchAgent()
|
|
117
|
-
|
|
118
|
-
// Start a new conversation for a user
|
|
119
|
-
const response1 = await myAgent.forUser('user-123').prompt('What is TypeScript?')
|
|
120
|
-
const convId = response1.conversationId!
|
|
121
|
-
|
|
122
|
-
// Continue the same conversation
|
|
123
|
-
const response2 = await myAgent.continue(convId).prompt('Tell me more about generics')
|
|
124
|
-
// The agent sees the full conversation history
|
|
125
|
-
|
|
126
|
-
// Streaming with conversations
|
|
127
|
-
const { stream, response } = myAgent.forUser('user-123').stream('Explain async/await')
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
A `ConversationStore` must be registered. The built-in `MemoryConversationStore` works for dev; implement the `ConversationStore` interface for production (database-backed).
|
|
131
|
-
|
|
132
|
-
### 6. Stop conditions
|
|
133
|
-
|
|
134
|
-
```ts
|
|
135
|
-
import { Agent, stepCountIs, hasToolCall } from '@rudderjs/ai'
|
|
136
|
-
|
|
137
|
-
class MyAgent extends Agent {
|
|
138
|
-
instructions() { return 'You are helpful.' }
|
|
139
|
-
|
|
140
|
-
stopWhen() {
|
|
141
|
-
return [
|
|
142
|
-
stepCountIs(5), // stop after 5 iterations
|
|
143
|
-
hasToolCall('final_answer'), // stop when this tool is called
|
|
144
|
-
]
|
|
145
|
-
// Multiple conditions use OR logic -- stops when any is true
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
### 7. Per-step control (prepareStep)
|
|
151
|
-
|
|
152
|
-
```ts
|
|
153
|
-
class AdaptiveAgent extends Agent {
|
|
154
|
-
instructions() { return 'You are helpful.' }
|
|
155
|
-
|
|
156
|
-
prepareStep(ctx: { stepNumber: number; steps: AgentStep[]; messages: AiMessage[] }) {
|
|
157
|
-
if (ctx.stepNumber > 3) {
|
|
158
|
-
return { model: 'anthropic/claude-haiku-3' } // cheaper model for later steps
|
|
159
|
-
}
|
|
160
|
-
return {}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
### 8. Middleware
|
|
166
|
-
|
|
167
|
-
```ts
|
|
168
|
-
import type { AiMiddleware } from '@rudderjs/ai'
|
|
169
|
-
|
|
170
|
-
const loggingMiddleware: AiMiddleware = {
|
|
171
|
-
name: 'logging',
|
|
172
|
-
onStart(ctx) { console.log(`Agent started, model: ${ctx.model}`) },
|
|
173
|
-
onChunk(ctx, chunk) {
|
|
174
|
-
if (chunk.type === 'text-delta') process.stdout.write(chunk.text ?? '')
|
|
175
|
-
return chunk // return null to suppress the chunk
|
|
176
|
-
},
|
|
177
|
-
onBeforeToolCall(ctx, toolName, args) {
|
|
178
|
-
console.log(`Calling ${toolName}`, args)
|
|
179
|
-
// Return { type: 'skip', result: 'mocked' } to skip execution
|
|
180
|
-
// Return { type: 'abort', reason: 'blocked' } to abort the loop
|
|
181
|
-
},
|
|
182
|
-
onAfterToolCall(ctx, toolName, args, result) {
|
|
183
|
-
console.log(`${toolName} returned`, result)
|
|
184
|
-
},
|
|
185
|
-
onUsage(ctx, usage) {
|
|
186
|
-
console.log(`Tokens: ${usage.totalTokens}`)
|
|
187
|
-
},
|
|
188
|
-
onError(ctx, error) {
|
|
189
|
-
console.error('Agent error:', error)
|
|
190
|
-
},
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
class MyAgent extends Agent implements HasMiddleware {
|
|
194
|
-
instructions() { return 'You are helpful.' }
|
|
195
|
-
middleware() { return [loggingMiddleware] }
|
|
196
|
-
}
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
### 9. Queue for background execution
|
|
200
|
-
|
|
201
|
-
```ts
|
|
202
|
-
const myAgent = new ResearchAgent()
|
|
203
|
-
|
|
204
|
-
// Queue for async processing (requires @rudderjs/queue)
|
|
205
|
-
myAgent.queue('Analyze this dataset').dispatch()
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
### 10. Failover providers
|
|
209
|
-
|
|
210
|
-
```ts
|
|
211
|
-
class ResilientAgent extends Agent {
|
|
212
|
-
instructions() { return 'You are helpful.' }
|
|
213
|
-
model() { return 'anthropic/claude-sonnet-4-5' }
|
|
214
|
-
failover() { return ['openai/gpt-4o', 'google/gemini-2.0-flash'] }
|
|
215
|
-
}
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
### 11. Attachments (images/documents)
|
|
219
|
-
|
|
220
|
-
```ts
|
|
221
|
-
const response = await agent('Describe this image.').prompt('What do you see?', {
|
|
222
|
-
attachments: [
|
|
223
|
-
{ type: 'image', data: base64String, mimeType: 'image/png' },
|
|
224
|
-
{ type: 'document', data: pdfBase64, mimeType: 'application/pdf', name: 'report.pdf' },
|
|
225
|
-
],
|
|
226
|
-
})
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
## Examples
|
|
230
|
-
|
|
231
|
-
See `playground/app/Agents/ResearchAgent.ts` for a working agent class.
|
|
232
|
-
|
|
233
|
-
## Common pitfalls
|
|
234
|
-
|
|
235
|
-
- **Provider SDK not installed**: Each provider's SDK is an optional peer dependency. Install only what you use: `@anthropic-ai/sdk`, `openai`, `@google/genai`.
|
|
236
|
-
- **No default model**: If `model()` returns `undefined`, the agent uses the registry default from `config/ai.ts`. Make sure one is configured.
|
|
237
|
-
- **ConversationStore missing**: `forUser()` / `continue()` throw if no `ConversationStore` is registered. Register one via `setConversationStore()` or through the AI service provider.
|
|
238
|
-
- **maxSteps exhaustion**: Default is 20 iterations. If the agent hits `maxSteps`, it stops with whatever text it has. Override `maxSteps()` for agents that need more iterations.
|
|
239
|
-
- **Streaming vs non-streaming tool updates**: `yield` from an `async function*` tool execute emits `tool-update` chunks during streaming. In non-streaming `prompt()`, yields are silently drained.
|
|
240
|
-
- **Client tools**: Tools without an `execute` function are client tools. The loop pauses with `finishReason: 'client_tool_calls'` and returns `pendingClientToolCalls` for browser-side execution.
|