Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions plugins/temporal/skills/temporal-developer/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
name: temporal-developer
description: Develop, debug, and manage Temporal applications across Python, TypeScript, Go, Java, .NET and Ruby. Use when the user is building workflows, activities, or workers with a Temporal SDK, debugging issues like non-determinism errors, stuck workflows, or activity retries, using Temporal CLI, Temporal Server, or Temporal Cloud, or working with durable execution concepts like signals, queries, heartbeats, versioning, continue-as-new, child workflows, or saga patterns. Also use when the user mentions "run a Temporal workflow from the CLI", "start a dev server", "run temporal server start-dev", "temporal workflow start", "temporal workflow execute", "temporal workflow signal", "temporal workflow query", "temporal workflow update".
version: 0.5.0
description: Develop, debug, and manage Temporal applications across Python, TypeScript, Go, Java, .NET, Ruby, and Rust. Use when the user is building workflows, activities, or workers with a Temporal SDK, debugging issues like non-determinism errors, stuck workflows, or activity retries, using Temporal CLI, Temporal Server, or Temporal Cloud, or working with durable execution concepts like signals, queries, heartbeats, versioning, continue-as-new, child workflows, or saga patterns. Also use when the user mentions "run a Temporal workflow from the CLI", "start a dev server", "run temporal server start-dev", "temporal workflow start", "temporal workflow execute", "temporal workflow signal", "temporal workflow query", "temporal workflow update".
version: 0.6.0
---

# Skill: temporal-developer

## Overview

Temporal is a durable execution platform that makes workflows survive failures automatically. This skill provides guidance for building Temporal applications in Python, TypeScript, Go, Java, .NET, and Ruby.
Temporal is a durable execution platform that makes workflows survive failures automatically. This skill provides guidance for building Temporal applications in Python, TypeScript, Go, Java, .NET, Ruby, and Rust.

## Core Architecture

Expand Down Expand Up @@ -59,6 +59,7 @@ Check if `temporal` CLI is installed. If not, follow the instructions at `refere
- Java -> read `references/java/java.md`
- .NET (C#) -> read `references/dotnet/dotnet.md`
- Ruby -> read `references/ruby/ruby.md`
- Rust -> read `references/rust/rust.md` (in Public Preview)
2. Second, read appropriate `core` and language-specific references for the task at hand.

## Primary References
Expand All @@ -71,6 +72,8 @@ Check if `temporal` CLI is installed. If not, follow the instructions at `refere
- Language-specific info at `references/{your_language}/gotchas.md`
- **`references/core/versioning.md`** - Versioning strategies and concepts - how to safely change workflow code while workflows are running
- Language-specific info at `references/{your_language}/versioning.md`
- **`references/core/standalone-activities.md`** - Standalone Activities: run an Activity directly from a Client without a Workflow (Public Preview)
- Language-specific info at `references/{your_language}/standalone-activities.md`
- **`references/core/troubleshooting.md`** - Decision trees, recovery procedures
- **`references/core/error-reference.md`** - Common error types, workflow status reference
- **`references/core/interactive-workflows.md`** - Testing signals, updates, queries
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ Each Temporal SDK language provides a different level of protection against non-
- Go: The Go SDK has no runtime sandbox. Therefore, non-determinism bugs will never be immediately appararent, and are usually only observable during replay. The optional `workflowcheck` static analysis tool can be used to check for many sources of non-determinism at compile time.
- .NET: The .NET SDK has no sandbox. It uses a custom TaskScheduler and a runtime EventListener to detect invalid task scheduling. Developers must use `Workflow.*` safe alternatives (e.g., Workflow.DelayAsync instead of Task.Delay) and avoid non-deterministic .NET Task APIs.
- Ruby: The Ruby SDK uses Illegal Call Tracing (via `TracePoint`) to detect forbidden method calls at runtime on the workflow fiber, combined with a Durable Fiber Scheduler that makes fiber operations deterministic.
- Rust: The Rust SDK has runtime nondeterminism detection for external async wake sources in Workflow code. Keep it enabled, use SDK primitives such as `ctx.timer()` and `temporalio_sdk::workflows::select!`, and still avoid synchronous nondeterminism by convention.

Regardless of which SDK you are using, it is your responsibility to ensure that workflow code does not contain sources of non-determinism. Use SDK-specific tools as well as replay tests for doing so.

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
> [!NOTE]
> Standalone Activities are in Public Preview. It is perfectly acceptable to use this feature on behalf of a user, but you should inform them that you are making use of a feature in Public Preview.

# Standalone Activities (Concepts)

This document provides core conceptual explanations of Standalone Activities in Temporal. For language-specific implementation details, see `references/{your_language}/standalone-activities.md` for the language you are working in (Python, TypeScript, Java, .NET, Go).

## What is a Standalone Activity?

A **Standalone Activity** is a top-level Activity Execution started directly by a Client, without using a Workflow. It is Temporal's job queue — the simplest way to run a single durable, retryable task.

The rule of thumb:

- **Need to orchestrate multiple Activities?** Use a Workflow.
- **Just need to execute a single Activity?** Use a Standalone Activity.

The same Activity Function code runs in both modes with no changes — the only difference is how it is invoked. An Activity defined for a Workflow can also be executed standalone, and the Worker that hosts it does not need to know how it will be invoked.

Compared to wrapping a single Activity in a Workflow, a Standalone Activity:

- Reduces billable actions in Temporal Cloud.
- Lowers latency for short-lived executions (fewer Worker round-trips).
- Lives in a separate ID space from Workflows.

### Use cases

Standalone Activities fit durable single-job processing where you don't need multi-step orchestration:

- Sending an email
- Processing a webhook
- Syncing data
- Any single-function task that benefits from built-in retries and timeouts

### Key features

- Execute Activities as a top-level primitive, without Workflow overhead.
- Native async job lifecycle: **schedule → dispatch → process → result**.
- Arbitrary-length jobs, with heartbeats for progress tracking.
- **At-least-once execution by default**, with native retry policy and timeouts.
- **At-most-once execution** when the retry policy's maximum attempts is 1.
- Addressable by Activity ID / Run ID for result retrieval, cancellation, and termination.
- Deduplication via configurable conflict policies.
- Priority and fairness support.
- Full visibility — list and count executions.

## Using Standalone Activities

### Defining activities

Defining standalone activities is IDENTICAL to defining activities callable from a workflow - there is no distinction AT ALL between the two at activity definition or worker configuration site. Follow language-specific guidance for how to normally define activities and configure workers to run them.

### Calling and Interacting with Standalone Activities

The CLI and every SDK exposes the same conceptual operations against a Standalone Activity (method names differ per language — see the language reference):

- **Execute** — durably enqueue the Activity, wait for a Worker to run it, and return the result.
- **Start** — durably enqueue the Activity and return a handle immediately, without waiting.
- **Get handle** — rebind a handle to a previously started Activity by ID (and optionally Run ID).
- **Get result** — wait on a handle for completion. `execute` is equivalent to `start` followed by awaiting the handle's result.
- **Cancel / Terminate** — via the handle or CLI.

**Choosing an Activity ID.** Every Standalone Activity call requires an **Activity ID**, which uniquely identifies that one call. It is the key you use later to get the result, describe, cancel, or terminate the Activity, and it is what conflict/reuse policies dedupe against. Use a **business-logic identifier** that uniquely identifies the call — for example `send-welcome-email:user-42`, `sync-invoice:INV-2026-001`, or `process-webhook:<event-id>`. This makes Activities addressable and naturally deduplicated by your domain. Only if you genuinely have no meaningful business-level identifier should you generate a **UUID** to use as the Activity ID.

Visibility operations are available as well:
- **List** — enumerate Standalone Activity Executions matching a query. Only Standalone Activities are returned; Activities running inside Workflows are not included.
- **Count** — return the total number of executions matching a query (running, completed, failed, etc. — not the number of queued tasks).
- **Describe** — via the handle or CLI.

See below for a quick reference how to call these operations from the CLI rather than SDKs.

> [!IMPORTANT]
> When using an SDK, these operations are owned by the Temporal Client, and belong **in your non-workflow application code**. It is INVALID to call an activity as a standalone activity from within a workflow: you instead should use standard within-workflow activity calls.

**Currently Supported SDKs: Python, TypeScript, Java, .NET, Go**

## Quick CLI Standalone Activity Man Page

Ultimately, any standalone activity invocation code should live in your application code and use the appropriate SDK, but the Temporal CLI is a quick and easy way to test invoking standalone activities during development. All subcommands live under `temporal activity`.

The key operations are:

**Execute (start and wait for the result).** Blocks until the Activity completes and prints the result to stdout. Requires `--activity-id`, `--type`, `--task-queue`, and at least one of `--start-to-close-timeout` / `--schedule-to-close-timeout`:

```bash
temporal activity execute \
--activity-id my-activity-id \
--type ComposeGreeting \
--task-queue my-task-queue \
--start-to-close-timeout 10s \
--input '{"some-key": "some-value"}'
```

`--input` takes a JSON value; pass it multiple times for multiple positional arguments. `--input-file` is also a convenient option for larger inputs. The same required flags apply to `start` below.

Reminder: `--activity-id` must be unique across all activity calls, as discussed above.

**Start (do not wait).** Enqueues the Activity and prints the Activity ID and Run ID without blocking:

```bash
temporal activity start \
--activity-id my-activity-id \
--type ComposeGreeting \
--task-queue my-task-queue \
--start-to-close-timeout 10s \
--input '{"some-key": "some-value"}'
```

Outputs this JSON shape:

```json
{
"activityId": "my-activity-id",
"runId": "019e84d3-949a-7a0e-ae78-63b8a0b172bd",
"namespace": "default"
}
```

**Result (wait for a started Activity).** Waits for completion and prints the result. `--run-id` is optional and defaults to the latest run of that Activity ID:

```bash
temporal activity result --activity-id my-activity-id
```

**Describe (current state of one Activity).** Shows status, run state, task queue, timeouts, attempt count, etc.:

```bash
temporal activity describe --activity-id my-activity-id
```

**List / Count (visibility across many Activities).** Only Standalone Activity Executions are returned (Activities running inside Workflows are not):

```bash
temporal activity list
temporal activity count
```

**Cancel / Terminate (stop an Activity).** `cancel` requests cooperative cancellation (surfaced to the Activity on its next heartbeat response); `terminate` forcefully ends it (Activity code cannot see or respond to it). Both accept `--reason`:

```bash
temporal activity cancel --activity-id my-activity-id --reason "no longer needed"
temporal activity terminate --activity-id my-activity-id --reason "no longer needed"
```

## Observability

All existing Activity metrics apply to Standalone Activities (scheduled, started, completed, failed, timed out, canceled).

## Public Preview limitations

- Pause, reset, and update options are not supported (scheduled for GA).
- The `TerminateExisting` conflict policy and `TerminateIfRunning` reuse policy are not yet supported.

## Temporal CLI support

- Requires **Temporal CLI v1.7.0+** and **Temporal Server v1.31.0+**. See `references/core/install_cli.md` if you need to update the CLI.
- The Temporal Dev Server (`temporal server start-dev`) has Standalone Activities enabled by default.

## Temporal Cloud support

Standalone Activities are available in Temporal Cloud as a Public Preview feature. Because the SDK client config loaders read environment variables and TOML profiles, the same code runs against a local server or Temporal Cloud with no code changes.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Workflow versioning allows safe deployment of code changes without breaking runn

1. **Patching API** - Code-level version branching
2. **Workflow Type Versioning** - New workflow types for incompatible changes
3. **Worker Versioning** - Deployment-level control with Build IDs
3. **Worker Versioning** - Deployment-level routing with Worker Deployment Versions

## Why Versioning is Needed

Expand Down Expand Up @@ -101,13 +101,16 @@ Create a new workflow type (e.g., `OrderWorkflowV2`) instead of patching.

### Concept

Manage versions at deployment level using Build IDs. Multiple worker versions can run simultaneously.
Manage versions through Worker Deployments. Multiple Worker Deployment Versions can run simultaneously, and each version is identified by a deployment name and Build ID.

> [!IMPORTANT]
> This is the current Worker Deployment-based versioning model. Do not confuse it with the legacy Build ID-based Worker Versioning APIs, which manage compatibility sets directly. Those APIs are deprecated.

```
Worker v1.0 (Build ID: abc123)
Worker Deployment Version (deployment: order-service, build: abc123)
└── Handles workflows started on this version

Worker v2.0 (Build ID: def456)
Worker Deployment Version (deployment: order-service, build: def456)
└── Handles new workflows
└── Can also handle upgraded old workflows
```
Expand All @@ -116,7 +119,9 @@ Worker v2.0 (Build ID: def456)

**Worker Deployment**: Logical service grouping (e.g., "order-service")

**Build ID**: Specific code version (e.g., git commit hash)
**Worker Deployment Version**: A specific snapshot identified by a Worker Deployment name and a Build ID

**Build ID**: The code-version component of a Worker Deployment Version (e.g., a git commit hash)

**Versioning Behaviors**:

Expand All @@ -136,14 +141,58 @@ Worker v2.0 (Build ID: def456)
- Workflows need bug fixes during execution
- Still requires patching for version transitions

## Upgrading on Continue-as-New

> [!NOTE]
> This feature is in Public Preview. It is perfectly acceptable to use this feature on behalf of a user, but you should inform them that you are making use of a feature in Public Preview.

Long-running Pinned Workflows that use Continue-as-New can upgrade to newer Worker Deployment Versions at the Continue-as-New boundary without patching.

This pattern is for:

- Entity Workflows that run for months or years
- Batch processing Workflows that checkpoint with Continue-as-New
- AI agent Workflows with long sleeps waiting for user input

### How it works

By default, Pinned Workflows stay on their original Worker Deployment Version even when they Continue-as-New. With the upgrade option enabled:

1. Each Workflow run remains pinned to its version (no patching needed during a run).
2. The Temporal Server tells the Workflow when a new **Target Version** becomes available — that is, when the Workflow's Worker Deployment gets a new Current or Ramping Version that the Workflow would move to next.
3. When the Workflow performs Continue-as-New with the upgrade option, the new run starts on the Target Version.

### Detection flag

Active Workflows detect a Target Version change by checking a per-Workflow flag exposed on `WorkflowInfo` (called `target_worker_deployment_version_changed` in the docs). The flag is refreshed after each Workflow Task completes; check it from code that runs as part of a Workflow Task (for example, before accepting an Update, starting an Activity, or starting a child Workflow). See the per-language `references/{your_language}/versioning.md` for the SDK-specific call.

### Triggering the new run

When the flag is set, return a Continue-as-New error with the new run's initial Versioning Behavior set to `AutoUpgrade`. This makes the new run start on the Target Version of its Worker Deployment. The Workflow Type itself retains its Pinned annotation; only the *initial* behavior of the *new* run is overridden so it picks up the Target Version. Once the new run is on the new version, the per-Workflow-type annotation continues to apply on subsequent CaN.

### Limitations

- **Lazy moving only — sleeping Workflows do not auto-upgrade.** Send a Signal to wake an idle Workflow so it can check the flag.
- **Interface compatibility is your responsibility.** When continuing as new to a different version, the previous version's Workflow input must be compatible with the new version's Workflow definition. If incompatible, the new run may fail on its first Workflow Task.
- **Pinned Workflows only.** Auto-Upgrade Workflows already move to the Target Version at Workflow Task boundaries; this pattern adds nothing for them.

### When to use this pattern

- Workflow Type is Pinned **and**
- Workflow runs longer than your Worker Deployment Version lifetime **and**
- Workflow already uses Continue-as-New to bound Event History size.

For long-running Workflows that cannot use Continue-as-New (e.g., compliance audits that need full history), use `AUTO_UPGRADE` with patching instead.

## Choosing an Approach

| Scenario | Recommended Approach |
|----------|---------------------|
| Small change, few running workflows | Patching API |
| Major rewrite | Workflow Type Versioning |
| Many short workflows, frequent deploys | Worker Versioning (PINNED) |
| Long-running workflows needing updates | Worker Versioning (AUTO_UPGRADE) + Patching |
| Long-running workflows, uses Continue-as-New | Worker Versioning (PINNED) + upgrade on Continue-as-New |
| Long-running workflows, no Continue-as-New | Worker Versioning (AUTO_UPGRADE) + Patching |
| Quick fix, can wait for completion | Wait for workflows to complete |

## Best Practices
Expand Down
Loading