aws / aws/aws-durable-execution-sdk-python

[Feature]: Support caller-provided stable identity for durable operations

Open
#573 0 comments 0 reactions 1 assignee Claimed by @yaythomas View on GitHub
enhancement
Dominant language
Python
Stars
53
Forks
25
Avg merge
1d 17h
Merged PRs (30d)
37

Description

### 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:

```python
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

- Pydantic AI Harness AWS Lambda durability PR:
https://github.com/pydantic/pydantic-ai-harness/pull/417
- Detailed motivation from the AWS SDK example review:
https://github.com/aws/aws-durable-execution-sdk-python/pull/552#issuecomment-5052376056
- Current sequence-derived ID implementation:
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

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.