Repository navigation
feat(events): give a session an event envelope carrying run lifecycle - #730
Closed
justintime4tea wants to merge 2 commits into
Closed
justintime4tea wants to merge 2 commits into
justintime4tea wants to merge 2 commits into
Conversation
|
This was referenced Sep 25, 2026
justintime4tea
force-pushed
the
justingross/GH-578-1-run-events-carry-lifecycle-and-activity
branch
from
October 7, 2026 19:22
69bfe5c to
c2e2337
Compare
This was referenced Oct 7, 2026
justintime4tea
force-pushed
the
justingross/GH-578-1-run-events-carry-lifecycle-and-activity
branch
from
October 7, 2026 20:56
c2e2337 to
ab55a86
Compare
justintime4tea
force-pushed
the
justingross/GH-578-1-run-events-carry-lifecycle-and-activity
branch
from
October 7, 2026 21:00
ab55a86 to
921232c
Compare
AgentEvent says what an agent did and nothing about the run it belongs to. Observers reconstruct the run's story from the transport — a stream closing, an A2A status update, a [DONE] — and no two agree. aura_events::run adds SessionEvent: the session id, the run id when the event belongs to a run, a sequence number dense per session across its runs, a timestamp, and either an AgentEvent or a LifecycleEvent (started, observer attached and detached, claims exhausted, liveness decided, parked, finished, cancelled, failed). One stream per session means an agent's history loads as one stream, and a run boundary is a position in it rather than a second stream. The payload is adjacently tagged, kind beside event, so no field of an event can collide with the envelope's tag. Lifecycle events stay internally tagged by type, like AgentEventPayload; the roundtrip test over every variant is what catches a field named after a tag. Internal tagging and flatten need a self-describing format, which the module doc records. RunId is a UUID, v7 when minted, so it agrees with the orchestration run id HITL parses and the park owner key; aura-events takes uuid for it. SessionId and RunCancelReason move into aura-events, re-exported from aura::config and aura::hooks. RunCancelReason is non_exhaustive and gains Unclaimed and Shutdown, so a liveness or shutdown cancel is not reported as External. ObserverDetached says why with a DetachCause, and Started carries the run's Liveness, read as cancel-at-once when an older payload omits it. No producer emits it yet; this is the type and its tests. Fixes: GH-778 Ref: GH-578
The envelope names a run by RunId, a UUID, while the task-local run context named it by the HTTP request id string, so the two could never be the same value. RunContext::id is now a RunId. The chat, A2A, and Slack handlers mint one before building the agent and use its string form as the request id, so every request-keyed registry (HITL approvals and their sweep, MCP cancellation, the A2A cancel map) keeps one value per run. begin_run, AgentRuntimeConfig, and RigBuilder's build_agent, build_streaming_agent_with_headers and build_streaming_agent_with_tools take a RunId, and an agent built without one mints its own. The orchestration factory streams under the run id it was built for, as Agent already did. RunContext::has_id compares a request id string against the run without allocating. Request ids become hyphenated UUIDs rather than req_<hex>, a2a_<task_id>, and slack_<channel>_<ts>; the A2A executor and the Slack runner log each run id beside the task or message it serves, at debug, so the two stay joinable. The orchestration RunId becomes a re-export of aura_events::RunId, so there is one run id type. Orchestration persistence still mints its own value for checkpoints and the park owner key; adopting the run's id there waits for the runtime, which owns resume. Fixes: GH-778 Ref: GH-578 Ref: GH-780
justintime4tea
force-pushed
the
justingross/GH-578-1-run-events-carry-lifecycle-and-activity
branch
from
October 7, 2026 21:02
921232c to
e5ce350
Compare
justintime4tea
deleted the
justingross/GH-578-1-run-events-carry-lifecycle-and-activity
branch
October 8, 2026 21:27
Collaborator
Author
|
Superseded by #794. Renaming this PR's branch to |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements #778, a sub-issue of #578. Two commits on
nightly, now that #710 and #719 have merged.AgentEventsays what an agent did and nothing about the run it belongs to, so every seam reconstructs a run's story from its transport. This gives the session an envelope that carries both, one ordered stream per session.feat(events): give a session an event envelope carrying run lifecycleaura_events::runaddsSessionEvent: the session id, the run id when the event belongs to a run, a sequence number dense per session across its runs, a timestamp, and either anAgentEventor aLifecycleEvent(started, observer attached and detached, claims exhausted, liveness decided, parked, finished, cancelled, failed). No producer emits it yet; #779 is the first.The items #778 lists to settle before a producer exists:
session_idis required,run_idoptional,seqdense per session.ends_run()says whether an event ends its run; the stream goes on.RunIdis a UUID, v7 when minted withRunId::mint().aura-eventstakesuuidfor it (the CLI already depends on the same workspace crate).kindbesideevent, so no event field can collide with the envelope's tag. Lifecycle events stay internally tagged bytype; the roundtrip test over every variant catches a field named after a tag. The module doc records that the family needs a self-describing format.RunCancelReasonmoves here fromaura::hooks(re-exported there), is#[non_exhaustive], and gainsUnclaimedandShutdown.ObserverDetachedcarries aDetachCause(Released,Expired,Displaced).Startedcarries the run'sLiveness, read as cancel-at-once when an older payload omits it.refactor(agents): name a run by its RunIdRunContext::idbecomes theRunId, so the envelope's id and the task-local id are one value.RunIdand use its string form as the request id, so approvals, their sweep, MCP cancellation, and the A2A cancel map keep one value per run.begin_run,AgentRuntimeConfig, andRigBuilder's build methods take aRunId; an agent built without one mints its own. The orchestration factory streams under the run id it was built for, asAgentalready did.RunIdis a re-export of the shared type. Orchestration persistence still mints its own value for checkpoints and the park owner key; adopting the run's id there waits for [FEATURE]: A runtime that owns sessions and their runs #780, which owns resume.Visible change: request ids are hyphenated UUIDs rather than
req_<hex>,a2a_<task_id>, andslack_<channel>_<ts>. The A2A executor and Slack runner log the run id beside the task or message it serves, at debug.Verification
cargo +nightly fmt --check,cargo clippy --workspace --all-targets --all-features -- -D warnings, andcargo test --workspace(2,560 passed) onnightlyat513f1ec1.make check-cli-http-onlyfails onnightlyindependently of this change; that is [BUG]: HTTP-only aura-cli build fails clippy with unused args in resolve_env_config #721.Fixes: GH-778
Ref: GH-578