Skip to main content

Standalone Activities - Go SDK

Standalone Activities are Activity Executions that run independently, without being orchestrated by a Workflow. Instead of starting an Activity from within a Workflow Definition using workflow.ExecuteActivity(), you start a Standalone Activity directly from a Temporal Client using client.ExecuteActivity().

The Activity definition and Worker registration are identical to regular Activities — only the execution path differs.

EXPERIMENTAL

Standalone Activities are Experimental. The API may change in future releases.

PREREQUISITES

Standalone Activities require server-side support. If you are running a self-hosted Temporal Server, the following dynamic config values must be enabled:

  • activity.enableStandalone=true
  • history.enableChasm=true
  • history.enableTransitionHistory=true

The ListActivities and CountActivities APIs use Go's iter.Seq2 type, which requires Go 1.23 or later.

This page covers the following:

Execute a Standalone Activity

Use client.ExecuteActivity() to start a Standalone Activity Execution. This is called from application code (for example, a starter program), not from inside a Workflow Definition.

ExecuteActivity returns an ActivityHandle that you can use to get the result, describe, cancel, or terminate the Activity.

View the source code

in the context of the rest of the application code.

import (
"context"
"log"
"time"

"go.temporal.io/sdk/client"
)

func main() {
c, err := client.Dial(client.Options{})
if err != nil {
log.Fatalln("Unable to create client", err)
}
defer c.Close()

activityOptions := client.StartActivityOptions{
ID: "my-standalone-activity-id",
TaskQueue: "my-task-queue",
ScheduleToCloseTimeout: 10 * time.Second,
}

handle, err := c.ExecuteActivity(
context.Background(), activityOptions, MyActivity, "Temporal",
)
if err != nil {
log.Fatalln("Unable to execute standalone activity", err)
}

log.Println("Started standalone activity",
"ActivityID", handle.GetID(),
"RunID", handle.GetRunID(),
)
}

You can pass the Activity as either a function reference or a string Activity type name:

// Using a function reference (recommended — enables compile-time parameter validation)
handle, err := c.ExecuteActivity(ctx, options, MyActivity, "arg1")

// Using a string type name
handle, err := c.ExecuteActivity(ctx, options, "MyActivity", "arg1")

client.StartActivityOptions requires ID, TaskQueue, and at least one of ScheduleToCloseTimeout or StartToCloseTimeout. See StartActivityOptions in the API reference for the full set of options.

Get the result of a Standalone Activity

Use ActivityHandle.Get() to block until the Activity completes and retrieve its result. This is analogous to calling Get() on a WorkflowRun.

var result string
err = handle.Get(context.Background(), &result)
if err != nil {
log.Fatalln("Activity failed", err)
}
log.Println("Activity result:", result)

If the Activity completed successfully, the result is deserialized into the provided pointer. If the Activity failed, the failure is returned as an error.

Get a handle to an existing Standalone Activity

Use client.GetActivityHandle() to create a handle to a previously started Standalone Activity. This is analogous to client.GetWorkflow() for Workflow Executions.

Both ActivityID and RunID are required.

handle := c.GetActivityHandle(client.GetActivityHandleOptions{
ActivityID: "my-standalone-activity-id",
RunID: "the-run-id",
})

// Use the handle to get the result, describe, cancel, or terminate
var result string
err := handle.Get(context.Background(), &result)
if err != nil {
log.Fatalln("Unable to get activity result", err)
}