|
In agent_framework_ag_ui._workflow_run.py:L968, executor activities use yield ActivitySnapshotEvent(
message_id=f"executor:{executor_id}" if executor_id else generate_event_id(),
activity_type="executor",
content=executor_payload,
)Issue:
When ActivitySnapshotEvent is converted to an ActivityMessage, the message_id becomes the message's id field. Our implementation stores these in a database where id is expected to be unique(or so we thought). Without run-scoping, multiple runs using the same executor (e.g., "executor:synthesizer") generate duplicate IDs, causing newer runs to overwrite activities from previous runs. We are still early on this development so maybe our understanding is off and that should be the case and we need to update how we store Messages. Question: Version: agent_framework_ag_ui==1.0.0 Thanks all, appreciate all the hard work in this package! |
Replies: 2 comments 2 replies
|
Your collision concern is valid if the database key is global. I would preserve a stable message_id within one workflow run so incremental ActivitySnapshotEvent updates can target the same activity, but include the run identity in persistence so a second run cannot overwrite the first. A useful split is: I would avoid making message_id alone the primary key unless the protocol explicitly guarantees uniqueness across runs and threads. If the wire contract requires broader uniqueness, adding run_id to the generated executor ID is safer than relying on executor_id alone. Either way, add a regression test that runs the same executor twice, replays both runs, and verifies that updates from run 2 cannot mutate run 1. It is also worth deciding whether a UI needs cross-run deduplication or only within-run updates; those are different requirements. |
|
Thanks for digging into this. Your collision concern is valid.
The AG-UI documentation describes a message ID as unique but does not explicitly define whether that means globally unique or thread-scoped. At minimum, it must be unique among distinct messages that can coexist in the same thread-level message collection. Applications therefore should not rely on For the reported cross-run case, including the run ID would prevent the collision while preserving updates to one executor activity during that run: message_id=f"{run_id}:executor:{executor_id}" if executor_id else generate_event_id()There is one additional case to consider: if the same executor can have multiple distinct invocations within a single run, So yes, the current |
Thanks for digging into this. Your collision concern is valid.
ActivitySnapshotEvent.message_ididentifies the targetActivityMessage. AG-UI clients use that ID to locate and replace an existing activity in the message collection. Reusing an ID for updates to the same logical activity is expected. For example, an activity’s in-progress and completed snapshots should share an ID. Reusing it for a distinct activity in a later run can replace the earlier activity, as you observed.The AG-UI documentation describes a message ID as unique but does not explicitly define whether that means globally unique or thread-scoped. At minimum, it must be unique among distinct messages that can coexist in…