Activity parameter design in .NET
Activity parameters are the method parameters of the method with the [Activity] attribute. Temporal strongly encourages using a single parameter containing all input fields rather than multiple parameters. This allows you to change what data is passed to the Activity without breaking the method signature. Activity parameters can be any data type Temporal can convert, including records.
Activity definition with [Activity] attribute in .NET
To define an Activity in the .NET SDK, use the [Activity] attribute from the Temporalio.Activities namespace on a method. If no custom name is specified, the activity name is the unqualified method name, with an "Async" suffix removed if the method is async. To register with a custom name, use an attribute parameter: [Activity("your-activity")].
Activities can be async or synchronous in .NET
The .NET SDK supports both asynchronous and synchronous Activity methods. Activities can also be static or instance methods.
.NET Activity example with [Activity] attribute
using Temporalio.Activities;
public class MyActivities
{
[Activity]
public string MyActivity(MyActivityParams input) =>
$"{input.Greeting}, {input.Name}!";
}
This example shows a synchronous Activity method that takes a single input parameter object and returns a string.
.NET Activities - Standalone Activities supported
The .NET SDK supports Standalone Activities as a distinct feature, which can be implemented separately from the main Activity documentation.
.NET SDK Activity documentation sections
The .NET SDK documentation for Activities covers the following topics: Activity basics, Activity execution, Standalone Activities, Timeouts, Asynchronous Activity completion, Dynamic Activity, and Benign exceptions.
.NET SDK version requirement for Standalone Activities
Standalone Activities are available in Temporal .NET SDK v1.12.0 or higher.
Worker setup for Standalone Activities in .NET
Running a Worker for Standalone Activities is the same as running a Worker for Workflow Activities. You create a Worker, register the Activity, and run the Worker. The Worker doesn't need to know whether the Activity will be invoked from a Workflow or as a Standalone Activity.
Worker setup example for Standalone Activities in .NET
using Microsoft.Extensions.Logging;
using Temporalio.Client;
using Temporalio.Common.EnvConfig;
using Temporalio.Worker;
using TemporalioSamples.StandaloneActivity;
var connectOptions = ClientEnvConfig.LoadClientConnectOptions();
connectOptions.TargetHost ??= "localhost:7233";
connectOptions.LoggerFactory = LoggerFactory.Create(builder =>
builder.
AddSimpleConsole(options => options.TimestampFormat = "[HH:mm:ss] ").
SetMinimumLevel(LogLevel.Information));
var client = await TemporalClient.ConnectAsync(connectOptions);
const string taskQueue = "standalone-activity-sample";
using var tokenSource = new CancellationTokenSource();
Console.CancelKeyPress += (_, eventArgs) =>
{
tokenSource.Cancel();
eventArgs.Cancel = true;
};
using var worker = new TemporalWorker(
client,
new TemporalWorkerOptions(taskQueue).
AddActivity(MyActivities.ComposeGreetingAsync));
await worker.ExecuteAsync(tokenSource.Token);
Standalone Activity code example in .NET
namespace TemporalioSamples.StandaloneActivity;
using Temporalio.Activities;
public static class MyActivities
{
[Activity]
public static Task<string> ComposeGreetingAsync(ComposeGreetingInput input) =>
Task.FromResult($"{input.Greeting}, {input.Name}!");
}
public record ComposeGreetingInput(string Greeting, string Name);
Define a Standalone Activity in .NET
An Activity in the Temporal .NET SDK is a method decorated with the [Activity] attribute. A Standalone Activity is defined identically to a Workflow Activity.
Activity definition with .NET SDK
An Activity in .NET is defined as a method decorated with the [Activity] attribute. Activities execute single, well-defined actions such as sending emails, making network requests, writing to databases, or calling APIs. Methods can be sync or async, static or instance. Example: public class MyActivities { [Activity] public string SayHello(string name) => $"Hello, {name}!"; }
AddAllActivities() registration methods
AddAllActivities() registers every method marked with [Activity]. Pass an instance to register instance methods, which allows activities to share state such as a database client. For a class of static activity methods, pass the type and null instead.
Basic Activity Definition example in Go
package yourapp
import (
"context"
"go.temporal.io/sdk/activity"
)
func YourSimpleActivityDefinition(ctx context.Context) error {
return nil
}
type YourActivityObject struct {
Message *string
Number *int
}
func (a *YourActivityObject) YourActivityDefinition(ctx context.Context, param YourActivityParam) (*YourActivityResultObject, error) {
logger := activity.GetLogger(ctx)
logger.Info("The message is:", param.ActivityParamX)
logger.Info("The number is:", param.ActivityParamY)
result := &YourActivityResultObject{
ResultFieldX: "Success",
ResultFieldY: 1,
}
return result, nil
}
This example shows both a standalone Activity function and an Activity defined as a struct method with parameter and return types.
Activity Definition structure in Go
An Activity Definition in the Temporal Go SDK is an exportable function or a struct method. Activities written as struct methods can use shared struct variables such as application-level DB pools, client connections to other services, reusable utilities, and other expensive resources that should only be initialized once per process.
Activity struct methods as separate Activity Types
An Activity struct can have more than one method, with each method acting as a separate Activity Type. This allows multiple activities to be defined and registered within a single struct.
Activity parameter struct example
type YourActivityParam struct {
ActivityParamX string
ActivityParamY int
}
type YourActivityObject struct {
Message *string
Number *int
}
func (a *YourActivityObject) YourActivityDefinition(ctx context.Context, param YourActivityParam) (*YourActivityResultObject, error) {
logger := activity.GetLogger(ctx)
logger.Info("The message is:", param.ActivityParamX)
logger.Info("The number is:", param.ActivityParamY)
result := &YourActivityResultObject{
ResultFieldX: "Success",
ResultFieldY: 1,
}
return result, nil
}
This example shows how to pass Activity parameters as a single struct for better backward compatibility and maintainability.
Registering Activity with custom type name
func main() {
temporalClient, err := client.Dial(client.Options{})
if err != nil {
log.Fatalln("Unable to create client", err)
}
defer temporalClient.Close()
yourWorker := worker.New(temporalClient, "your-custom-task-queue-name", worker.Options{})
registerAOptions := activity.RegisterOptions{
Name: "JustAnotherActivity",
}
yourWorker.RegisterActivityWithOptions(yourapp.YourSimpleActivityDefinition, registerAOptions)
err = yourWorker.Run(worker.InterruptCh())
if err != nil {
log.Fatalln("Unable to start Worker", err)
}
}
This example shows how to register an Activity with a custom Activity Type name using RegisterActivityWithOptions and the activity.RegisterOptions struct.
Customizing Activity Type with Name parameter
To customize the Activity Type in Go, set the Name parameter with RegisterOptions when registering an Activity with a Worker. This is done by calling RegisterActivityWithOptions and passing an activity.RegisterOptions struct with the Name field set to the desired Activity Type name.
Activity result struct example
type YourActivityResultObject struct {
ResultFieldX string
ResultFieldY int
}
func (a *YourActivityObject) YourActivityDefinition(ctx context.Context, param YourActivityParam) (*YourActivityResultObject, error) {
logger := activity.GetLogger(ctx)
logger.Info("The message is:", param.ActivityParamX)
logger.Info("The number is:", param.ActivityParamY)
result := &YourActivityResultObject{
ResultFieldX: "Success",
ResultFieldY: 1,
}
return result, nil
}
This example shows how to define and return Activity results using a struct type, which ensures backward compatibility when the struct needs to be updated.
Activity parameter context and serialization
The first parameter of an Activity Definition is context.Context, which is optional but recommended, especially if the Activity is expected to use other Go SDK APIs. All parameters must be serializable and cannot be channels, functions, variadic, or unsafe pointers. It is recommended to pass a single struct as a parameter that can be updated later, rather than multiple individual parameters.
Go SDK Activities documentation structure
The Go SDK Activities documentation covers the following topics: Activity basics, Activity execution, Standalone Activities, Timeouts, Asynchronous Activity completion, Dynamic Activity, and Benign exceptions.
Define standalone activity code example
package helloworld
import (
"context"
"go.temporal.io/sdk/activity"
)
func Activity(ctx context.Context, name string) (string, error) {
logger := activity.GetLogger(ctx)
logger.Info("Activity", "name", name)
return "Hello " + name + "!", nil
}
This example shows how to define a basic standalone activity that accepts a name parameter and returns a greeting string.
Activity Summary metadata in workflows
You can attach a Summary metadata parameter to Activities when starting them from within a Workflow using the Summary field in ActivityOptions. The input format for Summary is a string limited to 200 bytes. The summary text is shown directly on the activity bar label in the Timeline tab, making it possible to distinguish individual instances of the same Activity Type at a glance.
Example: Setting activity summary in workflow
import (
"time"
"go.temporal.io/sdk/workflow"
)
func YourWorkflow(ctx workflow.Context, input string) (string, error) {
// Activity options with summary
ao := workflow.ActivityOptions{
StartToCloseTimeout: 10 * time.Second,
Summary: "Processing user data",
}
ctx = workflow.WithActivityOptions(ctx, ao)
// Execute the activity
var result string
err := workflow.ExecuteActivity(ctx, YourActivity, input).Get(ctx, &result)
if err != nil {
return "", err
}
return result, nil
}
Activity Summary truncation on Timeline
Labels longer than 120 characters are truncated with an ellipsis on the Timeline tab of the Workflow details page.
Activity definition in Go
An Activity is a normal Go function that executes a single, well-defined action. Activities are typically prone to failure and interact with external systems like APIs, databases, or email services. If an Activity fails, Temporal automatically retries it based on configuration. Example: func Greet(ctx context.Context, name string) (string, error) { return fmt.Sprintf("Hello %s", name), nil }
Basic Activity interface definition - example
@ActivityInterface public interface GreetingActivities { String composeGreeting(String greeting, String language); }
Activity Type - custom name with @ActivityMethod name parameter
To override the default name and any inherited prefixes, use the name parameter in the @ActivityMethod annotation. For example, @ActivityMethod(name = "farewell") overrides the default naming. Using the name parameter will not automatically capitalize the result, so the Activity Type will be exactly as specified.
Activity interface with custom object parameters - example
An Activity interface can accept custom objects as parameters. Example: @ActivityInterface public interface YourActivities { String getCustomObject(CustomObj customobj); void sendCustomObject(CustomObj customobj, String abc); }
Activity purpose and role in Workflows
An Activity is a normal function or method execution that is intended to execute a single, well-defined action (either short or long-running), such as querying a database, calling a third-party API, or transcoding a media file. One of the primary things that Workflows do is orchestrate the execution of Activities. An Activity can interact with the world outside the Temporal Platform or use a Temporal Client to interact with a Temporal Service.
Activity Type naming - special characters caveat
Be cautious with Activity Type names that contain special characters, as these can be used as metric tags. Systems such as Prometheus may ignore metrics with tags using unsupported characters.
Activity Type - custom prefix with @ActivityInterface namePrefix
Using the namePrefix parameter in the @ActivityInterface annotation adds a prefix to each Activity Type name mentioned in the interface, unless the prefix is specifically overridden. For example, @ActivityInterface(namePrefix = "Messaging_") on an interface with method 'sendMessage' produces Activity Type 'Messaging_SendMessage'. The Activity Type is capitalized, even when using a prefix.
Activity Type - default naming convention
By default, an Activity Type is the method name with the first letter capitalized. For example, a method named 'sendMessage' has an Activity Type of 'SendMessage', and a method named 'composeGreeting' has an Activity Type of 'ComposeGreeting'. The Activity Type appears in the Workflow Execution Event History in the Summary tab for each Activity Task and lets you identify Activity Types called during the Execution.
Activity parameter best practices
When implementing Activities, be mindful of the amount of data transferred using Activity invocation parameters or return values because these are recorded in the Workflow Execution Events History. Large Event Histories can adversely impact performance. It is recommended to use a single object as an argument that wraps the application data passed to Activities, so that you can change what data is passed to the Activity without breaking a function or method signature. All inputs should be serializable by the default Jackson JSON Payload Converter.
Activity Definition - interface and implementation
An Activity Definition is a combination of a Temporal Java SDK Activity interface annotated with @ActivityInterface and an Activity implementation class that implements this interface. Each method defined in the Activity interface defines a separate Activity method. The Activity implementation is a Java class that implements the Activity annotated interface.
Activity implementation class - example
static class GreetingActivitiesImpl implements GreetingActivities { @Override public String composeGreeting(String greeting, String name) { return greeting + " " + name + "!"; } }
@ActivityInterface and @ActivityMethod annotations
An Activity interface is annotated with @ActivityInterface. Each method in the Activity interface can be annotated with the optional @ActivityMethod annotation, but this annotation is completely optional and not required.
Java SDK Activities documentation structure
The Java SDK Activities documentation covers activity basics, activity execution, standalone activities, timeouts, asynchronous activity completion, and benign exceptions.
Java SDK Activities topics
Activities in Java SDK are organized into the following topics: Activity basics, Activity execution, Standalone Activities, Timeouts, Asynchronous Activity Completion, and Benign exceptions.
Standalone Activities definition - same as Workflow Activities
An Activity in the Temporal Java SDK is an interface annotated with @ActivityInterface, with methods annotated with @ActivityMethod. The way you define a Standalone Activity is identical to how you define an Activity orchestrated by a Workflow. In fact, the same Activity can be executed both as a Standalone Activity and as a Workflow Activity.
Activity timeouts required before invocation
Before an Activity Execution is invoked, Activity options must be set. Either setStartToCloseTimeout or ScheduleToCloseTimeout must be set (at least one is required). The Activity must be registered with a Worker, and Activity code must be thread-safe.
Activity invocation in workflows requires ActivityStub
Activities are remote procedure calls that must be invoked from within a Workflow using ActivityStub. Activities are not executable on their own and cannot be started by themselves. An ActivityStub is created using Workflow.newActivityStub (type-safe) or Workflow.newUntypedActivityStub (untyped).
Java SDK Activity topics covered
Activity documentation includes: Activity basics, Activity execution, Standalone Activities, Timeouts, Asynchronous Activity Completion, and Benign exceptions.
Activity setSummary() in workflow
When creating an ActivityOptions within a Workflow, use setSummary() to attach a summary to an Activity. The input format for setSummary() is a string, limited to 200 bytes. The summary text is shown in the Timeline tab on the Workflow details page.
Example: Activity with summary
private final YourActivities activities =
Workflow.newActivityStub(YourActivities.class,
ActivityOptions.newBuilder()
.setStartToCloseTimeout(Duration.ofSeconds(10))
.setSummary("Processing user data")
.build());
String result = activities.yourActivity(input);
Activity implementation in Java
Implement the Activity interface without any Temporal annotations. Example: public class GreetActivitiesImpl implements GreetActivities { @Override public String greet(String name) { return "Hello " + name; } }
Activity interface definition in Java
Define Activities as an interface annotated with @ActivityInterface. Use @ActivityMethod to annotate the activity method. Example: @ActivityInterface public interface GreetActivities { @ActivityMethod String greet(String name); }
Create Activity stub in workflow
Use Workflow.newActivityStub() to create an activity stub within a workflow implementation. Example: private final GreetActivities activities = Workflow.newActivityStub(GreetActivities.class, ActivityOptions.newBuilder().setStartToCloseTimeout(Duration.ofSeconds(5)).build());
Override versioning intent for Activities using setVersioningIntent
You can override the default versioning behavior for Activities by calling setVersioningIntent(VersioningIntent.VERSIONING_INTENT_USE_ASSIGNMENT_RULES) on ActivityOptions. This makes the Activity use the latest assignment rules rather than inheriting from its parent workflow.
Activity return value serialization requirement
All data returned from an Activity must be serializable to a byte array using the provided DataConverter interface. The default implementation uses a JSON serializer, but alternative implementations can be configured. Activities can return both primitive types and objects.
Single activity argument size limit
A single argument passed to an Activity is limited to a maximum size of 2 MB.
Activity definition requires ActivityInterface annotation
Activities are defined as methods of a plain PHP interface annotated with #[ActivityInterface]. Each method in the interface defines a single Activity type.
Activity Type naming with ActivityInterface prefix
You can define a prefix for all Activity names by adding the prefix option to the ActivityInterface attribute. For example, #[ActivityInterface("file_activities.")] adds the prefix "file_activities." to all Activity names in that interface. The default prefix is empty.
Activity returning object type example
The following PHP code demonstrates an Activity implementation that returns an object:
class GreetingActivity implements GreetingActivityInterface
{
public function composeGreeting(string $greeting, string $name): Greeting
{
return new Greeting($greeting, $name);
}
}
Activity Type naming with ActivityMethod attribute
An optional #[ActivityMethod] attribute can be used to override the default Activity name. The attribute takes a string parameter that specifies the custom Activity Type name.
Activity implementation interface example
The following PHP code demonstrates an Activity interface definition with four Activity methods: upload, download, processFile, and deleteLocalFile. The download method uses #[ActivityMethod("transcode_file")] to override its default Activity name.
#[ActivityInterface]
interface FileProcessingActivities
{
public function upload(string $bucketName, string $localName, string $targetName): void;
#[ActivityMethod("transcode_file")]
public function download(string $bucketName, string $remoteName): void;
public function processFile(): string;
public function deleteLocalFile(string $fileName): void;
}
Activity returning primitive type example
The following PHP code demonstrates an Activity implementation that returns a primitive string type:
class GreetingActivity implements GreetingActivityInterface
{
public function composeGreeting(string $greeting, string $name): string
{
return $greeting . ' ' . $name;
}
}
Activity interface with custom prefix example
The following PHP code demonstrates an Activity interface with a custom prefix applied to all Activity names:
#[ActivityInterface("file_activities.")]
interface FileProcessingActivities
{
public function upload(string $bucketName, string $localName, string $targetName);
#[ActivityMethod("transcode_file")]
public function download(string $bucketName, string $remoteName);
public function processFile(): string;
public function deleteLocalFile(string $fileName);
}
This results in Activity names like "file_activities.upload", "file_activities.transcode_file", etc.
PHP SDK activities documentation sections
The PHP SDK documentation for activities is organized into four main sections: Activity Basics, Activity Execution, Timeouts, and Asynchronous Activity Completion.