@illuma-ai/agents 1.0.83 → 1.0.85
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 +485 -485
- package/dist/cjs/common/enum.cjs +2 -0
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +4 -0
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +83 -1
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/types/graph.cjs.map +1 -1
- package/dist/esm/common/enum.mjs +2 -0
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +4 -0
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +85 -3
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/types/graph.mjs.map +1 -1
- package/dist/types/common/enum.d.ts +2 -0
- package/dist/types/tools/ToolNode.d.ts +22 -1
- package/dist/types/types/graph.d.ts +8 -1
- package/dist/types/types/tools.d.ts +87 -0
- package/package.json +6 -2
- package/src/agents/__tests__/resolveStructuredOutputMode.test.ts +137 -137
- package/src/common/enum.ts +2 -0
- package/src/graphs/Graph.ts +5 -0
- package/src/graphs/__tests__/structured-output.integration.test.ts +809 -809
- package/src/graphs/__tests__/structured-output.test.ts +183 -183
- package/src/schemas/schema-preparation.test.ts +500 -500
- package/src/tools/ToolNode.ts +96 -0
- package/src/tools/__tests__/ToolApproval.test.ts +725 -0
- package/src/types/graph.ts +8 -1
- package/src/types/tools.ts +101 -0
package/README.md
CHANGED
|
@@ -1,485 +1,485 @@
|
|
|
1
|
-
# Illuma Agents
|
|
2
|
-
|
|
3
|
-
**Enterprise-grade TypeScript library for building and orchestrating LLM-powered agents.**
|
|
4
|
-
|
|
5
|
-
Built on [LangChain](https://js.langchain.com/) and [LangGraph](https://langchain-ai.github.io/langgraphjs/), Illuma Agents provides multi-agent orchestration, real-time streaming, tool integration, prompt caching, extended thinking, and structured output — supporting **12+ LLM providers** out of the box.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Features
|
|
10
|
-
|
|
11
|
-
- **Multi-Agent Orchestration** — Handoff, sequential, parallel (fan-out/fan-in), conditional, and hybrid agent flows
|
|
12
|
-
- **12+ LLM Providers** — OpenAI, Anthropic, AWS Bedrock, Google Gemini, Vertex AI, Azure OpenAI, Mistral, DeepSeek, xAI, OpenRouter, Moonshot
|
|
13
|
-
- **Streaming-First** — Real-time token streaming with split-stream buffering and content aggregation
|
|
14
|
-
- **Built-in Tools** — Code execution (12+ languages), calculator, web search, browser automation, programmatic tool calling
|
|
15
|
-
- **Prompt Caching** — Anthropic and Bedrock cache control for reduced latency and cost
|
|
16
|
-
- **Extended Thinking** — Anthropic/Bedrock thinking blocks with proper tool-call sequencing
|
|
17
|
-
- **Structured Output** — JSON schema-constrained responses via tool calling, provider-native, or auto mode
|
|
18
|
-
- **Dynamic Tool Discovery** — BM25-ranked tool search for large tool registries (MCP servers)
|
|
19
|
-
- **Context Management** — Automatic message pruning, token counting, and context window optimization
|
|
20
|
-
- **Observability** — Langfuse + OpenTelemetry tracing
|
|
21
|
-
- **Dual Module Output** — ESM + CJS with full TypeScript declarations
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
## Installation
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
npm install @illuma-ai/agents
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### Peer Dependencies
|
|
32
|
-
|
|
33
|
-
The library requires `@langchain/core` as a peer dependency. If not already installed:
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
npm install @langchain/core
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
## Environment Variables
|
|
42
|
-
|
|
43
|
-
Set API keys for the providers you plan to use:
|
|
44
|
-
|
|
45
|
-
```env
|
|
46
|
-
# LLM Providers (add the ones you need)
|
|
47
|
-
OPENAI_API_KEY=sk-...
|
|
48
|
-
ANTHROPIC_API_KEY=sk-ant-...
|
|
49
|
-
AWS_ACCESS_KEY_ID=...
|
|
50
|
-
AWS_SECRET_ACCESS_KEY=...
|
|
51
|
-
AWS_REGION=us-east-1
|
|
52
|
-
GOOGLE_API_KEY=...
|
|
53
|
-
AZURE_OPENAI_API_KEY=...
|
|
54
|
-
DEEPSEEK_API_KEY=...
|
|
55
|
-
XAI_API_KEY=...
|
|
56
|
-
MISTRAL_API_KEY=...
|
|
57
|
-
OPENROUTER_API_KEY=...
|
|
58
|
-
|
|
59
|
-
# Code Executor (optional)
|
|
60
|
-
CODE_EXECUTOR_BASEURL=http://localhost:8088
|
|
61
|
-
CODE_EXECUTOR_API_KEY=your-api-key
|
|
62
|
-
|
|
63
|
-
# Observability (optional)
|
|
64
|
-
LANGFUSE_SECRET_KEY=sk-lf-...
|
|
65
|
-
LANGFUSE_PUBLIC_KEY=pk-lf-...
|
|
66
|
-
LANGFUSE_BASE_URL=https://cloud.langfuse.com
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
---
|
|
70
|
-
|
|
71
|
-
## Quick Start
|
|
72
|
-
|
|
73
|
-
### Single Agent
|
|
74
|
-
|
|
75
|
-
```typescript
|
|
76
|
-
import { HumanMessage } from '@langchain/core/messages';
|
|
77
|
-
import {
|
|
78
|
-
Run,
|
|
79
|
-
ChatModelStreamHandler,
|
|
80
|
-
createContentAggregator,
|
|
81
|
-
ToolEndHandler,
|
|
82
|
-
ModelEndHandler,
|
|
83
|
-
GraphEvents,
|
|
84
|
-
Providers,
|
|
85
|
-
} from '@illuma-ai/agents';
|
|
86
|
-
import type * as t from '@illuma-ai/agents';
|
|
87
|
-
|
|
88
|
-
const { contentParts, aggregateContent } = createContentAggregator();
|
|
89
|
-
|
|
90
|
-
const run = await Run.create<t.IState>({
|
|
91
|
-
runId: 'my-run-001',
|
|
92
|
-
graphConfig: {
|
|
93
|
-
type: 'standard',
|
|
94
|
-
llmConfig: {
|
|
95
|
-
provider: Providers.ANTHROPIC,
|
|
96
|
-
model: 'claude-sonnet-4-20250514',
|
|
97
|
-
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
98
|
-
},
|
|
99
|
-
instructions: 'You are a helpful AI assistant.',
|
|
100
|
-
},
|
|
101
|
-
returnContent: true,
|
|
102
|
-
customHandlers: {
|
|
103
|
-
[GraphEvents.TOOL_END]: new ToolEndHandler(),
|
|
104
|
-
[GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
|
|
105
|
-
[GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
|
|
106
|
-
[GraphEvents.ON_RUN_STEP]: {
|
|
107
|
-
handle: (event: string, data: t.RunStep) => aggregateContent({ event, data }),
|
|
108
|
-
},
|
|
109
|
-
[GraphEvents.ON_RUN_STEP_DELTA]: {
|
|
110
|
-
handle: (event: string, data: t.RunStepDeltaEvent) => aggregateContent({ event, data }),
|
|
111
|
-
},
|
|
112
|
-
[GraphEvents.ON_MESSAGE_DELTA]: {
|
|
113
|
-
handle: (event: string, data: t.MessageDeltaEvent) => aggregateContent({ event, data }),
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
const result = await run.processStream(
|
|
119
|
-
{ messages: [new HumanMessage('What is the capital of France?')] },
|
|
120
|
-
{ version: 'v2', configurable: { user_id: 'user-123', thread_id: 'conv-1' } }
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
console.log('Response:', contentParts);
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### Multi-Agent with Handoffs
|
|
127
|
-
|
|
128
|
-
```typescript
|
|
129
|
-
import { Run, Providers } from '@illuma-ai/agents';
|
|
130
|
-
import type * as t from '@illuma-ai/agents';
|
|
131
|
-
|
|
132
|
-
const run = await Run.create({
|
|
133
|
-
runId: 'multi-agent-001',
|
|
134
|
-
graphConfig: {
|
|
135
|
-
type: 'multi-agent',
|
|
136
|
-
agents: [
|
|
137
|
-
{
|
|
138
|
-
agentId: 'flight_assistant',
|
|
139
|
-
provider: Providers.ANTHROPIC,
|
|
140
|
-
clientOptions: { modelName: 'claude-haiku-4-5' },
|
|
141
|
-
instructions: 'You are a flight booking assistant.',
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
agentId: 'hotel_assistant',
|
|
145
|
-
provider: Providers.ANTHROPIC,
|
|
146
|
-
clientOptions: { modelName: 'claude-haiku-4-5' },
|
|
147
|
-
instructions: 'You are a hotel booking assistant.',
|
|
148
|
-
},
|
|
149
|
-
],
|
|
150
|
-
edges: [
|
|
151
|
-
{
|
|
152
|
-
from: 'flight_assistant',
|
|
153
|
-
to: 'hotel_assistant',
|
|
154
|
-
description: 'Transfer when user needs hotel help',
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
from: 'hotel_assistant',
|
|
158
|
-
to: 'flight_assistant',
|
|
159
|
-
description: 'Transfer when user needs flight help',
|
|
160
|
-
},
|
|
161
|
-
],
|
|
162
|
-
},
|
|
163
|
-
customHandlers: { /* ...event handlers... */ },
|
|
164
|
-
returnContent: true,
|
|
165
|
-
});
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
### Parallel Fan-out / Fan-in
|
|
169
|
-
|
|
170
|
-
```typescript
|
|
171
|
-
const run = await Run.create({
|
|
172
|
-
runId: 'parallel-001',
|
|
173
|
-
graphConfig: {
|
|
174
|
-
type: 'multi-agent',
|
|
175
|
-
agents: [
|
|
176
|
-
{ agentId: 'coordinator', provider: Providers.ANTHROPIC, clientOptions: { modelName: 'claude-haiku-4-5' }, instructions: 'Coordinate research tasks.' },
|
|
177
|
-
{ agentId: 'analyst_a', provider: Providers.ANTHROPIC, clientOptions: { modelName: 'claude-haiku-4-5' }, instructions: 'Financial analysis.' },
|
|
178
|
-
{ agentId: 'analyst_b', provider: Providers.ANTHROPIC, clientOptions: { modelName: 'claude-haiku-4-5' }, instructions: 'Technical analysis.' },
|
|
179
|
-
{ agentId: 'summarizer', provider: Providers.ANTHROPIC, clientOptions: { modelName: 'claude-haiku-4-5' }, instructions: 'Synthesize all findings.' },
|
|
180
|
-
],
|
|
181
|
-
edges: [
|
|
182
|
-
{ from: 'coordinator', to: ['analyst_a', 'analyst_b'], edgeType: 'direct' }, // Fan-out (parallel)
|
|
183
|
-
{ from: ['analyst_a', 'analyst_b'], to: 'summarizer', edgeType: 'direct' }, // Fan-in
|
|
184
|
-
],
|
|
185
|
-
},
|
|
186
|
-
customHandlers: { /* ... */ },
|
|
187
|
-
});
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
### Using Tools
|
|
191
|
-
|
|
192
|
-
```typescript
|
|
193
|
-
import { createCodeExecutionTool, Calculator } from '@illuma-ai/agents';
|
|
194
|
-
|
|
195
|
-
const run = await Run.create<t.IState>({
|
|
196
|
-
runId: 'tools-001',
|
|
197
|
-
graphConfig: {
|
|
198
|
-
type: 'standard',
|
|
199
|
-
llmConfig: { provider: Providers.OPENAI, model: 'gpt-4o' },
|
|
200
|
-
instructions: 'You can execute code and do math.',
|
|
201
|
-
tools: [createCodeExecutionTool(), new Calculator()],
|
|
202
|
-
},
|
|
203
|
-
customHandlers: { /* ... */ },
|
|
204
|
-
});
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
### Extended Thinking
|
|
208
|
-
|
|
209
|
-
```typescript
|
|
210
|
-
const run = await Run.create<t.IState>({
|
|
211
|
-
runId: 'thinking-001',
|
|
212
|
-
graphConfig: {
|
|
213
|
-
type: 'standard',
|
|
214
|
-
llmConfig: {
|
|
215
|
-
provider: Providers.ANTHROPIC,
|
|
216
|
-
model: 'claude-3-7-sonnet-latest',
|
|
217
|
-
thinking: { type: 'enabled', budget_tokens: 5000 },
|
|
218
|
-
},
|
|
219
|
-
instructions: 'Think through problems carefully.',
|
|
220
|
-
},
|
|
221
|
-
customHandlers: {
|
|
222
|
-
// ...standard handlers...
|
|
223
|
-
[GraphEvents.ON_REASONING_DELTA]: {
|
|
224
|
-
handle: (event: string, data: t.ReasoningDeltaEvent) => {
|
|
225
|
-
// Receive thinking/reasoning tokens as they stream
|
|
226
|
-
},
|
|
227
|
-
},
|
|
228
|
-
},
|
|
229
|
-
});
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
### Structured Output
|
|
233
|
-
|
|
234
|
-
```typescript
|
|
235
|
-
const run = await Run.create<t.IState>({
|
|
236
|
-
runId: 'structured-001',
|
|
237
|
-
graphConfig: {
|
|
238
|
-
type: 'standard',
|
|
239
|
-
agents: [{
|
|
240
|
-
agentId: 'analyzer',
|
|
241
|
-
provider: Providers.OPENAI,
|
|
242
|
-
clientOptions: { model: 'gpt-4o' },
|
|
243
|
-
instructions: 'Analyze sentiment.',
|
|
244
|
-
structuredOutput: {
|
|
245
|
-
schema: {
|
|
246
|
-
type: 'object',
|
|
247
|
-
properties: {
|
|
248
|
-
sentiment: { type: 'string', enum: ['positive', 'negative', 'neutral'] },
|
|
249
|
-
confidence: { type: 'number' },
|
|
250
|
-
},
|
|
251
|
-
required: ['sentiment', 'confidence'],
|
|
252
|
-
},
|
|
253
|
-
mode: 'auto',
|
|
254
|
-
strict: true,
|
|
255
|
-
},
|
|
256
|
-
}],
|
|
257
|
-
},
|
|
258
|
-
customHandlers: {
|
|
259
|
-
[GraphEvents.ON_STRUCTURED_OUTPUT]: {
|
|
260
|
-
handle: (_event: string, data: unknown) => console.log('Result:', data),
|
|
261
|
-
},
|
|
262
|
-
},
|
|
263
|
-
});
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
---
|
|
267
|
-
|
|
268
|
-
## Providers
|
|
269
|
-
|
|
270
|
-
| Provider | Enum | Notes |
|
|
271
|
-
|----------|------|-------|
|
|
272
|
-
| OpenAI | `Providers.OPENAI` | GPT-4o, o1, o3 |
|
|
273
|
-
| Anthropic | `Providers.ANTHROPIC` | Claude 4, Sonnet, Haiku — thinking, caching, web search |
|
|
274
|
-
| AWS Bedrock | `Providers.BEDROCK` | Claude via Bedrock — caching, reasoning |
|
|
275
|
-
| Google Gemini | `Providers.GOOGLE` | Gemini Pro, Flash |
|
|
276
|
-
| Vertex AI | `Providers.VERTEXAI` | Google models via GCP |
|
|
277
|
-
| Azure OpenAI | `Providers.AZURE` | OpenAI models via Azure |
|
|
278
|
-
| Mistral | `Providers.MISTRALAI` | Large, Medium, Small |
|
|
279
|
-
| DeepSeek | `Providers.DEEPSEEK` | Reasoning models |
|
|
280
|
-
| xAI | `Providers.XAI` | Grok |
|
|
281
|
-
| OpenRouter | `Providers.OPENROUTER` | Multi-model routing |
|
|
282
|
-
| Moonshot | `Providers.MOONSHOT` | Moonshot AI |
|
|
283
|
-
|
|
284
|
-
**Provider config examples:**
|
|
285
|
-
|
|
286
|
-
```typescript
|
|
287
|
-
// OpenAI
|
|
288
|
-
{ provider: Providers.OPENAI, clientOptions: { model: 'gpt-4o', apiKey: '...' } }
|
|
289
|
-
|
|
290
|
-
// Anthropic
|
|
291
|
-
{ provider: Providers.ANTHROPIC, clientOptions: { modelName: 'claude-sonnet-4-20250514', apiKey: '...' } }
|
|
292
|
-
|
|
293
|
-
// AWS Bedrock
|
|
294
|
-
{ provider: Providers.BEDROCK, clientOptions: { model: 'us.anthropic.claude-sonnet-4-20250514-v1:0', region: 'us-east-1' } }
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
---
|
|
298
|
-
|
|
299
|
-
## Multi-Agent Patterns
|
|
300
|
-
|
|
301
|
-
### Edge Types
|
|
302
|
-
|
|
303
|
-
| Type | Behavior |
|
|
304
|
-
|------|----------|
|
|
305
|
-
| **Handoff** (default) | LLM decides when to transfer — auto-generates `transfer_to_<agent>` tools |
|
|
306
|
-
| **Direct** | Fixed routing — agents run in sequence or parallel |
|
|
307
|
-
|
|
308
|
-
### Handoff (Dynamic)
|
|
309
|
-
|
|
310
|
-
```typescript
|
|
311
|
-
{ from: 'triage', to: 'billing', description: 'Transfer for billing questions' }
|
|
312
|
-
// → triage agent gets a transfer_to_billing tool it can call
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
### Sequential Pipeline
|
|
316
|
-
|
|
317
|
-
```typescript
|
|
318
|
-
{ from: 'drafter', to: 'reviewer', edgeType: 'direct', prompt: 'Review the draft above.' }
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
### Fan-out / Fan-in (Parallel)
|
|
322
|
-
|
|
323
|
-
```typescript
|
|
324
|
-
{ from: 'coordinator', to: ['analyst_a', 'analyst_b'], edgeType: 'direct' } // parallel
|
|
325
|
-
{ from: ['analyst_a', 'analyst_b'], to: 'summarizer', edgeType: 'direct', prompt: '{results}' } // join
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
Use `{results}` in prompts to inject collected output from parallel agents.
|
|
329
|
-
|
|
330
|
-
### Conditional Routing
|
|
331
|
-
|
|
332
|
-
```typescript
|
|
333
|
-
{
|
|
334
|
-
from: 'router',
|
|
335
|
-
to: ['fast_model', 'powerful_model'],
|
|
336
|
-
condition: (state) => state.messages.at(-1)?.content.length > 500 ? 'powerful_model' : 'fast_model',
|
|
337
|
-
}
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
### Hybrid
|
|
341
|
-
|
|
342
|
-
Agents with both handoff and direct edges use **exclusive routing**: if a handoff fires, only the handoff destination runs; otherwise direct edges execute.
|
|
343
|
-
|
|
344
|
-
---
|
|
345
|
-
|
|
346
|
-
## Built-in Tools
|
|
347
|
-
|
|
348
|
-
| Tool | Import | Description |
|
|
349
|
-
|------|--------|-------------|
|
|
350
|
-
| **Code Executor** | `createCodeExecutionTool()` | Sandboxed execution in 12+ languages (Python, JS, TS, C, C++, Java, PHP, Rust, Go, D, Fortran, R) |
|
|
351
|
-
| **Calculator** | `new Calculator()` | Math expressions via [mathjs](https://mathjs.org/) |
|
|
352
|
-
| **Browser Tools** | `createBrowserTools()` | 12 browser actions (navigate, click, type, screenshot, etc.) |
|
|
353
|
-
| **Tool Search** | `createToolSearchTool()` | BM25-ranked discovery for large tool registries |
|
|
354
|
-
| **Programmatic Tool Calling** | `createProgrammaticToolCallingTool()` | LLM writes Python to call tools as async functions |
|
|
355
|
-
|
|
356
|
-
---
|
|
357
|
-
|
|
358
|
-
## Event System
|
|
359
|
-
|
|
360
|
-
Register handlers to receive real-time streaming events:
|
|
361
|
-
|
|
362
|
-
```typescript
|
|
363
|
-
const customHandlers = {
|
|
364
|
-
[GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(), // Token-by-token streaming
|
|
365
|
-
[GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(usageArray), // Usage metadata
|
|
366
|
-
[GraphEvents.TOOL_END]: new ToolEndHandler(), // Tool results
|
|
367
|
-
[GraphEvents.ON_RUN_STEP]: { handle: (e, data) => ... }, // New run step
|
|
368
|
-
[GraphEvents.ON_RUN_STEP_DELTA]: { handle: (e, data) => ... }, // Step delta (tool args)
|
|
369
|
-
[GraphEvents.ON_MESSAGE_DELTA]: { handle: (e, data) => ... }, // Text delta
|
|
370
|
-
[GraphEvents.ON_REASONING_DELTA]:{ handle: (e, data) => ... }, // Thinking delta
|
|
371
|
-
[GraphEvents.ON_AGENT_UPDATE]: { handle: (e, data) => ... }, // Agent switch
|
|
372
|
-
[GraphEvents.ON_STRUCTURED_OUTPUT]: { handle: (e, data) => ... },// Structured JSON
|
|
373
|
-
};
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
Use `createContentAggregator()` to automatically collect deltas into a complete response:
|
|
377
|
-
|
|
378
|
-
```typescript
|
|
379
|
-
const { contentParts, aggregateContent } = createContentAggregator();
|
|
380
|
-
// Pass aggregateContent into your handlers
|
|
381
|
-
// After streaming, contentParts has the full structured response
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
---
|
|
385
|
-
|
|
386
|
-
## Prompt Caching
|
|
387
|
-
|
|
388
|
-
Caching is **automatic** for Anthropic and Bedrock providers:
|
|
389
|
-
|
|
390
|
-
- System messages get cache control markers
|
|
391
|
-
- Last 2 conversation messages get cache breakpoints
|
|
392
|
-
- Use `dynamicContext` for per-request data (keeps system prompt cacheable):
|
|
393
|
-
|
|
394
|
-
```typescript
|
|
395
|
-
{
|
|
396
|
-
instructions: 'You are a helpful assistant.', // Cached
|
|
397
|
-
dynamicContext: `Current time: ${new Date().toISOString()}`, // Not cached
|
|
398
|
-
}
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
---
|
|
402
|
-
|
|
403
|
-
## Structured Output Modes
|
|
404
|
-
|
|
405
|
-
| Mode | Description |
|
|
406
|
-
|------|-------------|
|
|
407
|
-
| `'auto'` | Auto-selects best strategy per provider **(default)** |
|
|
408
|
-
| `'tool'` | Uses tool calling — universal compatibility |
|
|
409
|
-
| `'provider'` | Provider-native JSON mode |
|
|
410
|
-
| `'native'` | Constrained decoding — guaranteed schema compliance |
|
|
411
|
-
|
|
412
|
-
```typescript
|
|
413
|
-
structuredOutput: {
|
|
414
|
-
schema: { /* JSON Schema */ },
|
|
415
|
-
mode: 'auto',
|
|
416
|
-
strict: true,
|
|
417
|
-
handleErrors: true, // Auto-retry on validation failure
|
|
418
|
-
maxRetries: 2,
|
|
419
|
-
}
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
---
|
|
423
|
-
|
|
424
|
-
## Observability
|
|
425
|
-
|
|
426
|
-
Set these env vars to enable automatic Langfuse tracing:
|
|
427
|
-
|
|
428
|
-
```env
|
|
429
|
-
LANGFUSE_SECRET_KEY=sk-lf-...
|
|
430
|
-
LANGFUSE_PUBLIC_KEY=pk-lf-...
|
|
431
|
-
LANGFUSE_BASE_URL=https://cloud.langfuse.com
|
|
432
|
-
```
|
|
433
|
-
|
|
434
|
-
Each trace captures `userId`, `sessionId`, `messageId`, and full LangChain callback spans.
|
|
435
|
-
|
|
436
|
-
---
|
|
437
|
-
|
|
438
|
-
## Title Generation
|
|
439
|
-
|
|
440
|
-
Generate conversation titles from the first exchange:
|
|
441
|
-
|
|
442
|
-
```typescript
|
|
443
|
-
const { title, language } = await run.generateTitle({
|
|
444
|
-
provider: Providers.ANTHROPIC,
|
|
445
|
-
inputText: userMessage,
|
|
446
|
-
contentParts,
|
|
447
|
-
titleMethod: TitleMethod.COMPLETION,
|
|
448
|
-
clientOptions: { model: 'claude-3-5-haiku-latest' },
|
|
449
|
-
});
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
---
|
|
453
|
-
|
|
454
|
-
## API Exports
|
|
455
|
-
|
|
456
|
-
```typescript
|
|
457
|
-
// Core
|
|
458
|
-
export { Run } from '@illuma-ai/agents';
|
|
459
|
-
export { ChatModelStreamHandler, createContentAggregator, SplitStreamHandler } from '@illuma-ai/agents';
|
|
460
|
-
export { HandlerRegistry, ModelEndHandler, ToolEndHandler } from '@illuma-ai/agents';
|
|
461
|
-
|
|
462
|
-
// Tools
|
|
463
|
-
export { createCodeExecutionTool, Calculator, createBrowserTools } from '@illuma-ai/agents';
|
|
464
|
-
export { createToolSearchTool, createProgrammaticToolCallingTool } from '@illuma-ai/agents';
|
|
465
|
-
|
|
466
|
-
// Graphs
|
|
467
|
-
export { StandardGraph, MultiAgentGraph } from '@illuma-ai/agents';
|
|
468
|
-
|
|
469
|
-
// LLM
|
|
470
|
-
export { getChatModelClass, llmProviders } from '@illuma-ai/agents';
|
|
471
|
-
|
|
472
|
-
// Enums & Constants
|
|
473
|
-
export { GraphEvents, Providers, ContentTypes, StepTypes, TitleMethod, Constants } from '@illuma-ai/agents';
|
|
474
|
-
|
|
475
|
-
// Types
|
|
476
|
-
export type { IState, RunConfig, AgentInputs, GraphEdge, StructuredOutputConfig } from '@illuma-ai/agents';
|
|
477
|
-
```
|
|
478
|
-
|
|
479
|
-
---
|
|
480
|
-
|
|
481
|
-
## License
|
|
482
|
-
|
|
483
|
-
UNLICENSED — Proprietary software. All rights reserved @TeamIlluma.
|
|
484
|
-
|
|
485
|
-
|
|
1
|
+
# Illuma Agents
|
|
2
|
+
|
|
3
|
+
**Enterprise-grade TypeScript library for building and orchestrating LLM-powered agents.**
|
|
4
|
+
|
|
5
|
+
Built on [LangChain](https://js.langchain.com/) and [LangGraph](https://langchain-ai.github.io/langgraphjs/), Illuma Agents provides multi-agent orchestration, real-time streaming, tool integration, prompt caching, extended thinking, and structured output — supporting **12+ LLM providers** out of the box.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Multi-Agent Orchestration** — Handoff, sequential, parallel (fan-out/fan-in), conditional, and hybrid agent flows
|
|
12
|
+
- **12+ LLM Providers** — OpenAI, Anthropic, AWS Bedrock, Google Gemini, Vertex AI, Azure OpenAI, Mistral, DeepSeek, xAI, OpenRouter, Moonshot
|
|
13
|
+
- **Streaming-First** — Real-time token streaming with split-stream buffering and content aggregation
|
|
14
|
+
- **Built-in Tools** — Code execution (12+ languages), calculator, web search, browser automation, programmatic tool calling
|
|
15
|
+
- **Prompt Caching** — Anthropic and Bedrock cache control for reduced latency and cost
|
|
16
|
+
- **Extended Thinking** — Anthropic/Bedrock thinking blocks with proper tool-call sequencing
|
|
17
|
+
- **Structured Output** — JSON schema-constrained responses via tool calling, provider-native, or auto mode
|
|
18
|
+
- **Dynamic Tool Discovery** — BM25-ranked tool search for large tool registries (MCP servers)
|
|
19
|
+
- **Context Management** — Automatic message pruning, token counting, and context window optimization
|
|
20
|
+
- **Observability** — Langfuse + OpenTelemetry tracing
|
|
21
|
+
- **Dual Module Output** — ESM + CJS with full TypeScript declarations
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @illuma-ai/agents
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Peer Dependencies
|
|
32
|
+
|
|
33
|
+
The library requires `@langchain/core` as a peer dependency. If not already installed:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install @langchain/core
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Environment Variables
|
|
42
|
+
|
|
43
|
+
Set API keys for the providers you plan to use:
|
|
44
|
+
|
|
45
|
+
```env
|
|
46
|
+
# LLM Providers (add the ones you need)
|
|
47
|
+
OPENAI_API_KEY=sk-...
|
|
48
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
49
|
+
AWS_ACCESS_KEY_ID=...
|
|
50
|
+
AWS_SECRET_ACCESS_KEY=...
|
|
51
|
+
AWS_REGION=us-east-1
|
|
52
|
+
GOOGLE_API_KEY=...
|
|
53
|
+
AZURE_OPENAI_API_KEY=...
|
|
54
|
+
DEEPSEEK_API_KEY=...
|
|
55
|
+
XAI_API_KEY=...
|
|
56
|
+
MISTRAL_API_KEY=...
|
|
57
|
+
OPENROUTER_API_KEY=...
|
|
58
|
+
|
|
59
|
+
# Code Executor (optional)
|
|
60
|
+
CODE_EXECUTOR_BASEURL=http://localhost:8088
|
|
61
|
+
CODE_EXECUTOR_API_KEY=your-api-key
|
|
62
|
+
|
|
63
|
+
# Observability (optional)
|
|
64
|
+
LANGFUSE_SECRET_KEY=sk-lf-...
|
|
65
|
+
LANGFUSE_PUBLIC_KEY=pk-lf-...
|
|
66
|
+
LANGFUSE_BASE_URL=https://cloud.langfuse.com
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Quick Start
|
|
72
|
+
|
|
73
|
+
### Single Agent
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { HumanMessage } from '@langchain/core/messages';
|
|
77
|
+
import {
|
|
78
|
+
Run,
|
|
79
|
+
ChatModelStreamHandler,
|
|
80
|
+
createContentAggregator,
|
|
81
|
+
ToolEndHandler,
|
|
82
|
+
ModelEndHandler,
|
|
83
|
+
GraphEvents,
|
|
84
|
+
Providers,
|
|
85
|
+
} from '@illuma-ai/agents';
|
|
86
|
+
import type * as t from '@illuma-ai/agents';
|
|
87
|
+
|
|
88
|
+
const { contentParts, aggregateContent } = createContentAggregator();
|
|
89
|
+
|
|
90
|
+
const run = await Run.create<t.IState>({
|
|
91
|
+
runId: 'my-run-001',
|
|
92
|
+
graphConfig: {
|
|
93
|
+
type: 'standard',
|
|
94
|
+
llmConfig: {
|
|
95
|
+
provider: Providers.ANTHROPIC,
|
|
96
|
+
model: 'claude-sonnet-4-20250514',
|
|
97
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
98
|
+
},
|
|
99
|
+
instructions: 'You are a helpful AI assistant.',
|
|
100
|
+
},
|
|
101
|
+
returnContent: true,
|
|
102
|
+
customHandlers: {
|
|
103
|
+
[GraphEvents.TOOL_END]: new ToolEndHandler(),
|
|
104
|
+
[GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
|
|
105
|
+
[GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
|
|
106
|
+
[GraphEvents.ON_RUN_STEP]: {
|
|
107
|
+
handle: (event: string, data: t.RunStep) => aggregateContent({ event, data }),
|
|
108
|
+
},
|
|
109
|
+
[GraphEvents.ON_RUN_STEP_DELTA]: {
|
|
110
|
+
handle: (event: string, data: t.RunStepDeltaEvent) => aggregateContent({ event, data }),
|
|
111
|
+
},
|
|
112
|
+
[GraphEvents.ON_MESSAGE_DELTA]: {
|
|
113
|
+
handle: (event: string, data: t.MessageDeltaEvent) => aggregateContent({ event, data }),
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const result = await run.processStream(
|
|
119
|
+
{ messages: [new HumanMessage('What is the capital of France?')] },
|
|
120
|
+
{ version: 'v2', configurable: { user_id: 'user-123', thread_id: 'conv-1' } }
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
console.log('Response:', contentParts);
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Multi-Agent with Handoffs
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import { Run, Providers } from '@illuma-ai/agents';
|
|
130
|
+
import type * as t from '@illuma-ai/agents';
|
|
131
|
+
|
|
132
|
+
const run = await Run.create({
|
|
133
|
+
runId: 'multi-agent-001',
|
|
134
|
+
graphConfig: {
|
|
135
|
+
type: 'multi-agent',
|
|
136
|
+
agents: [
|
|
137
|
+
{
|
|
138
|
+
agentId: 'flight_assistant',
|
|
139
|
+
provider: Providers.ANTHROPIC,
|
|
140
|
+
clientOptions: { modelName: 'claude-haiku-4-5' },
|
|
141
|
+
instructions: 'You are a flight booking assistant.',
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
agentId: 'hotel_assistant',
|
|
145
|
+
provider: Providers.ANTHROPIC,
|
|
146
|
+
clientOptions: { modelName: 'claude-haiku-4-5' },
|
|
147
|
+
instructions: 'You are a hotel booking assistant.',
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
edges: [
|
|
151
|
+
{
|
|
152
|
+
from: 'flight_assistant',
|
|
153
|
+
to: 'hotel_assistant',
|
|
154
|
+
description: 'Transfer when user needs hotel help',
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
from: 'hotel_assistant',
|
|
158
|
+
to: 'flight_assistant',
|
|
159
|
+
description: 'Transfer when user needs flight help',
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
},
|
|
163
|
+
customHandlers: { /* ...event handlers... */ },
|
|
164
|
+
returnContent: true,
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Parallel Fan-out / Fan-in
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
const run = await Run.create({
|
|
172
|
+
runId: 'parallel-001',
|
|
173
|
+
graphConfig: {
|
|
174
|
+
type: 'multi-agent',
|
|
175
|
+
agents: [
|
|
176
|
+
{ agentId: 'coordinator', provider: Providers.ANTHROPIC, clientOptions: { modelName: 'claude-haiku-4-5' }, instructions: 'Coordinate research tasks.' },
|
|
177
|
+
{ agentId: 'analyst_a', provider: Providers.ANTHROPIC, clientOptions: { modelName: 'claude-haiku-4-5' }, instructions: 'Financial analysis.' },
|
|
178
|
+
{ agentId: 'analyst_b', provider: Providers.ANTHROPIC, clientOptions: { modelName: 'claude-haiku-4-5' }, instructions: 'Technical analysis.' },
|
|
179
|
+
{ agentId: 'summarizer', provider: Providers.ANTHROPIC, clientOptions: { modelName: 'claude-haiku-4-5' }, instructions: 'Synthesize all findings.' },
|
|
180
|
+
],
|
|
181
|
+
edges: [
|
|
182
|
+
{ from: 'coordinator', to: ['analyst_a', 'analyst_b'], edgeType: 'direct' }, // Fan-out (parallel)
|
|
183
|
+
{ from: ['analyst_a', 'analyst_b'], to: 'summarizer', edgeType: 'direct' }, // Fan-in
|
|
184
|
+
],
|
|
185
|
+
},
|
|
186
|
+
customHandlers: { /* ... */ },
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Using Tools
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
import { createCodeExecutionTool, Calculator } from '@illuma-ai/agents';
|
|
194
|
+
|
|
195
|
+
const run = await Run.create<t.IState>({
|
|
196
|
+
runId: 'tools-001',
|
|
197
|
+
graphConfig: {
|
|
198
|
+
type: 'standard',
|
|
199
|
+
llmConfig: { provider: Providers.OPENAI, model: 'gpt-4o' },
|
|
200
|
+
instructions: 'You can execute code and do math.',
|
|
201
|
+
tools: [createCodeExecutionTool(), new Calculator()],
|
|
202
|
+
},
|
|
203
|
+
customHandlers: { /* ... */ },
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Extended Thinking
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
const run = await Run.create<t.IState>({
|
|
211
|
+
runId: 'thinking-001',
|
|
212
|
+
graphConfig: {
|
|
213
|
+
type: 'standard',
|
|
214
|
+
llmConfig: {
|
|
215
|
+
provider: Providers.ANTHROPIC,
|
|
216
|
+
model: 'claude-3-7-sonnet-latest',
|
|
217
|
+
thinking: { type: 'enabled', budget_tokens: 5000 },
|
|
218
|
+
},
|
|
219
|
+
instructions: 'Think through problems carefully.',
|
|
220
|
+
},
|
|
221
|
+
customHandlers: {
|
|
222
|
+
// ...standard handlers...
|
|
223
|
+
[GraphEvents.ON_REASONING_DELTA]: {
|
|
224
|
+
handle: (event: string, data: t.ReasoningDeltaEvent) => {
|
|
225
|
+
// Receive thinking/reasoning tokens as they stream
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Structured Output
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
const run = await Run.create<t.IState>({
|
|
236
|
+
runId: 'structured-001',
|
|
237
|
+
graphConfig: {
|
|
238
|
+
type: 'standard',
|
|
239
|
+
agents: [{
|
|
240
|
+
agentId: 'analyzer',
|
|
241
|
+
provider: Providers.OPENAI,
|
|
242
|
+
clientOptions: { model: 'gpt-4o' },
|
|
243
|
+
instructions: 'Analyze sentiment.',
|
|
244
|
+
structuredOutput: {
|
|
245
|
+
schema: {
|
|
246
|
+
type: 'object',
|
|
247
|
+
properties: {
|
|
248
|
+
sentiment: { type: 'string', enum: ['positive', 'negative', 'neutral'] },
|
|
249
|
+
confidence: { type: 'number' },
|
|
250
|
+
},
|
|
251
|
+
required: ['sentiment', 'confidence'],
|
|
252
|
+
},
|
|
253
|
+
mode: 'auto',
|
|
254
|
+
strict: true,
|
|
255
|
+
},
|
|
256
|
+
}],
|
|
257
|
+
},
|
|
258
|
+
customHandlers: {
|
|
259
|
+
[GraphEvents.ON_STRUCTURED_OUTPUT]: {
|
|
260
|
+
handle: (_event: string, data: unknown) => console.log('Result:', data),
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Providers
|
|
269
|
+
|
|
270
|
+
| Provider | Enum | Notes |
|
|
271
|
+
|----------|------|-------|
|
|
272
|
+
| OpenAI | `Providers.OPENAI` | GPT-4o, o1, o3 |
|
|
273
|
+
| Anthropic | `Providers.ANTHROPIC` | Claude 4, Sonnet, Haiku — thinking, caching, web search |
|
|
274
|
+
| AWS Bedrock | `Providers.BEDROCK` | Claude via Bedrock — caching, reasoning |
|
|
275
|
+
| Google Gemini | `Providers.GOOGLE` | Gemini Pro, Flash |
|
|
276
|
+
| Vertex AI | `Providers.VERTEXAI` | Google models via GCP |
|
|
277
|
+
| Azure OpenAI | `Providers.AZURE` | OpenAI models via Azure |
|
|
278
|
+
| Mistral | `Providers.MISTRALAI` | Large, Medium, Small |
|
|
279
|
+
| DeepSeek | `Providers.DEEPSEEK` | Reasoning models |
|
|
280
|
+
| xAI | `Providers.XAI` | Grok |
|
|
281
|
+
| OpenRouter | `Providers.OPENROUTER` | Multi-model routing |
|
|
282
|
+
| Moonshot | `Providers.MOONSHOT` | Moonshot AI |
|
|
283
|
+
|
|
284
|
+
**Provider config examples:**
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
// OpenAI
|
|
288
|
+
{ provider: Providers.OPENAI, clientOptions: { model: 'gpt-4o', apiKey: '...' } }
|
|
289
|
+
|
|
290
|
+
// Anthropic
|
|
291
|
+
{ provider: Providers.ANTHROPIC, clientOptions: { modelName: 'claude-sonnet-4-20250514', apiKey: '...' } }
|
|
292
|
+
|
|
293
|
+
// AWS Bedrock
|
|
294
|
+
{ provider: Providers.BEDROCK, clientOptions: { model: 'us.anthropic.claude-sonnet-4-20250514-v1:0', region: 'us-east-1' } }
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Multi-Agent Patterns
|
|
300
|
+
|
|
301
|
+
### Edge Types
|
|
302
|
+
|
|
303
|
+
| Type | Behavior |
|
|
304
|
+
|------|----------|
|
|
305
|
+
| **Handoff** (default) | LLM decides when to transfer — auto-generates `transfer_to_<agent>` tools |
|
|
306
|
+
| **Direct** | Fixed routing — agents run in sequence or parallel |
|
|
307
|
+
|
|
308
|
+
### Handoff (Dynamic)
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
{ from: 'triage', to: 'billing', description: 'Transfer for billing questions' }
|
|
312
|
+
// → triage agent gets a transfer_to_billing tool it can call
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Sequential Pipeline
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
{ from: 'drafter', to: 'reviewer', edgeType: 'direct', prompt: 'Review the draft above.' }
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Fan-out / Fan-in (Parallel)
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
{ from: 'coordinator', to: ['analyst_a', 'analyst_b'], edgeType: 'direct' } // parallel
|
|
325
|
+
{ from: ['analyst_a', 'analyst_b'], to: 'summarizer', edgeType: 'direct', prompt: '{results}' } // join
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Use `{results}` in prompts to inject collected output from parallel agents.
|
|
329
|
+
|
|
330
|
+
### Conditional Routing
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
{
|
|
334
|
+
from: 'router',
|
|
335
|
+
to: ['fast_model', 'powerful_model'],
|
|
336
|
+
condition: (state) => state.messages.at(-1)?.content.length > 500 ? 'powerful_model' : 'fast_model',
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Hybrid
|
|
341
|
+
|
|
342
|
+
Agents with both handoff and direct edges use **exclusive routing**: if a handoff fires, only the handoff destination runs; otherwise direct edges execute.
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## Built-in Tools
|
|
347
|
+
|
|
348
|
+
| Tool | Import | Description |
|
|
349
|
+
|------|--------|-------------|
|
|
350
|
+
| **Code Executor** | `createCodeExecutionTool()` | Sandboxed execution in 12+ languages (Python, JS, TS, C, C++, Java, PHP, Rust, Go, D, Fortran, R) |
|
|
351
|
+
| **Calculator** | `new Calculator()` | Math expressions via [mathjs](https://mathjs.org/) |
|
|
352
|
+
| **Browser Tools** | `createBrowserTools()` | 12 browser actions (navigate, click, type, screenshot, etc.) |
|
|
353
|
+
| **Tool Search** | `createToolSearchTool()` | BM25-ranked discovery for large tool registries |
|
|
354
|
+
| **Programmatic Tool Calling** | `createProgrammaticToolCallingTool()` | LLM writes Python to call tools as async functions |
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## Event System
|
|
359
|
+
|
|
360
|
+
Register handlers to receive real-time streaming events:
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
const customHandlers = {
|
|
364
|
+
[GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(), // Token-by-token streaming
|
|
365
|
+
[GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(usageArray), // Usage metadata
|
|
366
|
+
[GraphEvents.TOOL_END]: new ToolEndHandler(), // Tool results
|
|
367
|
+
[GraphEvents.ON_RUN_STEP]: { handle: (e, data) => ... }, // New run step
|
|
368
|
+
[GraphEvents.ON_RUN_STEP_DELTA]: { handle: (e, data) => ... }, // Step delta (tool args)
|
|
369
|
+
[GraphEvents.ON_MESSAGE_DELTA]: { handle: (e, data) => ... }, // Text delta
|
|
370
|
+
[GraphEvents.ON_REASONING_DELTA]:{ handle: (e, data) => ... }, // Thinking delta
|
|
371
|
+
[GraphEvents.ON_AGENT_UPDATE]: { handle: (e, data) => ... }, // Agent switch
|
|
372
|
+
[GraphEvents.ON_STRUCTURED_OUTPUT]: { handle: (e, data) => ... },// Structured JSON
|
|
373
|
+
};
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
Use `createContentAggregator()` to automatically collect deltas into a complete response:
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
const { contentParts, aggregateContent } = createContentAggregator();
|
|
380
|
+
// Pass aggregateContent into your handlers
|
|
381
|
+
// After streaming, contentParts has the full structured response
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
## Prompt Caching
|
|
387
|
+
|
|
388
|
+
Caching is **automatic** for Anthropic and Bedrock providers:
|
|
389
|
+
|
|
390
|
+
- System messages get cache control markers
|
|
391
|
+
- Last 2 conversation messages get cache breakpoints
|
|
392
|
+
- Use `dynamicContext` for per-request data (keeps system prompt cacheable):
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
{
|
|
396
|
+
instructions: 'You are a helpful assistant.', // Cached
|
|
397
|
+
dynamicContext: `Current time: ${new Date().toISOString()}`, // Not cached
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## Structured Output Modes
|
|
404
|
+
|
|
405
|
+
| Mode | Description |
|
|
406
|
+
|------|-------------|
|
|
407
|
+
| `'auto'` | Auto-selects best strategy per provider **(default)** |
|
|
408
|
+
| `'tool'` | Uses tool calling — universal compatibility |
|
|
409
|
+
| `'provider'` | Provider-native JSON mode |
|
|
410
|
+
| `'native'` | Constrained decoding — guaranteed schema compliance |
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
structuredOutput: {
|
|
414
|
+
schema: { /* JSON Schema */ },
|
|
415
|
+
mode: 'auto',
|
|
416
|
+
strict: true,
|
|
417
|
+
handleErrors: true, // Auto-retry on validation failure
|
|
418
|
+
maxRetries: 2,
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
## Observability
|
|
425
|
+
|
|
426
|
+
Set these env vars to enable automatic Langfuse tracing:
|
|
427
|
+
|
|
428
|
+
```env
|
|
429
|
+
LANGFUSE_SECRET_KEY=sk-lf-...
|
|
430
|
+
LANGFUSE_PUBLIC_KEY=pk-lf-...
|
|
431
|
+
LANGFUSE_BASE_URL=https://cloud.langfuse.com
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
Each trace captures `userId`, `sessionId`, `messageId`, and full LangChain callback spans.
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## Title Generation
|
|
439
|
+
|
|
440
|
+
Generate conversation titles from the first exchange:
|
|
441
|
+
|
|
442
|
+
```typescript
|
|
443
|
+
const { title, language } = await run.generateTitle({
|
|
444
|
+
provider: Providers.ANTHROPIC,
|
|
445
|
+
inputText: userMessage,
|
|
446
|
+
contentParts,
|
|
447
|
+
titleMethod: TitleMethod.COMPLETION,
|
|
448
|
+
clientOptions: { model: 'claude-3-5-haiku-latest' },
|
|
449
|
+
});
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
## API Exports
|
|
455
|
+
|
|
456
|
+
```typescript
|
|
457
|
+
// Core
|
|
458
|
+
export { Run } from '@illuma-ai/agents';
|
|
459
|
+
export { ChatModelStreamHandler, createContentAggregator, SplitStreamHandler } from '@illuma-ai/agents';
|
|
460
|
+
export { HandlerRegistry, ModelEndHandler, ToolEndHandler } from '@illuma-ai/agents';
|
|
461
|
+
|
|
462
|
+
// Tools
|
|
463
|
+
export { createCodeExecutionTool, Calculator, createBrowserTools } from '@illuma-ai/agents';
|
|
464
|
+
export { createToolSearchTool, createProgrammaticToolCallingTool } from '@illuma-ai/agents';
|
|
465
|
+
|
|
466
|
+
// Graphs
|
|
467
|
+
export { StandardGraph, MultiAgentGraph } from '@illuma-ai/agents';
|
|
468
|
+
|
|
469
|
+
// LLM
|
|
470
|
+
export { getChatModelClass, llmProviders } from '@illuma-ai/agents';
|
|
471
|
+
|
|
472
|
+
// Enums & Constants
|
|
473
|
+
export { GraphEvents, Providers, ContentTypes, StepTypes, TitleMethod, Constants } from '@illuma-ai/agents';
|
|
474
|
+
|
|
475
|
+
// Types
|
|
476
|
+
export type { IState, RunConfig, AgentInputs, GraphEdge, StructuredOutputConfig } from '@illuma-ai/agents';
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
---
|
|
480
|
+
|
|
481
|
+
## License
|
|
482
|
+
|
|
483
|
+
UNLICENSED — Proprietary software. All rights reserved @TeamIlluma.
|
|
484
|
+
|
|
485
|
+
|