zeitlich 0.1.1 → 0.2.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.
Files changed (58) hide show
  1. package/README.md +165 -180
  2. package/dist/index.cjs +1314 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +128 -0
  5. package/dist/index.d.ts +51 -75
  6. package/dist/index.js +741 -1091
  7. package/dist/index.js.map +1 -1
  8. package/dist/workflow-uVNF7zoe.d.cts +941 -0
  9. package/dist/workflow-uVNF7zoe.d.ts +941 -0
  10. package/dist/workflow.cjs +914 -0
  11. package/dist/workflow.cjs.map +1 -0
  12. package/dist/workflow.d.cts +5 -0
  13. package/dist/workflow.d.ts +2 -1
  14. package/dist/workflow.js +543 -423
  15. package/dist/workflow.js.map +1 -1
  16. package/package.json +19 -17
  17. package/src/activities.ts +112 -0
  18. package/src/index.ts +49 -0
  19. package/src/lib/fs.ts +80 -0
  20. package/src/lib/model-invoker.ts +75 -0
  21. package/src/lib/session.ts +216 -0
  22. package/src/lib/state-manager.ts +268 -0
  23. package/src/lib/thread-manager.ts +169 -0
  24. package/src/lib/tool-router.ts +717 -0
  25. package/src/lib/types.ts +354 -0
  26. package/src/plugin.ts +28 -0
  27. package/src/tools/ask-user-question/handler.ts +25 -0
  28. package/src/tools/ask-user-question/tool.ts +46 -0
  29. package/src/tools/bash/bash.test.ts +104 -0
  30. package/src/tools/bash/handler.ts +36 -0
  31. package/src/tools/bash/tool.ts +20 -0
  32. package/src/tools/edit/handler.ts +156 -0
  33. package/src/tools/edit/tool.ts +39 -0
  34. package/src/tools/glob/handler.ts +62 -0
  35. package/src/tools/glob/tool.ts +27 -0
  36. package/src/tools/grep/tool.ts +45 -0
  37. package/src/tools/read/tool.ts +33 -0
  38. package/src/tools/task/handler.ts +75 -0
  39. package/src/tools/task/tool.ts +96 -0
  40. package/src/tools/task-create/handler.ts +49 -0
  41. package/src/tools/task-create/tool.ts +66 -0
  42. package/src/tools/task-get/handler.ts +38 -0
  43. package/src/tools/task-get/tool.ts +11 -0
  44. package/src/tools/task-list/handler.ts +33 -0
  45. package/src/tools/task-list/tool.ts +9 -0
  46. package/src/tools/task-update/handler.ts +79 -0
  47. package/src/tools/task-update/tool.ts +20 -0
  48. package/src/tools/write/tool.ts +26 -0
  49. package/src/workflow.ts +138 -0
  50. package/tsup.config.ts +20 -0
  51. package/dist/index.d.mts +0 -152
  52. package/dist/index.mjs +0 -1587
  53. package/dist/index.mjs.map +0 -1
  54. package/dist/workflow-7_MT-5-w.d.mts +0 -1203
  55. package/dist/workflow-7_MT-5-w.d.ts +0 -1203
  56. package/dist/workflow.d.mts +0 -4
  57. package/dist/workflow.mjs +0 -739
  58. package/dist/workflow.mjs.map +0 -1
package/README.md CHANGED
@@ -48,8 +48,7 @@ const google = new ChatGoogleGenerativeAI({ model: "gemini-1.5-pro" });
48
48
 
49
49
  // Pass to invokeModel in your activity
50
50
  return {
51
- runAgent: (config, invocationConfig) =>
52
- invokeModel(redis, { ...config, tools }, anthropic, invocationConfig),
51
+ runAgent: (config) => invokeModel(redis, config, anthropic),
53
52
  };
54
53
  ```
55
54
 
@@ -82,10 +81,10 @@ Zeitlich provides two entry points to work with Temporal's workflow sandboxing:
82
81
 
83
82
  ```typescript
84
83
  // In workflow files - no external dependencies (Redis, LangChain, etc.)
85
- import { createSession, createToolRegistry, ... } from 'zeitlich/workflow';
84
+ import { createSession, createAgentStateManager, askUserQuestionTool } from 'zeitlich/workflow';
86
85
 
87
86
  // In activity files and worker setup - full functionality
88
- import { ZeitlichPlugin, invokeModel, createGlobHandler, ... } from 'zeitlich';
87
+ import { ZeitlichPlugin, invokeModel, toTree } from 'zeitlich';
89
88
  ```
90
89
 
91
90
  **Why?** Temporal workflows run in an isolated V8 sandbox that cannot import modules with Node.js APIs or external dependencies. The `/workflow` entry point contains only pure TypeScript code safe for workflow use.
@@ -109,8 +108,6 @@ export const searchTool: ToolDefinition<"Search", typeof searchSchema> = {
109
108
  query: z.string().describe("The search query"),
110
109
  }),
111
110
  };
112
-
113
- export const tools = { Search: searchTool };
114
111
  ```
115
112
 
116
113
  ### 2. Create Activities
@@ -119,7 +116,6 @@ export const tools = { Search: searchTool };
119
116
  import type Redis from "ioredis";
120
117
  import { ChatAnthropic } from "@langchain/anthropic";
121
118
  import { invokeModel } from "zeitlich";
122
- import { tools } from "./tools";
123
119
 
124
120
  export const createActivities = (redis: Redis) => {
125
121
  const model = new ChatAnthropic({
@@ -128,70 +124,52 @@ export const createActivities = (redis: Redis) => {
128
124
  });
129
125
 
130
126
  return {
131
- runAgent: (config, invocationConfig) =>
132
- invokeModel(
133
- redis,
134
- { ...config, tools: Object.values(tools) },
135
- model,
136
- invocationConfig
137
- ),
127
+ runAgent: (config) => invokeModel(redis, config, model),
138
128
 
139
129
  handleSearchResult: async ({ args }) => {
140
- // Your tool implementation
141
130
  const results = await performSearch(args.query);
142
131
  return { result: { results } };
143
132
  },
144
133
  };
145
134
  };
135
+
136
+ export type MyActivities = ReturnType<typeof createActivities>;
146
137
  ```
147
138
 
148
139
  ### 3. Create the Workflow
149
140
 
150
141
  ```typescript
151
142
  import { proxyActivities, workflowInfo } from "@temporalio/workflow";
152
- import {
153
- createAgentStateManager,
154
- createSession,
155
- createPromptManager,
156
- createToolRegistry,
157
- createToolRouter,
158
- } from "zeitlich/workflow";
159
- import type { ZeitlichSharedActivities } from "zeitlich/workflow";
160
- import { tools } from "./tools";
143
+ import { createAgentStateManager, createSession } from "zeitlich/workflow";
144
+ import { searchTool } from "./tools";
145
+ import type { MyActivities } from "./activities";
161
146
 
162
147
  const { runAgent, handleSearchResult } = proxyActivities<MyActivities>({
163
148
  startToCloseTimeout: "30m",
164
149
  });
165
150
 
166
- const { appendToolResult } = proxyActivities<ZeitlichSharedActivities>({
167
- startToCloseTimeout: "30m",
168
- });
169
-
170
151
  export async function myAgentWorkflow({ prompt }: { prompt: string }) {
171
152
  const { runId } = workflowInfo();
172
153
 
173
- const stateManager = createAgentStateManager({
174
- initialState: { prompt },
175
- });
154
+ const stateManager = createAgentStateManager({});
176
155
 
177
- const toolRegistry = createToolRegistry(tools);
178
-
179
- const toolRouter = createToolRouter(
180
- { registry: toolRegistry, threadId: runId, appendToolResult },
181
- { Search: handleSearchResult }
182
- );
183
-
184
- const promptManager = createPromptManager({
156
+ const session = await createSession({
157
+ threadId: runId,
158
+ agentName: "my-agent",
159
+ maxTurns: 20,
160
+ runAgent,
185
161
  baseSystemPrompt: "You are a helpful assistant.",
162
+ instructionsPrompt: "Help the user with their request.",
186
163
  buildContextMessage: () => [{ type: "text", text: prompt }],
164
+ tools: {
165
+ Search: {
166
+ ...searchTool,
167
+ handler: handleSearchResult,
168
+ },
169
+ },
187
170
  });
188
171
 
189
- const session = await createSession(
190
- { threadId: runId, agentName: "my-agent", maxTurns: 20 },
191
- { runAgent, promptManager, toolRouter, toolRegistry }
192
- );
193
-
194
- await session.runSession(prompt, stateManager);
172
+ await session.runSession({ stateManager });
195
173
  return stateManager.getCurrentState();
196
174
  }
197
175
  ```
@@ -232,65 +210,72 @@ Manages workflow state with automatic versioning and status tracking:
232
210
  import { createAgentStateManager } from "zeitlich/workflow";
233
211
 
234
212
  const stateManager = createAgentStateManager({
235
- initialState: { customField: "value" },
213
+ customField: "value",
236
214
  });
237
215
 
238
216
  // State operations
239
217
  stateManager.set("customField", "new value");
218
+ stateManager.get("customField"); // Get current value
240
219
  stateManager.complete(); // Mark as COMPLETED
241
220
  stateManager.waitForInput(); // Mark as WAITING_FOR_INPUT
242
221
  stateManager.isRunning(); // Check if RUNNING
243
222
  stateManager.isTerminal(); // Check if COMPLETED/FAILED/CANCELLED
244
223
  ```
245
224
 
246
- ### Tool Registry
225
+ ### Tools with Handlers
247
226
 
248
- Type-safe tool management with Zod validation:
227
+ Define tools with their handlers inline in `createSession`:
249
228
 
250
229
  ```typescript
251
- import { createToolRegistry } from "zeitlich/workflow";
230
+ import { z } from "zod";
231
+ import type { ToolDefinition } from "zeitlich/workflow";
252
232
 
253
- const registry = createToolRegistry({
254
- Search: searchTool,
255
- Calculate: calculateTool,
256
- });
233
+ // Define tool schema
234
+ const searchTool: ToolDefinition<"Search", typeof searchSchema> = {
235
+ name: "Search",
236
+ description: "Search for information",
237
+ schema: z.object({ query: z.string() }),
238
+ };
257
239
 
258
- // Parse and validate tool calls from LLM
259
- const parsed = registry.parseToolCall(rawToolCall);
260
- // parsed.name is "Search" | "Calculate"
261
- // parsed.args is fully typed based on the tool's schema
240
+ // In workflow - combine tool definition with handler
241
+ const session = await createSession({
242
+ // ... other config
243
+ tools: {
244
+ Search: {
245
+ ...searchTool,
246
+ handler: handleSearchResult, // Activity that implements the tool
247
+ },
248
+ },
249
+ });
262
250
  ```
263
251
 
264
- ### Tool Router
252
+ ### Lifecycle Hooks
265
253
 
266
- Routes tool calls to handlers with lifecycle hooks:
254
+ Add hooks for tool execution and session lifecycle:
267
255
 
268
256
  ```typescript
269
- import { createToolRouter } from "zeitlich/workflow";
270
-
271
- const router = createToolRouter(
272
- {
273
- registry: toolRegistry,
274
- threadId,
275
- appendToolResult,
276
- hooks: {
277
- onPreToolUse: ({ toolCall }) => {
278
- console.log(`Executing ${toolCall.name}`);
279
- return {}; // Can return { skip: true } or { modifiedArgs: {...} }
280
- },
281
- onPostToolUse: ({ toolCall, result, durationMs }) => {
282
- console.log(`${toolCall.name} completed in ${durationMs}ms`);
283
- },
284
- onPostToolUseFailure: ({ toolCall, error }) => {
285
- return { fallbackContent: "Tool failed, please try again" };
286
- },
257
+ const session = await createSession({
258
+ // ... other config
259
+ hooks: {
260
+ onPreToolUse: ({ toolCall }) => {
261
+ console.log(`Executing ${toolCall.name}`);
262
+ return {}; // Can return { skip: true } or { modifiedArgs: {...} }
263
+ },
264
+ onPostToolUse: ({ toolCall, result, durationMs }) => {
265
+ console.log(`${toolCall.name} completed in ${durationMs}ms`);
266
+ // Access stateManager here to update state based on results
267
+ },
268
+ onPostToolUseFailure: ({ toolCall, error }) => {
269
+ return { fallbackContent: "Tool failed, please try again" };
270
+ },
271
+ onSessionStart: ({ threadId, agentName }) => {
272
+ console.log(`Session started: ${agentName}`);
273
+ },
274
+ onSessionEnd: ({ exitReason, turns }) => {
275
+ console.log(`Session ended: ${exitReason} after ${turns} turns`);
287
276
  },
288
277
  },
289
- {
290
- Search: handleSearchResult,
291
- Calculate: handleCalculateResult,
292
- }
293
- );
278
+ });
294
279
  ```
295
280
 
296
281
  ### Subagents
@@ -298,83 +283,71 @@ const router = createToolRouter(
298
283
  Spawn child agents as Temporal child workflows:
299
284
 
300
285
  ```typescript
301
- import { withSubagentSupport } from "zeitlich/workflow";
302
- import { z } from "zod";
303
-
304
- const { tools, taskHandler } = withSubagentSupport(baseTools, {
286
+ const session = await createSession({
287
+ // ... other config
305
288
  subagents: [
306
289
  {
307
290
  name: "researcher",
308
291
  description: "Researches topics and returns findings",
309
292
  workflowType: "researcherWorkflow",
310
- resultSchema: z.object({
311
- findings: z.string(),
312
- sources: z.array(z.string()),
313
- }),
293
+ },
294
+ {
295
+ name: "code-reviewer",
296
+ description: "Reviews code for quality and best practices",
297
+ workflowType: "codeReviewerWorkflow",
314
298
  },
315
299
  ],
316
300
  });
317
-
318
- // Include taskHandler in your tool router
319
- const router = createToolRouter(
320
- { registry, threadId, appendToolResult },
321
- { ...handlers, Task: taskHandler }
322
- );
323
301
  ```
324
302
 
303
+ The `Task` tool is automatically added when subagents are configured, allowing the agent to spawn child workflows.
304
+
325
305
  ### Filesystem Utilities
326
306
 
327
- Built-in support for file operations with pluggable providers:
307
+ Built-in support for file operations. Use `buildFileTree` to generate a file tree string that's included in the agent's context:
328
308
 
329
309
  ```typescript
330
- // In workflow - use the pure utilities and tool definitions
331
- import {
332
- buildFileTreePrompt,
333
- globTool,
334
- grepTool,
335
- readTool,
336
- } from "zeitlich/workflow";
310
+ // In activities
311
+ export const createActivities = () => ({
312
+ generateFileTree: async (): Promise<string> => {
313
+ // Return a formatted file tree string
314
+ return toTree("/path/to/workspace");
315
+ },
316
+ });
337
317
 
338
- // In activities - use the providers and handlers
339
- import {
340
- InMemoryFileSystemProvider,
341
- createGlobHandler,
342
- createGrepHandler,
343
- createReadHandler,
344
- } from "zeitlich";
318
+ // In workflow
319
+ const session = await createSession({
320
+ // ... other config
321
+ buildFileTree: generateFileTree, // Called at session start
322
+ });
323
+ ```
345
324
 
346
- // Create an in-memory filesystem
347
- const provider = InMemoryFileSystemProvider.fromTextFiles(
348
- fileTree,
349
- fileContents
350
- );
351
-
352
- // Create tool handlers
353
- const handlers = {
354
- Glob: createGlobHandler({ provider, scopedNodes: fileTree }),
355
- Grep: createGrepHandler({ provider, scopedNodes: fileTree }),
356
- FileRead: createReadHandler({ provider, scopedNodes: fileTree }),
357
- };
325
+ For more advanced file operations, use the built-in tool handlers:
358
326
 
359
- // Generate context for the agent
360
- const fileTreeContext = buildFileTreePrompt(fileTree, {
361
- headerText: "Available Files",
327
+ ```typescript
328
+ import { globHandler, editHandler, toTree } from "zeitlich";
329
+
330
+ export const createActivities = () => ({
331
+ generateFileTree: () => toTree("/workspace"),
332
+ handleGlob: (args) => globHandler(args),
333
+ handleEdit: (args) => editHandler(args, { basePath: "/workspace" }),
362
334
  });
363
335
  ```
364
336
 
365
337
  ### Built-in Tools
366
338
 
367
- Zeitlich provides ready-to-use tool definitions and handlers for common agent operations. More tools will be added in future releases.
339
+ Zeitlich provides ready-to-use tool definitions and handlers for common agent operations.
368
340
 
369
- | Tool | Description |
370
- | ----------------- | ------------------------------------------------------------------------- |
371
- | `FileRead` | Read file contents with optional pagination (supports text, images, PDFs) |
372
- | `FileWrite` | Create or overwrite files with new content |
373
- | `FileEdit` | Edit specific sections of a file by find/replace |
374
- | `Glob` | Search for files matching a glob pattern |
375
- | `Grep` | Search file contents with regex patterns |
376
- | `AskUserQuestion` | Ask the user questions during execution with structured options |
377
- | `Task` | Launch subagents as child workflows (see [Subagents](#subagents)) |
341
+ | Tool | Description |
342
+ | ----------------- | --------------------------------------------------------------- |
343
+ | `Read` | Read file contents with optional pagination |
344
+ | `Write` | Create or overwrite files with new content |
345
+ | `Edit` | Edit specific sections of a file by find/replace |
346
+ | `Glob` | Search for files matching a glob pattern |
347
+ | `Grep` | Search file contents with regex patterns |
348
+ | `Bash` | Execute shell commands |
349
+ | `AskUserQuestion` | Ask the user questions during execution with structured options |
350
+ | `Task` | Launch subagents as child workflows (see [Subagents](#subagents)) |
378
351
 
379
352
  ```typescript
380
353
  // Import tool definitions in workflows
@@ -384,59 +357,74 @@ import {
384
357
  editTool,
385
358
  globTool,
386
359
  grepTool,
360
+ bashTool,
387
361
  askUserQuestionTool,
388
362
  } from "zeitlich/workflow";
389
363
 
390
364
  // Import handlers in activities
391
365
  import {
392
- createReadHandler,
393
- createWriteHandler,
394
- createEditHandler,
395
- createGlobHandler,
396
- createGrepHandler,
366
+ editHandler,
367
+ globHandler,
368
+ handleBashTool,
369
+ handleAskUserQuestionToolResult,
397
370
  } from "zeitlich";
398
371
  ```
399
372
 
373
+ Built-in tools can be added via `buildInTools` (for tools with special handling like Bash) or as regular tools:
374
+
375
+ ```typescript
376
+ const session = await createSession({
377
+ // ... other config
378
+ tools: {
379
+ AskUserQuestion: {
380
+ ...askUserQuestionTool,
381
+ handler: handleAskUserQuestionToolResult,
382
+ },
383
+ },
384
+ buildInTools: {
385
+ Bash: handleBashToolResult,
386
+ },
387
+ });
388
+ ```
389
+
400
390
  ## API Reference
401
391
 
402
392
  ### Workflow Entry Point (`zeitlich/workflow`)
403
393
 
404
394
  Safe for use in Temporal workflow files:
405
395
 
406
- | Export | Description |
407
- | ------------------------- | ---------------------------------------------------------------------------------- |
408
- | `createSession` | Creates an agent session for running the agentic loop |
409
- | `createAgentStateManager` | Creates a state manager for workflow state |
410
- | `createPromptManager` | Creates a prompt manager for system/context prompts |
411
- | `createToolRegistry` | Creates a type-safe tool registry |
412
- | `createToolRouter` | Creates a tool router with handlers and hooks |
413
- | `withSubagentSupport` | Adds Task tool for spawning subagents |
414
- | `buildFileTreePrompt` | Generates file tree context for prompts |
415
- | Tool definitions | `askUserQuestionTool`, `globTool`, `grepTool`, `readTool`, `writeTool`, `editTool` |
416
- | Types | All TypeScript types and interfaces |
396
+ | Export | Description |
397
+ | ------------------------- | -------------------------------------------------------------------------------------------- |
398
+ | `createSession` | Creates an agent session with tools, prompts, subagents, and hooks |
399
+ | `createAgentStateManager` | Creates a state manager for workflow state |
400
+ | `createToolRouter` | Creates a tool router (used internally by session, or for advanced use) |
401
+ | `createTaskTool` | Creates the Task tool for subagent support |
402
+ | Tool definitions | `askUserQuestionTool`, `globTool`, `grepTool`, `readTool`, `writeTool`, `editTool`, `bashTool` |
403
+ | Task tools | `taskCreateTool`, `taskGetTool`, `taskListTool`, `taskUpdateTool` for workflow task management |
404
+ | Types | All TypeScript types and interfaces |
417
405
 
418
406
  ### Activity Entry Point (`zeitlich`)
419
407
 
420
408
  For use in activities, worker setup, and Node.js code:
421
409
 
422
- | Export | Description |
423
- | ----------------------------- | -------------------------------------------------------------------------------------------------------- |
424
- | `ZeitlichPlugin` | Temporal worker plugin that registers shared activities |
425
- | `createSharedActivities` | Creates thread management activities |
426
- | `invokeModel` | Core LLM invocation utility (requires Redis + LangChain) |
427
- | `InMemoryFileSystemProvider` | In-memory filesystem implementation |
428
- | `CompositeFileSystemProvider` | Combines multiple filesystem providers |
429
- | `BaseFileSystemProvider` | Base class for custom providers |
430
- | Tool handlers | `createGlobHandler`, `createGrepHandler`, `createReadHandler`, `createWriteHandler`, `createEditHandler` |
410
+ | Export | Description |
411
+ | -------------------------------- | ------------------------------------------------------ |
412
+ | `ZeitlichPlugin` | Temporal worker plugin that registers shared activities |
413
+ | `createSharedActivities` | Creates thread management activities |
414
+ | `invokeModel` | Core LLM invocation utility (requires Redis + LangChain) |
415
+ | `toTree` | Generate file tree string from a directory path |
416
+ | Tool handlers | `globHandler`, `editHandler`, `handleBashTool`, `handleAskUserQuestionToolResult` |
431
417
 
432
418
  ### Types
433
419
 
434
- | Export | Description |
435
- | ---------------- | ---------------------------------------------------------------------------- |
436
- | `AgentStatus` | `"RUNNING" \| "WAITING_FOR_INPUT" \| "COMPLETED" \| "FAILED" \| "CANCELLED"` |
437
- | `ToolDefinition` | Tool definition with name, description, and Zod schema |
438
- | `SubagentConfig` | Configuration for subagent workflows |
439
- | `SessionHooks` | Lifecycle hooks interface |
420
+ | Export | Description |
421
+ | ----------------------- | ---------------------------------------------------------------------------- |
422
+ | `AgentStatus` | `"RUNNING" \| "WAITING_FOR_INPUT" \| "COMPLETED" \| "FAILED" \| "CANCELLED"` |
423
+ | `ToolDefinition` | Tool definition with name, description, and Zod schema |
424
+ | `ToolWithHandler` | Tool definition combined with its handler |
425
+ | `SubagentConfig` | Configuration for subagent workflows |
426
+ | `SessionLifecycleHooks` | Lifecycle hooks interface |
427
+ | `AgentState` | Generic agent state type |
440
428
 
441
429
  ## Architecture
442
430
 
@@ -450,24 +438,19 @@ For use in activities, worker setup, and Node.js code:
450
438
  │ │ │
451
439
  │ ┌──────────────────────────────────────────────────────────┐ │
452
440
  │ │ Workflow │ │
453
- │ │ ┌────────────────┐ ┌─────────────┐ ┌──────────────┐ │ │
454
- │ │ │ State Manager │ │ Session │ Tool Router │ │ │
455
- │ │ │ • Status │ │ Run loop │ • Dispatch
456
- │ │ │ • Turns │ │ Max turns │ │ • Hooks │ │ │
457
- │ │ │ • Custom state │ │ Lifecycle • Handlers
458
- │ │ └────────────────┘ └─────────────┘ └──────────────┘ │ │
459
- │ │
460
- │ │ ┌────────────────┐ ┌─────────────┐ ┌──────────────┐ │ │
461
- │ │ │ Prompt Manager │ │Tool Registry│ │ Subagents │ │ │
462
- │ │ │ • System prompt│ │ • Parsing │ │ • Child WFs │ │ │
463
- │ │ │ • Context │ │ • Validation│ │ • Results │ │ │
464
- │ │ └────────────────┘ └─────────────┘ └──────────────┘ │ │
441
+ │ │ ┌────────────────┐ ┌───────────────────────────────┐ │ │
442
+ │ │ │ State Manager │ │ Session │ │ │
443
+ │ │ │ • Status │ │ Agent loop │ │ │
444
+ │ │ │ • Turns │ │ Tool routing & hooks │ │ │
445
+ │ │ │ • Custom state │ │ Prompts (system, context) │ │ │
446
+ │ │ └────────────────┘ • Subagent coordination │ │ │
447
+ │ │ └───────────────────────────────────┘ │ │
465
448
  │ └──────────────────────────────────────────────────────────┘ │
466
449
  │ │ │
467
450
  │ ┌──────────────────────────────────────────────────────────┐ │
468
451
  │ │ Activities │ │
469
452
  │ │ • runAgent (LLM invocation) │ │
470
- │ │ • Tool handlers │ │
453
+ │ │ • Tool handlers (search, file ops, bash, etc.) │ │
471
454
  │ └──────────────────────────────────────────────────────────┘ │
472
455
  └─────────────────────────────────────────────────────────────────┘
473
456
 
@@ -489,6 +472,8 @@ For use in activities, worker setup, and Node.js code:
489
472
 
490
473
  Contributions are welcome! Please open an issue or submit a PR.
491
474
 
475
+ For maintainers: see [RELEASING.md](./RELEASING.md) for the release process.
476
+
492
477
  ## License
493
478
 
494
479
  MIT © [Bead Technologies Inc.](https://usebead.ai)