@ariaflowagents/cf-agent 0.5.3 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +436 -135
- package/dist/AriaFlowAgent.d.ts +109 -0
- package/dist/AriaFlowAgent.d.ts.map +1 -0
- package/dist/AriaFlowAgent.js +170 -0
- package/dist/AriaFlowAgent.js.map +1 -0
- package/dist/BridgeSessionStore.d.ts +37 -0
- package/dist/BridgeSessionStore.d.ts.map +1 -0
- package/dist/BridgeSessionStore.js +120 -0
- package/dist/BridgeSessionStore.js.map +1 -0
- package/dist/OrchestrationStore.d.ts +25 -0
- package/dist/OrchestrationStore.d.ts.map +1 -0
- package/dist/OrchestrationStore.js +63 -0
- package/dist/OrchestrationStore.js.map +1 -0
- package/dist/StreamAdapter.d.ts +19 -0
- package/dist/StreamAdapter.d.ts.map +1 -0
- package/dist/StreamAdapter.js +205 -0
- package/dist/StreamAdapter.js.map +1 -0
- package/dist/index.d.ts +33 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -3
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +37 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +37 -27
- package/dist/AriaFlowChatAgent.d.ts +0 -24
- package/dist/AriaFlowChatAgent.d.ts.map +0 -1
- package/dist/AriaFlowChatAgent.js +0 -153
- package/dist/AriaFlowChatAgent.js.map +0 -1
- package/dist/AriaFlowFlowAgent.d.ts +0 -88
- package/dist/AriaFlowFlowAgent.d.ts.map +0 -1
- package/dist/AriaFlowFlowAgent.js +0 -185
- package/dist/AriaFlowFlowAgent.js.map +0 -1
- package/dist/stores/CloudflareSQLiteStore.d.ts +0 -12
- package/dist/stores/CloudflareSQLiteStore.d.ts.map +0 -1
- package/dist/stores/CloudflareSQLiteStore.js +0 -99
- package/dist/stores/CloudflareSQLiteStore.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,196 +1,497 @@
|
|
|
1
1
|
# @ariaflowagents/cf-agent
|
|
2
2
|
|
|
3
|
-
Cloudflare
|
|
3
|
+
AriaFlow integration for Cloudflare Workers using AIChatAgent. Build multi-agent AI systems with automatic persistence, resumable streaming, and real-time sync.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Features
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- **All AriaFlow Agent Types**: LLM, Flow, Triage, and Composite agents
|
|
8
|
+
- **Automatic Persistence**: Messages stored in SQLite, survive restarts
|
|
9
|
+
- **Resumable Streaming**: Reconnect without data loss
|
|
10
|
+
- **Multi-Client Sync**: Real-time updates across all connected clients
|
|
11
|
+
- **Full Tool Support**: Server-side, client-side, and approval tools
|
|
12
|
+
- **Zero Config**: Works out of the box with sensible defaults
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
|-------|----------|----------------|
|
|
11
|
-
| `AriaFlowChatAgent` | Multi-agent systems with handoffs | `HarnessConfig` or `Runtime` |
|
|
12
|
-
| `AriaFlowFlowAgent` | Structured single-flow conversations | `AriaFlowFlowConfig` or `AgentFlowManager` |
|
|
14
|
+
## Quick Start
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
```bash
|
|
17
|
+
# Create a new project
|
|
18
|
+
mkdir my-agent && cd my-agent
|
|
19
|
+
npm init -y
|
|
15
20
|
|
|
16
|
-
|
|
21
|
+
# Install dependencies
|
|
22
|
+
npm install @ariaflowagents/cf-agent ai zod
|
|
23
|
+
npm install -D @cloudflare/vite-plugin vite wrangler
|
|
17
24
|
|
|
18
|
-
|
|
25
|
+
# Create your agent
|
|
26
|
+
# See examples below...
|
|
27
|
+
|
|
28
|
+
# Run locally
|
|
29
|
+
npm run dev
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Open http://localhost:5173 to see your agent in action.
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install @ariaflowagents/cf-agent
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Project Structure
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
my-agent/
|
|
44
|
+
├── src/
|
|
45
|
+
│ ├── server.ts # Agent implementation
|
|
46
|
+
│ ├── app.tsx # React chat UI
|
|
47
|
+
│ └── client.tsx # React entry point
|
|
48
|
+
├── package.json
|
|
49
|
+
├── tsconfig.json
|
|
50
|
+
├── vite.config.ts
|
|
51
|
+
└── wrangler.jsonc
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Basic Example
|
|
55
|
+
|
|
56
|
+
### 1. Create Agent (`src/server.ts`)
|
|
19
57
|
|
|
20
58
|
```typescript
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
59
|
+
import { AriaFlowAIChatAgent } from "@ariaflowagents/cf-agent";
|
|
60
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
|
61
|
+
import { tool } from "ai";
|
|
62
|
+
import { z } from "zod";
|
|
23
63
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
id: 'triage',
|
|
28
|
-
name: 'Triage',
|
|
29
|
-
type: 'triage',
|
|
30
|
-
systemPrompt: 'Route customers to specialists.',
|
|
31
|
-
routes: [
|
|
32
|
-
{ agentId: 'orders', description: 'Order questions' },
|
|
33
|
-
{ agentId: 'billing', description: 'Billing questions' },
|
|
34
|
-
],
|
|
35
|
-
};
|
|
64
|
+
interface Env {
|
|
65
|
+
OPENAI_API_KEY: string;
|
|
66
|
+
}
|
|
36
67
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
type: 'llm',
|
|
41
|
-
systemPrompt: 'Help with order questions.',
|
|
42
|
-
};
|
|
68
|
+
export class MyAgent extends AriaFlowAIChatAgent<Env> {
|
|
69
|
+
protected getRuntimeConfig() {
|
|
70
|
+
const openai = createOpenAI({ apiKey: this.env.OPENAI_API_KEY });
|
|
43
71
|
|
|
44
72
|
return {
|
|
45
|
-
agents: [
|
|
46
|
-
|
|
73
|
+
agents: [{
|
|
74
|
+
id: "assistant",
|
|
75
|
+
type: "llm" as const,
|
|
76
|
+
name: "Assistant",
|
|
77
|
+
model: openai("gpt-4o"),
|
|
78
|
+
prompt: "You are a helpful assistant",
|
|
79
|
+
tools: {
|
|
80
|
+
getWeather: tool({
|
|
81
|
+
description: "Get weather for a city",
|
|
82
|
+
inputSchema: z.object({ city: z.string() }),
|
|
83
|
+
execute: async ({ city }) => {
|
|
84
|
+
return { temperature: 72, condition: "sunny" };
|
|
85
|
+
},
|
|
86
|
+
}),
|
|
87
|
+
},
|
|
88
|
+
}],
|
|
89
|
+
defaultAgentId: "assistant",
|
|
47
90
|
};
|
|
48
91
|
}
|
|
49
92
|
}
|
|
93
|
+
|
|
94
|
+
export default MyAgent;
|
|
50
95
|
```
|
|
51
96
|
|
|
52
|
-
|
|
97
|
+
### 2. Create UI (`src/app.tsx`)
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
import { useAgent } from "agents/react";
|
|
101
|
+
import { useAgentChat } from "@cloudflare/ai-chat/react";
|
|
102
|
+
|
|
103
|
+
export function Chat() {
|
|
104
|
+
const agent = useAgent({ agent: "MyAgent" });
|
|
105
|
+
const { messages, sendMessage, status } = useAgentChat({ agent });
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<div>
|
|
109
|
+
{messages.map((msg) => (
|
|
110
|
+
<div key={msg.id}>
|
|
111
|
+
<strong>{msg.role}:</strong>
|
|
112
|
+
{msg.parts.map((part, i) =>
|
|
113
|
+
part.type === "text" ? <span key={i}>{part.text}</span> : null
|
|
114
|
+
)}
|
|
115
|
+
</div>
|
|
116
|
+
))}
|
|
117
|
+
<form onSubmit={(e) => {
|
|
118
|
+
e.preventDefault();
|
|
119
|
+
const input = e.currentTarget.elements.namedItem("input") as HTMLInputElement;
|
|
120
|
+
sendMessage({ text: input.value });
|
|
121
|
+
input.value = "";
|
|
122
|
+
}}>
|
|
123
|
+
<input name="input" placeholder="Type a message..." />
|
|
124
|
+
<button type="submit" disabled={status === "streaming"}>Send</button>
|
|
125
|
+
</form>
|
|
126
|
+
</div>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### 3. Configuration Files
|
|
132
|
+
|
|
133
|
+
**`vite.config.ts`**:
|
|
53
134
|
```typescript
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
135
|
+
import { defineConfig } from "vite";
|
|
136
|
+
import { cloudflare } from "@cloudflare/vite-plugin";
|
|
137
|
+
import react from "@vitejs/plugin-react";
|
|
138
|
+
|
|
139
|
+
export default defineConfig({
|
|
140
|
+
plugins: [cloudflare(), react()],
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**`wrangler.jsonc`**:
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"name": "my-agent",
|
|
148
|
+
"main": "src/server.ts",
|
|
149
|
+
"compatibility_date": "2026-01-28",
|
|
150
|
+
"compatibility_flags": ["nodejs_compat"],
|
|
151
|
+
"ai": { "binding": "AI" },
|
|
152
|
+
"durable_objects": {
|
|
153
|
+
"bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }]
|
|
154
|
+
},
|
|
155
|
+
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyAgent"] }]
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**`package.json`** scripts:
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"scripts": {
|
|
163
|
+
"dev": "vite dev",
|
|
164
|
+
"deploy": "vite build && wrangler deploy",
|
|
165
|
+
"types": "wrangler types"
|
|
166
|
+
}
|
|
58
167
|
}
|
|
59
168
|
```
|
|
60
169
|
|
|
61
|
-
|
|
170
|
+
## Agent Types
|
|
62
171
|
|
|
63
|
-
|
|
172
|
+
### LLMAgent
|
|
64
173
|
|
|
65
|
-
|
|
174
|
+
Standard conversational agent with tools:
|
|
66
175
|
|
|
67
176
|
```typescript
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
177
|
+
{
|
|
178
|
+
id: "sales",
|
|
179
|
+
type: "llm" as const,
|
|
180
|
+
name: "Sales Agent",
|
|
181
|
+
model: openai("gpt-4o"),
|
|
182
|
+
prompt: "You are a sales specialist...",
|
|
183
|
+
tools: { /* ... */ },
|
|
184
|
+
canHandoffTo: ["support", "billing"]
|
|
185
|
+
}
|
|
186
|
+
```
|
|
73
187
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
},
|
|
99
|
-
],
|
|
100
|
-
};
|
|
188
|
+
### FlowAgent
|
|
189
|
+
|
|
190
|
+
Structured node-based conversation flows:
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
{
|
|
194
|
+
id: "order-flow",
|
|
195
|
+
type: "flow" as const,
|
|
196
|
+
name: "Order Flow",
|
|
197
|
+
model: openai("gpt-4o"),
|
|
198
|
+
flow: {
|
|
199
|
+
nodes: [
|
|
200
|
+
{
|
|
201
|
+
id: "initial",
|
|
202
|
+
task: "Ask what they want",
|
|
203
|
+
transitions: [{ to: "confirm", on: "product_selected" }]
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
id: "confirm",
|
|
207
|
+
task: "Confirm order",
|
|
208
|
+
transitions: [{ to: "end", on: "confirmed" }]
|
|
209
|
+
}
|
|
210
|
+
],
|
|
211
|
+
hybrid: true // Allow off-flow questions
|
|
101
212
|
}
|
|
102
213
|
}
|
|
103
214
|
```
|
|
104
215
|
|
|
105
|
-
|
|
216
|
+
### TriageAgent
|
|
217
|
+
|
|
218
|
+
Intelligent routing between agents:
|
|
219
|
+
|
|
106
220
|
```typescript
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
221
|
+
{
|
|
222
|
+
id: "router",
|
|
223
|
+
type: "triage" as const,
|
|
224
|
+
name: "Router",
|
|
225
|
+
model: openai("gpt-4o-mini"),
|
|
226
|
+
routingConfig: {
|
|
227
|
+
agents: ["sales", "support", "billing"],
|
|
228
|
+
instructions: "Route based on user intent..."
|
|
229
|
+
}
|
|
111
230
|
}
|
|
112
231
|
```
|
|
113
232
|
|
|
114
|
-
|
|
233
|
+
### CompositeAgent
|
|
115
234
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
Control conversation history behavior:
|
|
235
|
+
Multi-agent coordination:
|
|
119
236
|
|
|
120
237
|
```typescript
|
|
121
238
|
{
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
239
|
+
id: "supervisor",
|
|
240
|
+
type: "composite" as const,
|
|
241
|
+
name: "Supervisor",
|
|
242
|
+
model: openai("gpt-4o"),
|
|
243
|
+
agents: ["researcher", "analyst", "writer"],
|
|
244
|
+
coordinationMode: "sequential"
|
|
127
245
|
}
|
|
128
246
|
```
|
|
129
247
|
|
|
130
|
-
|
|
131
|
-
|----------|----------|
|
|
132
|
-
| `append` | Keep all messages (default) |
|
|
133
|
-
| `reset` | Clear messages on node entry |
|
|
134
|
-
| `reset_with_summary` | Summarize and replace messages |
|
|
248
|
+
## Tools
|
|
135
249
|
|
|
136
|
-
|
|
250
|
+
### Server-Side Tools
|
|
137
251
|
|
|
138
|
-
|
|
252
|
+
Run automatically on the server:
|
|
139
253
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
254
|
+
```typescript
|
|
255
|
+
tools: {
|
|
256
|
+
getWeather: tool({
|
|
257
|
+
description: "Get weather for a city",
|
|
258
|
+
inputSchema: z.object({ city: z.string() }),
|
|
259
|
+
execute: async ({ city }) => {
|
|
260
|
+
// Runs on server
|
|
261
|
+
return await fetchWeather(city);
|
|
262
|
+
}
|
|
263
|
+
})
|
|
264
|
+
}
|
|
265
|
+
```
|
|
145
266
|
|
|
146
|
-
|
|
147
|
-
| `GET /flow-state` | Flow-specific state (currentNode, nodeHistory, collectedData) |
|
|
267
|
+
### Client-Side Tools
|
|
148
268
|
|
|
149
|
-
|
|
269
|
+
No `execute` function - browser provides the result:
|
|
150
270
|
|
|
151
|
-
|
|
271
|
+
```typescript
|
|
272
|
+
// Server
|
|
273
|
+
tools: {
|
|
274
|
+
getLocation: tool({
|
|
275
|
+
description: "Get user location",
|
|
276
|
+
inputSchema: z.object({})
|
|
277
|
+
// No execute - client handles it
|
|
278
|
+
})
|
|
279
|
+
}
|
|
152
280
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
281
|
+
// Client
|
|
282
|
+
useAgentChat({
|
|
283
|
+
onToolCall: async ({ toolCall, addToolOutput }) => {
|
|
284
|
+
if (toolCall.toolName === "getLocation") {
|
|
285
|
+
const pos = await navigator.geolocation.getCurrentPosition();
|
|
286
|
+
addToolOutput({
|
|
287
|
+
toolCallId: toolCall.toolCallId,
|
|
288
|
+
output: { lat: pos.coords.latitude, lng: pos.coords.longitude }
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
```
|
|
160
294
|
|
|
161
|
-
|
|
295
|
+
### Approval Tools
|
|
162
296
|
|
|
163
|
-
|
|
297
|
+
Human-in-the-loop for sensitive operations:
|
|
164
298
|
|
|
165
299
|
```typescript
|
|
166
|
-
|
|
167
|
-
|
|
300
|
+
tools: {
|
|
301
|
+
processRefund: tool({
|
|
302
|
+
description: "Process a refund",
|
|
303
|
+
inputSchema: z.object({ orderId: z.string(), amount: z.number() }),
|
|
304
|
+
needsApproval: ({ amount }) => amount > 100,
|
|
305
|
+
execute: async ({ orderId, amount }) => {
|
|
306
|
+
// Only runs after user approval
|
|
307
|
+
return await processRefund(orderId, amount);
|
|
308
|
+
}
|
|
309
|
+
})
|
|
310
|
+
}
|
|
311
|
+
```
|
|
168
312
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
313
|
+
## Hooks
|
|
314
|
+
|
|
315
|
+
React to agent lifecycle events:
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
protected getHooks() {
|
|
319
|
+
return {
|
|
320
|
+
onHandoff: async (context, from, to, reason) => {
|
|
321
|
+
console.log(`Handoff: ${from} -> ${to} (${reason})`);
|
|
322
|
+
},
|
|
323
|
+
|
|
324
|
+
onToolCall: async (context, toolCall) => {
|
|
325
|
+
console.log(`Tool: ${toolCall.toolName}`);
|
|
326
|
+
},
|
|
327
|
+
|
|
328
|
+
onNodeEnter: async (context, node) => {
|
|
329
|
+
console.log(`Flow node: ${node.name}`);
|
|
330
|
+
}
|
|
331
|
+
};
|
|
176
332
|
}
|
|
333
|
+
```
|
|
177
334
|
|
|
178
|
-
|
|
179
|
-
import { AriaFlowFlowAgent } from '@ariaflowagents/cf-agent';
|
|
335
|
+
## State Persistence
|
|
180
336
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
337
|
+
AriaFlow stores two types of data:
|
|
338
|
+
|
|
339
|
+
1. **CF Tables** (`cf_ai_chat_*`): Chat messages, stream chunks, resumption data
|
|
340
|
+
2. **AriaFlow Tables** (`ariaflow_sessions`): Session state, working memory, flow state
|
|
341
|
+
|
|
342
|
+
```
|
|
343
|
+
SQLite Database:
|
|
344
|
+
├── cf_ai_chat_agent_messages (UIMessages for UI)
|
|
345
|
+
├── cf_ai_chat_stream_chunks (Stream chunks)
|
|
346
|
+
├── cf_ai_chat_stream_metadata (Stream state)
|
|
347
|
+
└── ariaflow_sessions (AriaFlow Session state)
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
## Custom Configuration
|
|
351
|
+
|
|
352
|
+
### Stream Adapter
|
|
353
|
+
|
|
354
|
+
Control which events are sent to the client:
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
protected getStreamAdapterConfig() {
|
|
358
|
+
return {
|
|
359
|
+
includeHandoffs: true, // Show agent handoffs in UI
|
|
360
|
+
includeFlowEvents: true, // Show flow node transitions
|
|
361
|
+
includeTripwires: true, // Show guardrail triggers
|
|
362
|
+
includeStepEvents: false, // Hide step lifecycle
|
|
363
|
+
includeAgentEvents: false // Hide agent lifecycle
|
|
364
|
+
};
|
|
189
365
|
}
|
|
366
|
+
```
|
|
190
367
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
368
|
+
### Session ID
|
|
369
|
+
|
|
370
|
+
Override default session ID generation:
|
|
371
|
+
|
|
372
|
+
```typescript
|
|
373
|
+
protected getSessionId(): string {
|
|
374
|
+
// Default uses Durable Object ID
|
|
375
|
+
// Override for custom session management
|
|
376
|
+
return `user-${this.getUserId()}`;
|
|
377
|
+
}
|
|
196
378
|
```
|
|
379
|
+
|
|
380
|
+
## Scripts
|
|
381
|
+
|
|
382
|
+
```bash
|
|
383
|
+
# Development (with hot reload)
|
|
384
|
+
npm run dev
|
|
385
|
+
|
|
386
|
+
# Deploy to Cloudflare
|
|
387
|
+
npm run deploy
|
|
388
|
+
|
|
389
|
+
# Generate types
|
|
390
|
+
npm run types
|
|
391
|
+
|
|
392
|
+
# Build only
|
|
393
|
+
npm run build
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
## Using Different AI Providers
|
|
397
|
+
|
|
398
|
+
### Workers AI (No API key needed)
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
import { createWorkersAI } from "workers-ai-provider";
|
|
402
|
+
|
|
403
|
+
const workersai = createWorkersAI({ binding: this.env.AI });
|
|
404
|
+
|
|
405
|
+
// In agent config:
|
|
406
|
+
model: workersai("@cf/meta/llama-3.3-70b-instruct-fp8-fast")
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### OpenAI
|
|
410
|
+
|
|
411
|
+
```bash
|
|
412
|
+
npm install @ai-sdk/openai
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
```typescript
|
|
416
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
|
417
|
+
|
|
418
|
+
const openai = createOpenAI({ apiKey: this.env.OPENAI_API_KEY });
|
|
419
|
+
|
|
420
|
+
// In agent config:
|
|
421
|
+
model: openai("gpt-4o")
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### Anthropic
|
|
425
|
+
|
|
426
|
+
```bash
|
|
427
|
+
npm install @ai-sdk/anthropic
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
```typescript
|
|
431
|
+
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
432
|
+
|
|
433
|
+
const anthropic = createAnthropic({ apiKey: this.env.ANTHROPIC_API_KEY });
|
|
434
|
+
|
|
435
|
+
// In agent config:
|
|
436
|
+
model: anthropic("claude-sonnet-4-20250514")
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
## API Reference
|
|
440
|
+
|
|
441
|
+
### AriaFlowAIChatAgent
|
|
442
|
+
|
|
443
|
+
Abstract base class extending CF's `AIChatAgent`.
|
|
444
|
+
|
|
445
|
+
```typescript
|
|
446
|
+
abstract class AriaFlowAIChatAgent<Env, State> {
|
|
447
|
+
// Required
|
|
448
|
+
protected abstract getRuntimeConfig(): HarnessConfig;
|
|
449
|
+
|
|
450
|
+
// Optional overrides
|
|
451
|
+
protected getHooks(): Partial<HarnessHooks>;
|
|
452
|
+
protected getStreamAdapterConfig(): Partial<StreamAdapterConfig>;
|
|
453
|
+
protected getSessionId(): string;
|
|
454
|
+
|
|
455
|
+
// Utility methods
|
|
456
|
+
protected async getSession(): Promise<Session | null>;
|
|
457
|
+
protected getSessionStats(): SessionStats | null;
|
|
458
|
+
}
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### Environment Variables
|
|
462
|
+
|
|
463
|
+
```bash
|
|
464
|
+
# For OpenAI
|
|
465
|
+
OPENAI_API_KEY=your-key
|
|
466
|
+
|
|
467
|
+
# For Anthropic
|
|
468
|
+
ANTHROPIC_API_KEY=your-key
|
|
469
|
+
|
|
470
|
+
# For custom providers
|
|
471
|
+
PROVIDER_API_KEY=your-key
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
## Architecture
|
|
475
|
+
|
|
476
|
+
```
|
|
477
|
+
Client (useAgentChat)
|
|
478
|
+
│
|
|
479
|
+
▼ WebSocket
|
|
480
|
+
CF AIChatAgent (Durable Object)
|
|
481
|
+
├─► CF SQLite: Chat messages, stream chunks
|
|
482
|
+
└─► AriaFlow Runtime
|
|
483
|
+
├─► CloudflareSessionStore (SQLite)
|
|
484
|
+
├─► Multi-agent execution
|
|
485
|
+
└─► StreamAdapter
|
|
486
|
+
└─► UIMessageChunk format
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
## Learn More
|
|
490
|
+
|
|
491
|
+
- [AriaFlow Documentation](https://github.com/ariaflowagents/ariaflow)
|
|
492
|
+
- [Cloudflare Agents SDK](https://developers.cloudflare.com/agents/)
|
|
493
|
+
- [Vercel AI SDK](https://ai-sdk.dev)
|
|
494
|
+
|
|
495
|
+
## License
|
|
496
|
+
|
|
497
|
+
MIT
|