or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

agents.mdchat-engines.mddocument-processing.mdembeddings.mdindex.mdllm-integration.mdquery-engines.mdresponse-synthesis.mdsettings.mdstorage.mdtools.mdvector-indexing.md
tile.json

agents.mddocs/

0

# Agent Framework

1

2

ReAct agents and task execution system for complex reasoning and multi-step operations with tool usage in LlamaIndex.TS.

3

4

## Import

5

6

```typescript

7

import { ReActAgent } from "llamaindex/agent";

8

// Or main package import

9

import { ReActAgent } from "llamaindex";

10

```

11

12

## Overview

13

14

The agent framework in LlamaIndex.TS implements ReAct (Reasoning + Acting) agents that can break down complex problems, use tools, and execute multi-step workflows. Agents can access various tools including query engines, calculators, APIs, and custom functions.

15

16

## Task-Based Agent Architecture

17

18

LlamaIndex.TS implements a sophisticated task-based agent system built around the ReAct (Reasoning + Acting) pattern with support for streaming, parallel execution, and complex multi-step workflows.

19

20

### AgentRunner

21

22

The core agent execution engine that manages task scheduling and execution.

23

24

```typescript { .api }

25

class AgentRunner<AI = LLM, Store = ChatMemoryBuffer, AdditionalMessageOptions = object, AdditionalChatOptions = object> {

26

constructor(params: AgentParamsBase<AI, AdditionalMessageOptions, AdditionalChatOptions>);

27

28

chat(message: string, options?: AdditionalChatOptions & { stream?: false }): Promise<AgentChatResponse>;

29

chat(message: string, options: AdditionalChatOptions & { stream: true }): AsyncIterable<AgentTaskStepOutput>;

30

31

createTask(input: string, options?: AdditionalChatOptions): Task<AdditionalMessageOptions>;

32

33

finalize(): void;

34

}

35

```

36

37

### ReActAgent

38

39

The main ReAct agent implementation that uses structured reasoning and tool execution.

40

41

```typescript { .api }

42

class ReActAgent extends AgentRunner {

43

constructor(params: ReACTAgentParams);

44

45

// Inherited from AgentRunner

46

chat(message: string, options?: AgentChatOptions): Promise<AgentChatResponse>;

47

achat(message: string, options?: AgentChatOptions): AsyncIterable<AgentTaskStepOutput>;

48

createTask(input: string, options?: AgentChatOptions): Task;

49

50

// Agent properties

51

readonly worker: ReACTAgentWorker;

52

readonly tools: BaseToolWithCall[];

53

readonly llm: LLM;

54

readonly memory: ChatMemoryBuffer;

55

readonly verbose: boolean;

56

}

57

```

58

59

### Task System

60

61

The task system enables complex multi-step agent workflows with step-by-step execution and monitoring.

62

63

```typescript { .api }

64

class Task<AdditionalMessageOptions = object> {

65

taskId: string;

66

input: string;

67

memory: ChatMemoryBuffer;

68

extraState: Record<string, any>;

69

70

step(): Promise<TaskStepOutput>;

71

stepAsync(): AsyncIterable<TaskStepOutput>;

72

run(): Promise<AgentChatResponse>;

73

runAsync(): AsyncIterable<TaskStepOutput>;

74

75

isFinished(): boolean;

76

getResult(): TaskStepOutput | undefined;

77

}

78

79

interface TaskStepOutput {

80

output: AgentChatResponse;

81

taskStep: TaskStep;

82

nextSteps: TaskStep[];

83

isLast: boolean;

84

}

85

86

interface TaskStep<Model = LLM, Store = ChatMemoryBuffer, AdditionalMessageOptions = object, AdditionalChatOptions = object> {

87

taskId: string;

88

stepId: string;

89

input: string;

90

stepState: Record<string, any>;

91

92

// Context for step execution

93

context: AgentTaskContext<Model, Store, AdditionalMessageOptions, AdditionalChatOptions>;

94

}

95

```

96

97

## Agent Parameters and Types

98

99

### ReACTAgentParams

100

101

Configuration parameters for ReAct agents with support for static tools or dynamic tool retrieval.

102

103

```typescript { .api }

104

type ReACTAgentParams = AgentParamsBase<LLM, object, object> & {

105

maxIterations?: number;

106

reactSystemHeaderStr?: string;

107

reactSystemPrompt?: string;

108

};

109

110

type AgentParamsBase<AI, AdditionalMessageOptions, AdditionalChatOptions> =

111

| {

112

llm?: AI;

113

chatHistory?: ChatMessage<AdditionalMessageOptions>[];

114

systemPrompt?: MessageContent;

115

verbose?: boolean;

116

tools: BaseToolWithCall[];

117

additionalChatOptions?: AdditionalChatOptions;

118

}

119

| {

120

llm?: AI;

121

chatHistory?: ChatMessage<AdditionalMessageOptions>[];

122

systemPrompt?: MessageContent;

123

verbose?: boolean;

124

toolRetriever: ObjectRetriever<BaseToolWithCall>;

125

additionalChatOptions?: AdditionalChatOptions;

126

};

127

```

128

129

### Agent Response Types

130

131

```typescript { .api }

132

interface AgentChatResponse {

133

response: string;

134

sources: ToolOutput[];

135

sourceNodes?: NodeWithScore[];

136

isStreamingFinished?: boolean;

137

}

138

139

interface AgentChatOptions {

140

chatHistory?: ChatMessage[];

141

toolChoice?: ToolChoice | "auto" | "none";

142

stream?: boolean;

143

}

144

145

interface AgentTaskStepOutput {

146

output: AgentChatResponse;

147

taskStep: TaskStep;

148

nextSteps: TaskStep[];

149

isLast: boolean;

150

}

151

```

152

153

### Tool System

154

155

The tool system supports both static tool sets and dynamic tool retrieval with sophisticated parameter validation.

156

157

```typescript { .api }

158

interface BaseToolWithCall {

159

metadata: ToolMetadata;

160

call(input: string): Promise<ToolOutput>;

161

}

162

163

interface ToolMetadata {

164

name: string;

165

description: string;

166

parameters?: ToolMetadataParameters;

167

fnSchema?: any;

168

}

169

170

interface ToolMetadataParameters {

171

type: "object";

172

properties: Record<string, ToolParameterProperty>;

173

required?: string[];

174

}

175

176

interface ToolParameterProperty {

177

type: string;

178

description?: string;

179

enum?: string[];

180

items?: ToolParameterProperty;

181

}

182

183

interface ToolOutput {

184

content: string;

185

tool: BaseToolWithCall;

186

rawInput: string;

187

rawOutput?: any;

188

isError?: boolean;

189

}

190

```

191

192

### Function Tool Creation

193

194

```typescript { .api }

195

class FunctionTool<T = any, R = any> implements BaseToolWithCall {

196

static from<T, R>(

197

fn: (params: T) => R | Promise<R>,

198

metadata: ToolMetadata

199

): FunctionTool<T, R>;

200

201

constructor(

202

fn: (params: T) => R | Promise<R>,

203

metadata: ToolMetadata

204

);

205

206

metadata: ToolMetadata;

207

call(input: string): Promise<ToolOutput>;

208

}

209

```

210

211

### Agent Worker System

212

213

The worker system enables custom agent implementations and task scheduling strategies.

214

215

```typescript { .api }

216

abstract class AgentWorker<

217

AI = LLM,

218

Store = ChatMemoryBuffer,

219

AdditionalMessageOptions = object,

220

AdditionalChatOptions = object

221

> {

222

abstract initializeStep(task: Task<AdditionalMessageOptions>): TaskStep<AI, Store, AdditionalMessageOptions, AdditionalChatOptions>;

223

224

abstract runStep(

225

step: TaskStep<AI, Store, AdditionalMessageOptions, AdditionalChatOptions>,

226

task: Task<AdditionalMessageOptions>

227

): Promise<TaskStepOutput>;

228

229

abstract streamStep(

230

step: TaskStep<AI, Store, AdditionalMessageOptions, AdditionalChatOptions>,

231

task: Task<AdditionalMessageOptions>

232

): AsyncIterable<TaskStepOutput>;

233

234

abstract finalizeTask(task: Task<AdditionalMessageOptions>): void;

235

}

236

237

class ReACTAgentWorker extends AgentWorker {

238

constructor(

239

tools: BaseToolWithCall[] | ObjectRetriever<BaseToolWithCall>,

240

llm: LLM,

241

options?: {

242

maxIterations?: number;

243

reactSystemHeaderStr?: string;

244

reactSystemPrompt?: string;

245

verbose?: boolean;

246

}

247

);

248

}

249

```

250

251

## Basic Usage

252

253

### Simple Agent with Query Tool

254

255

```typescript

256

import { ReActAgent, VectorStoreIndex, Document, QueryEngineTool } from "llamaindex";

257

258

// Create knowledge base

259

const documents = [

260

new Document({ text: "The capital of France is Paris." }),

261

new Document({ text: "Python is a programming language." }),

262

new Document({ text: "Machine learning is a subset of AI." }),

263

];

264

265

const index = await VectorStoreIndex.fromDocuments(documents);

266

267

// Create query engine tool

268

const queryTool = new QueryEngineTool({

269

queryEngine: index.asQueryEngine(),

270

metadata: {

271

name: "knowledge_search",

272

description: "Search the knowledge base for factual information",

273

},

274

});

275

276

// Create agent

277

const agent = new ReActAgent({

278

tools: [queryTool],

279

llm: /* your LLM instance */,

280

verbose: true, // Enable verbose logging

281

});

282

283

// Use the agent

284

const response = await agent.chat("What is the capital of France and how is it related to programming?");

285

console.log("Agent response:", response.response);

286

287

// View sources used

288

console.log("Tools used:", response.sources.map(source => source.tool.metadata.name));

289

```

290

291

### Agent with Multiple Tools

292

293

```typescript

294

import { ReActAgent, FunctionTool, QueryEngineTool } from "llamaindex";

295

296

// Create calculator tool

297

const calculatorTool = FunctionTool.from(

298

({ a, b, operation }: { a: number; b: number; operation: string }) => {

299

switch (operation) {

300

case "add": return a + b;

301

case "subtract": return a - b;

302

case "multiply": return a * b;

303

case "divide": return a / b;

304

default: throw new Error("Unknown operation");

305

}

306

},

307

{

308

name: "calculator",

309

description: "Perform basic arithmetic operations",

310

parameters: {

311

type: "object",

312

properties: {

313

a: { type: "number", description: "First number" },

314

b: { type: "number", description: "Second number" },

315

operation: {

316

type: "string",

317

description: "Operation to perform",

318

enum: ["add", "subtract", "multiply", "divide"]

319

},

320

},

321

required: ["a", "b", "operation"],

322

},

323

}

324

);

325

326

// Create web search tool (example)

327

const webSearchTool = FunctionTool.from(

328

async ({ query }: { query: string }) => {

329

// Implement web search logic

330

return `Search results for: ${query}`;

331

},

332

{

333

name: "web_search",

334

description: "Search the web for current information",

335

parameters: {

336

type: "object",

337

properties: {

338

query: { type: "string", description: "Search query" },

339

},

340

required: ["query"],

341

},

342

}

343

);

344

345

// Create multi-tool agent

346

const multiToolAgent = new ReActAgent({

347

tools: [queryTool, calculatorTool, webSearchTool],

348

llm: /* your LLM */,

349

maxIterations: 10,

350

});

351

352

// Complex query requiring multiple tools

353

const response = await multiToolAgent.chat(

354

"Search my knowledge base for information about Python, then calculate 15 * 23, and search the web for the latest Python version."

355

);

356

```

357

358

## Advanced Usage

359

360

### Custom System Prompt

361

362

```typescript

363

const customAgent = new ReActAgent({

364

tools: [queryTool, calculatorTool],

365

llm: /* your LLM */,

366

systemPrompt: `

367

You are a helpful research assistant with access to tools.

368

369

Guidelines:

370

- Always think step by step

371

- Use tools when you need specific information or calculations

372

- Provide clear explanations of your reasoning

373

- If you can't find information, say so clearly

374

- Cite sources when using tool results

375

376

Available tools: {tool_desc}

377

`,

378

});

379

```

380

381

### Task-Based Agent Usage

382

383

```typescript

384

// Create a task for complex multi-step processing

385

const task = agent.createTask(

386

"Analyze the performance metrics in my knowledge base and calculate the year-over-year growth rate."

387

);

388

389

// Execute task step by step

390

while (!task.isFinished()) {

391

const step = await task.step();

392

console.log(`Step ${step.stepId}:`, step.output);

393

}

394

395

const result = task.getResult();

396

console.log("Final result:", result);

397

```

398

399

### Streaming Agent Responses

400

401

```typescript

402

// Stream agent responses for real-time interaction

403

for await (const chunk of agent.achat("Explain machine learning and calculate 2 + 2")) {

404

console.log("Chunk:", chunk.response);

405

406

if (chunk.sources && chunk.sources.length > 0) {

407

console.log("Tool used:", chunk.sources[0].tool.metadata.name);

408

}

409

}

410

```

411

412

## Custom Tools

413

414

### Function Tool Creation

415

416

```typescript

417

import { FunctionTool } from "llamaindex";

418

419

// Simple function tool

420

const timestampTool = FunctionTool.from(

421

() => new Date().toISOString(),

422

{

423

name: "get_timestamp",

424

description: "Get the current timestamp",

425

}

426

);

427

428

// Complex function tool with validation

429

const dataAnalysisTool = FunctionTool.from(

430

async ({ data, analysis_type }: { data: number[]; analysis_type: string }) => {

431

if (!data || data.length === 0) {

432

throw new Error("Data array cannot be empty");

433

}

434

435

switch (analysis_type) {

436

case "mean":

437

return data.reduce((a, b) => a + b, 0) / data.length;

438

case "max":

439

return Math.max(...data);

440

case "min":

441

return Math.min(...data);

442

case "sum":

443

return data.reduce((a, b) => a + b, 0);

444

default:

445

throw new Error(`Unknown analysis type: ${analysis_type}`);

446

}

447

},

448

{

449

name: "data_analysis",

450

description: "Perform statistical analysis on numerical data",

451

parameters: {

452

type: "object",

453

properties: {

454

data: {

455

type: "array",

456

items: { type: "number" },

457

description: "Array of numbers to analyze",

458

},

459

analysis_type: {

460

type: "string",

461

enum: ["mean", "max", "min", "sum"],

462

description: "Type of analysis to perform",

463

},

464

},

465

required: ["data", "analysis_type"],

466

},

467

}

468

);

469

```

470

471

### Custom Tool Class

472

473

```typescript

474

import { BaseTool, ToolMetadata, ToolOutput } from "llamaindex";

475

476

class DatabaseTool implements BaseTool {

477

metadata: ToolMetadata = {

478

name: "database_query",

479

description: "Execute SQL queries against the database",

480

parameters: {

481

type: "object",

482

properties: {

483

query: { type: "string", description: "SQL query to execute" },

484

table: { type: "string", description: "Table to query" },

485

},

486

required: ["query"],

487

},

488

};

489

490

async call(input: string): Promise<ToolOutput> {

491

try {

492

const params = JSON.parse(input);

493

494

// Implement database query logic

495

const result = await this.executeQuery(params.query, params.table);

496

497

return {

498

content: JSON.stringify(result),

499

tool: this,

500

rawInput: input,

501

rawOutput: result,

502

};

503

} catch (error) {

504

return {

505

content: `Database error: ${error.message}`,

506

tool: this,

507

rawInput: input,

508

isError: true,

509

};

510

}

511

}

512

513

private async executeQuery(query: string, table?: string): Promise<any> {

514

// Implement your database query logic here

515

return { rows: [], count: 0 };

516

}

517

}

518

519

// Use custom tool

520

const dbTool = new DatabaseTool();

521

const agent = new ReActAgent({

522

tools: [dbTool],

523

llm: /* your LLM */,

524

});

525

```

526

527

## Agent Memory and State

528

529

### Persistent Memory

530

531

```typescript

532

import { ChatMemoryBuffer } from "llamaindex";

533

534

// Create agent with persistent memory

535

const persistentMemory = new ChatMemoryBuffer({

536

tokenLimit: 4000,

537

chatHistory: [], // Start with empty history

538

});

539

540

const agent = new ReActAgent({

541

tools: [queryTool],

542

llm: /* your LLM */,

543

memory: persistentMemory,

544

});

545

546

// The agent will remember conversation context across sessions

547

await agent.chat("My name is John.");

548

await agent.chat("What's my name?"); // Agent remembers "John"

549

```

550

551

### Memory Management

552

553

```typescript

554

// Save agent memory state

555

const saveAgentState = (agent: ReActAgent, filename: string) => {

556

const state = {

557

chatHistory: agent.memory.getAll(),

558

timestamp: new Date().toISOString(),

559

};

560

561

// Save to file or database

562

// fs.writeFileSync(filename, JSON.stringify(state, null, 2));

563

};

564

565

// Load agent memory state

566

const loadAgentState = (agent: ReActAgent, stateData: any) => {

567

agent.memory.set(stateData.chatHistory);

568

};

569

```

570

571

## Error Handling and Robustness

572

573

### Tool Error Handling

574

575

```typescript

576

// Create robust tools with error handling

577

const robustCalculatorTool = FunctionTool.from(

578

({ expression }: { expression: string }) => {

579

try {

580

// Safely evaluate mathematical expressions

581

const result = eval(expression.replace(/[^0-9+\-*/().\s]/g, ''));

582

583

if (typeof result !== 'number' || !isFinite(result)) {

584

throw new Error("Invalid mathematical expression");

585

}

586

587

return result;

588

} catch (error) {

589

throw new Error(`Calculation error: ${error.message}`);

590

}

591

},

592

{

593

name: "safe_calculator",

594

description: "Safely evaluate mathematical expressions",

595

parameters: {

596

type: "object",

597

properties: {

598

expression: {

599

type: "string",

600

description: "Mathematical expression to evaluate (numbers and +, -, *, /, parentheses only)",

601

},

602

},

603

required: ["expression"],

604

},

605

}

606

);

607

```

608

609

### Agent Error Recovery

610

611

```typescript

612

const robustAgentChat = async (agent: ReActAgent, message: string): Promise<AgentChatResponse | null> => {

613

try {

614

const response = await agent.chat(message);

615

616

// Validate response

617

if (!response.response || response.response.trim().length === 0) {

618

console.warn("Empty response from agent");

619

return null;

620

}

621

622

return response;

623

} catch (error) {

624

console.error("Agent error:", error);

625

626

// Handle specific error types

627

if (error.message.includes("max_iterations")) {

628

console.error("Agent exceeded maximum iterations");

629

// Possibly retry with different parameters

630

} else if (error.message.includes("tool_error")) {

631

console.error("Tool execution failed");

632

// Possibly retry without problematic tools

633

}

634

635

return null;

636

}

637

};

638

```

639

640

## Performance Optimization

641

642

### Tool Selection Optimization

643

644

```typescript

645

import { ObjectRetriever } from "llamaindex";

646

647

// Create tool retriever for large tool sets

648

const toolRetriever = new ObjectRetriever({

649

objects: [queryTool, calculatorTool, webSearchTool, /* many more tools */],

650

retrieveTopK: 3, // Only consider top 3 most relevant tools

651

});

652

653

const optimizedAgent = new ReActAgent({

654

tools: [], // Empty - tools will be retrieved dynamically

655

toolRetriever,

656

llm: /* your LLM */,

657

});

658

```

659

660

### Parallel Tool Execution

661

662

```typescript

663

// Custom agent with parallel tool execution capability

664

class ParallelReActAgent extends ReActAgent {

665

async executeToolsInParallel(toolCalls: Array<{tool: BaseTool, input: string}>) {

666

const results = await Promise.all(

667

toolCalls.map(async ({ tool, input }) => {

668

try {

669

return await tool.call(input);

670

} catch (error) {

671

return {

672

content: `Error: ${error.message}`,

673

tool,

674

rawInput: input,

675

isError: true,

676

};

677

}

678

})

679

);

680

681

return results;

682

}

683

}

684

```

685

686

## Integration Patterns

687

688

### Agent Workflows

689

690

```typescript

691

// Create a workflow with multiple specialized agents

692

class AgentWorkflow {

693

private researchAgent: ReActAgent;

694

private analysisAgent: ReActAgent;

695

private reportAgent: ReActAgent;

696

697

constructor() {

698

this.researchAgent = new ReActAgent({

699

tools: [webSearchTool, queryTool],

700

llm: /* your LLM */,

701

systemPrompt: "You are a research specialist. Gather comprehensive information.",

702

});

703

704

this.analysisAgent = new ReActAgent({

705

tools: [calculatorTool, dataAnalysisTool],

706

llm: /* your LLM */,

707

systemPrompt: "You are a data analyst. Analyze and interpret information.",

708

});

709

710

this.reportAgent = new ReActAgent({

711

tools: [], // No tools, just synthesis

712

llm: /* your LLM */,

713

systemPrompt: "You are a report writer. Synthesize information into clear reports.",

714

});

715

}

716

717

async executeWorkflow(query: string): Promise<string> {

718

// Step 1: Research

719

const researchResponse = await this.researchAgent.chat(`Research: ${query}`);

720

721

// Step 2: Analysis

722

const analysisResponse = await this.analysisAgent.chat(

723

`Analyze this research: ${researchResponse.response}`

724

);

725

726

// Step 3: Report

727

const reportResponse = await this.reportAgent.chat(

728

`Create a report based on this research and analysis:

729

Research: ${researchResponse.response}

730

Analysis: ${analysisResponse.response}`

731

);

732

733

return reportResponse.response;

734

}

735

}

736

```

737

738

## Best Practices

739

740

### Agent Configuration

741

742

```typescript

743

// Configure agents for different use cases

744

const createAgent = (useCase: string, tools: BaseTool[]) => {

745

const baseConfig = {

746

tools,

747

llm: /* your LLM */,

748

verbose: process.env.NODE_ENV === "development",

749

};

750

751

switch (useCase) {

752

case "research":

753

return new ReActAgent({

754

...baseConfig,

755

maxIterations: 15, // Allow more iterations for complex research

756

systemPrompt: "You are a thorough researcher. Use tools to gather comprehensive information.",

757

});

758

759

case "analysis":

760

return new ReActAgent({

761

...baseConfig,

762

maxIterations: 8, // Focused analysis

763

systemPrompt: "You are a data analyst. Use tools to analyze information and provide insights.",

764

});

765

766

case "support":

767

return new ReActAgent({

768

...baseConfig,

769

maxIterations: 5, // Quick support responses

770

systemPrompt: "You are a helpful support agent. Provide clear, actionable assistance.",

771

});

772

773

default:

774

return new ReActAgent(baseConfig);

775

}

776

};

777

```

778

779

### Monitoring and Debugging

780

781

```typescript

782

// Add comprehensive logging

783

const monitoredAgent = new ReActAgent({

784

tools: [queryTool, calculatorTool],

785

llm: /* your LLM */,

786

verbose: true,

787

});

788

789

// Wrap agent calls with monitoring

790

const monitoredChat = async (agent: ReActAgent, message: string) => {

791

const startTime = Date.now();

792

793

try {

794

const response = await agent.chat(message);

795

const duration = Date.now() - startTime;

796

797

console.log({

798

timestamp: new Date().toISOString(),

799

message: message.substring(0, 100),

800

responseLength: response.response.length,

801

toolsUsed: response.sources.map(s => s.tool.metadata.name),

802

duration: `${duration}ms`,

803

memorySize: agent.memory.getAll().length,

804

});

805

806

return response;

807

} catch (error) {

808

console.error({

809

timestamp: new Date().toISOString(),

810

message: message.substring(0, 100),

811

error: error.message,

812

duration: `${Date.now() - startTime}ms`,

813

});

814

throw error;

815

}

816

};

817

```