Skip to content

core: make EnvClient WebSocket keepalive (ping_interval) configurable #875

Description

@sergiopaniego

Problem

EnvClient opens its WebSocket with the websockets library defaults, which send keepalive pings (~every 20s) and expect pongs:

https://github.com/huggingface/OpenEnv/blob/main/src/openenv/core/env_client.py#L214

self._ws = await ws_connect(
    self._ws_url,
    open_timeout=self._connect_timeout,
    max_size=self._max_message_size,
    **connect_kwargs,
)

Some cloud sandbox tunnels do not forward WebSocket ping/pong frames. Modal's encrypted tunnel is one: with the default ping_interval, the client never receives a pong and closes the connection on the keepalive timeout. This surfaced in #821 (ModalProvider), where the only working E2E required monkeypatching:

import openenv.core.env_client as _ec
_ec.ws_connect = functools.partial(_ec.ws_connect, ping_interval=None)

This is a core limitation, not a provider bug: the provider returns a valid https/wss base_url and has no hook into how EnvClient opens its socket. It also conflicts with the cloud-provider contract in RFC 002 (the returned base_url should work with a stock EnvClient).

Proposed change

Make the WebSocket keepalive configurable on EnvClient (e.g. ping_interval / ping_timeout constructor args, forwarded to ws_connect), so sandbox services whose tunnels drop ping/pong work without monkeypatching. Open questions:

  • Sensible default: keep the current keepalive, or relax it for robustness across tunnels?
  • Whether a ContainerProvider should be able to hint a value (e.g. Modal returning ping_interval=None) so users do not have to know the tunnel quirk.

Context

  • Raised in Add ModalProvider(ContainerProvider) #821 (review) by @burtenshaw: "Make Modal work through stock EnvClient ... lmk if we should make changes in core to facilitate sandbox services without the ws ping route."
  • Unblocks merging Modal and other tunnel-backed providers without the client-side workaround.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions