@helix-agents/runtime-cloudflare
Cloudflare Workflows runtime for edge deployment. Durable execution using Cloudflare Workers, D1, and Durable Objects.
Installation
bash
npm install @helix-agents/runtime-cloudflareAgentRegistry
Maps agent type names to configurations.
typescript
import { AgentRegistry } from '@helix-agents/runtime-cloudflare';
const registry = new AgentRegistry();
registry.register(MyAgent);
registry.register(SubAgent);
// Use default global registry
import { defaultAgentRegistry } from '@helix-agents/runtime-cloudflare';CloudflareAgentExecutor
Executor that starts and manages Cloudflare Workflows.
typescript
import { CloudflareAgentExecutor } from '@helix-agents/runtime-cloudflare';
const executor = new CloudflareAgentExecutor({
workflowBinding, // AgentWorkflowBinding from env
stateStore, // StateStore (D1StateStore)
streamManager, // StreamManager (DurableObjectStreamManager)
logger, // Optional
});
// Execute agent
const handle = await executor.execute(MyAgent, {
message: 'Hello',
state: { userId: 'user-123' },
});
// Get existing handle
const handle = await executor.getHandle(MyAgent, 'run-123');AgentExecutionHandle
typescript
// Run ID and stream ID
handle.runId;
handle.streamId;
// Stream events
const stream = await handle.stream();
for await (const chunk of stream) {
// Process chunk
}
// Wait for result
const result = await handle.result();
// Abort execution
await handle.abort('User cancelled');runAgentWorkflow
Core workflow function for Cloudflare Workflows.
typescript
import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from 'cloudflare:workers';
import { runAgentWorkflow, AgentRegistry } from '@helix-agents/runtime-cloudflare';
import { createCloudflareStore } from '@helix-agents/store-cloudflare';
import { VercelAIAdapter } from '@helix-agents/llm-vercel';
export class AgentWorkflow extends WorkflowEntrypoint<Env, AgentWorkflowInput> {
async run(event: WorkflowEvent<AgentWorkflowInput>, step: WorkflowStep) {
const { stateStore, streamManager } = createCloudflareStore({
db: this.env.AGENT_DB,
streams: this.env.STREAMS,
});
return runAgentWorkflow(event, step, {
stateStore,
streamManager,
llmAdapter: new VercelAIAdapter(),
registry,
workflowBinding: this.env.AGENT_WORKFLOW,
});
}
}AgentSteps
Step implementations for workflow execution.
typescript
import { AgentSteps } from '@helix-agents/runtime-cloudflare';
const steps = new AgentSteps({
stateStore,
streamManager,
llmAdapter,
registry,
});
// Use in workflow
await steps.initializeAgentState(step, input);
await steps.executeAgentStep(step, input);
await steps.executeToolCall(step, toolCall);createWorkflowRunner
Alternative factory for creating workflow runners.
typescript
import { createWorkflowRunner } from '@helix-agents/runtime-cloudflare';
const runner = createWorkflowRunner({
stateStore,
streamManager,
llmAdapter,
registry,
workflowBinding,
});
// Use in workflow
return runner.run(event, step);Binding Types
Types for Cloudflare bindings.
typescript
import type {
AgentWorkflowBinding,
WorkflowBinding,
WorkflowInstance,
WorkflowStatus,
WorkflowDependencies,
WorkflowOptions,
} from '@helix-agents/runtime-cloudflare';
// Define your environment
interface Env {
AGENT_DB: D1Database;
STREAMS: DurableObjectNamespace;
AGENT_WORKFLOW: AgentWorkflowBinding;
OPENAI_API_KEY: string;
}DTOs
Type-safe schemas for workflow inputs/outputs.
typescript
import {
// Workflow DTOs
AgentWorkflowInputSchema,
AgentWorkflowResultSchema,
type AgentWorkflowInput,
type AgentWorkflowResult,
// Step DTOs
InitializeAgentInputSchema,
ExecuteAgentStepInputSchema,
ExecuteToolCallInputSchema,
ToolCallResultSchema,
// Sub-agent DTOs
RegisterSubAgentsInputSchema,
RecordSubAgentResultInputSchema,
MarkAgentFailedInputSchema,
// Stream DTOs
EndAgentStreamInputSchema,
FailAgentStreamInputSchema,
} from '@helix-agents/runtime-cloudflare';Workflow Types
typescript
import type {
WorkflowStep,
WorkflowEvent,
WorkflowDuration,
WorkflowRetryConfig,
WorkflowStepConfig,
WaitForEventOptions,
WaitForEventResult,
SubAgentCompletionEvent,
} from '@helix-agents/runtime-cloudflare';Utilities
pollUntil
Poll until a condition is met.
typescript
import { pollUntil } from '@helix-agents/runtime-cloudflare';
const result = await pollUntil({
check: async () => {
const status = await getStatus();
if (status === 'done') {
return { done: true, value: status };
}
return { done: false };
},
interval: 1000,
timeout: 60000,
});Complete Example
wrangler.toml
toml
name = "my-agent-worker"
main = "src/worker.ts"
compatibility_date = "2024-12-01"
compatibility_flags = ["nodejs_compat"]
[[d1_databases]]
binding = "AGENT_DB"
database_name = "agents-db"
database_id = "xxx"
[[durable_objects.bindings]]
name = "STREAMS"
class_name = "StreamDurableObject"
[[workflows]]
name = "agent-workflow"
binding = "AGENT_WORKFLOW"
class_name = "AgentWorkflow"
[[migrations]]
tag = "v1"
new_sqlite_classes = ["StreamDurableObject"]worker.ts
typescript
import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from 'cloudflare:workers';
import {
runAgentWorkflow,
AgentRegistry,
CloudflareAgentExecutor,
type AgentWorkflowInput,
} from '@helix-agents/runtime-cloudflare';
import { createCloudflareStore, StreamDurableObject } from '@helix-agents/store-cloudflare';
import { VercelAIAdapter } from '@helix-agents/llm-vercel';
import { MyAgent } from './agent.js';
// Re-export Durable Object
export { StreamDurableObject };
// Registry
const registry = new AgentRegistry();
registry.register(MyAgent);
// Workflow
export class AgentWorkflow extends WorkflowEntrypoint<Env, AgentWorkflowInput> {
async run(event: WorkflowEvent<AgentWorkflowInput>, step: WorkflowStep) {
const { stateStore, streamManager } = createCloudflareStore({
db: this.env.AGENT_DB,
streams: this.env.STREAMS,
});
return runAgentWorkflow(event, step, {
stateStore,
streamManager,
llmAdapter: new VercelAIAdapter(),
registry,
workflowBinding: this.env.AGENT_WORKFLOW,
});
}
}
// HTTP handler
export default {
async fetch(request: Request, env: Env) {
const { stateStore, streamManager } = createCloudflareStore({
db: env.AGENT_DB,
streams: env.STREAMS,
});
const executor = new CloudflareAgentExecutor({
workflowBinding: env.AGENT_WORKFLOW,
stateStore,
streamManager,
});
// POST /agent/run
if (request.method === 'POST') {
const { message } = await request.json();
const handle = await executor.execute(MyAgent, { message });
return Response.json({ runId: handle.runId });
}
return Response.json({ error: 'Not found' }, { status: 404 });
},
};
interface Env {
AGENT_DB: D1Database;
STREAMS: DurableObjectNamespace;
AGENT_WORKFLOW: AgentWorkflowBinding;
}