mirror of
https://github.com/run-llama/workflows-py.git
synced 2026-07-21 04:05:25 -04:00
[Question]: Race condition between step and wait_for_event #16
Closed
opened 2026-02-16 02:16:06 -05:00 by yindo
·
7 comments
No Branch/Tag Specified
main
update-debugger-assets
changeset-release/main
adrianbot/mlflow-workflow-tracing-tests
adrianbot/child-workflows-recursive
adrianbot/cw-stack-3-alive-timeout
adrianbot/cw-stack-1-broker-tree
adrian/child-workflows-slim
adrian/llamactl-organizations-use
adrianbot/mlflow-dbos-e2e
adrian/child-workflows-runtime-compat
adrian/child-workflows-durable
adrian/child-workflows
adrian/child-workflow-prep-refactors
adrian/child-workflows-page
adrian/child-workflows-docs
adrian/fan-out-fan-in-l0
claude/centralize-instance-checks-y7ogi1
adrian/fan-out-async-iterator
adrianbot/statedb-go-binary
adrian/workflow-pressure-diagnostics
chore/fix-lint-594
adrian/llamactl-get-split
claude/simplify-mapreduce-syntax-2CPyP
claude/setup-python-311-env-3BfmE
claude/plan-operator-namespace-jzsmq
vasu/retryable_exceptions
chore/fix-lint-525
logan/error-handling
claude/fix-handler-idle-state-SCxQj
claude/organize-examples-KJFTa
clelia/agentcore-memory
adrian/issue-404
changeset-release/dev
adrian/multi-result
claude/fix-database-locked-tests-d2yrv
quickstart
claude/slack-feedback-notification-PehCn
claude/add-durable-workflow-example-YnY23
claude/add-runtime-decorator-abstractions-UJNsv
adrian/mcp
chore/fix-lint-330
adrian/server-decorator
chore/fix-lint-323
claude/test-precommit-fix-sACsb
adrian/store-interface
claude/resolve-package-conflicts-dV32a
claude/add-dbos-test-suite-v0yfb
adrian/wf-registry
claude/relative-workflow-paths-RGVg8
claude/refactor-workflows-server-package-hqICG
claude/release-idle-workflows-VaCpR
logan/child_workflows
logan/building_blocks
adrian/handler-id-quote-issue-53e3
cursor/LI-4612-implement-dedicated-stop-event-subtypes-for-failures-86ee
adrian/test-ctx
cursor/LI-4463-implement-lazy-file-reference-system-b1b3
copilot/sub-pr-202
cursor/LI-3952-generate-workflow-server-reference-docs-0107
cursor/LI-4105-update-wait-for-event-documentation-3bdd
clelia/golden-examples
cursor/LI-3867-refactor-event-api-for-consistency-and-flexibility-dc87
logan/attach_sequence_number_to_events
logan/handler_metadata
adrian/version-bump
cursor/LI-3715-stop-workflow-handler-and-cancel-tasks-807e
cursor/LI-3710-prevent-workflow-server-crash-on-invalid-reload-3421
cursor/LI-3716-filter-internal-events-in-workflow-consumer-eb17
massi/api-reference
clelia/gather-in-step-decorator
v1.3.1
logan/typed_state_poc
llama-agents-server@v0.6.4
llama-agents-server@0.6.4
llama-agents@0.12.5
llama-agents-control-plane@0.12.3
llama-agents-server@0.6.3
llama-agents-server@v0.6.3
llama-index-workflows@2.22.2
llama-agents-client@0.3.11
llama-agents-server@v0.6.2
llama-agents-client@0.3.10
llama-index-workflows@2.22.1
llama-agents-server@0.6.2
llama-agents-dbos@0.4.1
llama-agents-server@v0.6.1
llama-index-workflows@2.22.0
llama-agents-client@0.3.9
llama-agents-server@0.6.1
llama-index-utils-workflow@0.11.0
llamactl@0.10.3
llama-agents-server@0.6.0
llama-index-workflows@2.21.0
llama-agents-dbos@0.4.0
llama-agents-server@v0.6.0
llama-agents-appserver@0.11.5
llama-agents-agentcore@0.9.4
llama-agents@0.12.4
llama-agents-client@0.3.8
llamactl@0.10.2
llamactl@0.10.1
llamactl@0.10.0
llama-agents-control-plane@0.12.2
llama-agents-appserver@0.11.4
llama-agents@0.12.3
llama-agents-agentcore@0.9.3
llama-agents-core@0.10.2
llama-agents-dbos@0.3.1
llama-agents-dbos@0.3.0
llamactl@0.9.1
llama-agents-server@0.5.0
llama-agents-core@0.10.1
llamactl@0.9.0
llama-agents-control-plane@0.12.1
llama-agents-appserver@0.11.3
llama-agents-agentcore@0.9.2
llama-agents-server@v0.5.0
llama-agents@0.12.2
llama-agents-dbos@0.2.3
llama-agents@0.12.1
llama-agents-appserver@0.11.2
llama-agents-core@0.10.0
llama-agents-agentcore@0.9.1
llamactl@0.8.0
llama-agents-control-plane@0.12.0
llamactl@0.7.3
llama-index-workflows@2.20.0
llama-agents@0.12.0
llama-agents-server@v0.4.7
llama-agents-server@0.4.7
llama-agents-client@0.3.7
llamactl@0.7.2
llama-index-workflows@2.19.1
llama-agents-client@0.3.6
llama-agents-agentcore@0.9.0
llama-agents-appserver@0.11.1
llama-agents-server@v0.4.6
llama-agents-dbos@0.2.2
llama-agents-server@0.4.6
llama-agents@0.11.1
llama-agents-appserver@0.11.0
llama-agents-control-plane@0.11.1
llama-agents-agentcore@0.8.19
llamactl@0.7.1
llama-agents@0.11.0
llama-agents-operator@0.11.1
llama-agents-agentcore@0.8.18
llama-agents-crds@0.7.2
llama-agents@0.10.12
llama-agents-server@v0.4.5
llama-agents-client@0.3.5
llama-agents-server@0.4.5
llama-index-workflows@2.19.0
llamactl@0.7.0
llama-agents-core@0.9.0
llama-agents-appserver@0.10.5
llama-agents-server@0.4.4
llama-agents-control-plane@0.11.0
llama-agents-client@0.3.4
llama-index-workflows@2.18.0
llama-agents@0.10.11
llama-agents-agentcore@0.8.17
llama-agents-server@v0.4.4
llama-agents-agentcore@0.8.16
llama-agents-agentcore@0.8.15
llama-agents-server@0.4.3
llama-agents-server@v0.4.3
llama-agents-core@0.8.5
llamactl@0.6.9
llama-agents-control-plane@0.10.5
llama-agents-appserver@0.10.4
llama-agents-agentcore@0.8.14
llama-agents@0.10.10
llama-agents-server@0.4.2
llama-agents-agentcore@0.8.13
llama-agents-server@v0.4.2
llama-agents-appserver@0.10.3
llamactl@0.6.8
llama-agents@0.10.9
llama-agents-agentcore@0.8.12
llama-agents@0.10.8
llamactl@0.6.7
llama-agents-control-plane@0.10.4
llama-agents-agentcore@0.8.11
llama-agents-server@0.4.1
llama-agents-server@v0.4.1
llama-agents-agentcore@0.8.10
llama-agents-agentcore@0.8.9
llama-agents-agentcore@0.8.8
llama-index-workflows@2.17.3
llama-agents-server@0.4.0
llama-agents-client@0.3.3
llama-index-workflows@2.17.2
llama-agents-server@0.3.3
llama-agents-client@0.3.2
llama-agents-server@v0.3.2
llama-agents-server@0.3.2
llama-agents-dbos@0.2.1
llama-index-workflows@2.17.1
llama-agents-server@0.3.1
llama-agents-server@v0.3.1
llama-index-utils-workflow@0.10.1
llama-agents-client@0.3.1
llama-index-utils-workflow@0.10.0
llama-agents-dbos@0.2.0
llama-agents-client@0.3.0
llama-agents-server@v0.3.0
llama-agents-server@0.3.0
llama-index-workflows@2.17.0
llama-agents-server@v0.2.3
llama-agents-server@0.2.3
llama-agents-client@0.2.3
llama-index-workflows@2.16.1
llama-index-workflows@2.16.0
llama-index-utils-workflow@0.9.5
llama-agents-dbos@0.1.2
llama-agents-server@v0.2.2
llama-agents-client@0.2.2
llama-agents-server@0.2.2
llama-index-workflows@2.15.1
llama-agents-client@0.2.1
llama-agents-server@0.2.1
llama-agents-dbos@0.1.1
llama-index-utils-workflow@0.9.4
llama-agents-server@v0.2.1
llama-index-utils-workflow@0.9.3
llama-index-workflows@2.15.0
llama-agents-dbos@0.1.0
llama-agents-server@v0.2.0
llama-agents-server@0.2.0
llama-agents-client@0.2.0
llama-index-workflows@2.15.0-rc.1
llama-agents-client@0.2.0-rc.1
llama-index-utils-workflow@0.9.3-rc.1
llama-agents-server@0.2.0-rc.3
llama-agents-dbos@0.1.0-rc.1
llama-agents-server@0.1.3
llama-index-utils-workflow@0.9.2
llama-agents-server@v0.1.3
llama-agents-client@0.1.3
llama-index-workflows@2.14.2
llama-agents-server@0.2.0-rc.2
llama-agents-dbos@0.1.0-rc.0
llama-agents-server@0.2.0-rc.1
llama-agents-client@0.2.0-rc.0
llama-index-utils-workflow@0.9.2-rc.0
llama-index-workflows@2.15.0-rc.0
llama-agents-server@0.2.0-rc.0
llama-agents-server@v0.2.0-rc.0
llama-agents-client@0.1.2
llama-index-utils-workflow@0.9.1
llama-index-workflows@2.14.1
llama-agents-server@v0.1.2
llama-agents-server@0.1.2
llama-agents-server@v0.1.1
llama-index-utils-workflow@0.9.0
llama-agents-client@0.1.1
llama-agents-server@0.1.1
llama-index-workflows@2.14.0
llama-index-workflows@2.13.1
llama-index-workflows@v2.13.1
llama-index-workflows@2.13.0
llama-index-utils-workflow@0.8.0
llama-index-workflows@v2.13.0
llama-index-workflows@2.12.2
llama-index-workflows@v2.12.2
llama-index-utils-workflow@0.7.1
llama-index-workflows@v2.12.1
llama-index-workflows@2.12.1
llama-index-workflows@2.12.0
llama-index-utils-workflow@0.7.0
llama-index-workflows@v2.12.0
llama-index-utils-workflow@0.6.0
llama-index-workflows@v2.11.7
llama-index-workflows@2.11.7
llama-index-workflows@v2.11.6
llama-index-workflows@2.11.6
llama-index-utils-workflow@0.5.2
llama-index-workflows@2.11.5
llama-index-workflows@v2.11.5
llama-index-workflows@v2.11.4
llama-index-workflows@2.11.4
llama-index-utils-workflow@0.5.1
llama-index-workflows@2.11.3
llama-index-workflows@v2.11.3
llama-index-workflows@2.11.2
llama-index-utils-workflow@0.5.0
llama-index-workflows@v2.11.2
llama-index-workflows@v2.11.1
v2.11.1
v2.11.0
v2.10.3
v2.10.2
v2.10.1
v2.10.0
v2.9.1
v2.9.0
llama-index-utils-workflow@v0.5.0
v2.8.3
v2.8.2
v2.8.1
v2.8.0
v2.7.1
v2.7.0
v2.6.0
v2.5.0
v2.4.0
v2.3.0
v2.2.2
v2.2.1
v2.2.0
v2.1.0
v2.0.1
v2.0.0
v1.3.0
v1.2.0
v1.1.0
v1.0.1
v1.0.0
v0.2.2
v0.2.1
v0.2.0
v0.1.0
Milestone
No items
No Milestone
Projects
Clear projects
No project
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: run-llama/workflows-py#16
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @mrityu-jha on GitHub (Aug 31, 2025).
Question Validation
Question
I wanted to understand the intended behavior for the below case:
If step A is awaiting on wait_for_event(HumanResponseEvent, ..) but we also have step B which accepts HumanResponseEvent.
In this case, once we do ctx.send_event(HumanResponseEvent()) is it guaranteed that wait_for_event will receive it always?
I tried a couple of times and everytime the response was received by awaiting event itself.
@dosubot[bot] commented on GitHub (Aug 31, 2025):
When you use
ctx.send_event(HumanResponseEvent())and have one step awaitingwait_for_event(HumanResponseEvent, ...)while another step also acceptsHumanResponseEvent, the event will be delivered to the step awaitingwait_for_event—but only one consumer will actually receive it. This is by design: events are queued and dispatched to waiting steps, but unless the event is broadcasted, only one consumer (the first to await) will consume it. This means that if step A is awaitingwait_for_event, it will reliably receive the event, and step B (if not awaiting) will not consume it in parallel. This behavior is robust and has been tested to avoid race conditions between steps and event delivery, with recent fixes ensuring proper queue management and event dispatching source.If you want multiple steps to process the same event, you should design your workflow so that both steps are triggered by the event independently, rather than relying on
wait_for_eventin both places. If you encounter unexpected behavior, make sure you are on a recent version, as there were previous bugs with event consumption that have since been fixed source.To reply, just mention @dosu.
How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

@mrityu-jha commented on GitHub (Aug 31, 2025):
@dosu unable to follow here.
As per my understanding, step B registers itself at initialization itself that it can accept HumanResponseEvent. And since the event queue is shared, how is it being ensured that step A (wait_for_event) will always get it?
@dosubot[bot] commented on GitHub (Aug 31, 2025):
Great question! The current design is that when you send a
HumanResponseEvent, only one consumer will receive it—either a step awaitingwait_for_eventor a step registered to accept the event, but not both. If step A is actively awaitingwait_for_event(HumanResponseEvent, ...), it will reliably get the event, and step B (registered at initialization) will not consume it in parallel. This is becausewait_for_eventconsumes the event from the shared queue as soon as it matches, removing it so other consumers can't see it. This behavior is intentional, but there are known bugs and ongoing work to improve how multiple consumers can observe events (see discussion and maintainer comment). If you want multiple steps to process the same event, you'll need to design your workflow so each step is triggered independently, or wait for future updates that may change this behavior.To reply, just mention @dosu.
How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

@mrityu-jha commented on GitHub (Aug 31, 2025):
From the code what I have understood is,
send_event(..)puts the given event in all the queues if step is not mentioned, each step then discards this event if it doesn't accept it.wait_for_eventcreate a new entry inself._queueswithwaiter_idas key and start waiting on it with the specified event type.By above understanding, it seems that step B will also receive this HumanResponseEvent.
@dosu
@logan-markewich commented on GitHub (Aug 31, 2025):
@mrityu-jha in the case you are describing, both would get the event. This is why its helpful to subclass HumanResponseEvent to customize and control the event flow further
@logan-markewich commented on GitHub (Aug 31, 2025):
Alternatively, you can add some tag or ID to the HumanResponseEvent so that your workflow knows when/how to process it
Really it's just a matter of understanding how the workflow works (which it sounds like you do) and designing your code appropriately for that
@mrityu-jha commented on GitHub (Aug 31, 2025):
thanks @logan-markewich for confirming.