Skip to content

Add support for workflow history propagation #1737

@cicoyle

Description

@cicoyle

Background

Dapr Workflows now supports propagating execution history from a parent workflow to its child workflows and activities. This lets downstream code inspect what happened upstream — useful for chain-of-custody verification, fraud detection, audit, and AI-agent context flow.

Two scopes are exposed:

  • PropagateLineage — caller's own events plus the full ancestor chain
  • PropagateOwnHistory — caller's events only (a trust boundary; ancestors are dropped)

The Go path is implemented end-to-end. To use this feature from a Java app, this SDK needs the matching API.

Proto surface

From dapr/durabletask-protobuf (PR #38):

  • history_events.proto
    • TaskScheduledEvent.historyPropagationScope (optional, field 7)
    • ChildWorkflowInstanceCreatedEvent.historyPropagationScope (optional, field 7)
    • new PropagatedHistory { repeated HistoryEvent events; HistoryPropagationScope scope; repeated PropagatedHistoryChunk chunks; }
    • new PropagatedHistoryChunk { string appId; int32 startEventIndex; int32 eventCount; string instanceId; string workflowName; }
  • orchestration.proto
    • new HistoryPropagationScope enum: HISTORY_PROPAGATION_SCOPE_NONE = 0, HISTORY_PROPAGATION_SCOPE_OWN_HISTORY = 1, HISTORY_PROPAGATION_SCOPE_LINEAGE = 2
  • orchestrator_actions.proto
    • ScheduleTaskAction.historyPropagationScope (optional, field 6)
    • CreateChildWorkflowAction.historyPropagationScope (optional, field 6)

What needs to happen here

1. Proto regen + plumbing

  • Pull the updated .proto files from dapr/durabletask-protobuf and regenerate the Java protobuf classes
  • Plumb the new historyPropagationScope field through the schedule-task / create-child-workflow code paths
  • Surface the received PropagatedHistory to the workflow runtime so it can be handed to user code

2. User-facing API to add

Schedule-side (parent workflow author):

  • WithHistoryPropagation(scope) builder option on CallActivity / CallChildWorkflow
  • PropagateLineage() and PropagateOwnHistory() static factories returning a scope value

Receive-side (child workflow / activity author):

  • getPropagatedHistory() returning Optional<PropagatedHistory> on both WorkflowContext and ActivityContext
  • PropagatedHistory class with:
    • getEvents() — list of HistoryEvent
    • getScope() — the scope enum value
    • getWorkflows() — chunks (each with appId, workflowName, instanceId, startEventIndex, eventCount)
    • getAppIDs() — deduplicated list of app IDs in the chain
    • convenience filters: getWorkflowByName(name), getEventsByAppID(appId), getEventsByInstanceID(id), getEventsByWorkflowName(name)
    • throws PropagationNotFoundException (or returns empty Optional) for missing names

3. Example to add

examples/workflow-history-propagation/ mirroring the Go demo: a 3-tier payment workflow (parent → activity → child workflow with PropagateLineage → activity with PropagateOwnHistory). Standalone dapr run mode at minimum; K8s + signing variant a stretch.

4. Tests

At least one test per scope:

  • Lineage: parent → child receives parent's events
  • OwnHistory: parent → child receives caller's events but NOT grandparent's

AI bootstrap prompt

Paste the following into Claude/Cursor with the dapr/java-sdk repo open:

I'm adding workflow history propagation to dapr/java-sdk. The Go reference implementation is at https://github.com/dapr/go-sdk/tree/main/examples/workflow-history-propagation (PR dapr/go-sdk#823). The proto surface I need to support is in dapr/durabletask-protobuf PR dapr/durabletask-protobuf#38TaskScheduledEvent.historyPropagationScope, ChildWorkflowInstanceCreatedEvent.historyPropagationScope, HistoryPropagationScope enum, PropagatedHistory + PropagatedHistoryChunk messages. The durabletask Java is colocated in this repo, so all changes happen here. Tasks: (1) regen the Java protobuf classes from the updated .proto files and plumb the new historyPropagationScope field through the schedule-task / create-child-workflow paths; (2) add a WithHistoryPropagation(scope) builder option on CallActivity/CallChildWorkflow with PropagateLineage() and PropagateOwnHistory() static factories; (3) add getPropagatedHistory() returning Optional<PropagatedHistory> on both WorkflowContext and ActivityContext; (4) implement PropagatedHistory with getters getEvents(), getScope(), getWorkflows(), getAppIDs(), plus name/appId/instanceId filters; (5) add an examples/workflow-history-propagation/ matching the Go example shape (parent → activity → child wf with Lineage → activity with OwnHistory); (6) add a unit/integration test covering both scopes. Use Java idioms — Optional, builder pattern, checked exceptions where natural. Don't break existing API.

References

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions