What would you like?
Add an optional caller-provided stable identity for every durable operation
created through DurableContext, so logical work can map to the same checkpoint
independently of the order in which concurrent calls reach the SDK.
For example, operation APIs could consistently accept a logical key:
tool_result = context.step(
run_tool,
name="tool.fetch_weather",
key=tool_call_id,
)
context.wait(duration, name="rate-limit", key="provider-rate-limit")
context.invoke(function_name, payload, name="worker", key=request_id)
The exact parameter name and shape are open for design. A logical key that the
SDK scopes and hashes is preferable to accepting an arbitrary raw operation ID,
because the SDK can preserve service constraints, parent scoping, and collision
protection.
This should cover all public context APIs that create durable operations,
including step, wait, invoke, create_callback, run_in_child_context,
wait_for_callback, wait_for_condition, map, and parallel.
Today operation IDs are generally derived from the context's step-ID prefix and
a monotonically increasing invocation counter. The name is observability
metadata and does not provide identity. This makes concurrently scheduled
logical operations sensitive to scheduling order: if calls reach the SDK in a
different order during replay, they can be assigned one another's checkpoints.
The immediate use case is Pydantic AI durability. Tool calls have a stable
tool_call_id, but the AWS Lambda integration must currently force sequential
tool execution so operation ordering remains replay-compatible. Stable
caller-provided identity would allow those independent tool calls to remain
parallel. The same capability would help other async frameworks and workflow
adapters whose logical work already has deterministic IDs.
Desired properties:
- The same key in the same parent context deterministically produces the same
operation ID across replay.
- Keys are scoped by parent context and operation subtype.
- Concurrent keyed operations may be reached and complete in different orders.
- Duplicate use of a key within one context/invocation fails clearly.
- Keyed and existing sequence-identified operations can coexist.
- Omitting the key preserves current behavior and replay compatibility.
- Replay still validates operation subtype and relevant metadata consistently.
- Composite APIs propagate identity deterministically to the operation tree they
create.
map iterations and parallel branches have a way to use stable item/branch
identity when index-based identity is insufficient.
Possible Implementation
Extend the DurableContext protocol and implementation with a consistent
optional keyword such as key on operation-creating methods. A shared internal
operation-identity abstraction should avoid implementing subtly different
identity rules for each API.
For keyed operations, derive the operation ID from a versioned domain separator,
context step-ID prefix/parent, operation subtype, and caller key, using the SDK's
existing bounded hash format. Do not expose the raw service operation ID unless
there is a compelling need.
The replay-aware lookahead currently assumes that the next operation ID comes
from the sequence counter. It would need to accept the known keyed operation ID
when entering a keyed operation. The design should also decide whether keyed
operations consume the positional counter; not consuming it would keep unrelated
positional identities stable when keyed work is added or removed.
Operation trees need explicit identity semantics:
- For
run_in_child_context, the caller key can identify the outer operation
and child context, with nested operation IDs continuing to derive from that
stable parent.
- For
wait_for_callback, the caller key can identify its outer
RUN_IN_CHILD_CONTEXT operation, with callback internals deriving beneath
that stable parent.
- For
wait_for_condition, the caller key directly identifies the polling
operation.
- For
map, consider an item_key callback analogous to item_namer, but used
for identity rather than display.
- For
parallel, consider a key on ParallelBranch.
- Alternatively, define a smaller first phase that keys only the parent
map/parallel operation and clearly retains index-based child identity.
Suggested tests:
- Reaching the same keyed operations in opposite scheduling orders reuses the
correct checkpoints for every operation subtype.
- Keyed operations are distinct across parent contexts and operation subtypes.
- Duplicate keys are rejected.
- Keyed and positional operations can be mixed deterministically.
- Composite operations produce stable nested IDs.
- Reordered keyed map items and parallel branches reuse the intended
checkpoints when item/branch identity is enabled.
- Existing unkeyed executions retain their current operation IDs.
- Replay divergence still produces a clear error for incompatible operation
metadata.
Is this a breaking change?
No. The new identity input would be optional and existing operation calls would
retain their sequence-derived IDs.
Does this require an RFC?
Yes. It changes the operation identity model and interacts with replay-boundary
detection, concurrency, collision handling, and compatibility.
Additional Context
What would you like?
Add an optional caller-provided stable identity for every durable operation
created through
DurableContext, so logical work can map to the same checkpointindependently of the order in which concurrent calls reach the SDK.
For example, operation APIs could consistently accept a logical key:
The exact parameter name and shape are open for design. A logical
keythat theSDK scopes and hashes is preferable to accepting an arbitrary raw operation ID,
because the SDK can preserve service constraints, parent scoping, and collision
protection.
This should cover all public context APIs that create durable operations,
including
step,wait,invoke,create_callback,run_in_child_context,wait_for_callback,wait_for_condition,map, andparallel.Today operation IDs are generally derived from the context's step-ID prefix and
a monotonically increasing invocation counter. The
nameis observabilitymetadata and does not provide identity. This makes concurrently scheduled
logical operations sensitive to scheduling order: if calls reach the SDK in a
different order during replay, they can be assigned one another's checkpoints.
The immediate use case is Pydantic AI durability. Tool calls have a stable
tool_call_id, but the AWS Lambda integration must currently force sequentialtool execution so operation ordering remains replay-compatible. Stable
caller-provided identity would allow those independent tool calls to remain
parallel. The same capability would help other async frameworks and workflow
adapters whose logical work already has deterministic IDs.
Desired properties:
operation ID across replay.
create.
mapiterations andparallelbranches have a way to use stable item/branchidentity when index-based identity is insufficient.
Possible Implementation
Extend the
DurableContextprotocol and implementation with a consistentoptional keyword such as
keyon operation-creating methods. A shared internaloperation-identity abstraction should avoid implementing subtly different
identity rules for each API.
For keyed operations, derive the operation ID from a versioned domain separator,
context step-ID prefix/parent, operation subtype, and caller key, using the SDK's
existing bounded hash format. Do not expose the raw service operation ID unless
there is a compelling need.
The replay-aware lookahead currently assumes that the next operation ID comes
from the sequence counter. It would need to accept the known keyed operation ID
when entering a keyed operation. The design should also decide whether keyed
operations consume the positional counter; not consuming it would keep unrelated
positional identities stable when keyed work is added or removed.
Operation trees need explicit identity semantics:
run_in_child_context, the caller key can identify the outer operationand child context, with nested operation IDs continuing to derive from that
stable parent.
wait_for_callback, the caller key can identify its outerRUN_IN_CHILD_CONTEXToperation, with callback internals deriving beneaththat stable parent.
wait_for_condition, the caller key directly identifies the pollingoperation.
map, consider anitem_keycallback analogous toitem_namer, but usedfor identity rather than display.
parallel, consider a key onParallelBranch.map/paralleloperation and clearly retains index-based child identity.Suggested tests:
correct checkpoints for every operation subtype.
checkpoints when item/branch identity is enabled.
metadata.
Is this a breaking change?
No. The new identity input would be optional and existing operation calls would
retain their sequence-derived IDs.
Does this require an RFC?
Yes. It changes the operation identity model and interacts with replay-boundary
detection, concurrency, collision handling, and compatibility.
Additional Context
feat(aws-lambda): AWSLambdaDurability for AWS Lambda durable functions pydantic/pydantic-ai-harness#417
Add Pydantic AI Durable Capability Example #552 (comment)
https://github.com/aws/aws-durable-execution-sdk-python/blob/main/packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/context.py