name: temporal-typescript description: Use when building, debugging, or configuring Temporal.io workflows, activities, workers, or clients using the TypeScript SDK. Triggers on mentions of Temporal, durable workflows, workflow orchestration, or task queues in a TypeScript/Node.js context. version: 1.0.0
Temporal TypeScript SDK
Guide for building durable workflow applications with the Temporal TypeScript SDK. Covers workflows, activities, workers, clients, signals, queries, updates, schedules, and deployment configuration.
When to Use
- Building durable workflow applications with TypeScript/Node.js.
- Implementing workflows, activities, workers, or clients using the Temporal TypeScript SDK.
- Debugging or configuring Temporal.io in a TypeScript context.
- Working with task queues, signals, queries, updates, or schedules in Temporal.
- Any mention of Temporal, durable workflows, or workflow orchestration in a TypeScript/Node.js project.
How to Use
FIRST: Gather Environment Context
Before writing any Temporal code, you MUST ask the user these questions:
Where is Temporal running?
- Local development server (
localhost:7233) - Self-hosted (ask for full address, e.g.
temporal.example.com:7233) - Temporal Cloud (ask for namespace and address, e.g.
my-ns.a1b2c.tmprl.cloud:7233)
- Local development server (
What is the full Temporal gRPC address? (if not local)
- Example:
flow.remodl.ai:7233 - Include port number
- Example:
Is TLS required? (always yes for Temporal Cloud, ask for self-hosted)
- If yes, ask whether they have mTLS certs or API keys
Is there ingress set up for the Temporal HTTP API?
- This matters for Temporal UI access, health checks, and HTTP-based tooling
- If yes, get the full URL (e.g.
https://flow.remodl.ai:443) - If no, note that only gRPC client connections will work
What namespace are they using? (default is
"default")
Store these answers and use them to configure all connection snippets throughout the session.
Connection Configuration
Local Development
import { Connection, Client } from '@temporalio/client';
const connection = await Connection.connect({ address: 'localhost:7233' });
const client = new Client({ connection, namespace: 'default' });
Remote / Self-Hosted
import { Connection, Client } from '@temporalio/client';
const connection = await Connection.connect({
address: '<USER_PROVIDED_ADDRESS>', // e.g. 'flow.remodl.ai:7233'
tls: true, // if TLS is required
});
const client = new Client({ connection, namespace: '<USER_PROVIDED_NAMESPACE>' });
Temporal Cloud (mTLS)
import { Connection, Client } from '@temporalio/client';
import fs from 'fs';
const connection = await Connection.connect({
address: '<NAMESPACE>.tmprl.cloud:7233',
tls: {
clientCertPair: {
crt: fs.readFileSync('client.pem'),
key: fs.readFileSync('client.key'),
},
},
});
const client = new Client({ connection, namespace: '<NAMESPACE>' });
Core Concepts Quick Reference
| Concept | Package | Purpose |
|---|---|---|
| Workflow | @temporalio/workflow |
Deterministic orchestration function |
| Activity | @temporalio/activity |
Non-deterministic side-effect (API calls, DB, I/O) |
| Worker | @temporalio/worker |
Process that executes workflows and activities |
| Client | @temporalio/client |
Starts workflows, sends signals/queries |
| Signal | @temporalio/workflow |
Send data into a running workflow |
| Query | @temporalio/workflow |
Read state from a running workflow |
| Update | @temporalio/workflow |
Mutate workflow state with a response |
Project Structure
src/
workflows.ts # Workflow definitions (deterministic only)
activities.ts # Activity implementations (side effects)
worker.ts # Worker setup and configuration
client.ts # Client code to start/interact with workflows
shared.ts # Shared types, task queue names, etc.
Workflow Rules (Deterministic Constraints)
Workflows MUST be deterministic. Inside a workflow you CANNOT:
- Use
Date.now()orMath.random()(useworkflow.now()and sinks) - Make network/HTTP calls (use activities instead)
- Access filesystem or databases directly
- Use
setTimeout(useworkflow.sleep()) - Import non-deterministic libraries
Documentation Lookup
When you don't know the answer or need current API details, use Context7:
Search the SDK documentation:
context7 query /temporalio/sdk-typescript "<your question>"
Search code samples and patterns:
context7 query /temporalio/samples-typescript "<your question>"
Search the Temporal HTTP/gRPC API (protobuf and OpenAPI definitions):
context7 query /temporalio/api "<your question>"
When to Use Each Context7 Library
| Need | Library ID | Examples |
|---|---|---|
| SDK APIs, TypeScript imports, config options | /temporalio/sdk-typescript |
proxyActivities signature, Worker options, Client setup |
| Working code examples and patterns | /temporalio/samples-typescript |
Saga pattern, polling, cron, encryption samples |
| HTTP/gRPC API endpoints, protobuf types, REST calls | /temporalio/api |
StartWorkflowExecution HTTP request, ListWorkflows query params, SignalWorkflowExecution payload format |
When to Use /temporalio/api
Use this library when the user's question involves:
- HTTP API calls to the Temporal server (REST endpoints, curl examples)
- Protobuf message types (Payload, RetryPolicy, TaskQueue, WorkflowExecution)
- Server-side API operations (namespace management, batch operations, schedule CRUD via HTTP)
- Workflow visibility queries via the HTTP API (ListWorkflowExecutions, CountWorkflowExecutions)
- Activity heartbeat/completion via HTTP (RecordActivityTaskHeartbeat, RespondActivityTaskCompleted)
- Nexus endpoint management (CreateNexusEndpoint, ListNexusEndpoints)
- Cluster and system info (GetClusterInfo, GetSystemInfo)
- Worker deployment management (experimental API)
- Task queue inspection via HTTP (DescribeTaskQueue, GetWorkerVersioningRules)
The HTTP API base URL depends on the user's environment. If they confirmed ingress is set up for the Temporal HTTP API, use their provided URL (e.g. https://flow.remodl.ai:443). The default port for the HTTP API is 8080 on self-hosted servers.
Example Lookups
| Question | Library ID | Query |
|---|---|---|
| How to define a signal | /temporalio/sdk-typescript |
How to define and handle signals in a workflow |
| Saga/compensation pattern | /temporalio/samples-typescript |
Saga pattern with compensation |
| Worker tuning options | /temporalio/sdk-typescript |
Worker configuration options and tuning |
| Schedule a recurring workflow | /temporalio/sdk-typescript |
How to create a schedule for recurring workflows |
| Activity retry policy | /temporalio/sdk-typescript |
Activity retry policy configuration |
| Testing workflows | /temporalio/sdk-typescript |
How to test workflows with TestWorkflowEnvironment |
| Start workflow via HTTP REST | /temporalio/api |
StartWorkflowExecution HTTP API request format |
| List workflows via HTTP | /temporalio/api |
ListWorkflowExecutions visibility query |
| Signal a workflow via HTTP | /temporalio/api |
SignalWorkflowExecution HTTP endpoint |
| Create a schedule via HTTP | /temporalio/api |
CreateSchedule HTTP API with cron |
| Describe a task queue via HTTP | /temporalio/api |
DescribeTaskQueue API pollers and backlog |
| Batch terminate workflows | /temporalio/api |
StartBatchOperation termination |
| Register a namespace via HTTP | /temporalio/api |
RegisterNamespace HTTP API |
Common Patterns
Starting a Workflow
const handle = await client.workflow.start(myWorkflow, {
taskQueue: 'my-task-queue',
workflowId: 'my-unique-id',
args: [inputArg],
});
const result = await handle.result();
Defining Activities with Retry
import { proxyActivities } from '@temporalio/workflow';
import type * as activities from './activities';
const { myActivity } = proxyActivities<typeof activities>({
startToCloseTimeout: '30s',
retry: {
maximumAttempts: 3,
initialInterval: '1s',
backoffCoefficient: 2,
},
});
Worker Setup
import { Worker } from '@temporalio/worker';
import * as activities from './activities';
const worker = await Worker.create({
workflowsPath: require.resolve('./workflows'),
activities,
taskQueue: 'my-task-queue',
connection, // from Connection.connect()
});
await worker.run();
Common Mistakes
| Mistake | Fix |
|---|---|
| Importing activities directly in workflow | Use proxyActivities<typeof activities>() |
Using Date.now() in workflow |
Use workflow.now() |
| Non-deterministic code in workflow | Move to an activity |
Missing workflowsPath in Worker |
Must point to compiled workflow file |
Forgetting await worker.run() |
Worker won't process tasks without it |
| Wrong task queue name mismatch | Ensure client and worker use same task queue string |
Debugging Tips
- Workflow not executing: Check task queue names match between client and worker
- Activity timeout: Increase
startToCloseTimeoutor check activity is registered on worker - Non-determinism error: Audit workflow code for side effects, random, or date usage
- Connection refused: Verify Temporal server address and that the server is running
- TLS errors: Check certificate paths and that certs match the server configuration
When in Doubt
If the information above doesn't cover what you need:
- Search
/temporalio/sdk-typescripton Context7 for SDK API docs and TypeScript usage - Search
/temporalio/samples-typescripton Context7 for working code examples - Search
/temporalio/apion Context7 for HTTP/gRPC API endpoints, protobuf types, and REST call formats - Search
/temporalio/documentationon Context7 for conceptual guides