Link automation.action.* events to automation.triggered event#169
Conversation
When debugging automation failures at high volumes, it's difficult to trace from an `automation.action.failed` event back to the `automation.triggered` event that spawned it. This adds an `automation_triggered_event_id` field to `TriggeredAction` and includes it as a related resource with role `automation-triggered-event` on all action events (`.triggered`, `.executed`, and `.failed`). Port of https://github.com/PrefectHQ/nebula/pull/10911 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The triggering-event related resource should appear on all three action event types (.triggered, .executed, .failed) to enable full traceability. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Now that automation.action.executed and automation.action.failed events include a triggering-event related resource, update the tests to expect it in their assertions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Build related_resources once at the start of fail() and succeed() methods and reuse it for both the .triggered and .failed/.executed events, rather than building separate lists with identical logic. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add a brief section to the automations docs explaining the events emitted during automation execution and the related resources (triggering-event and automation-triggered-event) available for tracing action failures back to their source. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Review Summary by QodoLink automation.action.* events to automation.triggered event for improved traceability
WalkthroughsDescription• Add automation_triggered_event_id field to link action events to triggering automation event • Include automation-triggered-event related resource on all action events (.triggered, .executed, .failed) • Refactor related_resources building to avoid duplication in fail() and succeed() methods • Update all action tests to verify triggering-event and automation-triggered-event related resources • Add documentation explaining automation event tracing and related resource links Diagramflowchart LR
A["automation.triggered/<br/>automation.resolved event"] -->|automation_triggered_event_id| B["TriggeredAction"]
B -->|includes related resource| C["automation.action.triggered"]
B -->|includes related resource| D["automation.action.executed/<br/>automation.action.failed"]
C -->|automation-triggered-event role| A
D -->|automation-triggered-event role| A
B -->|includes related resource| E["triggering-event"]
C -->|triggering-event role| E
D -->|triggering-event role| E
File Changes1. src/prefect/server/events/schemas/automations.py
|
Code Review by Qodo
1. triggers.py lacks future annotations
|
| source_actions: List[ | ||
| Tuple[Optional[ReceivedEvent], ServerActionTypes, UUID | None] | ||
| ] = [ |
There was a problem hiding this comment.
1. triggers.py lacks future annotations 📘 Rule violation ✓ Correctness
src/prefect/server/events/triggers.py contains type annotations but does not include `from __future__ import annotations` as the first import. This violates the required typing setup and can lead to inconsistent annotation behavior across the codebase.
Agent Prompt
## Issue description
`src/prefect/server/events/triggers.py` contains type annotations but is missing `from __future__ import annotations` as the first import.
## Issue Context
Compliance requires this future import in all `src/` Python files that contain type annotations.
## Fix Focus Areas
- src/prefect/server/events/triggers.py[1-20]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| @field_validator("automation_triggered_event_id") | ||
| @classmethod | ||
| def validate_automation_triggered_event_id(cls, v, info): | ||
| """Ensure automation_triggered_event_id is only set when triggering_event exists.""" | ||
| if v is not None and info.data.get("triggering_event") is None: | ||
| raise ValueError( | ||
| "automation_triggered_event_id can only be set when triggering_event is provided" | ||
| ) | ||
| return v |
There was a problem hiding this comment.
2. automation_triggered_event_id uses field_validator 📘 Rule violation ✓ Correctness
The new validation for automation_triggered_event_id uses a @field_validator while depending on another field (triggering_event). This is cross-field validation and should be implemented with @model_validator to avoid order-dependent behavior.
Agent Prompt
## Issue description
`TriggeredAction.validate_automation_triggered_event_id` is implemented as a `@field_validator` but performs cross-field validation by depending on `triggering_event`.
## Issue Context
Compliance requires cross-field validation to use Pydantic v2 `@model_validator` to ensure correct sequencing and avoid reading partially-validated fields.
## Fix Focus Areas
- src/prefect/server/events/schemas/automations.py[763-780]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| occurred=triggered_action.triggered, | ||
| event="prefect.automation.action.triggered", | ||
| resource=resource, | ||
| related=related_resources, | ||
| related=self._resulting_related_resources, | ||
| payload=action_details, | ||
| id=triggered_event_id, | ||
| follows=follows_id, |
There was a problem hiding this comment.
3. Fail event drops related 🐞 Bug ✓ Correctness
In Action.fail, the code constructs related_resources (including automation-triggered-event and triggering-event) but emits prefect.automation.action.triggered with related=self._resulting_related_resources, omitting the new links and contradicting success-path behavior.
Agent Prompt
### Issue description
`Action.fail()` builds an augmented `related_resources` list (including `automation-triggered-event` and `triggering-event`) but emits the `prefect.automation.action.triggered` event with `related=self._resulting_related_resources`, dropping those links.
### Issue Context
This makes failure-path `action.triggered` events inconsistent with success-path behavior and with the updated tests expecting a `triggering-event` related resource.
### Fix Focus Areas
- src/prefect/server/events/actions.py[197-207]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| automation_triggered_event_id: UUID | None = Field( | ||
| default=None, | ||
| description=( | ||
| "The ID of the automation.triggered or automation.resolved event that " | ||
| "prompted this action, used to link automation.action.* events back to " | ||
| "the state change event" | ||
| ), | ||
| ) | ||
|
|
||
| @field_validator("automation_triggered_event_id") | ||
| @classmethod | ||
| def validate_automation_triggered_event_id(cls, v, info): | ||
| """Ensure automation_triggered_event_id is only set when triggering_event exists.""" | ||
| if v is not None and info.data.get("triggering_event") is None: | ||
| raise ValueError( | ||
| "automation_triggered_event_id can only be set when triggering_event is provided" | ||
| ) | ||
| return v |
There was a problem hiding this comment.
4. Proactive actions validation crash 🐞 Bug ✓ Correctness
TriggeredAction now forbids setting automation_triggered_event_id when triggering_event is null, but triggers.act() sets automation_triggered_event_id from the generated automation state-change event even for proactive firings where triggering_event can be null, causing TriggeredAction creation/parsing to raise ValueError.
Agent Prompt
### Issue description
`TriggeredAction.automation_triggered_event_id` validation rejects the valid combination of `automation_triggered_event_id != None` with `triggering_event == None`, but `triggers.act()` sets `automation_triggered_event_id` from the generated automation state-change event id even for proactive firings where `triggering_event` may be null.
### Issue Context
This will raise during `TriggeredAction(...)` creation in `triggers.act()` and/or during message parsing in the actions consumer, breaking proactive-trigger automations.
### Fix Focus Areas
- src/prefect/server/events/schemas/automations.py[763-780]
- src/prefect/server/events/triggers.py[439-488]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Benchmark PR from agentic-review-benchmarks#2