Skip to content

[Feature]: Custom subtype for step, callback, and child context operations #749

Open

Description

@ParidelPooya

What would you like?

Let a caller set a custom subtype on a step, a callback, and a child context.

  1. A function can compose several durable operations into one larger operation.
  2. Every operation records a subtype in its checkpoint. Execution history and plugins read it.
  3. In Python, StepConfig and CallbackConfig have no subtype field. ChildConfig.sub_type exists, but it is typed as the OperationSubType enum, and its docstring says the execution engine uses it internally.
  4. So the parts of a composed operation all record Step, Callback, or RunInChildContext. History and plugins can tell them apart only by parsing their names.

The JS SDK supports this today: ChildConfig.subType, and since aws/aws-durable-execution-sdk-js#939, StepConfig.subType and CreateCallbackConfig.subType. The Go SDK has WithChildSubType.

Possible Implementation

  1. Add sub_type: str | None = None to StepConfig and CallbackConfig. Widen ChildConfig.sub_type to accept a str as well as an OperationSubType.
  2. Three places assume that every subtype is an enum value. Each would fail on a custom subtype:
    • OperationType.from_sub_type raises ValueError for an unknown subtype. OperationIdentifier uses it to derive the operation type. So the identifier needs the operation type passed in.
    • Operation.from_dict in lambda_service.py parses SubType with OperationSubType(...). An execution that recorded a custom subtype then fails to load its own state on the next invocation. So parsing must keep an unknown subtype as a string.
    • Serialization writes self.sub_type.value. It must also accept a string.
  3. Use the custom subtype in checkpoint updates, replay validation, and plugin events.
  4. Validate the value before the operation is created:
    • None or an empty string selects the default.
    • The service accepts 1 to 32 characters from [a-zA-Z0-9-_]. It rejects any other subtype with HTTP 400 ValidationException, and the execution then fails. So the SDK should reject such a value with a clear error.
    • Optionally reject the values the SDK uses for its own operations, as the Go SDK does.
  5. Optionally, make the local checkpoint server in aws-durable-execution-sdk-python-testing reject an invalid subtype with the service's message. It already rejects a subtype that changes between updates of one operation. The JS testing SDK does this since feat(sdk): add subType to step and createCallback aws-durable-execution-sdk-js#939.

Nothing in the SDK decides how to suspend or retry from the subtype. So no other logic needs to change.

Is this a breaking change?

No. Without the option, the SDK records the same subtypes as today. Code that passes an OperationSubType to ChildConfig.sub_type keeps working.

Does this require an RFC?

No.

Additional Context

  • Replay compares the subtype with the checkpoint. So changing a subtype is a breaking change for executions in flight. The docstrings should say this.
  • Step 2 is a prerequisite. Without it, the first custom subtype makes the next invocation fail while it loads state.

Activity

  1. added
    pkg:sdkPackage: aws-durable-execution-sdk-python
    and removed on Oct 1, 2026
  2. yaythomas commented on Oct 13, 2026

    @yaythomas
    Contributor

    implementation suggestion following the prep work in #768 that removes the code that worked out the operation type from the subtype.

    1. Subtype fields are typed str | None. This covers Operation, OperationUpdate, ChildConfig, the plugin info classes, the testing package's Operation, and the new sub_type options on StepConfig and CallbackConfig.

    2. OperationSubType becomes a StrEnum. It lists only the subtypes the SDK records for its own operations. Its members are strings, so they fit the str fields.

    3. Loading state keeps any subtype string. An SDK subtype loads as its OperationSubType member. Any other value loads as a plain string.

    4. Validation. In step, create_callback, and run_in_child_context, a sub_type of None or "" selects the operation's default subtype. Any other value raises ValidationError before the operation starts if it:

      • is not 1 to 32 characters from [a-zA-Z0-9-_], or
      • is the subtype of a different SDK operation, such as "Map" on a step.

      For ChildConfig.sub_type, the second rule is a change: today that field accepts any SDK subtype.

    5. Plugins. A custom subtype is a plain string, so it has no .value. Plugins should read subtypes as strings. The OTel and insight plugins and the testing package will be changed to do that.

    We won't merge #762. With #762, OperationSubType("anything") returns a member, so an OperationSubType value is no longer always one of the SDK's subtypes. Item 3 replaces its fix for loading unknown subtypes.

    # operation: any Operation in the execution state
    operation.sub_type                          # a str, or None if no subtype was recorded
    operation.sub_type == OperationSubType.MAP  # True for the operation that context.map() records
    operation.sub_type == "OrderSaga"           # True for a child context run with ChildConfig(sub_type="OrderSaga")
  3. yaythomas commented on Oct 13, 2026

    @yaythomas
    Contributor

    for the dependency packages,

    • OTel, in execution_plugin.py and invocation_plugin.py: replace info.sub_type.value with getattr(info.sub_type, "value", info.sub_type).
    • Testing, in model.py: make the same replacement in the sub_type property. In the two places that parse with OperationSubType(...), keep the raw string when the value isn't a member.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpkg:sdkPackage: aws-durable-execution-sdk-python

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions