@providerprotocol/agents 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/dist/checkpoint/index.d.ts +43 -0
  3. package/dist/checkpoint/index.js +73 -0
  4. package/dist/checkpoint/index.js.map +1 -0
  5. package/{src/execution/loop.ts → dist/chunk-4ESYN66B.js} +54 -162
  6. package/dist/chunk-4ESYN66B.js.map +1 -0
  7. package/dist/chunk-EKRXMSDX.js +8 -0
  8. package/dist/chunk-EKRXMSDX.js.map +1 -0
  9. package/dist/chunk-T47B3VAF.js +427 -0
  10. package/dist/chunk-T47B3VAF.js.map +1 -0
  11. package/dist/execution/index.d.ts +105 -0
  12. package/dist/execution/index.js +679 -0
  13. package/dist/execution/index.js.map +1 -0
  14. package/dist/index-qsPwbY86.d.ts +65 -0
  15. package/dist/index.d.ts +101 -0
  16. package/dist/index.js +218 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/middleware/index.d.ts +23 -0
  19. package/dist/middleware/index.js +82 -0
  20. package/dist/middleware/index.js.map +1 -0
  21. package/dist/thread-tree/index.d.ts +115 -0
  22. package/dist/thread-tree/index.js +4 -0
  23. package/dist/thread-tree/index.js.map +1 -0
  24. package/dist/types-2Vsthzyu.d.ts +163 -0
  25. package/dist/types-BiyEVOnf.d.ts +65 -0
  26. package/dist/types-D1egxttz.d.ts +270 -0
  27. package/dist/types-DChRdQoX.d.ts +98 -0
  28. package/package.json +41 -9
  29. package/.claude/settings.local.json +0 -29
  30. package/AGENTS.md +0 -681
  31. package/CLAUDE.md +0 -681
  32. package/bun.lock +0 -472
  33. package/eslint.config.js +0 -75
  34. package/index.ts +0 -1
  35. package/llms.md +0 -796
  36. package/specs/UAP-1.0.md +0 -2355
  37. package/src/agent/index.ts +0 -384
  38. package/src/agent/types.ts +0 -91
  39. package/src/checkpoint/file.ts +0 -126
  40. package/src/checkpoint/index.ts +0 -40
  41. package/src/checkpoint/types.ts +0 -95
  42. package/src/execution/index.ts +0 -37
  43. package/src/execution/plan.ts +0 -497
  44. package/src/execution/react.ts +0 -340
  45. package/src/execution/tool-ordering.ts +0 -186
  46. package/src/execution/types.ts +0 -315
  47. package/src/index.ts +0 -80
  48. package/src/middleware/index.ts +0 -7
  49. package/src/middleware/logging.ts +0 -123
  50. package/src/middleware/types.ts +0 -69
  51. package/src/state/index.ts +0 -301
  52. package/src/state/types.ts +0 -173
  53. package/src/thread-tree/index.ts +0 -249
  54. package/src/thread-tree/types.ts +0 -29
  55. package/src/utils/uuid.ts +0 -7
  56. package/tests/live/agent-anthropic.test.ts +0 -288
  57. package/tests/live/agent-strategy-hooks.test.ts +0 -268
  58. package/tests/live/checkpoint.test.ts +0 -243
  59. package/tests/live/execution-strategies.test.ts +0 -255
  60. package/tests/live/plan-strategy.test.ts +0 -160
  61. package/tests/live/subagent-events.live.test.ts +0 -249
  62. package/tests/live/thread-tree.test.ts +0 -186
  63. package/tests/unit/agent.test.ts +0 -703
  64. package/tests/unit/checkpoint.test.ts +0 -232
  65. package/tests/unit/execution/equivalence.test.ts +0 -402
  66. package/tests/unit/execution/loop.test.ts +0 -437
  67. package/tests/unit/execution/plan.test.ts +0 -590
  68. package/tests/unit/execution/react.test.ts +0 -604
  69. package/tests/unit/execution/subagent-events.test.ts +0 -235
  70. package/tests/unit/execution/tool-ordering.test.ts +0 -310
  71. package/tests/unit/middleware/logging.test.ts +0 -276
  72. package/tests/unit/state.test.ts +0 -573
  73. package/tests/unit/thread-tree.test.ts +0 -249
  74. package/tsconfig.json +0 -29
package/llms.md DELETED
@@ -1,796 +0,0 @@
1
- # How to Use @providerprotocol/agents
2
-
3
- `@providerprotocol/agents` is a Unified Agent Protocol (UAP) 1.0 implementation built on `@providerprotocol/ai` (UPP-1.2). It provides a complete framework for building AI agents with explicit control, functional state management, and composable execution strategies.
4
-
5
- **Core Philosophy: "UAP is a pipe, not a nanny."**
6
- The protocol provides orchestration primitives; the developer provides the constraints. There are no artificial limits by default - infinite execution is standard.
7
-
8
- ## Quick Start
9
-
10
- ```typescript
11
- import { agent, AgentState } from '@providerprotocol/agents';
12
- import { anthropic } from '@providerprotocol/ai/anthropic';
13
-
14
- // Create an agent
15
- const coder = agent({
16
- model: anthropic('claude-sonnet-4-20250514'),
17
- params: { max_tokens: 4096 },
18
- system: 'You are an expert software engineer.',
19
- tools: [myReadTool, myWriteTool],
20
- });
21
-
22
- // Execute with immutable state
23
- const state = AgentState.initial();
24
- const { turn, state: newState } = await coder.generate('Hello!', state);
25
- console.log(turn.response.text);
26
- ```
27
-
28
- ## Installation
29
-
30
- ```bash
31
- bun install @providerprotocol/agents @providerprotocol/ai
32
- ```
33
-
34
- The library requires `@providerprotocol/ai >= 0.0.11` as a peer dependency.
35
-
36
- ## Architecture Overview
37
-
38
- ```
39
- Application Layer (your code)
40
- |
41
- Agent Interface (generate, stream, ask, query)
42
- |
43
- Middleware Pipeline (logging, guardrails, context pruning)
44
- |
45
- Execution Strategies (loop, react, plan)
46
- |
47
- UPP-1.2 Layer (@providerprotocol/ai)
48
- |
49
- LLM Provider Adapters (Anthropic, OpenAI, Google, Ollama, etc.)
50
- ```
51
-
52
- ## Creating Agents
53
-
54
- ### Basic Agent
55
-
56
- ```typescript
57
- import { agent, AgentState } from '@providerprotocol/agents';
58
- import { anthropic } from '@providerprotocol/ai/anthropic';
59
-
60
- const myAgent = agent({
61
- model: anthropic('claude-sonnet-4-20250514'),
62
- params: { max_tokens: 4096 },
63
- system: 'You are a helpful assistant.',
64
- });
65
- ```
66
-
67
- ### Agent with Tools
68
-
69
- ```typescript
70
- import { agent, AgentState } from '@providerprotocol/agents';
71
- import { anthropic } from '@providerprotocol/ai/anthropic';
72
-
73
- const calculator = {
74
- name: 'calculate',
75
- description: 'Perform arithmetic calculations',
76
- parameters: {
77
- type: 'object' as const,
78
- properties: {
79
- expression: { type: 'string' as const, description: 'Math expression' },
80
- },
81
- required: ['expression'],
82
- },
83
- run: async (params: { expression: string }) => {
84
- return String(eval(params.expression)); // Use a proper math parser in production
85
- },
86
- };
87
-
88
- const mathAgent = agent({
89
- model: anthropic('claude-sonnet-4-20250514'),
90
- params: { max_tokens: 1000 },
91
- tools: [calculator],
92
- });
93
- ```
94
-
95
- ### Full Agent Options
96
-
97
- ```typescript
98
- import { agent, AgentState } from '@providerprotocol/agents';
99
- import { react } from '@providerprotocol/agents/execution';
100
- import { logging } from '@providerprotocol/agents/middleware';
101
- import { anthropic } from '@providerprotocol/ai/anthropic';
102
-
103
- const fullAgent = agent({
104
- // Required: Model from UPP provider
105
- model: anthropic('claude-sonnet-4-20250514'),
106
-
107
- // LLM parameters (provider-specific)
108
- params: { max_tokens: 8192 },
109
-
110
- // Provider configuration
111
- config: {
112
- apiKey: 'sk-...', // Override env var
113
- baseUrl: 'https://...', // Custom endpoint
114
- },
115
-
116
- // System prompt
117
- system: 'You are an expert coder.',
118
-
119
- // Tools array
120
- tools: [readTool, writeTool, bashTool],
121
-
122
- // Execution strategy (default: loop())
123
- execution: react({ maxSteps: 20 }),
124
-
125
- // Middleware pipeline
126
- middleware: [logging({ level: 'info' })],
127
-
128
- // Lifecycle hooks
129
- strategy: {
130
- stopCondition: (state) => state.step > 50,
131
- onStepStart: (step, state) => console.log(`Step ${step}`),
132
- onComplete: (result) => console.log('Done!'),
133
- },
134
-
135
- // Tool execution hooks (passed to UPP)
136
- toolStrategy: {
137
- maxIterations: Infinity,
138
- onToolCall: (tool, params) => console.log(`Calling ${tool.name}`),
139
- },
140
-
141
- // Checkpointing for persistence
142
- checkpoints: fileCheckpoints({ dir: '.checkpoints' }),
143
- sessionId: 'my-session-123', // Auto-generated if not provided
144
- });
145
- ```
146
-
147
- ## Agent Methods
148
-
149
- ### generate(input, state)
150
-
151
- Execute agent and return result with new state.
152
-
153
- ```typescript
154
- const state = AgentState.initial();
155
- const { turn, state: newState } = await myAgent.generate('Hello!', state);
156
-
157
- console.log(turn.response.text); // Response text
158
- console.log(turn.usage.totalTokens); // Token usage
159
- console.log(turn.toolExecutions); // Tool executions
160
- console.log(newState.step); // Current step number
161
- console.log(newState.messages.length); // Message count
162
- ```
163
-
164
- ### stream(input, state)
165
-
166
- Execute agent with streaming events.
167
-
168
- ```typescript
169
- const stream = myAgent.stream('Explain quantum computing', state);
170
-
171
- // Iterate over events
172
- for await (const event of stream) {
173
- if (event.source === 'upp' && event.upp?.type === 'text_delta') {
174
- // LLM text streaming
175
- process.stdout.write(event.upp.delta.text ?? '');
176
- }
177
- if (event.source === 'uap' && event.uap?.type === 'step_start') {
178
- // Agent-level events
179
- console.log(`\nStep ${event.uap.step} started`);
180
- }
181
- }
182
-
183
- // Get final result after stream completes
184
- const { turn, state: newState } = await stream.result;
185
-
186
- // Abort if needed
187
- stream.abort();
188
- ```
189
-
190
- ### ask(input, state)
191
-
192
- Multi-turn convenience method that automatically appends messages to state.
193
-
194
- ```typescript
195
- let state = AgentState.initial();
196
-
197
- // First turn
198
- const result1 = await myAgent.ask('My name is Alice', state);
199
- state = result1.state;
200
-
201
- // Second turn (model remembers context)
202
- const result2 = await myAgent.ask('What is my name?', state);
203
- // result2.turn.response.text contains "Alice"
204
- ```
205
-
206
- ### query(input)
207
-
208
- Stateless single-turn execution. Creates ephemeral state, executes, discards state.
209
-
210
- ```typescript
211
- const turn = await myAgent.query('What is 2+2?');
212
- console.log(turn.response.text); // "4"
213
- ```
214
-
215
- ## Execution Strategies
216
-
217
- Import from `@providerprotocol/agents/execution`.
218
-
219
- ### loop() - Simple Tool Loop
220
-
221
- Simplest strategy - equivalent to UPP's built-in tool loop.
222
-
223
- ```typescript
224
- import { loop } from '@providerprotocol/agents/execution';
225
-
226
- const agent = agent({
227
- model: anthropic('claude-sonnet-4-20250514'),
228
- execution: loop({ maxIterations: Infinity }), // Default
229
- });
230
- ```
231
-
232
- Behavior:
233
- 1. Send input to LLM
234
- 2. If response has tool calls, execute tools
235
- 3. Loop until no more tool calls or maxIterations reached
236
-
237
- ### react() - Reason-Act-Observe
238
-
239
- ReAct pattern with explicit reasoning phase.
240
-
241
- ```typescript
242
- import { react } from '@providerprotocol/agents/execution';
243
-
244
- const agent = agent({
245
- model: anthropic('claude-sonnet-4-20250514'),
246
- execution: react({
247
- maxSteps: Infinity, // Default
248
- reasoningPrompt: 'Think step by step about what you need to do next.',
249
- }),
250
- });
251
- ```
252
-
253
- Behavior:
254
- 1. **Reason**: LLM outputs reasoning about what to do
255
- 2. **Act**: LLM selects and executes tool(s)
256
- 3. **Observe**: Tool results fed back
257
- 4. Repeat until no actions or maxSteps reached
258
-
259
- Stream events emitted: `step_start`, `reasoning`, `action`, `observation`, `step_end`
260
-
261
- ### plan() - Plan-then-Execute
262
-
263
- Generate structured plan with dependencies, then execute.
264
-
265
- ```typescript
266
- import { plan } from '@providerprotocol/agents/execution';
267
-
268
- const agent = agent({
269
- model: anthropic('claude-sonnet-4-20250514'),
270
- execution: plan({
271
- maxPlanSteps: Infinity, // Default
272
- allowReplan: true, // Replan on failure
273
- }),
274
- });
275
- ```
276
-
277
- Behavior:
278
- 1. **Planning phase**: LLM generates structured plan with step dependencies
279
- 2. **Execution phase**: Execute steps in topological order
280
- 3. Optionally replan if a step fails
281
-
282
- Stream events emitted: `plan_created`, `plan_step_start`, `action`, `observation`, `plan_step_end`
283
-
284
- ## State Management
285
-
286
- `AgentState` is immutable - all operations return new instances.
287
-
288
- ### Creating State
289
-
290
- ```typescript
291
- import { AgentState } from '@providerprotocol/agents';
292
-
293
- // Create initial state
294
- const state = AgentState.initial();
295
- ```
296
-
297
- ### State Operations
298
-
299
- All operations return new `AgentState` instances:
300
-
301
- ```typescript
302
- // Add message
303
- const state2 = state.withMessage(new UserMessage('Hello'));
304
-
305
- // Add multiple messages
306
- const state3 = state.withMessages([msg1, msg2]);
307
-
308
- // Replace entire context (for pruning/summarization)
309
- const state4 = state.withContext([prunedMessages]);
310
-
311
- // Update step number
312
- const state5 = state.withStep(5);
313
-
314
- // Add metadata
315
- const state6 = state.withMetadata('customKey', 'value');
316
-
317
- // Add reasoning trace (ReAct)
318
- const state7 = state.withReasoning('I should read the file first...');
319
-
320
- // Set execution plan
321
- const state8 = state.withPlan([
322
- { id: 'step1', description: 'Read file', status: 'pending', dependsOn: [] },
323
- ]);
324
- ```
325
-
326
- ### State Properties
327
-
328
- ```typescript
329
- state.id // UUIDv4 state identifier
330
- state.messages // Conversation messages (readonly)
331
- state.step // Current step number
332
- state.metadata // Key-value metadata
333
- state.reasoning // Reasoning traces (ReAct)
334
- state.plan // Execution plan steps
335
- ```
336
-
337
- ### Serialization
338
-
339
- ```typescript
340
- // Save state
341
- const json = state.toJSON();
342
- await Bun.write('state.json', JSON.stringify(json));
343
-
344
- // Restore state
345
- const loaded = await Bun.file('state.json').json();
346
- const restoredState = AgentState.fromJSON(loaded);
347
- ```
348
-
349
- ## Middleware
350
-
351
- Import from `@providerprotocol/agents/middleware`.
352
-
353
- ### Built-in Logging Middleware
354
-
355
- ```typescript
356
- import { logging } from '@providerprotocol/agents/middleware';
357
-
358
- const agent = agent({
359
- model: anthropic('claude-sonnet-4-20250514'),
360
- middleware: [
361
- logging({
362
- level: 'info', // 'debug' | 'info' | 'warn' | 'error'
363
- logger: console.log, // Custom logger function
364
- includeMessages: false, // Log message contents
365
- includeTiming: true, // Log execution duration
366
- }),
367
- ],
368
- });
369
- ```
370
-
371
- ### Custom Middleware
372
-
373
- ```typescript
374
- import type { Middleware, MiddlewareContext } from '@providerprotocol/agents/middleware';
375
- import type { GenerateResult } from '@providerprotocol/agents';
376
-
377
- const myMiddleware: Middleware = {
378
- name: 'my-middleware',
379
-
380
- // Runs before execution (forward order)
381
- async before(context: MiddlewareContext) {
382
- console.log('Before:', context.input);
383
- // Optionally return modified context
384
- return context;
385
- },
386
-
387
- // Runs after execution (reverse order)
388
- async after(context: MiddlewareContext, result: GenerateResult) {
389
- console.log('After:', result.turn.response.text);
390
- // Must return result (possibly modified)
391
- return result;
392
- },
393
-
394
- // Runs on error (reverse order)
395
- async onError(context: MiddlewareContext, error: Error) {
396
- console.error('Error:', error.message);
397
- // Return recovery result or undefined to propagate error
398
- return undefined;
399
- },
400
- };
401
- ```
402
-
403
- ### Middleware Execution Order
404
-
405
- ```
406
- first.before() → second.before() → third.before()
407
- → Agent Execution
408
- → third.after() → second.after() → first.after()
409
- ```
410
-
411
- ## Thread Trees
412
-
413
- For branching conversations. Import from `@providerprotocol/agents/thread-tree`.
414
-
415
- ```typescript
416
- import { ThreadTree } from '@providerprotocol/agents/thread-tree';
417
- import { agent, AgentState } from '@providerprotocol/agents';
418
-
419
- // Create tree
420
- const tree = new ThreadTree();
421
-
422
- // Execute on current node
423
- const { turn, state } = await myAgent.generate('Start conversation', tree.history());
424
- tree.current.state = state;
425
-
426
- // Create a branch
427
- const branchId = tree.branch(tree.current.id, 'alternative-path');
428
-
429
- // Switch to branch
430
- tree.checkout(branchId);
431
-
432
- // Execute on branch
433
- const { turn: t2, state: s2 } = await myAgent.generate('Different direction', tree.history());
434
- tree.current.state = s2;
435
-
436
- // Navigation
437
- tree.getLeaves(); // All leaf node IDs
438
- tree.getBranches(); // Map of node IDs to names
439
-
440
- // Serialization
441
- const json = tree.toJSON();
442
- const restored = ThreadTree.fromJSON(json);
443
- ```
444
-
445
- ## Checkpointing
446
-
447
- For session persistence and recovery.
448
-
449
- ### File-based Checkpoints
450
-
451
- ```typescript
452
- import { agent, AgentState } from '@providerprotocol/agents';
453
- import { fileCheckpoints } from '@providerprotocol/agents/checkpoint';
454
-
455
- const store = fileCheckpoints({ dir: '.checkpoints' });
456
-
457
- const myAgent = agent({
458
- model: anthropic('claude-sonnet-4-20250514'),
459
- checkpoints: store,
460
- sessionId: 'my-session', // Auto-generated UUIDv4 if not provided
461
- });
462
-
463
- // Execute - checkpoints saved automatically after each step
464
- const { turn, state } = await myAgent.generate('Hello', AgentState.initial());
465
-
466
- // Later: manually load checkpoint
467
- const savedState = await store.load('my-session');
468
- if (savedState) {
469
- const restoredState = AgentState.fromJSON(savedState);
470
- // Continue from saved state
471
- const { turn: t2 } = await myAgent.generate('Continue', restoredState);
472
- }
473
-
474
- // List all sessions
475
- const sessions = await store.list();
476
-
477
- // Delete a session
478
- await store.delete('my-session');
479
- ```
480
-
481
- ### Custom Checkpoint Store
482
-
483
- ```typescript
484
- import type { CheckpointStore, AgentStateJSON } from '@providerprotocol/agents';
485
-
486
- const customStore: CheckpointStore = {
487
- async save(sessionId: string, state: AgentStateJSON): Promise<void> {
488
- // Save to database, S3, etc.
489
- },
490
- async load(sessionId: string): Promise<AgentStateJSON | null> {
491
- // Load from storage
492
- },
493
- async delete(sessionId: string): Promise<void> {
494
- // Delete from storage
495
- },
496
- async list(): Promise<string[]> {
497
- // List all session IDs
498
- },
499
- };
500
- ```
501
-
502
- ## Strategy Hooks
503
-
504
- Control agent lifecycle with hooks:
505
-
506
- ```typescript
507
- const agent = agent({
508
- model: anthropic('claude-sonnet-4-20250514'),
509
- strategy: {
510
- // Stop execution when condition is met
511
- stopCondition: async (state) => {
512
- return state.step > 50 || state.metadata.shouldStop === true;
513
- },
514
-
515
- // Called when each step begins
516
- onStepStart: (step, state) => {
517
- console.log(`Step ${step} starting...`);
518
- },
519
-
520
- // Called during reasoning phase (ReAct strategy)
521
- onReason: (step, reasoning) => {
522
- console.log(`Reasoning: ${reasoning}`);
523
- },
524
-
525
- // Called when tools are invoked
526
- onAct: (step, toolCalls) => {
527
- console.log(`Tools: ${toolCalls.map(t => t.toolName).join(', ')}`);
528
- },
529
-
530
- // Called when tool results are received
531
- onObserve: (step, observations) => {
532
- console.log(`Results: ${observations.length} tool outputs`);
533
- },
534
-
535
- // Called when each step completes
536
- onStepEnd: (step, result) => {
537
- console.log(`Step ${step} complete, tokens: ${result.turn.usage?.totalTokens}`);
538
- },
539
-
540
- // Called when execution completes successfully
541
- onComplete: (result) => {
542
- console.log(`Done! Total steps: ${result.state.step}`);
543
- },
544
-
545
- // Called on error
546
- onError: (error, state) => {
547
- console.error(`Error at step ${state.step}: ${error.message}`);
548
- // Optionally return recovery result
549
- return undefined;
550
- },
551
- },
552
- });
553
- ```
554
-
555
- ## Stream Events
556
-
557
- ### UAP Events (source: 'uap')
558
-
559
- Agent-level events from execution strategies:
560
-
561
- | Event | Data | Description |
562
- |-------|------|-------------|
563
- | `step_start` | `{ step, agentId, data }` | Step began |
564
- | `step_end` | `{ step, agentId, data }` | Step completed |
565
- | `reasoning` | `{ step, agentId, data: { reasoning } }` | ReAct reasoning |
566
- | `action` | `{ step, agentId, data: { toolCalls } }` | Tools invoked |
567
- | `observation` | `{ step, agentId, data: { observations } }` | Tool results |
568
- | `plan_created` | `{ step, agentId, data: { plan } }` | Plan generated |
569
- | `plan_step_start` | `{ step, agentId, data: { planStep } }` | Plan step began |
570
- | `plan_step_end` | `{ step, agentId, data: { planStep } }` | Plan step done |
571
-
572
- ### UPP Events (source: 'upp')
573
-
574
- LLM-level events from @providerprotocol/ai:
575
-
576
- | Event | Data | Description |
577
- |-------|------|-------------|
578
- | `text_delta` | `{ delta: { text } }` | Streaming text |
579
- | `tool_call_delta` | `{ delta: { toolCallId, toolName, argumentsJson } }` | Tool call streaming |
580
- | `message_start` | - | Message began |
581
- | `message_stop` | - | Message completed |
582
- | `content_block_start` | - | Content block began |
583
- | `content_block_stop` | - | Content block done |
584
-
585
- ## Tool Dependencies
586
-
587
- Tools can declare execution ordering:
588
-
589
- ```typescript
590
- import type { ToolWithDependencies } from '@providerprotocol/agents/execution';
591
-
592
- const readTool: ToolWithDependencies = {
593
- name: 'read_file',
594
- description: 'Read file contents',
595
- parameters: { /* ... */ },
596
- sequential: true, // Must complete before other tools
597
- run: async (params) => { /* ... */ },
598
- };
599
-
600
- const writeTool: ToolWithDependencies = {
601
- name: 'write_file',
602
- description: 'Write file contents',
603
- parameters: { /* ... */ },
604
- dependsOn: ['read_file'], // Waits for read_file
605
- run: async (params) => { /* ... */ },
606
- };
607
- ```
608
-
609
- ## Sub-agents
610
-
611
- Agents can spawn sub-agents via tools:
612
-
613
- ```typescript
614
- import { agent, AgentState } from '@providerprotocol/agents';
615
- import type { OnSubagentEvent } from '@providerprotocol/agents';
616
-
617
- // Sub-agent event callback
618
- const onSubagentEvent: OnSubagentEvent = (event) => {
619
- switch (event.type) {
620
- case 'subagent_start':
621
- console.log(`Sub-agent ${event.subagentType} started`);
622
- break;
623
- case 'subagent_event':
624
- console.log(`Sub-agent event: ${event.innerEvent.source}`);
625
- break;
626
- case 'subagent_end':
627
- console.log(`Sub-agent completed: ${event.success}`);
628
- break;
629
- }
630
- };
631
-
632
- // Create sub-agent tool
633
- const explorerTool = {
634
- name: 'explore',
635
- description: 'Explore codebase for information',
636
- parameters: {
637
- type: 'object' as const,
638
- properties: {
639
- query: { type: 'string' as const },
640
- },
641
- required: ['query'],
642
- },
643
- run: async (params: { query: string }) => {
644
- const explorer = agent({
645
- model: anthropic('claude-3-5-haiku-latest'),
646
- params: { max_tokens: 2000 },
647
- tools: [globTool, grepTool, readTool],
648
- });
649
-
650
- const turn = await explorer.query(params.query);
651
- return turn.response.text;
652
- },
653
- };
654
- ```
655
-
656
- ## Provider Support
657
-
658
- All providers from `@providerprotocol/ai` are supported:
659
-
660
- ```typescript
661
- // Anthropic
662
- import { anthropic } from '@providerprotocol/ai/anthropic';
663
- agent({ model: anthropic('claude-sonnet-4-20250514'), params: { max_tokens: 4096 } });
664
-
665
- // OpenAI
666
- import { openai } from '@providerprotocol/ai/openai';
667
- agent({ model: openai('gpt-4o'), params: { max_output_tokens: 4096 } });
668
-
669
- // Google
670
- import { google } from '@providerprotocol/ai/google';
671
- agent({ model: google('gemini-2.0-flash'), params: { maxOutputTokens: 4096 } });
672
-
673
- // Ollama (local)
674
- import { ollama } from '@providerprotocol/ai/ollama';
675
- agent({ model: ollama('llama3:8b'), params: { num_predict: 4096 } });
676
-
677
- // OpenRouter
678
- import { openrouter } from '@providerprotocol/ai/openrouter';
679
- agent({ model: openrouter('anthropic/claude-3.5-sonnet'), params: { max_tokens: 4096 } });
680
-
681
- // xAI
682
- import { xai } from '@providerprotocol/ai/xai';
683
- agent({ model: xai('grok-2'), params: { max_tokens: 4096 } });
684
- ```
685
-
686
- ## Environment Variables
687
-
688
- Set API keys in `.env` (Bun auto-loads):
689
-
690
- ```
691
- ANTHROPIC_API_KEY=sk-ant-...
692
- OPENAI_API_KEY=sk-...
693
- GOOGLE_API_KEY=AI...
694
- XAI_API_KEY=xai-...
695
- OPENROUTER_API_KEY=sk-or-...
696
- ```
697
-
698
- ## Testing
699
-
700
- Run tests with Bun:
701
-
702
- ```bash
703
- bun test # All tests
704
- bun test:unit # Unit tests only
705
- bun test:live # Live API tests
706
- ```
707
-
708
- ## Complete Example
709
-
710
- ```typescript
711
- import { agent, AgentState } from '@providerprotocol/agents';
712
- import { react } from '@providerprotocol/agents/execution';
713
- import { logging } from '@providerprotocol/agents/middleware';
714
- import { anthropic } from '@providerprotocol/ai/anthropic';
715
-
716
- // Define tools
717
- const readFile = {
718
- name: 'read_file',
719
- description: 'Read contents of a file',
720
- parameters: {
721
- type: 'object' as const,
722
- properties: {
723
- path: { type: 'string' as const, description: 'File path' },
724
- },
725
- required: ['path'],
726
- },
727
- run: async (params: { path: string }) => {
728
- return await Bun.file(params.path).text();
729
- },
730
- };
731
-
732
- // Create agent
733
- const coder = agent({
734
- model: anthropic('claude-sonnet-4-20250514'),
735
- params: { max_tokens: 8192 },
736
- system: `You are an expert software engineer.
737
- Always read files before suggesting changes.
738
- Think step by step about the best approach.`,
739
- tools: [readFile],
740
- execution: react({ maxSteps: 10 }),
741
- middleware: [logging({ level: 'info' })],
742
- strategy: {
743
- onStepEnd: (step, result) => {
744
- console.log(`Step ${step}: ${result.turn.usage?.totalTokens} tokens`);
745
- },
746
- },
747
- });
748
-
749
- // Interactive session
750
- async function main() {
751
- let state = AgentState.initial();
752
-
753
- // First turn
754
- const r1 = await coder.ask('Read package.json and summarize dependencies', state);
755
- console.log(r1.turn.response.text);
756
- state = r1.state;
757
-
758
- // Follow-up (with context)
759
- const r2 = await coder.ask('Which of these are dev dependencies?', state);
760
- console.log(r2.turn.response.text);
761
- }
762
-
763
- main();
764
- ```
765
-
766
- ## Key Exports
767
-
768
- ```typescript
769
- // Main entry
770
- import { agent, AgentState } from '@providerprotocol/agents';
771
-
772
- // Types
773
- import type {
774
- Agent,
775
- AgentOptions,
776
- GenerateResult,
777
- AgentStreamResult,
778
- AgentStreamEvent,
779
- AgentStrategy,
780
- } from '@providerprotocol/agents';
781
-
782
- // Execution strategies
783
- import { loop, react, plan } from '@providerprotocol/agents/execution';
784
- import type { LoopOptions, ReactOptions, PlanOptions } from '@providerprotocol/agents/execution';
785
-
786
- // Middleware
787
- import { logging } from '@providerprotocol/agents/middleware';
788
- import type { Middleware, LoggingOptions } from '@providerprotocol/agents/middleware';
789
-
790
- // Thread trees
791
- import { ThreadTree, ThreadNode } from '@providerprotocol/agents/thread-tree';
792
-
793
- // Checkpoints
794
- import { fileCheckpoints } from '@providerprotocol/agents/checkpoint';
795
- import type { CheckpointStore } from '@providerprotocol/agents';
796
- ```