diff --git a/src/bedrock_agentcore/runtime/app.py b/src/bedrock_agentcore/runtime/app.py index 403f12da..76af20d4 100644 --- a/src/bedrock_agentcore/runtime/app.py +++ b/src/bedrock_agentcore/runtime/app.py @@ -610,6 +610,14 @@ async def _handle_invocation(self, request): return JSONResponse({"error": str(e)}, status_code=500) def _handle_ping(self, request): + """Handle GET /ping — return status and last-update timestamp. + + Response body: ``{"status": "Healthy|HealthyBusy", "time_of_last_update": }`` + + Both fields are required by the platform. ``time_of_last_update`` is a + Unix timestamp (seconds); without it the idle reaper fires even when + ``status`` is ``HealthyBusy``. See :class:`PingStatus` for details. + """ try: status = self.get_current_ping_status() self.logger.debug("Ping request - status: %s", status.value) diff --git a/src/bedrock_agentcore/runtime/models.py b/src/bedrock_agentcore/runtime/models.py index cad309da..9f71bec4 100644 --- a/src/bedrock_agentcore/runtime/models.py +++ b/src/bedrock_agentcore/runtime/models.py @@ -7,7 +7,22 @@ class PingStatus(str, Enum): - """Ping status enum for health check responses.""" + """Ping status enum for the ``GET /ping`` health-check endpoint. + + The platform polls ``/ping`` every few seconds to decide whether to keep + the container alive. The full JSON response body emitted by this SDK is:: + + { + "status": "", + "time_of_last_update": + } + + ``time_of_last_update`` is **required** for the idle-reaper logic. If it + is absent, ``idleRuntimeSessionTimeout`` fires at the configured boundary + even when ``status`` is ``HealthyBusy``, silently terminating the + container mid-execution. The SDK populates this field automatically; if + you implement a custom ping handler outside of the SDK, you must include it. + """ HEALTHY = "Healthy" HEALTHY_BUSY = "HealthyBusy"