@providerprotocol/agents 0.0.1 → 0.0.2
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/.claude/settings.local.json +3 -1
- package/README.md +333 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,15 +1,342 @@
|
|
|
1
|
-
# providerprotocol
|
|
1
|
+
# @providerprotocol/agents
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A powerful, flexible agent framework implementing the Unified Agent Protocol (UAP) 1.0. Built on top of [@providerprotocol/ai](https://github.com/providerprotocol/ai) for seamless multi-provider LLM support.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Functional State Management** - Immutable state with explicit data flow
|
|
8
|
+
- **Execution Strategies** - Choose from `loop`, `react`, or `plan` patterns
|
|
9
|
+
- **Middleware Pipeline** - Composable before/after hooks for logging, guardrails, etc.
|
|
10
|
+
- **Multi-Provider Support** - Works with Anthropic, OpenAI, Google, Ollama, and more
|
|
11
|
+
- **Streaming** - Full streaming support with UAP and UPP events
|
|
12
|
+
- **Checkpointing** - Built-in session persistence and recovery
|
|
13
|
+
- **Thread Trees** - Branching conversation support
|
|
14
|
+
- **Type-Safe** - 100% TypeScript with full type inference
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
4
17
|
|
|
5
18
|
```bash
|
|
6
|
-
bun install
|
|
19
|
+
bun install @providerprotocol/agents @providerprotocol/ai
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { agent, AgentState } from '@providerprotocol/agents';
|
|
26
|
+
import { anthropic } from '@providerprotocol/ai/anthropic';
|
|
27
|
+
|
|
28
|
+
// Create an agent
|
|
29
|
+
const assistant = agent({
|
|
30
|
+
model: anthropic('claude-sonnet-4-20250514'),
|
|
31
|
+
params: { max_tokens: 4096 },
|
|
32
|
+
system: 'You are a helpful assistant.',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Single query (stateless)
|
|
36
|
+
const turn = await assistant.query('What is the capital of France?');
|
|
37
|
+
console.log(turn.response.text);
|
|
38
|
+
|
|
39
|
+
// Multi-turn conversation (stateful)
|
|
40
|
+
let state = AgentState.initial();
|
|
41
|
+
const r1 = await assistant.ask('My name is Alice.', state);
|
|
42
|
+
state = r1.state;
|
|
43
|
+
|
|
44
|
+
const r2 = await assistant.ask('What is my name?', state);
|
|
45
|
+
console.log(r2.turn.response.text); // "Alice"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Adding Tools
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import { agent, AgentState } from '@providerprotocol/agents';
|
|
52
|
+
import { anthropic } from '@providerprotocol/ai/anthropic';
|
|
53
|
+
|
|
54
|
+
const calculator = {
|
|
55
|
+
name: 'calculate',
|
|
56
|
+
description: 'Evaluate a math expression',
|
|
57
|
+
parameters: {
|
|
58
|
+
type: 'object' as const,
|
|
59
|
+
properties: {
|
|
60
|
+
expression: { type: 'string' as const },
|
|
61
|
+
},
|
|
62
|
+
required: ['expression'],
|
|
63
|
+
},
|
|
64
|
+
run: async (params: { expression: string }) => {
|
|
65
|
+
// Use a proper math parser in production
|
|
66
|
+
return String(eval(params.expression));
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const mathBot = agent({
|
|
71
|
+
model: anthropic('claude-sonnet-4-20250514'),
|
|
72
|
+
params: { max_tokens: 1000 },
|
|
73
|
+
tools: [calculator],
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const turn = await mathBot.query('What is 42 * 17?');
|
|
77
|
+
console.log(turn.response.text);
|
|
78
|
+
console.log(turn.toolExecutions); // Shows calculator was used
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Execution Strategies
|
|
82
|
+
|
|
83
|
+
Choose how your agent thinks and acts:
|
|
84
|
+
|
|
85
|
+
### Loop (Default)
|
|
86
|
+
|
|
87
|
+
Simple tool loop - keeps executing until no more tool calls.
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { loop } from '@providerprotocol/agents/execution';
|
|
91
|
+
|
|
92
|
+
const myAgent = agent({
|
|
93
|
+
model: anthropic('claude-sonnet-4-20250514'),
|
|
94
|
+
execution: loop({ maxIterations: 10 }),
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### ReAct
|
|
99
|
+
|
|
100
|
+
Reason-Act-Observe pattern with explicit reasoning phase.
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { react } from '@providerprotocol/agents/execution';
|
|
104
|
+
|
|
105
|
+
const myAgent = agent({
|
|
106
|
+
model: anthropic('claude-sonnet-4-20250514'),
|
|
107
|
+
execution: react({ maxSteps: 20 }),
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Plan
|
|
112
|
+
|
|
113
|
+
Generate a structured plan, then execute steps with dependencies.
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { plan } from '@providerprotocol/agents/execution';
|
|
117
|
+
|
|
118
|
+
const myAgent = agent({
|
|
119
|
+
model: anthropic('claude-sonnet-4-20250514'),
|
|
120
|
+
execution: plan({ maxPlanSteps: 10, allowReplan: true }),
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Streaming
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
const stream = myAgent.stream('Explain quantum computing', state);
|
|
128
|
+
|
|
129
|
+
for await (const event of stream) {
|
|
130
|
+
if (event.source === 'upp' && event.upp?.type === 'text_delta') {
|
|
131
|
+
process.stdout.write(event.upp.delta.text ?? '');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const { turn, state: newState } = await stream.result;
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Middleware
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
import { logging } from '@providerprotocol/agents/middleware';
|
|
142
|
+
|
|
143
|
+
const myAgent = agent({
|
|
144
|
+
model: anthropic('claude-sonnet-4-20250514'),
|
|
145
|
+
middleware: [
|
|
146
|
+
logging({ level: 'info', includeTiming: true }),
|
|
147
|
+
],
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Create custom middleware:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
import type { Middleware } from '@providerprotocol/agents/middleware';
|
|
155
|
+
|
|
156
|
+
const rateLimiter: Middleware = {
|
|
157
|
+
name: 'rate-limiter',
|
|
158
|
+
async before(context) {
|
|
159
|
+
await checkRateLimit(context.agent.id);
|
|
160
|
+
return context;
|
|
161
|
+
},
|
|
162
|
+
async after(context, result) {
|
|
163
|
+
recordUsage(result.turn.usage);
|
|
164
|
+
return result;
|
|
165
|
+
},
|
|
166
|
+
};
|
|
7
167
|
```
|
|
8
168
|
|
|
9
|
-
|
|
169
|
+
## Checkpointing
|
|
170
|
+
|
|
171
|
+
Persist agent sessions for recovery:
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
import { fileCheckpoints } from '@providerprotocol/agents/checkpoint';
|
|
175
|
+
|
|
176
|
+
const store = fileCheckpoints({ dir: '.checkpoints' });
|
|
177
|
+
|
|
178
|
+
const myAgent = agent({
|
|
179
|
+
model: anthropic('claude-sonnet-4-20250514'),
|
|
180
|
+
checkpoints: store,
|
|
181
|
+
sessionId: 'my-session',
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Execute - state automatically saved after each step
|
|
185
|
+
await myAgent.generate('Hello', AgentState.initial());
|
|
186
|
+
|
|
187
|
+
// Later: restore and continue
|
|
188
|
+
const saved = await store.load('my-session');
|
|
189
|
+
if (saved) {
|
|
190
|
+
const state = AgentState.fromJSON(saved);
|
|
191
|
+
await myAgent.generate('Continue...', state);
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Lifecycle Hooks
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
const myAgent = agent({
|
|
199
|
+
model: anthropic('claude-sonnet-4-20250514'),
|
|
200
|
+
strategy: {
|
|
201
|
+
stopCondition: (state) => state.step > 50,
|
|
202
|
+
onStepStart: (step, state) => console.log(`Step ${step}`),
|
|
203
|
+
onAct: (step, toolCalls) => console.log('Tools:', toolCalls),
|
|
204
|
+
onComplete: (result) => console.log('Done!'),
|
|
205
|
+
onError: (error, state) => console.error(error),
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Provider Support
|
|
211
|
+
|
|
212
|
+
Works with all providers from `@providerprotocol/ai`:
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
import { anthropic } from '@providerprotocol/ai/anthropic';
|
|
216
|
+
import { openai } from '@providerprotocol/ai/openai';
|
|
217
|
+
import { google } from '@providerprotocol/ai/google';
|
|
218
|
+
import { ollama } from '@providerprotocol/ai/ollama';
|
|
219
|
+
|
|
220
|
+
// Anthropic
|
|
221
|
+
agent({ model: anthropic('claude-sonnet-4-20250514'), params: { max_tokens: 4096 } });
|
|
222
|
+
|
|
223
|
+
// OpenAI
|
|
224
|
+
agent({ model: openai('gpt-4o'), params: { max_output_tokens: 4096 } });
|
|
225
|
+
|
|
226
|
+
// Google
|
|
227
|
+
agent({ model: google('gemini-2.0-flash'), params: { maxOutputTokens: 4096 } });
|
|
228
|
+
|
|
229
|
+
// Ollama (local)
|
|
230
|
+
agent({ model: ollama('llama3:8b'), params: { num_predict: 4096 } });
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## Environment Variables
|
|
234
|
+
|
|
235
|
+
Create a `.env` file with your API keys:
|
|
236
|
+
|
|
237
|
+
```env
|
|
238
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
239
|
+
OPENAI_API_KEY=sk-...
|
|
240
|
+
GOOGLE_API_KEY=AI...
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## API Reference
|
|
244
|
+
|
|
245
|
+
### agent(options)
|
|
246
|
+
|
|
247
|
+
Creates an agent instance.
|
|
248
|
+
|
|
249
|
+
| Option | Type | Description |
|
|
250
|
+
|--------|------|-------------|
|
|
251
|
+
| `model` | `ModelReference` | Required. Model from UPP provider |
|
|
252
|
+
| `params` | `object` | LLM parameters (provider-specific) |
|
|
253
|
+
| `system` | `string` | System prompt |
|
|
254
|
+
| `tools` | `Tool[]` | Available tools |
|
|
255
|
+
| `execution` | `ExecutionStrategy` | Strategy: `loop()`, `react()`, `plan()` |
|
|
256
|
+
| `middleware` | `Middleware[]` | Middleware pipeline |
|
|
257
|
+
| `strategy` | `AgentStrategy` | Lifecycle hooks |
|
|
258
|
+
| `checkpoints` | `CheckpointStore` | Session persistence |
|
|
259
|
+
| `sessionId` | `string` | Session identifier |
|
|
260
|
+
|
|
261
|
+
### Agent Methods
|
|
262
|
+
|
|
263
|
+
| Method | Returns | Description |
|
|
264
|
+
|--------|---------|-------------|
|
|
265
|
+
| `generate(input, state)` | `Promise<GenerateResult>` | Execute with state |
|
|
266
|
+
| `stream(input, state)` | `AgentStreamResult` | Stream execution |
|
|
267
|
+
| `ask(input, state)` | `Promise<GenerateResult>` | Multi-turn convenience |
|
|
268
|
+
| `query(input)` | `Promise<Turn>` | Stateless single-turn |
|
|
269
|
+
|
|
270
|
+
### AgentState
|
|
271
|
+
|
|
272
|
+
Immutable state with chainable operations:
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
state.withMessage(msg) // Add message
|
|
276
|
+
state.withMessages(msgs) // Add messages
|
|
277
|
+
state.withContext(msgs) // Replace all messages
|
|
278
|
+
state.withStep(n) // Set step number
|
|
279
|
+
state.withMetadata(k, v) // Add metadata
|
|
280
|
+
state.withReasoning(text) // Add reasoning trace
|
|
281
|
+
state.withPlan(steps) // Set execution plan
|
|
282
|
+
state.toJSON() // Serialize
|
|
283
|
+
AgentState.fromJSON(json) // Deserialize
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Examples
|
|
287
|
+
|
|
288
|
+
See the [`examples/`](./examples) directory for complete examples:
|
|
289
|
+
|
|
290
|
+
- **coding-agent** - A Claude Code-style coding assistant with file operations, bash, search, and sub-agents
|
|
291
|
+
|
|
292
|
+
Run the coding agent example:
|
|
10
293
|
|
|
11
294
|
```bash
|
|
12
|
-
bun
|
|
295
|
+
ANTHROPIC_API_KEY=sk-... bun examples/coding-agent/index.ts "List all TypeScript files"
|
|
13
296
|
```
|
|
14
297
|
|
|
15
|
-
|
|
298
|
+
Interactive mode:
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
ANTHROPIC_API_KEY=sk-... bun examples/coding-agent/index.ts -i
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
TUI mode:
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
ANTHROPIC_API_KEY=sk-... bun examples/coding-agent/index.ts --tui
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
## Testing
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
bun test # All tests
|
|
314
|
+
bun test:unit # Unit tests
|
|
315
|
+
bun test:live # Live API tests
|
|
316
|
+
bun lint # Lint
|
|
317
|
+
bun typecheck # Type check
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Philosophy
|
|
321
|
+
|
|
322
|
+
**"UAP is a pipe, not a nanny."**
|
|
323
|
+
|
|
324
|
+
This framework provides orchestration primitives with sensible defaults but no artificial limits. By default:
|
|
325
|
+
|
|
326
|
+
- Execution continues until naturally complete (no max iterations)
|
|
327
|
+
- State is explicit and immutable
|
|
328
|
+
- All UPP types flow through without abstraction
|
|
329
|
+
- You control safety, budgets, and constraints
|
|
330
|
+
|
|
331
|
+
## Documentation
|
|
332
|
+
|
|
333
|
+
- [llms.md](./llms.md) - Comprehensive API documentation for LLMs and developers
|
|
334
|
+
- [CLAUDE.md](./CLAUDE.md) - Project coding guidelines and @providerprotocol/ai usage
|
|
335
|
+
|
|
336
|
+
## License
|
|
337
|
+
|
|
338
|
+
MIT
|
|
339
|
+
|
|
340
|
+
## Related
|
|
341
|
+
|
|
342
|
+
- [@providerprotocol/ai](https://github.com/providerprotocol/ai) - Unified Provider Protocol for LLM inference
|