new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Temporal · Develop · all subjects

nexus/basics

88 notes in this subject, read out of this brain and free to use. This is page 1 of 2.

Example caller Workflow invoking Nexus operation in C#

namespace MyNamespace; using Temporalio.Workflows; [Workflow] public class CallerWorkflow { public static readonly string CallerTaskQueue = "my-caller-task-queue"; [WorkflowRun] public async Task<string> RunAsync(string name) { return await Workflow .CreateNexusWorkflowClient<ISayHelloNexusService>( ISayHelloNexusService.EndpointName) .ExecuteNexusOperationAsync(svc => svc.SayHello(new(name))); } } This example shows a Workflow that creates a Nexus client and invokes the SayHello operation.

Connect TemporalClient to specific Namespace

When creating a TemporalClient, specify the target Namespace using the TemporalConnectionOptions constructor: new("localhost:7233") { Namespace = "my-caller-namespace" }. This allows the client to connect to a specific Namespace rather than the default one.

Example caller starter program setup

using MyNamespace; using Temporalio.Client; using Temporalio.Worker; var client = await TemporalClient.ConnectAsync( new("localhost:7233") { Namespace = "my-caller-namespace" }); using var tokenSource = new CancellationTokenSource(); Console.CancelKeyPress += (_, eventArgs) => { tokenSource.Cancel(); eventArgs.Cancel = true; }; using var worker = new TemporalWorker( client, new TemporalWorkerOptions(CallerWorkflow.CallerTaskQueue) .AddWorkflow<CallerWorkflow>()); Console.WriteLine("Running caller worker"); var workerTask = worker.ExecuteAsync(tokenSource.Token); var result = await client.ExecuteWorkflowAsync( (CallerWorkflow wf) => wf.RunAsync("Temporal"), new(id: $"caller-workflow-{Guid.NewGuid()}", taskQueue: CallerWorkflow.CallerTaskQueue)); Console.WriteLine("Workflow result: {0}", result); tokenSource.Cancel(); try { await workerTask; } catch (OperationCanceledException) { } This example shows how to set up a caller Worker, start it, execute a caller Workflow, and handle cancellation.

Nexus Service definition with [NexusService] attribute

Define a Nexus Service by creating an interface decorated with the [NexusService] attribute. Mark each callable method with [NexusOperation]. Include a static EndpointName field to keep the endpoint name in one place for use by both handler and caller. The operation output type matches the method return type, and input is typically a record carrying the workflow arguments.

Example Nexus Service interface definition in C#

namespace MyNamespace; using NexusRpc; [NexusService] public interface ISayHelloNexusService { public static readonly string EndpointName = "my-nexus-endpoint-name"; [NexusOperation] string SayHello(MyInput input); public record MyInput(string Name); } This example defines a Nexus Service with one operation that takes a MyInput record and returns a string.

Nexus Operation handler definition with [NexusServiceHandler]

Create a Nexus Operation handler class decorated with [NexusServiceHandler(typeof(TService))] where TService is the service interface. Mark each handler method with [NexusOperationHandler]. Use WorkflowRunOperationHandler.FromHandleFactory to create asynchronous operations backed by Workflow runs. Use context.HandlerContext.RequestId as the Workflow ID to ensure retried Nexus operation requests are deduplicated.

Example Nexus Operation handler in C#

namespace MyNamespace; using NexusRpc.Handlers; using Temporalio.Nexus; [NexusServiceHandler(typeof(ISayHelloNexusService))] public class SayHelloNexusServiceHandler { [NexusOperationHandler] public IOperationHandler<ISayHelloNexusService.MyInput, string> SayHello() => WorkflowRunOperationHandler.FromHandleFactory( (WorkflowRunOperationContext context, ISayHelloNexusService.MyInput input) => context.StartWorkflowAsync( (SayHelloWorkflow wf) => wf.RunAsync(input.Name), new() { Id = context.HandlerContext.RequestId })); } This example shows how to handle a Nexus operation by starting a Workflow run and using the request ID as the Workflow ID for deduplication.

Example registering Nexus Service handler in Worker

var activities = new MyActivities(); using var worker = new TemporalWorker( client, new TemporalWorkerOptions("my-task-queue") .AddActivity(activities.SayHello) .AddWorkflow<SayHelloWorkflow>() .AddNexusService(new SayHelloNexusServiceHandler())); This example shows how to register a Nexus Service handler alongside Activity and Workflow registrations in a Worker.

Standalone Nexus Operations .NET SDK version requirement

Standalone Nexus Operations require .NET SDK version 1.16.0 or above. All APIs are experimental and may be subject to backwards-incompatible changes.

Count Standalone Nexus Operations

Use ITemporalClient.CountNexusOperationsAsync() to count Standalone Nexus Operation Executions that match a List Filter query. CountNexusOperationsAsync is called on the base ITemporalClient, not on the NexusClient.

List Nexus Operations example

Example of listing Standalone Nexus Operations: await foreach (var execution in client.ListNexusOperationsAsync( "Endpoint = 'my-nexus-endpoint'")) { logger.LogInformation( "OperationID: {Id}, Operation: {Operation}, Status: {Status}", execution.OperationId, execution.Operation, execution.Status); }

List Standalone Nexus Operations

Use ITemporalClient.ListNexusOperationsAsync() to list Standalone Nexus Operation Executions that match a List Filter query. The call returns an IAsyncEnumerable<NexusOperationExecution> that you can iterate with await foreach. ListNexusOperationsAsync is called on the base ITemporalClient, not on the NexusClient.

Recover handle for already-started Nexus Operation

You can recover a handle for an already-started Nexus Operation using GetNexusOperationHandle<TResult>() on the Temporal Client: var handle = client.GetNexusOperationHandle<IHelloService.EchoOutput>("unique-operation-id"); var output = await handle.GetResultAsync();

Execute Standalone Nexus Operation with untyped client

Example of executing a Standalone Nexus Operation with an untyped NexusClient using operation name as a string: var nexusClient = client.CreateNexusClient("my-nexus-endpoint", "HelloService"); var handle = await nexusClient.StartNexusOperationAsync<IHelloService.EchoOutput>( "Echo", new IHelloService.EchoInput("Nexus Echo 👋"), new("unique-operation-id") { ScheduleToCloseTimeout = TimeSpan.FromSeconds(10), });

Execute Standalone Nexus Operation with typed client

Example of executing a Standalone Nexus Operation with a typed NexusClient: var nexusClient = client.CreateNexusClient<IHelloService>("my-nexus-endpoint"); var result = await nexusClient.ExecuteNexusOperationAsync( svc => svc.Echo(new("Nexus Echo 👋")), new("unique-operation-id") { ScheduleToCloseTimeout = TimeSpan.FromSeconds(10), });

NexusOperationOptions requirements and defaults

On NexusOperationOptions, the Id field is required. ScheduleToCloseTimeout is optional and defaults to the maximum allowed by the Temporal server.

Count Nexus Operations example

Example of counting Standalone Nexus Operations: var count = await client.CountNexusOperationsAsync( "Endpoint = 'my-nexus-endpoint'"); logger.LogInformation("Total Nexus operations: {Count}", count.Count);

ExecuteNexusOperationAsync shortcut method

ExecuteNexusOperationAsync is a shortcut that starts a Standalone Nexus Operation and waits for the result. If you need a handle to the Operation while it runs, call StartNexusOperationAsync instead, which returns a NexusOperationHandle.

Context propagation over Nexus uses interceptors, not ContextPropagator

Nexus does not use the ContextPropagator interface. It relies on a Temporal-agnostic protocol with its own header format (nexus.Header, a wrapper around map[string]string). To propagate context over Nexus Operation calls, use interceptors to explicitly serialize and deserialize context into the Nexus header.

Temporal Nexus documentation structure for Go SDK

The Temporal Nexus documentation for the Go SDK is organized into three main sections: Quickstart, Feature guide, and Standalone Operations.

Nexus Service decouples caller and handler implementations

Nexus Services provide loose coupling between caller and handler implementations. The caller depends only on the Service contract (constants and input/output types), not the handler implementation. This allows caller and handler to live in separate Namespaces, repositories, or even teams while remaining type-safe through the shared contract definition.

Standalone Nexus Operations require Go SDK v1.46.0 or above

Standalone Nexus Operations require Go SDK version 1.46.0 or above. All APIs are experimental and may be subject to backwards-incompatible changes.

Java SDK Nexus documentation sections

Temporal Nexus documentation for Java includes: Quickstart, Feature guide, and Standalone Operations.

Java SDK Nexus documentation structure

The Java SDK Nexus documentation is organized into four main sections: Quickstart, Feature guide, Standalone Operations, and a Nexus sync tutorial available at learn.temporal.io.

Temporal Nexus Java SDK overview

Temporal Nexus allows connecting Temporal Applications within and across Namespaces using a Nexus Endpoint, a Nexus Service contract, and Nexus Operations. The Nexus Java SDK is used to develop Nexus Services, Operation handlers, and caller Workflows that use Nexus Services.

Get Standalone Nexus Operation result via CLI

Wait for a Standalone Nexus Operation result by Operation ID using the Temporal CLI: ./temporal nexus operation result --namespace my-caller-namespace --operation-id my-greet-op

Count Standalone Nexus Operations with GROUP BY

Passing a GROUP BY query to countNexusOperationExecutions() (for example, "GROUP BY ExecutionStatus") returns a count per group, available through NexusOperationExecutionCount.getGroups().

Count Standalone Nexus Operations example

String query = "Endpoint = \"" + ENDPOINT_NAME + "\""; NexusOperationExecutionCount count = nexusClient.countNexusOperationExecutions(query); System.out.println("Total Nexus operations: " + count.getCount());

List Filter syntax for Standalone Nexus Operations

The query parameter for listNexusOperationExecutions() accepts List Filter syntax. For example: "Endpoint = 'my-endpoint' AND ExecutionStatus = 'Running'"

List Standalone Nexus Operations example

String query = "Endpoint = \"" + ENDPOINT_NAME + "\""; nexusClient .listNexusOperationExecutions(query) .forEach( op -> System.out.printf( "OperationId: %s, Operation: %s, Status: %s%n", op.getOperationId(), op.getOperation(), op.getStatus()));

ExecuteAsync Standalone Nexus Operation example

CompletableFuture<GreetingOutput> future = greetingClient.executeAsync( GreetingNexusService::greet, options, new GreetingInput("World")); GreetingOutput greeting = future.get();

Execute Standalone Nexus Operation via CLI

Execute a Standalone Nexus Operation using the Temporal CLI with: ./temporal nexus operation execute --namespace my-caller-namespace --endpoint my-nexus-endpoint --service GreetingNexusService --operation greet --operation-id my-greet-op --input '{"name":"World"}'

Standalone Nexus Operations definition

Standalone Nexus Operations let you run Nexus Operation Executions independently, without being orchestrated by a Workflow. Instead of calling a Nexus Operation from within a Workflow Definition using Workflow.newNexusServiceStub(), you execute a Standalone Nexus Operation directly from a Nexus service client created from a NexusClient using NexusClient.newNexusServiceClient().

Standalone Nexus Operations prerequisites

Standalone Nexus Operations require Java SDK v1.36.1 or above. All APIs are experimental and may be subject to backwards-incompatible changes. They require a Pre-release build of the Temporal CLI that includes Standalone Nexus Operations support. The standard brew install temporal build does not include Standalone Nexus Operation support during Pre-release.

Execute Standalone Nexus Operation synchronously

Create a NexusClient, derive a typed NexusServiceClient from it with newNexusServiceClient(), bound to a specific Nexus Endpoint and Service, then call execute() from application code. The execute() method waits for the Operation to complete and returns the result. It takes a StartNexusOperationOptions where id is required (the SDK never generates one) and scheduleToCloseTimeout is optional, defaulting to the maximum allowed by the Temporal server.

Execute Standalone Nexus Operation example

NexusClient nexusClient = NexusClient.newInstance(stubs, options); NexusServiceClient<GreetingNexusService> greetingClient = nexusClient.newNexusServiceClient(GreetingNexusService.class, ENDPOINT_NAME); // Block until the operation completes and return its result. GreetingOutput greeting = greetingClient.execute( GreetingNexusService::greet, StartNexusOperationOptions.newBuilder() .setId("greet-" + UUID.randomUUID()) .setScheduleToCloseTimeout(Duration.ofSeconds(10)) .build(), new GreetingInput("World"));

Execute Standalone Nexus Operation asynchronously

Call executeAsync() on a NexusServiceClient to execute a Nexus Operation asynchronously. This method returns a CompletableFuture instead of blocking.

Start Standalone Nexus Operation and get handle

Call start() on a NexusServiceClient to start a Standalone Nexus Operation. This returns a NexusOperationHandle. Use NexusOperationHandle.getResult() to wait until the Operation completes and retrieve its result. This works for both synchronous and asynchronous Operations.

NexusOperationHandle.getResult() example

// Start an operation and get a NexusOperationHandle. NexusOperationHandle<GreetingOutput> handle = greetingClient.start( GreetingNexusService::startGreeting, options, new GreetingInput("World")); // Block until the operation completes and retrieve its result. GreetingOutput greeting = handle.getResult();

NexusOperationHandle result retrieval methods

If a Standalone Nexus Operation completed successfully, NexusOperationHandle.getResult() returns the result. If the Operation failed, the failure is thrown as a NexusOperationException. Use getResultAsync() for a non-blocking CompletableFuture, or getResult(long timeout, TimeUnit unit) to bound the wait.

List Standalone Nexus Operations

Use NexusClient.listNexusOperationExecutions() to list Standalone Nexus Operation Executions that match a List Filter query. The result is a Stream of operation metadata entries. Note that listNexusOperationExecutions() is called on a NexusClient, not on the typed NexusServiceClient.

Go plugin example with Nexus operation

Example of registering a Nexus operation in a Go plugin: type WeatherInput struct { City string `json:"city"` } type Weather struct { City string `json:"city"` TemperatureRange string `json:"temperatureRange"` Conditions string `json:"conditions"` } var WeatherService = nexus.NewService("weather-service") var GetWeatherOperation = nexus.NewSyncOperation( "get-weather", func(ctx context.Context, input WeatherInput, options nexus.StartOperationOptions) (Weather, error) { return Weather{ City: input.City, TemperatureRange: "14-20C", Conditions: "Sunny with wind.", }, nil }, ) func createNexusPlugin() (*temporal.SimplePlugin, error) { return temporal.NewSimplePlugin(temporal.SimplePluginOptions{ Name: "organization.PluginName", RunContextBefore: func(ctx context.Context, options temporal.SimplePluginRunContextBeforeOptions) error { options.Registry.RegisterNexusService(WeatherService) return nil }, }) }

DotNet plugin example with Nexus operation

Example of registering a Nexus operation in a DotNet plugin: [NexusService] public interface IStringService { [NexusOperation] string DoSomething(string name); } [NexusServiceHandler(typeof(IStringService))] public class HandlerFactoryStringService { private readonly Func<IOperationHandler<string, string>> handlerFactory; public HandlerFactoryStringService(Func<IOperationHandler<string, string>> handlerFactory) => this.handlerFactory = handlerFactory; [NexusOperationHandler] public IOperationHandler<string, string> DoSomething() => handlerFactory(); } SimplePlugin nexusPlugin = new SimplePlugin( "organization.PluginName", new SimplePluginOptions() { }.AddNexusService(new HandlerFactoryStringService(() => OperationHandler.Sync<string, string>((ctx, name) => $"Hello, {name}"))) );

TypeScript plugin example with Nexus operation

Example of registering a Nexus operation in a TypeScript plugin: const testServiceHandler = nexus.serviceHandler( nexus.service('testService', { testSyncOp: nexus.operation<string, string>(), }), { async testSyncOp(_, input) { return input; }, }, ); const plugin = new SimplePlugin({ name: 'organization.PluginName', nexusServices: [testServiceHandler], });

Java plugin example with Nexus operation

Example of registering a Nexus operation in a Java plugin: public class WeatherService { public Weather getWeather(WeatherInput input) { return new Weather(input.getCity(), "14-20C", "Sunny with wind."); } } public static class Weather { private final String city; private final String temperatureRange; private final String conditions; public Weather(String city, String temperatureRange, String conditions) { this.city = city; this.temperatureRange = temperatureRange; this.conditions = conditions; } } public static class WeatherInput { private final String city; public WeatherInput(String city) { this.city = city; } public String getCity() { return city; } } SimplePlugin nexusPlugin = SimplePlugin.newBuilder("organization.PluginName") .registerNexusServiceImplementation(new WeatherService()) .build();

Python plugin example with Nexus operation

Example of registering a Nexus operation in a Python plugin: @nexusrpc.service class WeatherService: get_weather_nexus_operation: nexusrpc.Operation[WeatherInput, Weather] @nexusrpc.handler.service_handler(service=WeatherService) class WeatherServiceHandler: @nexusrpc.handler.sync_operation async def get_weather_nexus_operation( self, ctx: nexusrpc.handler.StartOperationContext, input: WeatherInput ) -> Weather: return Weather( city=input.city, temperature_range="14-20C", conditions="Sunny with wind.", ) plugin = SimplePlugin( "organization.PluginName", nexus_service_handlers=[WeatherServiceHandler()] )

Temporal Nexus Python SDK documentation sections

The Temporal Nexus Python SDK documentation is organized into three main sections: Quickstart, Feature guide, and Standalone Operations.

Standalone Nexus Operations use same contract and handlers as workflow-driven operations

Standalone Nexus Operations use the same Nexus Service contract, Operation handlers, and Worker setup as Workflow-driven Operations. Only the execution path differs.

list_nexus_operations example

query = f'Endpoint = "{ENDPOINT_NAME}"' async for op in client.list_nexus_operations(query): print( f" OperationId: {op.operation_id},", f" Operation: {op.operation},", f" Status: {op.status.name}", )

execute_operation waits for operation completion

execute_operation waits for the Nexus Operation to complete and returns the result. It requires an id parameter. schedule_to_close_timeout is optional and defaults to the maximum allowed by the Temporal server.

Standalone Nexus Operations require Python SDK 1.30.0+

Standalone Nexus Operations require Python SDK version 1.30.0 or above. All APIs are experimental and may be subject to backwards-incompatible changes.

Define Nexus Service contract with @nexusrpc.service decorator

Use the @nexusrpc.service decorator to declare a service with typed operations. Each operation is a class attribute declared as nexusrpc.Operation[InputType, OutputType]. For example, a service that wraps SayHelloWorkflow returning str would declare say_hello: nexusrpc.Operation[MyInput, str].

Complete Python Nexus quickstart example - full service definition

To define a Nexus Service contract in a file called service.py: ```python from dataclasses import dataclass import nexusrpc @dataclass class MyInput: name: str @nexusrpc.service class SayHelloNexusService: say_hello: nexusrpc.Operation[MyInput, str] ```

Caller and handler workflows must be in separate namespaces

In Nexus, the caller Workflow and handler Workflow run in separate Namespaces to provide isolation. A Nexus Endpoint routes requests from the caller Namespace to the handler's target Namespace and Task Queue. The caller Workflow does not import handler code directly, keeping them decoupled so they can live in separate Namespaces, repositories, or teams.

Nexus Operation events in workflow history

When a Workflow invokes a Nexus Operation, the execution history contains NexusOperationScheduled, NexusOperationStarted, and NexusOperationCompleted events. These events can be viewed in the Temporal Web UI to track operation progress.

Rust SDK Temporal Nexus support

The Rust SDK includes support for Temporal Nexus, with a feature guide available at /develop/rust/nexus/feature-guide.

Temporal Nexus TypeScript SDK documentation structure

The Temporal Nexus TypeScript SDK documentation includes three main sections: Quickstart, Feature guide, and Standalone Operations.

Nexus Service contract definition with nexus.service()

A Nexus Service is defined using nexus.service() which declares a named service, and nexus.operation<I, O>() which defines a typed operation with input type I and output type O. The example shows creating a service named 'say-hello' with a 'sayHello' operation that takes MyInput (containing a name string) and returns a string.

Nexus Service decoupling between caller and handler

The caller Workflow only depends on the Service contract (defined in service.ts), not on the handler implementation. This keeps the caller and handler decoupled so they can live in separate Namespaces, repositories, or even teams.

Create Nexus service client for standalone operations

Create a NexusServiceClient using client.nexus.createServiceClient(), bound to a specific Nexus Endpoint and Service. The endpoint must be pre-created on the server. Then call startOperation() or executeOperation() from application code (for example, a starter program), not from inside a Workflow Definition.

Give your agent this brain