Repository navigation
refactor(agent-hypervisor)!: make session methods synchronous - #3645
Conversation
|
🟡 Contributor Check: MEDIUM
Automated check by AGT Contributor Check. |
PR Review Summary
Verdict: AI review comments are untrusted advisory output. The summary reports workflow-generated completion status only, not model-authored pass/fail claims. |
There was a problem hiding this comment.
Pull request overview
Syncs the Hypervisor session lifecycle API (6 methods) to remove async-without-await footguns, updates repo call sites (docs/tests/examples/API), and adds a runtime guard in SagaOrchestrator to ensure step executors/compensators return awaitables.
TL;DR: 1 blocker, 2 warnings. Fix #1 and this ships.
| # | Sev | Issue | Where |
|---|---|---|---|
| 1 | Block | Awaitable guard rejects valid non-coroutine awaitables | SagaOrchestrator._ensure_awaitable |
| 2 | Warn | Quick start missing required creator_did (example will raise TypeError) |
docs/packages/agent-runtime.md |
| 3 | Warn | Quick start missing required creator_did (example will raise TypeError) |
agent-governance-python/agent-runtime/README.md |
#1: Validate generic awaitables (e.g., __await__) instead of only asyncio.isfuture/iscoroutine.
Changes:
- Convert
Hypervisorsession lifecycle methods fromasync def→def. - Update Python call sites (API server, tests, examples, benchmarks) to remove
await. - Add an executor/compensator awaitable return-type guard in
SagaOrchestrator.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/packages/agent-runtime.md | Update runtime quick start to sync session creation |
| docs/packages/agent-os.md | Update runtime session lifecycle example to sync calls |
| docs/packages/agent-hypervisor.md | Update hypervisor lifecycle examples to sync calls |
| agent-governance-python/agent-runtime/README.md | Update runtime README example to sync session creation |
| agent-governance-python/agent-os/README.md | Update Agent OS README lifecycle example to sync calls |
| agent-governance-python/agent-hypervisor/tests/unit/test_cli.py | Remove awaits in fixture session setup |
| agent-governance-python/agent-hypervisor/tests/test_agent_manager.py | Remove awaits across hypervisor unit tests |
| agent-governance-python/agent-hypervisor/tests/integration/test_scenarios.py | Remove awaits in integration scenarios |
| agent-governance-python/agent-hypervisor/tests/integration/test_hypervisor_e2e.py | Remove awaits in E2E hypervisor tests |
| agent-governance-python/agent-hypervisor/src/hypervisor/saga/orchestrator.py | Add runtime awaitable guard for step execution/compensation |
| agent-governance-python/agent-hypervisor/src/hypervisor/core.py | Make session lifecycle methods synchronous |
| agent-governance-python/agent-hypervisor/src/hypervisor/api/server.py | Update FastAPI handlers to call sync hypervisor methods |
| agent-governance-python/agent-hypervisor/README.md | Update README lifecycle examples to sync calls |
| agent-governance-python/agent-hypervisor/examples/docker-compose/app/server.py | Update example server to call sync hypervisor methods |
| agent-governance-python/agent-hypervisor/examples/demo.py | Update demo flows to call sync hypervisor methods |
| agent-governance-python/agent-hypervisor/docs/api-reference.md | Update API reference examples to sync calls |
| agent-governance-python/agent-hypervisor/benchmarks/bench_hypervisor.py | Update benchmarks to call sync lifecycle methods |
| agent-governance-python/agent-compliance/examples/governed_agent.py | Update compliance example to call sync runtime session creation |
MohammadHaroonAbuomar
left a comment
There was a problem hiding this comment.
- PR title: fails the required Validate PR title check; use the conventional format with the breaking marker, e.g. refactor(agent-hypervisor)!: make session methods synchronous.
- BREAKING_CHANGES.md: no entry, though the six converted methods ship in the published agent-governance-toolkit-core wheel (the pyproject force-includes hypervisor/src), so external consumers awaiting them break. Add an entry with a how-to-update line (drop the await).
Minor:
- a small test for _ensure_awaitable would make the checklist claim true; everything else verified clean: zero stale awaited call sites repo-wide, 640/640 hypervisor tests on the sync API, no fail-open - the conversion actually removes the forgot-await silent no-op class. Direction is maintainer-ordered per issue #3178.
|
Addressed the review items:
Validation:
Ready for re-review. |
Imran Siddique (imran-siddique)
left a comment
There was a problem hiding this comment.
Re-reviewed current head 1c76630f. The approved sync direction is implemented consistently across the six Hypervisor methods and direct repository call sites.
The subsequent blockers are all addressed:
- generic
__await__objects are accepted viainspect.isawaitable; - sync executor contract violations are rejected before retry/backoff, preventing repeated side effects;
- both behaviors have focused regression tests;
- the breaking API change is documented with the correct “drop
await” migration; - runtime examples now pass the required
creator_did; - unrelated async Saga APIs remain awaited.
The content is approved. GitHub currently reports the branch as not mergeable, so any current base conflict/check gate still needs to be resolved before merge.
066a48c to
1c76630
Compare
Signed-off-by: Electric Wolfe Marshmallow Hypertext <tionne@gmail.com>
Signed-off-by: Electric Wolfe Marshmallow Hypertext <tionne@gmail.com>
Signed-off-by: Electric Wolfe Marshmallow Hypertext <tionne@gmail.com>
1c76630 to
4c065da
Compare
|
MohammadHaroonAbuomar liamcrumm Quick follow-up here as well — the requested implementation/review changes were addressed, and Imran previously confirmed the content was approved. I’m traveling today, but I can refresh the branch against current main tomorrow if that’s the remaining blocker. When you have a chance, could you confirm whether anything else is needed from me? |
MohammadHaroonAbuomar
left a comment
There was a problem hiding this comment.
- SagaOrchestrator.execute_step now invokes executor() BEFORE the step-state guard (step.transition(EXECUTING)), so a replayed/duplicate execute_step on an already COMMITTED step fires the action's side effects and only then raises SagaStateError. On origin/main the guard ran first and the executor was never called. Any executor that schedules eagerly (asyncio.ensure_future, loop.run_in_executor as the method's own docstring recommends, or a sync prefix before returning a coroutine) is double-executed. The new _ensure_awaitable check explicitly admits such Task/Future awaitables (test_execute_step_accepts_generic_awaitable), so this is in-contract input.
- SagaOrchestrator.compensate moved the compensator(step) call (and the new _ensure_awaitable TypeError) out of the try/except that records COMPENSATION_FAILED and escalates the saga. Any exception raised at call time (e.g. KeyError from an undo-handler lookup, or the new TypeError for a sync compensator) now escapes compensate() after step.transition(COMPENSATING) and saga.transition(COMPENSATING) have already run: the saga is left in COMPENSATING (never ESCALATED, saga.error None, no 'Joint Liability penalty triggered'), the offending step is stuck in COMPENSATING, and every remaining committed step is never compensated. The saga cannot be recovered through the API because COMPENSATING->COMPENSATING is an invalid transition, and it sits in active_sagas forever. On origin/main the same inputs produced COMPENSATION_FAILED + ESCALATED with the other steps still compensated (fail-safe). This is the fail-open regression: the rollback-failure control is skipped and the failure is not recorded.
- Shipped tutorial notebook not migrated. notebooks/hypervisor-exploration.ipynb still wraps the now-synchronous methods in its run() helper (run_until_complete): lines 115 create_session, 193 join_session, 248 activate_session, 705 terminate_session. Each of those cells now raises TypeError. CI does not execute notebooks, so the suite cannot catch it. The PR diff touches no .ipynb file.
Signed-off-by: Electric Wolfe Marshmallow Hypertext <tionne@gmail.com>
MohammadHaroonAbuomar
left a comment
There was a problem hiding this comment.
- tests/unit/test_saga.py: add regression coverage for the two blockers fixed in ef8cc87 that the suite still cannot detect (the previous head 4c065da passed the whole suite with both defects present). (1) Execute a step to COMMITTED, then call execute_step again with an executor that counts invocations (e.g. returns asyncio.ensure_future(coro)); assert pytest.raises(SagaStateError) and calls == 0 (pins orchestrator.py:126 running before :128). (2) In test_sync_executor_contract_error_is_not_retried (test_saga.py:158-177) also assert step.state == StepState.FAILED and 'executor must return an awaitable' in step.error (pins orchestrator.py:141-142).
Signed-off-by: Electric Wolfe Marshmallow Hypertext <tionne@gmail.com>
MohammadHaroonAbuomar
left a comment
There was a problem hiding this comment.
Verified at f92f45d: the requested regression tests are in place (test_saga.py:139-159 and :203-204) and a mutation check shows both fail against the pre-fix orchestrator and pass on this head. No production code changed since ef8cc87; 16 adversarial saga probes pass, 646 hypervisor tests pass, DCO clean on all five commits.
…oft#3645) * Make hypervisor session methods synchronous Signed-off-by: Electric Wolfe Marshmallow Hypertext <tionne@gmail.com> * fix: accept generic saga awaitables Signed-off-by: Electric Wolfe Marshmallow Hypertext <tionne@gmail.com> * docs: document hypervisor breaking changes Signed-off-by: Electric Wolfe Marshmallow Hypertext <tionne@gmail.com> * fix(agent-hypervisor): preserve saga failure semantics Signed-off-by: Electric Wolfe Marshmallow Hypertext <tionne@gmail.com> * test(agent-hypervisor): cover saga executor regressions Signed-off-by: Electric Wolfe Marshmallow Hypertext <tionne@gmail.com> --------- Signed-off-by: Electric Wolfe Marshmallow Hypertext <tionne@gmail.com> Signed-off-by: yuvrajsingh2428 <offcyuvi2428@gmail.com>

Related Issue
Fixes #3178.
Problem & Solution
The Hypervisor session surface mixed sync and async methods even though six methods had no internal await points.
This PR implements the maintainer-approved sync direction for:
create_sessionjoin_sessionactivate_sessionterminate_sessionverify_behaviormonitor_sessionsDirect call sites were updated across the current repository. Unrelated same-name async APIs were left unchanged.
SagaOrchestrator.execute_stepandcompensateremain async, with a narrow runtime guard requiring executor/compensator results to be awaitable.Impact on Your Work
Removes the mixed sync/async Hypervisor API footgun and makes the session surface consistent with the existing synchronous helpers and callers.
Timeline
None.
Alternatives Considered
Keeping the six methods async was rejected because they contain no internal await points and the maintainer explicitly selected the synchronous direction in #3178.
Type of Change
Package(s) Affected
Core & runtime:
Governance & security:
Platform & tooling:
CLI plugins:
Shared / other:
Testing
Unit Testing
Focused Hypervisor test suite:
102 passed, 5 skippedManual Testing
py_compilepassed for edited Python filesgit diff --checkpassedmesh.create_session(...)await remains intentionally unchangedChecklist
Attribution & Prior Art
Prior art / related projects (if any):
None.
AI Assistance
If AI tools materially shaped this change, briefly note what was used:
AI-assisted code review and repository search were used during implementation; all changes were reviewed and validated manually before submission.
IP, Patents, and Licensing