@providerprotocol/agents 0.0.2 → 0.0.3
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/dist/checkpoint/index.d.ts +43 -0
- package/dist/checkpoint/index.js +64 -0
- package/dist/checkpoint/index.js.map +1 -0
- package/{src/execution/loop.ts → dist/chunk-4ESYN66B.js} +54 -162
- package/dist/chunk-4ESYN66B.js.map +1 -0
- package/dist/chunk-EKRXMSDX.js +8 -0
- package/dist/chunk-EKRXMSDX.js.map +1 -0
- package/dist/chunk-PHI5ULBV.js +427 -0
- package/dist/chunk-PHI5ULBV.js.map +1 -0
- package/dist/execution/index.d.ts +105 -0
- package/dist/execution/index.js +679 -0
- package/dist/execution/index.js.map +1 -0
- package/dist/index-qsPwbY86.d.ts +65 -0
- package/dist/index.d.ts +101 -0
- package/dist/index.js +218 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/index.d.ts +23 -0
- package/dist/middleware/index.js +82 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/thread-tree/index.d.ts +115 -0
- package/dist/thread-tree/index.js +4 -0
- package/dist/thread-tree/index.js.map +1 -0
- package/dist/types-2Vsthzyu.d.ts +163 -0
- package/dist/types-BhX9uD_d.d.ts +91 -0
- package/dist/types-DR02gtFv.d.ts +270 -0
- package/dist/types-NGQMdnaD.d.ts +65 -0
- package/package.json +40 -8
- package/.claude/settings.local.json +0 -29
- package/AGENTS.md +0 -681
- package/CLAUDE.md +0 -681
- package/bun.lock +0 -472
- package/eslint.config.js +0 -75
- package/index.ts +0 -1
- package/llms.md +0 -796
- package/specs/UAP-1.0.md +0 -2355
- package/src/agent/index.ts +0 -384
- package/src/agent/types.ts +0 -91
- package/src/checkpoint/file.ts +0 -126
- package/src/checkpoint/index.ts +0 -40
- package/src/checkpoint/types.ts +0 -95
- package/src/execution/index.ts +0 -37
- package/src/execution/plan.ts +0 -497
- package/src/execution/react.ts +0 -340
- package/src/execution/tool-ordering.ts +0 -186
- package/src/execution/types.ts +0 -315
- package/src/index.ts +0 -80
- package/src/middleware/index.ts +0 -7
- package/src/middleware/logging.ts +0 -123
- package/src/middleware/types.ts +0 -69
- package/src/state/index.ts +0 -301
- package/src/state/types.ts +0 -173
- package/src/thread-tree/index.ts +0 -249
- package/src/thread-tree/types.ts +0 -29
- package/src/utils/uuid.ts +0 -7
- package/tests/live/agent-anthropic.test.ts +0 -288
- package/tests/live/agent-strategy-hooks.test.ts +0 -268
- package/tests/live/checkpoint.test.ts +0 -243
- package/tests/live/execution-strategies.test.ts +0 -255
- package/tests/live/plan-strategy.test.ts +0 -160
- package/tests/live/subagent-events.live.test.ts +0 -249
- package/tests/live/thread-tree.test.ts +0 -186
- package/tests/unit/agent.test.ts +0 -703
- package/tests/unit/checkpoint.test.ts +0 -232
- package/tests/unit/execution/equivalence.test.ts +0 -402
- package/tests/unit/execution/loop.test.ts +0 -437
- package/tests/unit/execution/plan.test.ts +0 -590
- package/tests/unit/execution/react.test.ts +0 -604
- package/tests/unit/execution/subagent-events.test.ts +0 -235
- package/tests/unit/execution/tool-ordering.test.ts +0 -310
- package/tests/unit/middleware/logging.test.ts +0 -276
- package/tests/unit/state.test.ts +0 -573
- package/tests/unit/thread-tree.test.ts +0 -249
- 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
|
-
```
|