Skip to content

fix(runtime): drop time_of_last_update from A2A and AG-UI ping responses - #542

Merged
nborges-aws merged 2 commits into
mainfrom
fix/drop-time-of-last-update-a2a-agui
Jun 22, 2026
Merged

fix(runtime): drop time_of_last_update from A2A and AG-UI ping responses#542
nborges-aws merged 2 commits into
mainfrom
fix/drop-time-of-last-update-a2a-agui

Conversation

@aidandaly24

@aidandaly24 aidandaly24 commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Summary

The A2A (a2a.py) and AG-UI (ag_ui.py) /ping handlers set time_of_last_update to the current time on every ping, instead of reporting when the status last changed. This PR drops time_of_last_update from the A2A and AG-UI ping responses, which now return {"status": ...}. app.py is intentionally left unchanged.

Why this is the fix

The Runtime platform consumes time_of_last_update to detect session idleness — it expects the timestamp to reflect when the status last changed. Because the A2A and AG-UI handlers re-stamped it to "now" on every ping (every poll interval), the platform saw a continuous status change and never treated the session as idle. As a result:

  • The idle session timeout (IdleRuntimeSessionTimeout) never fired.
  • Sessions persisted until MaxLifetime instead of being released when idle.
  • Under load, session count grew unbounded and could exhaust the session/VM quota (ServiceQuotaExceededException).

Overriding the ping handler did not help, because the SDK set time_of_last_update regardless of the handler's return value — so there was no customer workaround.

Dropping the field is the correct fix: with time_of_last_update absent, the platform tracks status changes using its own clock, and the idle timeout works as configured. app.py is unaffected — it already stamps the timestamp only on an actual status change, so its idle behavior was already correct.

Changes

  • src/bedrock_agentcore/runtime/a2a.py_handle_ping returns {"status": status.value}; removed the per-ping last_status_update_time tracking (and its nonlocal) and the now-unused import time.
  • src/bedrock_agentcore/runtime/ag_ui.py — same change; removed the self._last_status_update_time attribute and now-unused import time.
  • Tests — updated the A2A/AG-UI unit and integration ping tests to assert time_of_last_update is absent from the response. test_app.py is unchanged (the HTTP app still emits the field, correctly, on status transition).

Backward compatibility

Removing the field is non-breaking: the platform treats time_of_last_update as optional, so omitting it is accepted. Agents on older SDK versions (still sending the field) and agents on this version (omitting it) both pass the health check.

Testing

  • uv run pytest tests/bedrock_agentcore/runtime/test_a2a.py tests/bedrock_agentcore/runtime/test_ag_ui.py tests/bedrock_agentcore/runtime/test_app.py191 passed
  • ruff check clean on all changed files

Note

A companion internal docs change updates the AgentCore Runtime protocol-contract pages to document time_of_last_update correctly — as an optional field that must reflect the last status change, with a warning against re-stamping it on every ping.

The A2A and AG-UI ping handlers reset the status-update timestamp to the
current time on every ping, so `time_of_last_update` always reported "now"
rather than the time the status last changed — making the field meaningless
on those paths (unlike app.py, which only stamps it on a status transition).

The Runtime data plane parses `time_of_last_update` as optional and never
uses its value: session keep-alive is driven entirely by the `status` field
(`HealthyBusy` keeps the session active). Dropping the field from the A2A and
AG-UI responses removes the misleading value without affecting platform
behavior. app.py is left unchanged.

- a2a.py / ag_ui.py: ping returns `{"status": ...}`; remove the now-dead
  last_status_update_time tracking and unused `import time`
- tests: assert `time_of_last_update` is absent from A2A/AG-UI ping responses
@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

✅ No Breaking Changes Detected

No public API breaking changes found in this PR.

@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Jun 22, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: the review did not analyze this PR (model took 0 turns). See the run for details; a later push or re-run is needed.

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Jun 22, 2026
A prior commit message stated the Runtime platform "never uses" and
"discards" time_of_last_update. That is inaccurate. The platform consumes
the field to detect session idleness: it expects the timestamp to reflect
when the status last changed.

The A2A and AG-UI handlers set time_of_last_update to the current time on
every ping, so the platform saw a continuous status change and never
considered the session idle — the idle session timeout never fired and
sessions persisted until MaxLifetime, exhausting the session quota.

Dropping the field (this change) is the correct fix: with the field absent,
the platform tracks status changes using its own clock, so the idle timeout
works as configured. app.py is unaffected — it already stamps the timestamp
only on a status change.
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: the review did not analyze this PR (model took 0 turns). See the run for details; a later push or re-run is needed.

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Jun 22, 2026
@nborges-aws
nborges-aws merged commit 44b1a92 into main Jun 22, 2026
40 of 41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants