From fdf61d7c892a4488e4b6c15f913d399c3699d34c Mon Sep 17 00:00:00 2001 From: Wenlong Gu Date: Thu, 1 Oct 2026 17:21:08 -0500 Subject: [PATCH 1/7] Add eager standalone activity start API --- temporal/api/workflowservice/v1/request_response.proto | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/temporal/api/workflowservice/v1/request_response.proto b/temporal/api/workflowservice/v1/request_response.proto index 1aae988d8..c17c82055 100644 --- a/temporal/api/workflowservice/v1/request_response.proto +++ b/temporal/api/workflowservice/v1/request_response.proto @@ -3270,6 +3270,9 @@ message StartActivityExecutionRequest { temporal.api.common.v1.OnConflictOptions on_conflict_options = 21; // Time to wait before making the first activity task available for dispatch. This delay is not applied to retry attempts. google.protobuf.Duration start_delay = 22; + // Request that the first activity task be returned directly in the start response instead of + // being dispatched through a task queue. The server may decline this request. + bool request_eager_execution = 23; } message StartActivityExecutionResponse { @@ -3279,6 +3282,9 @@ message StartActivityExecutionResponse { bool started = 2; // Link to the started activity. temporal.api.common.v1.Link link = 3; + // The first activity task when eager execution was requested and accepted. + // This is set only for the first attempt of a newly started activity. + PollActivityTaskQueueResponse eager_activity_task = 4; } message DescribeActivityExecutionRequest { From 750038b8e71643c579a6b5f9a549fa6dd46c6a4d Mon Sep 17 00:00:00 2001 From: Wenlong Gu Date: Tue, 6 Oct 2026 10:24:48 -0500 Subject: [PATCH 2/7] Document eager activity execution requirements --- temporal/api/workflowservice/v1/request_response.proto | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/temporal/api/workflowservice/v1/request_response.proto b/temporal/api/workflowservice/v1/request_response.proto index c17c82055..ea17f70cb 100644 --- a/temporal/api/workflowservice/v1/request_response.proto +++ b/temporal/api/workflowservice/v1/request_response.proto @@ -3271,7 +3271,9 @@ message StartActivityExecutionRequest { // Time to wait before making the first activity task available for dispatch. This delay is not applied to retry attempts. google.protobuf.Duration start_delay = 22; // Request that the first activity task be returned directly in the start response instead of - // being dispatched through a task queue. The server may decline this request. + // being dispatched through a task queue. If set to true, the caller is expected to have a + // worker available and capable of processing the task. The returned task will be marked as + // started. The server may decline this request. bool request_eager_execution = 23; } From bb482566dba54dd0754b076bca9f6df05a4ead4b Mon Sep 17 00:00:00 2001 From: Wenlong Gu Date: Tue, 6 Oct 2026 10:39:03 -0500 Subject: [PATCH 3/7] Update generated OpenAPI for eager activities --- openapi/openapiv2.json | 109 +++++++++++++++++++++++++++++++++ openapi/openapiv3.yaml | 135 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 244 insertions(+) diff --git a/openapi/openapiv2.json b/openapi/openapiv2.json index 0b643ceb7..293d38258 100644 --- a/openapi/openapiv2.json +++ b/openapi/openapiv2.json @@ -12634,6 +12634,10 @@ "startDelay": { "type": "string", "description": "Time to wait before making the first activity task available for dispatch. This delay is not applied to retry attempts." + }, + "requestEagerExecution": { + "type": "boolean", + "description": "Request that the first activity task be returned directly in the start response instead of\nbeing dispatched through a task queue. If set to true, the caller is expected to have a\nworker available and capable of processing the task. The returned task will be marked as\nstarted. The server may decline this request." } } }, @@ -18423,6 +18427,107 @@ } } }, + "v1PollActivityTaskQueueResponse": { + "type": "object", + "properties": { + "taskToken": { + "type": "string", + "format": "byte", + "title": "A unique identifier for this task" + }, + "workflowNamespace": { + "type": "string", + "description": "The namespace of the activity. If this is a workflow activity then this is the namespace of\nthe workflow also. If this is a standalone activity then the name of this field is\nmisleading, but retained for compatibility with workflow activities." + }, + "workflowType": { + "$ref": "#/definitions/v1WorkflowType", + "description": "Type of the requesting workflow (if this is a workflow activity)." + }, + "workflowExecution": { + "$ref": "#/definitions/v1WorkflowExecution", + "title": "Execution info of the requesting workflow (if this is a workflow activity)" + }, + "activityType": { + "$ref": "#/definitions/v1ActivityType" + }, + "activityId": { + "type": "string", + "description": "The autogenerated or user specified identifier of this activity. Can be used to complete the\nactivity via `RespondActivityTaskCompletedById`. May be re-used as long as the last usage\nhas resolved, but unique IDs for every activity invocation is a good idea.\nNote that only a workflow activity ID may be autogenerated." + }, + "header": { + "$ref": "#/definitions/v1Header", + "description": "Headers specified by the scheduling workflow. Commonly used to propagate contextual info\nfrom the workflow to its activities. For example, tracing contexts." + }, + "input": { + "$ref": "#/definitions/v1Payloads", + "title": "Arguments to the activity invocation" + }, + "heartbeatDetails": { + "$ref": "#/definitions/v1Payloads", + "description": "Details of the last heartbeat that was recorded for this activity as of the time this task\nwas delivered." + }, + "scheduledTime": { + "type": "string", + "format": "date-time", + "title": "When was this task first scheduled" + }, + "currentAttemptScheduledTime": { + "type": "string", + "format": "date-time", + "title": "When was this task attempt scheduled" + }, + "startedTime": { + "type": "string", + "format": "date-time", + "title": "When was this task started (this attempt)" + }, + "attempt": { + "type": "integer", + "format": "int32", + "title": "Starting at 1, the number of attempts to perform this activity" + }, + "scheduleToCloseTimeout": { + "type": "string", + "title": "First scheduled -> final result reported timeout" + }, + "startToCloseTimeout": { + "type": "string", + "title": "Current attempt start -> final result reported timeout" + }, + "heartbeatTimeout": { + "type": "string", + "description": "Window within which the activity must report a heartbeat, or be timed out." + }, + "retryPolicy": { + "$ref": "#/definitions/v1RetryPolicy", + "description": "This is the retry policy the service uses which may be different from the one provided\n(or not) during activity scheduling. The service can override the provided one if some\nvalues are not specified or exceed configured system limits." + }, + "pollerScalingDecision": { + "$ref": "#/definitions/v1PollerScalingDecision", + "description": "Server-advised information the SDK may use to adjust its poller count." + }, + "priority": { + "$ref": "#/definitions/v1Priority", + "title": "Priority metadata" + }, + "activityRunId": { + "type": "string", + "description": "The run ID of the activity execution, only set for standalone activities." + }, + "pollerGroupInfos": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1PollerGroupInfo" + }, + "description": "The weighted list of poller groups IDs that client should use for future polls to this task\nqueue. Client is expected to:\n 1. Maintain minimum number of pollers no less than the number of groups.\n 2. Try to assign the next poll to a group without any pending polls,\n 3. If every group has some pending polls, assign the next poll to a group randomly\n according to the weights." + }, + "pollerGroupsInfo": { + "$ref": "#/definitions/v1PollerGroupsInfo", + "description": "The weighted, versioned list of poller groups IDs that client should use for future polls to\nthis task queue. Client should ignore this if it has already applied a snapshot with a\nversion greater than or equal to `poller_groups_info.version`. Client is expected to:\n 1. Maintain minimum number of pollers no less than the number of groups.\n 2. Try to assign the next poll to a group without any pending polls,\n 3. If every group has some pending polls, assign the next poll to a group randomly\n according to the weights." + } + } + }, "v1PollNexusOperationExecutionResponse": { "type": "object", "properties": { @@ -19855,6 +19960,10 @@ "link": { "$ref": "#/definitions/v1Link", "description": "Link to the started activity." + }, + "eagerActivityTask": { + "$ref": "#/definitions/v1PollActivityTaskQueueResponse", + "description": "The first activity task when eager execution was requested and accepted.\nThis is set only for the first attempt of a newly started activity." } } }, diff --git a/openapi/openapiv3.yaml b/openapi/openapiv3.yaml index 2aa7c45bf..829500edd 100644 --- a/openapi/openapiv3.yaml +++ b/openapi/openapiv3.yaml @@ -14687,6 +14687,128 @@ components: description: The run ID of the activity, useful when run_id was not specified in the request. outcome: $ref: '#/components/schemas/ActivityExecutionOutcome' + PollActivityTaskQueueResponse: + type: object + properties: + taskToken: + type: string + description: A unique identifier for this task + format: bytes + workflowNamespace: + type: string + description: |- + The namespace of the activity. If this is a workflow activity then this is the namespace of + the workflow also. If this is a standalone activity then the name of this field is + misleading, but retained for compatibility with workflow activities. + workflowType: + allOf: + - $ref: '#/components/schemas/WorkflowType' + description: Type of the requesting workflow (if this is a workflow activity). + workflowExecution: + allOf: + - $ref: '#/components/schemas/WorkflowExecution' + description: Execution info of the requesting workflow (if this is a workflow activity) + activityType: + $ref: '#/components/schemas/ActivityType' + activityId: + type: string + description: |- + The autogenerated or user specified identifier of this activity. Can be used to complete the + activity via `RespondActivityTaskCompletedById`. May be re-used as long as the last usage + has resolved, but unique IDs for every activity invocation is a good idea. + Note that only a workflow activity ID may be autogenerated. + header: + allOf: + - $ref: '#/components/schemas/Header' + description: |- + Headers specified by the scheduling workflow. Commonly used to propagate contextual info + from the workflow to its activities. For example, tracing contexts. + input: + allOf: + - $ref: '#/components/schemas/Payloads' + description: Arguments to the activity invocation + heartbeatDetails: + allOf: + - $ref: '#/components/schemas/Payloads' + description: |- + Details of the last heartbeat that was recorded for this activity as of the time this task + was delivered. + scheduledTime: + type: string + description: When was this task first scheduled + format: date-time + currentAttemptScheduledTime: + type: string + description: When was this task attempt scheduled + format: date-time + startedTime: + type: string + description: When was this task started (this attempt) + format: date-time + attempt: + type: integer + description: Starting at 1, the number of attempts to perform this activity + format: int32 + scheduleToCloseTimeout: + pattern: ^-?(?:0|[1-9][0-9]{0,11})(?:\.[0-9]{1,9})?s$ + type: string + description: |- + First scheduled -> final result reported timeout + + (-- api-linter: core::0140::prepositions=disabled + aip.dev/not-precedent: "to" is used to indicate interval. --) + startToCloseTimeout: + pattern: ^-?(?:0|[1-9][0-9]{0,11})(?:\.[0-9]{1,9})?s$ + type: string + description: |- + Current attempt start -> final result reported timeout + + (-- api-linter: core::0140::prepositions=disabled + aip.dev/not-precedent: "to" is used to indicate interval. --) + heartbeatTimeout: + pattern: ^-?(?:0|[1-9][0-9]{0,11})(?:\.[0-9]{1,9})?s$ + type: string + description: Window within which the activity must report a heartbeat, or be timed out. + retryPolicy: + allOf: + - $ref: '#/components/schemas/RetryPolicy' + description: |- + This is the retry policy the service uses which may be different from the one provided + (or not) during activity scheduling. The service can override the provided one if some + values are not specified or exceed configured system limits. + pollerScalingDecision: + allOf: + - $ref: '#/components/schemas/PollerScalingDecision' + description: Server-advised information the SDK may use to adjust its poller count. + priority: + allOf: + - $ref: '#/components/schemas/Priority' + description: Priority metadata + activityRunId: + type: string + description: The run ID of the activity execution, only set for standalone activities. + pollerGroupInfos: + type: array + items: + $ref: '#/components/schemas/PollerGroupInfo' + description: |- + The weighted list of poller groups IDs that client should use for future polls to this task + queue. Client is expected to: + 1. Maintain minimum number of pollers no less than the number of groups. + 2. Try to assign the next poll to a group without any pending polls, + 3. If every group has some pending polls, assign the next poll to a group randomly + according to the weights. + pollerGroupsInfo: + allOf: + - $ref: '#/components/schemas/PollerGroupsInfo' + description: |- + The weighted, versioned list of poller groups IDs that client should use for future polls to + this task queue. Client should ignore this if it has already applied a snapshot with a + version greater than or equal to `poller_groups_info.version`. Client is expected to: + 1. Maintain minimum number of pollers no less than the number of groups. + 2. Try to assign the next poll to a group without any pending polls, + 3. If every group has some pending polls, assign the next poll to a group randomly + according to the weights. PollNexusOperationExecutionResponse: type: object properties: @@ -17124,6 +17246,13 @@ components: pattern: ^-?(?:0|[1-9][0-9]{0,11})(?:\.[0-9]{1,9})?s$ type: string description: Time to wait before making the first activity task available for dispatch. This delay is not applied to retry attempts. + requestEagerExecution: + type: boolean + description: |- + Request that the first activity task be returned directly in the start response instead of + being dispatched through a task queue. If set to true, the caller is expected to have a + worker available and capable of processing the task. The returned task will be marked as + started. The server may decline this request. StartActivityExecutionResponse: type: object properties: @@ -17137,6 +17266,12 @@ components: allOf: - $ref: '#/components/schemas/Link' description: Link to the started activity. + eagerActivityTask: + allOf: + - $ref: '#/components/schemas/PollActivityTaskQueueResponse' + description: |- + The first activity task when eager execution was requested and accepted. + This is set only for the first attempt of a newly started activity. StartBatchOperationRequest: type: object properties: From e43848de8b7dff9698514c0fc6e2ec6bceb9debc Mon Sep 17 00:00:00 2001 From: Wenlong Gu Date: Thu, 8 Oct 2026 09:58:23 -0500 Subject: [PATCH 4/7] Clarify eager execution fallback --- temporal/api/workflowservice/v1/request_response.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/temporal/api/workflowservice/v1/request_response.proto b/temporal/api/workflowservice/v1/request_response.proto index 5ad54abc0..bfdac483a 100644 --- a/temporal/api/workflowservice/v1/request_response.proto +++ b/temporal/api/workflowservice/v1/request_response.proto @@ -3284,7 +3284,7 @@ message StartActivityExecutionRequest { // Request that the first activity task be returned directly in the start response instead of // being dispatched through a task queue. If set to true, the caller is expected to have a // worker available and capable of processing the task. The returned task will be marked as - // started. The server may decline this request. + // started. The server may ignore this request. bool request_eager_execution = 24; } From 078262b4c24025a291474db44eb2d697e0c5f659 Mon Sep 17 00:00:00 2001 From: Wenlong Gu Date: Thu, 8 Oct 2026 10:43:39 -0500 Subject: [PATCH 5/7] Update generated OpenAPI descriptions --- openapi/openapiv2.json | 2 +- openapi/openapiv3.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openapi/openapiv2.json b/openapi/openapiv2.json index af38f714c..f792cdbd1 100644 --- a/openapi/openapiv2.json +++ b/openapi/openapiv2.json @@ -12643,7 +12643,7 @@ }, "requestEagerExecution": { "type": "boolean", - "description": "Request that the first activity task be returned directly in the start response instead of\nbeing dispatched through a task queue. If set to true, the caller is expected to have a\nworker available and capable of processing the task. The returned task will be marked as\nstarted. The server may decline this request." + "description": "Request that the first activity task be returned directly in the start response instead of\nbeing dispatched through a task queue. If set to true, the caller is expected to have a\nworker available and capable of processing the task. The returned task will be marked as\nstarted. The server may ignore this request." } } }, diff --git a/openapi/openapiv3.yaml b/openapi/openapiv3.yaml index a45ffe61c..31c6b0fe9 100644 --- a/openapi/openapiv3.yaml +++ b/openapi/openapiv3.yaml @@ -17312,7 +17312,7 @@ components: Request that the first activity task be returned directly in the start response instead of being dispatched through a task queue. If set to true, the caller is expected to have a worker available and capable of processing the task. The returned task will be marked as - started. The server may decline this request. + started. The server may ignore this request. StartActivityExecutionResponse: type: object properties: From 99686f2884c6527076cecfc62e3acf822e67ef85 Mon Sep 17 00:00:00 2001 From: Wenlong Gu Date: Thu, 8 Oct 2026 13:11:21 -0500 Subject: [PATCH 6/7] Expose eager activity execution acceptance --- openapi/openapiv2.json | 4 ++++ openapi/openapiv3.yaml | 5 +++++ temporal/api/activity/v1/message.proto | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/openapi/openapiv2.json b/openapi/openapiv2.json index f792cdbd1..2097b12c3 100644 --- a/openapi/openapiv2.json +++ b/openapi/openapiv2.json @@ -13930,6 +13930,10 @@ "propagatedNexusSerializationContext": { "$ref": "#/definitions/v1PropagatedSerializationContext", "description": "Serialization context propagated from the Nexus caller that started this activity." + }, + "eagerExecutionAccepted": { + "type": "boolean", + "description": "Indicates whether eager execution was requested for this activity and accepted by the server\nfor its first task." } }, "description": "Information about a standalone activity." diff --git a/openapi/openapiv3.yaml b/openapi/openapiv3.yaml index 31c6b0fe9..4c877cd6d 100644 --- a/openapi/openapiv3.yaml +++ b/openapi/openapiv3.yaml @@ -9919,6 +9919,11 @@ components: allOf: - $ref: '#/components/schemas/PropagatedSerializationContext' description: Serialization context propagated from the Nexus caller that started this activity. + eagerExecutionAccepted: + type: boolean + description: |- + Indicates whether eager execution was requested for this activity and accepted by the server + for its first task. description: Information about a standalone activity. ActivityExecutionListInfo: type: object diff --git a/temporal/api/activity/v1/message.proto b/temporal/api/activity/v1/message.proto index 862729526..13bb5ceee 100644 --- a/temporal/api/activity/v1/message.proto +++ b/temporal/api/activity/v1/message.proto @@ -199,6 +199,10 @@ message ActivityExecutionInfo { // Serialization context propagated from the Nexus caller that started this activity. temporal.api.nexus.v1.PropagatedSerializationContext propagated_nexus_serialization_context = 39; + + // Indicates whether eager execution was requested for this activity and accepted by the server + // for its first task. + bool eager_execution_accepted = 40; } // Limited activity information returned in the list response. From 1c1e0d33240831b2979b0e4a3072467ba139be00 Mon Sep 17 00:00:00 2001 From: Wenlong Gu Date: Thu, 8 Oct 2026 14:33:27 -0500 Subject: [PATCH 7/7] Retrigger CLA check