Skip to content

@helix-agents/runtime-temporal

Temporal runtime for durable agent execution. Provides crash recovery, automatic retries, and distributed execution using Temporal workflows.

Installation

bash
npm install @helix-agents/runtime-temporal

AgentRegistry

Maps agent type names to configurations.

typescript
import { AgentRegistry } from '@helix-agents/runtime-temporal';

const registry = new AgentRegistry();

// Register agents
registry.register(ResearchAgent);
registry.register(SummarizerAgent);

// Get agent by name
const agent = registry.get('research-assistant');

// Check if registered
const exists = registry.has('research-assistant');

// Use default global registry
import { defaultAgentRegistry } from '@helix-agents/runtime-temporal';

GenericAgentActivities

Activity implementations for Temporal workflows. No decorators—wrap these with platform-specific activity decorators.

typescript
import { GenericAgentActivities } from '@helix-agents/runtime-temporal';

const activities = new GenericAgentActivities({
  registry, // AgentRegistry
  stateStore, // StateStore
  streamManager, // StreamManager
  llmAdapter, // LLMAdapter
  logger, // Optional: Logger
});

// Available activity methods:
activities.initializeAgentState(input);
activities.executeAgentStep(input);
activities.executeToolCall(input);
activities.registerSubAgents(input);
activities.recordSubAgentResult(input);
activities.markAgentFailed(input);
activities.markAgentAborted(input);
activities.endAgentStream(input);
activities.failAgentStream(input);
activities.checkExistingState(input);
activities.updateAgentStatus(input);

runAgentWorkflow

Core workflow logic function. Wrap with Temporal workflow decorators.

typescript
import { runAgentWorkflow } from '@helix-agents/runtime-temporal/workflow-exports';
import type { AgentWorkflowActivities } from '@helix-agents/runtime-temporal/workflow-exports';

// In your workflow file
export async function agentWorkflow(input: AgentWorkflowInput): Promise<AgentWorkflowResult> {
  const activities = proxyActivities<AgentWorkflowActivities>({
    startToCloseTimeout: '5m',
  });

  return runAgentWorkflow(input, activities, {
    startChildWorkflow: async (childInput) => {
      return executeChild(agentWorkflow, {
        workflowId: childInput.runId,
        args: [childInput],
      });
    },
    isCancellation: (error) => isCancellation(error),
    log: {
      info: (msg, data) => log.info(msg, data),
      warn: (msg, data) => log.warn(msg, data),
      error: (msg, data) => log.error(msg, data),
    },
  });
}

Options:

  • startChildWorkflow - Function to start sub-agent workflows
  • isCancellation - Check if error is Temporal cancellation
  • log - Workflow-safe logger

TemporalAgentExecutor

Executor that starts and manages Temporal workflows. Same API as JSAgentExecutor.

typescript
import { TemporalAgentExecutor } from '@helix-agents/runtime-temporal';

const executor = new TemporalAgentExecutor({
  client, // Temporal Client
  taskQueue, // Task queue name
  stateStore, // StateStore
  streamManager, // StreamManager
  logger, // Optional
});

// Execute agent
const handle = await executor.execute(MyAgent, 'Hello');

// Get existing handle
const handle = await executor.getHandle(MyAgent, 'run-123');

// Check if resumable
const result = await executor.canResume(MyAgent, 'run-123');

DTOs

Type-safe schemas for workflow and activity inputs/outputs.

Workflow DTOs

typescript
import {
  AgentWorkflowInputSchema,
  AgentWorkflowResultSchema,
  type AgentWorkflowInput,
  type AgentWorkflowResult,
} from '@helix-agents/runtime-temporal';

interface AgentWorkflowInput {
  agentType: string;
  runId: string;
  streamId: string;
  message: string;
  initialState?: Record<string, unknown>;
  parentAgentId?: string;
}

interface AgentWorkflowResult {
  status: 'completed' | 'failed' | 'cancelled';
  output?: unknown;
  error?: string;
}

Activity DTOs

typescript
import {
  InitializeAgentInputSchema,
  ExecuteAgentStepInputSchema,
  ExecuteToolCallInputSchema,
  AgentStepResultSchema,
  ToolCallResultSchema,
  // ... and more
} from '@helix-agents/runtime-temporal';

Signal DTOs

typescript
import {
  PauseAgentSignalSchema,
  ResumeAgentSignalSchema,
  AbortAgentSignalSchema,
} from '@helix-agents/runtime-temporal';

Cancellation Helpers

typescript
import {
  type CancellationSignalProvider,
  defaultCancellationSignalProvider,
  createLinkedAbortController,
  isActivityCancelled,
} from '@helix-agents/runtime-temporal';

// Check if activity is cancelled
if (isActivityCancelled()) {
  throw new Error('Activity cancelled');
}

// Create linked abort controller
const controller = createLinkedAbortController();

Heartbeat Helpers

typescript
import {
  type HeartbeatProvider,
  defaultHeartbeatProvider,
  HeartbeatManager,
} from '@helix-agents/runtime-temporal';

// Manage heartbeats for long activities
const heartbeat = new HeartbeatManager({
  intervalMs: 5000,
  onHeartbeat: () => console.log('Heartbeat'),
});

heartbeat.start();
// ... do work ...
heartbeat.stop();

Complete Example

activities.ts

typescript
import { GenericAgentActivities, AgentRegistry } from '@helix-agents/runtime-temporal';
import { InMemoryStateStore, InMemoryStreamManager } from '@helix-agents/store-memory';
import { VercelAIAdapter } from '@helix-agents/llm-vercel';
import { MyAgent } from './agent.js';

const registry = new AgentRegistry();
registry.register(MyAgent);

export function createActivities() {
  const activities = new GenericAgentActivities({
    registry,
    stateStore: new InMemoryStateStore(),
    streamManager: new InMemoryStreamManager(),
    llmAdapter: new VercelAIAdapter(),
  });

  return {
    initializeAgentState: activities.initializeAgentState.bind(activities),
    executeAgentStep: activities.executeAgentStep.bind(activities),
    executeToolCall: activities.executeToolCall.bind(activities),
    registerSubAgents: activities.registerSubAgents.bind(activities),
    recordSubAgentResult: activities.recordSubAgentResult.bind(activities),
    markAgentFailed: activities.markAgentFailed.bind(activities),
    markAgentAborted: activities.markAgentAborted.bind(activities),
    endAgentStream: activities.endAgentStream.bind(activities),
    failAgentStream: activities.failAgentStream.bind(activities),
    checkExistingState: activities.checkExistingState.bind(activities),
    updateAgentStatus: activities.updateAgentStatus.bind(activities),
  };
}

workflows.ts

typescript
import { proxyActivities, executeChild, isCancellation, log } from '@temporalio/workflow';
import type { AgentWorkflowActivities } from '@helix-agents/runtime-temporal/workflow-exports';
import { runAgentWorkflow } from '@helix-agents/runtime-temporal/workflow-exports';
import type { AgentWorkflowInput, AgentWorkflowResult } from '@helix-agents/runtime-temporal';

const activities = proxyActivities<AgentWorkflowActivities>({
  startToCloseTimeout: '5m',
  retry: {
    initialInterval: '1s',
    maximumInterval: '30s',
    backoffCoefficient: 2,
    maximumAttempts: 3,
  },
});

export async function agentWorkflow(input: AgentWorkflowInput): Promise<AgentWorkflowResult> {
  return runAgentWorkflow(input, activities, {
    startChildWorkflow: async (childInput) => {
      return executeChild(agentWorkflow, {
        workflowId: childInput.runId,
        args: [childInput],
        parentClosePolicy: 'ABANDON',
      });
    },
    isCancellation: (error) => isCancellation(error),
    log: { info: log.info, warn: log.warn, error: log.error },
  });
}

worker.ts

typescript
import { Worker, bundleWorkflowCode, NativeConnection } from '@temporalio/worker';
import { createActivities } from './activities.js';

async function main() {
  const connection = await NativeConnection.connect({ address: 'localhost:7233' });

  const workflowBundle = await bundleWorkflowCode({
    workflowsPath: './workflows.ts',
  });

  const worker = await Worker.create({
    connection,
    taskQueue: 'my-agents',
    workflowBundle,
    activities: createActivities(),
  });

  await worker.run();
}

See Also

Released under the MIT License.