@octavus/docs 2.10.0 → 2.11.0
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/content/02-server-sdk/01-overview.md +16 -0
- package/content/02-server-sdk/06-workers.md +218 -143
- package/content/04-protocol/01-overview.md +26 -4
- package/content/04-protocol/05-skills.md +43 -7
- package/content/04-protocol/06-handlers.md +3 -0
- package/content/04-protocol/07-agent-config.md +18 -13
- package/content/04-protocol/09-skills-advanced.md +50 -29
- package/content/04-protocol/11-workers.md +40 -5
- package/dist/{chunk-HPVIPOLY.js → chunk-6TO62UOU.js} +13 -13
- package/dist/chunk-6TO62UOU.js.map +1 -0
- package/dist/chunk-EIUCL4CP.js +1489 -0
- package/dist/chunk-EIUCL4CP.js.map +1 -0
- package/dist/{chunk-RZZE5BMI.js → chunk-H6M6M3MY.js} +23 -23
- package/dist/chunk-H6M6M3MY.js.map +1 -0
- package/dist/chunk-NCTX3Y2J.js +1489 -0
- package/dist/chunk-NCTX3Y2J.js.map +1 -0
- package/dist/content.js +1 -1
- package/dist/docs.json +12 -12
- package/dist/index.js +1 -1
- package/dist/search-index.json +1 -1
- package/dist/search.js +1 -1
- package/dist/search.js.map +1 -1
- package/dist/sections.json +12 -12
- package/package.json +1 -1
- package/dist/chunk-HPVIPOLY.js.map +0 -1
- package/dist/chunk-RZZE5BMI.js.map +0 -1
|
@@ -96,6 +96,22 @@ return new Response(toSSEStream(events), {
|
|
|
96
96
|
});
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
### Workers
|
|
100
|
+
|
|
101
|
+
Execute worker agents for task-based processing:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// Non-streaming: get the output directly
|
|
105
|
+
const { output } = await client.workers.generate(agentId, {
|
|
106
|
+
TOPIC: 'AI safety',
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Streaming: observe events in real-time
|
|
110
|
+
for await (const event of client.workers.execute(agentId, input)) {
|
|
111
|
+
// Handle stream events
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
99
115
|
## API Reference
|
|
100
116
|
|
|
101
117
|
### OctavusClient
|
|
@@ -17,59 +17,56 @@ const client = new OctavusClient({
|
|
|
17
17
|
apiKey: 'your-api-key',
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
const events = client.workers.execute(agentId, {
|
|
20
|
+
const { output, sessionId } = await client.workers.generate(agentId, {
|
|
22
21
|
TOPIC: 'AI safety',
|
|
23
22
|
DEPTH: 'detailed',
|
|
24
23
|
});
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (event.type === 'worker-start') {
|
|
29
|
-
console.log(`Worker ${event.workerSlug} started`);
|
|
30
|
-
}
|
|
31
|
-
if (event.type === 'text-delta') {
|
|
32
|
-
process.stdout.write(event.delta);
|
|
33
|
-
}
|
|
34
|
-
if (event.type === 'worker-result') {
|
|
35
|
-
console.log('Output:', event.output);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
25
|
+
console.log('Result:', output);
|
|
26
|
+
console.log(`Debug: ${client.baseUrl}/sessions/${sessionId}`);
|
|
38
27
|
```
|
|
39
28
|
|
|
40
29
|
## WorkersApi Reference
|
|
41
30
|
|
|
42
|
-
###
|
|
31
|
+
### generate()
|
|
43
32
|
|
|
44
|
-
Execute a worker and
|
|
33
|
+
Execute a worker and return the output directly.
|
|
45
34
|
|
|
46
35
|
```typescript
|
|
47
|
-
async
|
|
36
|
+
async generate(
|
|
48
37
|
agentId: string,
|
|
49
38
|
input: Record<string, unknown>,
|
|
50
39
|
options?: WorkerExecuteOptions
|
|
51
|
-
):
|
|
40
|
+
): Promise<WorkerGenerateResult>
|
|
52
41
|
```
|
|
53
42
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
| Parameter | Type | Description |
|
|
57
|
-
| --------- | ------------------------- | --------------------------- |
|
|
58
|
-
| `agentId` | `string` | The worker agent ID |
|
|
59
|
-
| `input` | `Record<string, unknown>` | Input values for the worker |
|
|
60
|
-
| `options` | `WorkerExecuteOptions` | Optional configuration |
|
|
43
|
+
Runs the worker to completion and returns the output value. This is the simplest way to execute a worker.
|
|
61
44
|
|
|
62
|
-
**
|
|
45
|
+
**Returns:**
|
|
63
46
|
|
|
64
47
|
```typescript
|
|
65
|
-
interface
|
|
66
|
-
/**
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
|
|
48
|
+
interface WorkerGenerateResult {
|
|
49
|
+
/** The worker's output value */
|
|
50
|
+
output: unknown;
|
|
51
|
+
/** Session ID for debugging (usable for session URLs) */
|
|
52
|
+
sessionId: string;
|
|
70
53
|
}
|
|
71
54
|
```
|
|
72
55
|
|
|
56
|
+
**Throws:** `WorkerError` if the worker fails or completes without producing output.
|
|
57
|
+
|
|
58
|
+
### execute()
|
|
59
|
+
|
|
60
|
+
Execute a worker and stream the response. Use this when you need to observe intermediate events like text deltas, tool calls, or progress tracking.
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
async *execute(
|
|
64
|
+
agentId: string,
|
|
65
|
+
input: Record<string, unknown>,
|
|
66
|
+
options?: WorkerExecuteOptions
|
|
67
|
+
): AsyncGenerator<StreamEvent>
|
|
68
|
+
```
|
|
69
|
+
|
|
73
70
|
### continue()
|
|
74
71
|
|
|
75
72
|
Continue execution after client-side tool handling.
|
|
@@ -85,19 +82,39 @@ async *continue(
|
|
|
85
82
|
|
|
86
83
|
Use this when the worker has tools without server-side handlers. The execution pauses with a `client-tool-request` event, you execute the tools, then call `continue()` to resume.
|
|
87
84
|
|
|
85
|
+
### Shared Options
|
|
86
|
+
|
|
87
|
+
All methods accept the same options:
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
interface WorkerExecuteOptions {
|
|
91
|
+
/** Tool handlers for server-side tool execution */
|
|
92
|
+
tools?: ToolHandlers;
|
|
93
|
+
/** Abort signal to cancel the execution */
|
|
94
|
+
signal?: AbortSignal;
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Parameters:**
|
|
99
|
+
|
|
100
|
+
| Parameter | Type | Description |
|
|
101
|
+
| --------- | ------------------------- | --------------------------- |
|
|
102
|
+
| `agentId` | `string` | The worker agent ID |
|
|
103
|
+
| `input` | `Record<string, unknown>` | Input values for the worker |
|
|
104
|
+
| `options` | `WorkerExecuteOptions` | Optional configuration |
|
|
105
|
+
|
|
88
106
|
## Tool Handlers
|
|
89
107
|
|
|
90
108
|
Provide tool handlers to execute tools server-side:
|
|
91
109
|
|
|
92
110
|
```typescript
|
|
93
|
-
const
|
|
111
|
+
const { output } = await client.workers.generate(
|
|
94
112
|
agentId,
|
|
95
113
|
{ TOPIC: 'AI safety' },
|
|
96
114
|
{
|
|
97
115
|
tools: {
|
|
98
116
|
'web-search': async (args) => {
|
|
99
|
-
|
|
100
|
-
return results;
|
|
117
|
+
return await searchWeb(args.query);
|
|
101
118
|
},
|
|
102
119
|
'get-user-data': async (args) => {
|
|
103
120
|
return await db.users.findById(args.userId);
|
|
@@ -109,85 +126,141 @@ const events = client.workers.execute(
|
|
|
109
126
|
|
|
110
127
|
Tools defined in the worker protocol but not provided as handlers become client tools — the execution pauses and emits a `client-tool-request` event.
|
|
111
128
|
|
|
112
|
-
##
|
|
129
|
+
## Error Handling
|
|
113
130
|
|
|
114
|
-
|
|
131
|
+
### WorkerError (generate)
|
|
115
132
|
|
|
116
|
-
|
|
133
|
+
`generate()` throws a `WorkerError` on failure. The error includes an optional `sessionId` for constructing debug URLs:
|
|
117
134
|
|
|
118
135
|
```typescript
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
136
|
+
import { OctavusClient, WorkerError } from '@octavus/server-sdk';
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
const { output } = await client.workers.generate(agentId, input);
|
|
140
|
+
console.log('Result:', output);
|
|
141
|
+
} catch (error) {
|
|
142
|
+
if (error instanceof WorkerError) {
|
|
143
|
+
console.error('Worker failed:', error.message);
|
|
144
|
+
if (error.sessionId) {
|
|
145
|
+
console.error(`Debug: ${client.baseUrl}/sessions/${error.sessionId}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
125
148
|
}
|
|
149
|
+
```
|
|
126
150
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
151
|
+
### Stream Errors (execute)
|
|
152
|
+
|
|
153
|
+
When using `execute()`, errors appear as stream events:
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
for await (const event of client.workers.execute(agentId, input)) {
|
|
157
|
+
if (event.type === 'error') {
|
|
158
|
+
console.error(`Error: ${event.message}`);
|
|
159
|
+
console.error(`Type: ${event.errorType}`);
|
|
160
|
+
console.error(`Retryable: ${event.retryable}`);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (event.type === 'worker-result' && event.error) {
|
|
164
|
+
console.error(`Worker failed: ${event.error}`);
|
|
165
|
+
}
|
|
133
166
|
}
|
|
134
167
|
```
|
|
135
168
|
|
|
136
|
-
###
|
|
169
|
+
### Error Types
|
|
137
170
|
|
|
138
|
-
|
|
|
139
|
-
|
|
|
140
|
-
| `
|
|
141
|
-
| `
|
|
142
|
-
| `
|
|
143
|
-
| `
|
|
144
|
-
| `
|
|
145
|
-
| `block-start` | Step started |
|
|
146
|
-
| `block-end` | Step completed |
|
|
147
|
-
| `tool-input-available` | Tool arguments ready |
|
|
148
|
-
| `tool-output-available` | Tool result ready |
|
|
149
|
-
| `client-tool-request` | Client tools need execution |
|
|
150
|
-
| `error` | Error occurred |
|
|
171
|
+
| Type | Description |
|
|
172
|
+
| ------------------ | --------------------- |
|
|
173
|
+
| `validation_error` | Invalid input |
|
|
174
|
+
| `not_found_error` | Worker not found |
|
|
175
|
+
| `provider_error` | LLM provider error |
|
|
176
|
+
| `tool_error` | Tool execution failed |
|
|
177
|
+
| `execution_error` | Worker step failed |
|
|
151
178
|
|
|
152
|
-
##
|
|
179
|
+
## Cancellation
|
|
153
180
|
|
|
154
|
-
|
|
181
|
+
Use an abort signal to cancel execution:
|
|
155
182
|
|
|
156
183
|
```typescript
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
): Promise<unknown> {
|
|
162
|
-
const events = client.workers.execute(agentId, input);
|
|
184
|
+
const { output } = await client.workers.generate(agentId, input, {
|
|
185
|
+
signal: AbortSignal.timeout(30_000),
|
|
186
|
+
});
|
|
187
|
+
```
|
|
163
188
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
189
|
+
With `execute()` and a manual controller:
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
const controller = new AbortController();
|
|
193
|
+
setTimeout(() => controller.abort(), 30000);
|
|
194
|
+
|
|
195
|
+
try {
|
|
196
|
+
for await (const event of client.workers.execute(agentId, input, {
|
|
197
|
+
signal: controller.signal,
|
|
198
|
+
})) {
|
|
199
|
+
// Process events
|
|
200
|
+
}
|
|
201
|
+
} catch (error) {
|
|
202
|
+
if (error.name === 'AbortError') {
|
|
203
|
+
console.log('Worker cancelled');
|
|
171
204
|
}
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Streaming
|
|
172
209
|
|
|
173
|
-
|
|
210
|
+
When you need real-time visibility into the worker's execution — text generation, tool calls, or progress — use `execute()` instead of `generate()`.
|
|
211
|
+
|
|
212
|
+
### Basic Streaming
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
const events = client.workers.execute(agentId, {
|
|
216
|
+
TOPIC: 'AI safety',
|
|
217
|
+
DEPTH: 'detailed',
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
for await (const event of events) {
|
|
221
|
+
if (event.type === 'worker-start') {
|
|
222
|
+
console.log(`Worker ${event.workerSlug} started`);
|
|
223
|
+
}
|
|
224
|
+
if (event.type === 'text-delta') {
|
|
225
|
+
process.stdout.write(event.delta);
|
|
226
|
+
}
|
|
227
|
+
if (event.type === 'worker-result') {
|
|
228
|
+
console.log('Output:', event.output);
|
|
229
|
+
}
|
|
174
230
|
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Streaming to HTTP Response
|
|
234
|
+
|
|
235
|
+
Convert worker events to an SSE stream:
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
import { toSSEStream } from '@octavus/server-sdk';
|
|
239
|
+
|
|
240
|
+
export async function POST(request: Request) {
|
|
241
|
+
const { agentId, input } = await request.json();
|
|
242
|
+
|
|
243
|
+
const events = client.workers.execute(agentId, input, {
|
|
244
|
+
tools: {
|
|
245
|
+
search: async (args) => await search(args.query),
|
|
246
|
+
},
|
|
247
|
+
});
|
|
175
248
|
|
|
176
|
-
|
|
177
|
-
|
|
249
|
+
return new Response(toSSEStream(events), {
|
|
250
|
+
headers: { 'Content-Type': 'text/event-stream' },
|
|
251
|
+
});
|
|
252
|
+
}
|
|
178
253
|
```
|
|
179
254
|
|
|
180
|
-
|
|
255
|
+
### Client Tool Continuation
|
|
181
256
|
|
|
182
257
|
When workers have tools without handlers, execution pauses:
|
|
183
258
|
|
|
184
259
|
```typescript
|
|
185
260
|
for await (const event of client.workers.execute(agentId, input)) {
|
|
186
261
|
if (event.type === 'client-tool-request') {
|
|
187
|
-
// Execute tools client-side
|
|
188
262
|
const results = await executeClientTools(event.toolCalls);
|
|
189
263
|
|
|
190
|
-
// Continue execution
|
|
191
264
|
for await (const ev of client.workers.continue(agentId, event.executionId, results)) {
|
|
192
265
|
// Handle remaining events
|
|
193
266
|
}
|
|
@@ -210,84 +283,87 @@ The `client-tool-request` event includes:
|
|
|
210
283
|
}
|
|
211
284
|
```
|
|
212
285
|
|
|
213
|
-
|
|
286
|
+
### Stream Events
|
|
214
287
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
```typescript
|
|
218
|
-
import { toSSEStream } from '@octavus/server-sdk';
|
|
288
|
+
Workers emit standard stream events plus worker-specific events.
|
|
219
289
|
|
|
220
|
-
|
|
221
|
-
const { agentId, input } = await request.json();
|
|
290
|
+
#### Worker Events
|
|
222
291
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
292
|
+
```typescript
|
|
293
|
+
// Worker started
|
|
294
|
+
{
|
|
295
|
+
type: 'worker-start',
|
|
296
|
+
workerId: string, // Unique ID (also used as session ID for debug)
|
|
297
|
+
workerSlug: string, // The worker's slug
|
|
298
|
+
description?: string, // Display description for UI
|
|
299
|
+
}
|
|
228
300
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
301
|
+
// Worker completed
|
|
302
|
+
{
|
|
303
|
+
type: 'worker-result',
|
|
304
|
+
workerId: string,
|
|
305
|
+
output?: unknown, // The worker's output value
|
|
306
|
+
error?: string, // Error message if worker failed
|
|
232
307
|
}
|
|
233
308
|
```
|
|
234
309
|
|
|
235
|
-
|
|
310
|
+
#### Common Events
|
|
236
311
|
|
|
237
|
-
|
|
312
|
+
| Event | Description |
|
|
313
|
+
| ----------------------- | --------------------------- |
|
|
314
|
+
| `start` | Execution started |
|
|
315
|
+
| `finish` | Execution completed |
|
|
316
|
+
| `text-start` | Text generation started |
|
|
317
|
+
| `text-delta` | Text chunk received |
|
|
318
|
+
| `text-end` | Text generation ended |
|
|
319
|
+
| `block-start` | Step started |
|
|
320
|
+
| `block-end` | Step completed |
|
|
321
|
+
| `tool-input-available` | Tool arguments ready |
|
|
322
|
+
| `tool-output-available` | Tool result ready |
|
|
323
|
+
| `client-tool-request` | Client tools need execution |
|
|
324
|
+
| `error` | Error occurred |
|
|
238
325
|
|
|
239
|
-
|
|
240
|
-
const controller = new AbortController();
|
|
326
|
+
## Full Examples
|
|
241
327
|
|
|
242
|
-
|
|
243
|
-
|
|
328
|
+
### generate()
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
import { OctavusClient, WorkerError } from '@octavus/server-sdk';
|
|
244
332
|
|
|
245
|
-
const
|
|
246
|
-
|
|
333
|
+
const client = new OctavusClient({
|
|
334
|
+
baseUrl: 'https://octavus.ai',
|
|
335
|
+
apiKey: process.env.OCTAVUS_API_KEY!,
|
|
247
336
|
});
|
|
248
337
|
|
|
249
338
|
try {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
```typescript
|
|
265
|
-
for await (const event of client.workers.execute(agentId, input)) {
|
|
266
|
-
// Stream-level error event
|
|
267
|
-
if (event.type === 'error') {
|
|
268
|
-
console.error(`Error: ${event.message}`);
|
|
269
|
-
console.error(`Type: ${event.errorType}`);
|
|
270
|
-
console.error(`Retryable: ${event.retryable}`);
|
|
271
|
-
}
|
|
339
|
+
const { output, sessionId } = await client.workers.generate(
|
|
340
|
+
'research-assistant-id',
|
|
341
|
+
{
|
|
342
|
+
TOPIC: 'AI safety best practices',
|
|
343
|
+
DEPTH: 'detailed',
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
tools: {
|
|
347
|
+
'web-search': async ({ query }) => await performWebSearch(query),
|
|
348
|
+
},
|
|
349
|
+
signal: AbortSignal.timeout(120_000),
|
|
350
|
+
},
|
|
351
|
+
);
|
|
272
352
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
353
|
+
console.log('Result:', output);
|
|
354
|
+
} catch (error) {
|
|
355
|
+
if (error instanceof WorkerError) {
|
|
356
|
+
console.error('Failed:', error.message);
|
|
357
|
+
if (error.sessionId) {
|
|
358
|
+
console.error(`Debug: ${client.baseUrl}/sessions/${error.sessionId}`);
|
|
359
|
+
}
|
|
276
360
|
}
|
|
277
361
|
}
|
|
278
362
|
```
|
|
279
363
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
| Type | Description |
|
|
283
|
-
| ------------------ | --------------------- |
|
|
284
|
-
| `validation_error` | Invalid input |
|
|
285
|
-
| `not_found_error` | Worker not found |
|
|
286
|
-
| `provider_error` | LLM provider error |
|
|
287
|
-
| `tool_error` | Tool execution failed |
|
|
288
|
-
| `execution_error` | Worker step failed |
|
|
364
|
+
### execute()
|
|
289
365
|
|
|
290
|
-
|
|
366
|
+
For full control over streaming events and progress tracking:
|
|
291
367
|
|
|
292
368
|
```typescript
|
|
293
369
|
import { OctavusClient, type StreamEvent } from '@octavus/server-sdk';
|
|
@@ -348,7 +424,6 @@ async function runResearchWorker(topic: string) {
|
|
|
348
424
|
return output;
|
|
349
425
|
}
|
|
350
426
|
|
|
351
|
-
// Run the worker
|
|
352
427
|
const result = await runResearchWorker('AI safety best practices');
|
|
353
428
|
console.log('Result:', result);
|
|
354
429
|
```
|
|
@@ -105,12 +105,16 @@ Each agent is a folder with:
|
|
|
105
105
|
my-agent/
|
|
106
106
|
├── protocol.yaml # Main logic (required)
|
|
107
107
|
├── settings.json # Agent metadata (required)
|
|
108
|
-
└── prompts/ # Prompt templates
|
|
108
|
+
└── prompts/ # Prompt templates (supports subdirectories)
|
|
109
109
|
├── system.md
|
|
110
110
|
├── user-message.md
|
|
111
|
-
└──
|
|
111
|
+
└── shared/
|
|
112
|
+
├── company-info.md
|
|
113
|
+
└── formatting-rules.md
|
|
112
114
|
```
|
|
113
115
|
|
|
116
|
+
Prompts can be organized in subdirectories. In the protocol, reference nested prompts by their path relative to `prompts/` (without `.md`): `shared/company-info`.
|
|
117
|
+
|
|
114
118
|
### settings.json
|
|
115
119
|
|
|
116
120
|
```json
|
|
@@ -133,7 +137,7 @@ my-agent/
|
|
|
133
137
|
|
|
134
138
|
- **Slugs**: `lowercase-with-dashes`
|
|
135
139
|
- **Variables**: `UPPERCASE_SNAKE_CASE`
|
|
136
|
-
- **Prompts**: `lowercase-with-dashes.md`
|
|
140
|
+
- **Prompts**: `lowercase-with-dashes.md` (paths use `/` for subdirectories)
|
|
137
141
|
- **Tools**: `lowercase-with-dashes`
|
|
138
142
|
- **Triggers**: `lowercase-with-dashes`
|
|
139
143
|
|
|
@@ -153,7 +157,25 @@ Help users with their {{PRODUCT_NAME}} questions.
|
|
|
153
157
|
{{SUPPORT_POLICIES}}
|
|
154
158
|
```
|
|
155
159
|
|
|
156
|
-
Variables are replaced with their values at runtime. If a variable is not provided,
|
|
160
|
+
Variables are replaced with their values at runtime. If a variable is not provided, the placeholder is kept as-is.
|
|
161
|
+
|
|
162
|
+
## Prompt Interpolation
|
|
163
|
+
|
|
164
|
+
Include other prompts inside a prompt with `{{@path.md}}`:
|
|
165
|
+
|
|
166
|
+
```markdown
|
|
167
|
+
<!-- prompts/system.md -->
|
|
168
|
+
|
|
169
|
+
You are a customer support agent.
|
|
170
|
+
|
|
171
|
+
{{@shared/company-info.md}}
|
|
172
|
+
|
|
173
|
+
{{@shared/formatting-rules.md}}
|
|
174
|
+
|
|
175
|
+
Help users with their questions.
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
The referenced prompt content is inserted before variable interpolation, so variables in included prompts work the same way. Circular references are not allowed and will be caught during validation.
|
|
157
179
|
|
|
158
180
|
## Next Steps
|
|
159
181
|
|
|
@@ -61,24 +61,48 @@ skills:
|
|
|
61
61
|
|
|
62
62
|
## Enabling Skills
|
|
63
63
|
|
|
64
|
-
After defining skills in the `skills:` section, specify which skills are available
|
|
64
|
+
After defining skills in the `skills:` section, specify which skills are available. Skills work in both interactive agents and workers.
|
|
65
|
+
|
|
66
|
+
### Interactive Agents
|
|
67
|
+
|
|
68
|
+
Reference skills in `agent.skills`:
|
|
65
69
|
|
|
66
70
|
```yaml
|
|
67
|
-
# All skills available to this agent (defined once at protocol level)
|
|
68
71
|
skills:
|
|
69
72
|
qr-code:
|
|
70
73
|
display: description
|
|
71
74
|
description: Generating QR codes
|
|
72
75
|
|
|
73
|
-
# Skills available for this chat thread
|
|
74
76
|
agent:
|
|
75
77
|
model: anthropic/claude-sonnet-4-5
|
|
76
78
|
system: system
|
|
77
79
|
tools: [get-user-account]
|
|
78
|
-
skills: [qr-code]
|
|
80
|
+
skills: [qr-code]
|
|
79
81
|
agentic: true
|
|
80
82
|
```
|
|
81
83
|
|
|
84
|
+
### Workers and Named Threads
|
|
85
|
+
|
|
86
|
+
Reference skills per-thread in `start-thread.skills`:
|
|
87
|
+
|
|
88
|
+
```yaml
|
|
89
|
+
skills:
|
|
90
|
+
qr-code:
|
|
91
|
+
display: description
|
|
92
|
+
description: Generating QR codes
|
|
93
|
+
|
|
94
|
+
steps:
|
|
95
|
+
Start thread:
|
|
96
|
+
block: start-thread
|
|
97
|
+
thread: worker
|
|
98
|
+
model: anthropic/claude-sonnet-4-5
|
|
99
|
+
system: system
|
|
100
|
+
skills: [qr-code]
|
|
101
|
+
maxSteps: 10
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
This also works for named threads in interactive agents, allowing different threads to have different skills.
|
|
105
|
+
|
|
82
106
|
## Skill Tools
|
|
83
107
|
|
|
84
108
|
When skills are enabled, the LLM has access to these tools:
|
|
@@ -290,23 +314,35 @@ agent:
|
|
|
290
314
|
|
|
291
315
|
## Sandbox Timeout
|
|
292
316
|
|
|
293
|
-
The default sandbox timeout is 5 minutes.
|
|
317
|
+
The default sandbox timeout is 5 minutes. You can configure a custom timeout using `sandboxTimeout` in the agent config or on individual `start-thread` blocks:
|
|
294
318
|
|
|
295
319
|
```yaml
|
|
320
|
+
# Agent-level timeout (applies to main thread)
|
|
296
321
|
agent:
|
|
297
322
|
model: anthropic/claude-sonnet-4-5
|
|
298
323
|
skills: [data-analysis]
|
|
299
324
|
sandboxTimeout: 1800000 # 30 minutes (in milliseconds)
|
|
300
325
|
```
|
|
301
326
|
|
|
302
|
-
|
|
327
|
+
```yaml
|
|
328
|
+
# Thread-level timeout (overrides agent-level for this thread)
|
|
329
|
+
steps:
|
|
330
|
+
Start thread:
|
|
331
|
+
block: start-thread
|
|
332
|
+
thread: analysis
|
|
333
|
+
model: anthropic/claude-sonnet-4-5
|
|
334
|
+
skills: [data-analysis]
|
|
335
|
+
sandboxTimeout: 3600000 # 1 hour
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Thread-level `sandboxTimeout` takes priority over agent-level. Maximum: 1 hour (3,600,000 ms).
|
|
303
339
|
|
|
304
340
|
## Security
|
|
305
341
|
|
|
306
342
|
Skills run in isolated sandbox environments:
|
|
307
343
|
|
|
308
344
|
- **No network access** (unless explicitly configured)
|
|
309
|
-
- **No persistent storage** (sandbox destroyed after execution)
|
|
345
|
+
- **No persistent storage** (sandbox destroyed after each `next-message` execution)
|
|
310
346
|
- **File output only** via `/output/` directory
|
|
311
347
|
- **Time limits** enforced (5-minute default, configurable via `sandboxTimeout`)
|
|
312
348
|
|
|
@@ -148,6 +148,9 @@ Start summary thread:
|
|
|
148
148
|
maxSteps: 1 # Tool call limit
|
|
149
149
|
system: escalation-summary # System prompt
|
|
150
150
|
input: [COMPANY_NAME] # Variables for prompt
|
|
151
|
+
skills: [qr-code] # Octavus skills for this thread
|
|
152
|
+
sandboxTimeout: 600000 # Skill sandbox timeout (default: 5 min, max: 1 hour)
|
|
153
|
+
imageModel: google/gemini-2.5-flash-image # Image generation model
|
|
151
154
|
```
|
|
152
155
|
|
|
153
156
|
The `model` field can also reference a variable for dynamic model selection:
|