Python AgentServer health check (GET /) returns 200 before the worker has registered with LiveKit
メンテナーはふだん 1 日以内に返信
評価
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 初心者へのやさしさ
- 35/100
調査の方向性
Start in worker.py at the health handler and connection state described in the issue; compare the Python behavior with the Node SDK's connection check. Run the supplied reproduction to confirm the response before registration, then verify the chosen health or readiness behavior during registration and reconnection. Done means the endpoint behavior matches its documented purpose, including the existing unregistered=True mode; an open linked pull request already addresses this issue.
索引モデルが issue の本文から書いたものです。
説明
Bug Description
The built-in health endpoint returns 200 OK after its HTTP server starts, even before the worker receives RegisterWorkerResponse and registers with LiveKit. I reproduced this with livekit-agents==1.8.8 and with main at 7e824e3637b06198176c4cd619489134ce51d2bb.
The Server options documentation says the endpoint returns 200 when connected and 503 when the server is not connected, and notes that LiveKit Cloud uses it for rolling deployments. In worker.py, the health handler checks only whether the inference process is alive and whether _connection_failed is true. _connection_failed starts as False and becomes True only after the retry limit is exhausted. The HTTP server starts before the connection task. _connecting is tracked but is not checked by the health handler.
Expected Behavior
Before receiving RegisterWorkerResponse, GET / should indicate that the worker is not yet connected, consistent with the documentation. If / is intended to be a liveness check that remains healthy during reconnection, could a separate readiness endpoint be provided and documented? The Node SDK returns 503 while connecting or while its WebSocket is not open.
Reproduction Steps
- Run the script below in an environment with the package versions listed under Package Versions.
- The fake LiveKit endpoint accepts the worker's WebSocket and reads its registration message, but deliberately never sends
RegisterWorkerResponse. - Observe that
worker_registeredis still false whileGET /returns 200.
import asyncio
import aiohttp
from aiohttp import web
from livekit.agents import AgentServer, JobContext, __version__
FAKE_PORT, HEALTH_PORT = 18880, 18881
async def main() -> None:
register_requests = 0
async def agent_ws(request: web.Request) -> web.WebSocketResponse:
nonlocal register_requests
ws = web.WebSocketResponse()
await ws.prepare(request)
async for _ in ws: # read RegisterWorkerRequest, never send RegisterWorkerResponse
register_requests += 1
return ws
app = web.Application()
app.router.add_get("/agent", agent_ws)
runner = web.AppRunner(app)
await runner.setup()
await web.TCPSite(runner, "127.0.0.1", FAKE_PORT).start()
server = AgentServer(
ws_url=f"ws://127.0.0.1:{FAKE_PORT}", api_key="devkey", api_secret="secret" * 6,
host="127.0.0.1", port=HEALTH_PORT, num_idle_processes=0,
)
@server.rtc_session()
async def entrypoint(ctx: JobContext) -> None: ...
registered = asyncio.Event()
server.on("worker_registered", lambda *_: registered.set())
run_task = asyncio.create_task(server.run(devmode=False))
await asyncio.sleep(5)
async with aiohttp.ClientSession() as http:
async with http.get(f"http://127.0.0.1:{HEALTH_PORT}/") as resp:
print(f"livekit-agents {__version__}: register_requests={register_requests} "
f"worker_registered={registered.is_set()} GET / -> {resp.status} {await resp.text()!r}")
await server.aclose()
run_task.cancel()
await runner.cleanup()
asyncio.run(main())
Output on both tested versions:
livekit-agents 1.8.8: register_requests=1 worker_registered=False GET / -> 200 'OK'
Operating System
macOS 27.0.1, arm64.
Models Used
Not applicable; this reproduction tests worker registration only and does not use STT, LLM, or TTS models.
Package Versions
Python 3.12.13
Release test:
livekit-agents==1.8.8
livekit==1.1.20
livekit-api==1.2.2
aiohttp==3.14.5
main @ 7e824e3637b06198176c4cd619489134ce51d2bb:
livekit-agents==1.8.8
livekit==1.1.21
livekit-api==1.2.2
aiohttp==3.14.5
Session/Room/Call IDs
Not applicable; this uses a local fake LiveKit endpoint and does not create a LiveKit Cloud session or room.
Proposed Solution
Return 503 while the worker is not registered, for example while _connecting is true or using a registered state that is cleared on disconnect. Preserve the existing behavior for unregistered=True mode. If / is intended to be a liveness check so short LiveKit outages do not restart workers with active jobs, could you add a separate readiness endpoint and update the docs? I can open a PR for either option.
Additional Context
- The same health-check code is present in 1.8.2, 1.8.8, and the tested
mainrevision. - The Node SDK checks connection state and returns 503 while connecting or while the socket is not open (
agents-jschange). - Related: #4419 reports failure after retries are exhausted, but does not cover the initial registration gap. #6918 proposes moving the existing checks into
agent_health(), which appears to retain the same gap.
- 主要言語
- Python
- スター
- 14.6k
- フォーク
- 3.9k
- 平均マージ
- 3日 11時間
- マージ済み PR(30日)
- 196
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
livekit/agents のほかの issue
-
Assistant markup is stripped from chat history when expressive mode is off対応中かも @ShivamSharma43 が 17 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 1 日以内に返信
-
docs: openai.LLM vs openai.responses.LLM for HTTP OpenAI-compat hosts再び着手できるかも @AbarnaaSree が 56 日前に担当しましたが、オープン中のプルリクエストはありません。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
livekit/agents#7022 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
メンテナーはふだん 1 日以内に返信
-
TranslationRoomIO: unset_track() before a track is linked stalls startup, so the translation is never published対応中かも @RaphaelFakhri が今日担当しました。 オープン
livekit/agents#8114 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
OpenAI Realtime engine: expose the WebSocket close code and reason to subclasses対応中かも @ninglinLiu が 2 日前に担当しました。 オープン
難易度 3/5 1〜2日 初心者へのやさしさ 35/100
livekit/agents#8076 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
似ている issue
-
Project submission:オープン
難易度 1/5 1時間未満 初心者へのやさしさ 72/100
slavakurilyak/awesome-ai-agents#845 ·
メンテナーはふだん 1 日以内に返信
-
tests: pin that the atomic writers in utils/paths.py stage the temporary file in the target's directory対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープンdifficulty:2 enhancement good first issue
難易度 1/5 1〜3時間 初心者へのやさしさ 92/100
MakazhanAlpamys/Soup#2178 ·
メンテナーはふだん 1 日以内に返信
-
[BUG] dcg.waggr permutation p-values are folded twice, so near-zero scores get the smallest p-valuesオープン
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
scverse/rapids-singlecell#854 ·
メンテナーはふだん 1 日以内に返信
-
Slang input: int8_t4_packed and uint8_t4_packed are copied into CrossGL対応中かも @ninglinLiu が今日担当しました。 オープンarea:frontend backend:slang bug direction:input
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
メンテナーはふだん 1 日以内に返信
-
random_elements(unique=True) on an OrderedDict: ZeroDivisionError once only zero weights remain, AssertionError with use_weighting=False対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
メンテナーはふだん 13 日以内に返信