Skip to content

[Tech Debt][API][Event] Enforce framework-owned lineage at the event emission boundary #1192

Closed

Description

@wenjin272

Search before asking

  • I searched existing issues for duplicates; related work is linked below where applicable.

Description

This is a child issue of #1055.

Problem

Event identity and lineage are framework metadata, but callers can populate upstreamEventId/upstreamActionName (Python: upstream_event_id/upstream_action_name) before emission. ActionTask.finalizeOutputEvents currently overwrites existing lineage, including during replay. Silent replacement obscures the public contract and lets invalid user declarations pass the send boundary.

Python Event IDs are immutable, but assignment errors only provide the generic frozen-field diagnostic rather than guidance for reconstructing an Event with an existing identity.

Proposed direction

  • Validate user-originated emission in Java/Python sendEvent/send_event and reject prepopulated framework-owned lineage with an actionable error. User business metadata belongs in attributes.
  • Preserve the existing output-versus-trigger identity invariant and align its behavior across native and cross-language paths.
  • Keep legitimate deserialization, replay, and typed reconstruction able to preserve identity and lineage. Distinguish these internal paths from a new user emission; do not apply a blanket rejection to restored framework events.
  • For Python immutable-ID assignment, explain when to use reconstruct_from(event) instead of only reporting Field is frozen.

Acceptance criteria

  • Preset lineage fails clearly at user emission instead of being silently overwritten; valid emissions receive correct framework lineage.
  • Java/Python and cross-language tests cover normal emission, invalid identity/lineage, typed reconstruction, and recovery/replay.
  • Documentation distinguishes framework identity/lineage, user attributes, and reconstruction.

Related: #1125 covers built-in event restoration; this issue covers ownership and validation at emission.

Relevant code: Java/Python Event, RunnerContext implementations, and runtime/.../operator/ActionTask.java.

Are you willing to submit a PR?

  • I'm willing to submit a PR!

Activity

  1. added
    tech debt[Issue Type] User-unaware issues, such as code refactor and infrastructure maintenance.
    priority/majorDefault priority of the PR or issue.
    on Oct 3, 2026
  2. sangkyoonnam commented on Oct 8, 2026

    @sangkyoonnam
    Contributor

    I'd like to take this one, following #1197 in the same #1055 set.

    The check would go in RunnerContextImpl.sendEvent, which every user emission reaches, Python included through sendEventJson. An event that arrives there with upstreamEventId or upstreamActionName set fails with an error that points to attributes. ActionTask.finalizeOutputEvents keeps binding lineage as it does today. Outputs restored from the action state don't go through sendEvent: they keep their IDs, and finalizeOutputEvents binds their lineage to the replayed trigger. The operator sets AgentRunBeginEvent's lineage itself. Python's send_event would run the same check before serializing, so the error names the Python field, and the frozen-ID error would mention reconstruct_from.

    A typed reconstruction (fromEvent/reconstruct_from) keeps the source's ID and lineage, so sending one that carries lineage is rejected too; one without lineage still meets the existing self-loop check at finalization if it is the trigger. The docs would say that a new emission starts from a fresh event. Could you assign it to me?

  3. wenjin272 commented on Oct 9, 2026

    @wenjin272
    ContributorAuthor

    Thanks for picking this up. The proposed approach sounds good to me. Looking forward to the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

fixVersion/0.4.0priority/majorDefault priority of the PR or issue.tech debt[Issue Type] User-unaware issues, such as code refactor and infrastructure maintenance.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions