Skip to content

[runtime] Share execution identity across action state and graph calls - #1351

Merged
wenjin272 merged 1 commit into
apache:mainfrom
wenjin272:codex/shared-execution-identity
Nov 9, 2026
Merged

wenjin272 merged 1 commit into
apache:mainfrom
wenjin272:codex/shared-execution-identity

Conversation

@wenjin272

@wenjin272 wenjin272 commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Linked issue: #1084

Follow-up to #1342.

Purpose of change

Repeated equal-payload events in one input round must produce distinct chat/subagent calls as well as distinct durable action states. This follow-up applies the event occurrence identity to those calls and preserves it through suspension and recovery.

Runtime flow

RuntimeIdentity derives a root occurrence from the serialized business-key identity and input sequence, an Action execution ID from its triggering occurrence and action name, and an emitted occurrence from its producer execution and emission ordinal. ActionTaskContextManager binds the execution's emission counter and per-target call allocators to RunnerContextImpl on each task switch or continuation transfer.

Events receive identity before enqueueing, including subgraph bootstraps dispatched before their parent finishes. Completion-time memory observation and synthesized failure events receive identity before persistence/dispatch. ActionStateSerde saves occurrence metadata with both triggering and output events. Completed-action replay reuses those saved identities.

Key decisions

  • Put derivation in a shared runtime component so call allocation does not depend on ActionState storage.
  • Retain attributes in the ActionState event fingerprint for replay-divergence detection; use occurrence identity to distinguish equal-payload executions.
  • Generate call IDs from execution/target namespace, session ID and call ordinal, including caller-supplied sessions. A session ID alone cannot distinguish calls from different executions.
  • Require explicit occurrence metadata instead of a content-only fallback. Direct lower-level test fixtures now supply it.

Behavioral Semantics

Interaction decisions

Execution state Identity behavior
Persistence disabled Events and generated call IDs still use occurrence-based identity.
Persistence enabled, fresh call Bootstrap consumes an emission ordinal; completed outputs retain their IDs in ActionState.
Parent suspends/resumes The same emission and call counters continue across tasks, for continuation and parallel execution.
Unfinished parent restarts, earlier graph result cached Counters restart; replay still reserves the skipped bootstrap's ordinal before reusing its result.
Completed Action replayed Recorded output identities are preserved; filtered bootstrap events do not renumber remaining outputs.

Behavioral contracts

Distinct equal-payload occurrences produce distinct downstream execution and generated call identities. Repeating the same deterministic execution reproduces its identity sequence. Explicit sessions can be continued across executions without generated call-ID collisions. Durable serialization preserves event occurrence IDs; ordinary Event JSON continues to omit them.

Failure behavior

Missing occurrence metadata fails immediately rather than falling back to content. Ordinary Java emission rejects an event whose occurrence ID is already assigned. Negative emission ordinals are rejected. State serialization/deserialization errors continue to propagate through the existing durable-state failure handling. This change adds no retries or provider-error handling.

Tests

Contract Coverage
Equal-payload triggers and multiple waits remain distinct without persistence RuntimeIdentityIntegrationTest: chat/subagent, serial/parallel execution
Replay reproduces identity and explicit sessions remain execution/target scoped RuntimeIdentityTest, DeterministicIdAllocatorTest, BaseSubagentSetupTest
Cached graph results preserve subsequent emission ordinals ChatDurableFutureTest
Identity survives durable serialization but stays out of ordinary JSON ActionStateSerdeTest, EventTest
Existing recovery and content-divergence behavior remains valid ChatCallTest, InternalSubagentRecoveryTest, ActionStateDivergenceRecoveryTest, Kafka/Fluss recovery suites
Missing metadata, reused assigned events and negative ordinals fail ActionStateUtilTest, RuntimeIdentityTest

Validation after rebasing onto main with #1342 merged: clean JDK 21 API/MCP/Plan/Runtime reactor tests (3,080 tests, 81 skipped, no failures); clean JDK 11 focused regression build (189 tests, 19 skipped, no failures); Spotless and Apache RAT checks on a clean export of the committed tree.

Not verified: Python-only/cross-language E2E suites for this follow-up, external provider services, recovery across old/new ID formats. Deterministic emission/call order remains required; arbitrary user nondeterminism is not made replay-safe.

Implementation invariants and validation commands

The emission allocator belongs to a logical Action execution. RunnerContext holds the active reference; context transfer retains that reference and a fresh restarted execution constructs a new one. Length-prefixed hash components keep tuple boundaries unambiguous. Public Event JSON ignores occurrence metadata; the ActionState-specific Jackson mixin explicitly restores that property for durable serialization.

Targeted reactor builds use mvn ... -pl runtime -am to rebuild local API, MCP, Plan and Runtime artifacts together. The JDK 21 full run used -Dtest=*Test,Test*; JDK switches used clean to remove continuation overlays. The clean JDK 11 run covered event JSON, runtime identity, call allocation, ActionState keys/serialization/divergence, context transfer, chat/subagent recovery and Python action execution.

API

Public API signatures are unchanged. Internal identity utility/allocator signatures change. Root, emitted and generated call IDs change; no migration of old persisted keys or IDs is provided. Ordinary Java emission now rejects already-assigned Event instances. Java and Python calls use the shared runtime identity path; Python Event's JSON shape is unchanged.

Documentation

  • doc-needed
  • doc-not-needed
  • doc-included

Was this patch authored or co-authored using generative AI tooling?

  • Yes
  • No

Generated-by: Codex CLI 0.153.4 (GPT-6)

@github-actions github-actions Bot added doc-not-needed Your PR changes do not impact docs fixVersion/1.0.0 The feature or bug should be implemented/fixed in the 1.0.0 version. priority/major Default priority of the PR or issue. labels Nov 4, 2026
Follow up PR apache#1342 with a shared causal identity utility for event
occurrences and chat/subagent session and call allocation. Assign output
identities before dispatch and preserve counters across suspension and
cached-result replay. Persist occurrence metadata in ActionState JSON,
remove content-only fallbacks and obsolete comments.

Cover repeated identical triggers, multiple yields, explicit sessions,
durable serialization and replay. Update direct runtime test fixtures to
provide occurrence metadata explicitly.

Validation: JDK 21 API/Plan/MCP/Runtime test reactor; clean JDK 11 focused
regressions; Spotless and Apache RAT checks.

Generated-by: Codex CLI 0.153.4 (GPT-6)
Co-authored-by: Codex <codex@openai.com>
@wenjin272
wenjin272 force-pushed the codex/shared-execution-identity branch from cadac8f to 9d2282b Compare November 4, 2026 03:27
@wenjin272
wenjin272 marked this pull request as ready for review November 4, 2026 03:27
@github-actions github-actions Bot added doc-not-needed Your PR changes do not impact docs and removed doc-not-needed Your PR changes do not impact docs labels Nov 4, 2026
@wenjin272
wenjin272 merged commit c9da864 into apache:main Nov 9, 2026
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

doc-not-needed Your PR changes do not impact docs fixVersion/1.0.0 The feature or bug should be implemented/fixed in the 1.0.0 version. priority/major Default priority of the PR or issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant