Skip to content

feat(runtime-core): env-override the native sidecar frame timeout#1641

Merged
NathanFlurry merged 1 commit into
rivet-dev:mainfrom
khaled-mansour-zid:pr/frame-timeout-option
Jul 8, 2026
Merged

feat(runtime-core): env-override the native sidecar frame timeout#1641
NathanFlurry merged 1 commit into
rivet-dev:mainfrom
khaled-mansour-zid:pr/frame-timeout-option

Conversation

@khaled-mansour-zid

Copy link
Copy Markdown
Contributor

Summary

NATIVE_SIDECAR_FRAME_TIMEOUT_MS (packages/runtime-core/src/sidecar-process.ts) is hardcoded to 120_000 and is the value both native-sidecar spawn sites pass as frameTimeoutMs (packages/core/src/agent-os.ts, packages/core/src/runtime-compat.ts). There is currently no way to raise it without editing the source.

Why

A single long-running host request maps to one sidecar protocol frame. Workloads with legitimately long turns — an agent turn with many tool calls, media/asset generation, etc. — exceed 120s and are killed mid-turn with timed out waiting for sidecar protocol frame, which tears down the sidecar and hangs the turn.

Change

Resolve the const from AGENTOS_SIDECAR_FRAME_TIMEOUT_MS (validated finite + positive), falling back to 120_000. Behavior is unchanged when the env var is unset.

The native sidecar is process-global (spawned once and multiplexed across sessions), so an env override is the correct surface — a per-AgentOs.create option would be ambiguous for a shared process. Happy to expose it through AgentOsOptions instead if you'd prefer, but env matches the shared-resource model.

Notes

  • One-line-of-behavior change; both existing spawn sites already read this const, so no call-site edits are needed.

NATIVE_SIDECAR_FRAME_TIMEOUT_MS is hardcoded to 120_000 and is the value both
sidecar spawn sites pass as `frameTimeoutMs`. A single long-running host request
maps to one protocol frame, so workloads with legitimately long turns (an agent
turn with many tool calls, media generation, etc.) exceed 120s and get killed
mid-turn with "timed out waiting for sidecar protocol frame". There is currently
no way to raise it without editing the source.

Make the const resolve from AGENTOS_SIDECAR_FRAME_TIMEOUT_MS (validated: finite,
positive), falling back to 120_000. The native sidecar is process-global (spawned
once and multiplexed), so an env override is the right surface rather than a
per-AgentOs.create option. Behavior is unchanged when the env var is unset.
@NathanFlurry NathanFlurry marked this pull request as ready for review July 8, 2026 04:04
@NathanFlurry NathanFlurry merged commit 9323e64 into rivet-dev:main Jul 8, 2026
NathanFlurry added a commit that referenced this pull request Jul 8, 2026
…meout override

- Builds on #1641: extract the env resolution into an exported, unit-testable `resolveNativeSidecarFrameTimeoutMs`.
- Warn loudly on invalid `AGENTOS_SIDECAR_FRAME_TIMEOUT_MS` values instead of silently falling back.
- Unit tests for default/valid/invalid values; document the knob on the resource-limits docs page.
NathanFlurry added a commit that referenced this pull request Jul 8, 2026
…t silence watchdog

- The native sidecar emits a connection-scoped `StructuredEvent{name:"heartbeat"}` every 10s from a dedicated thread, so beats keep flowing while the dispatch loop is busy inside one long request. No protocol schema change — reuses the existing structured-event variant.
- The host replaces the per-frame 120s timeout with a silence watchdog: any inbound frame resets a 30s clock; sustained total silence kills the sidecar and rejects in-flight requests with a typed `SidecarSilenceTimeout` (stderr tail included).
- Individual requests no longer have a deadline: a legitimately long agent turn runs for minutes without teardown, while a genuinely dead or wedged sidecar is detected in ~30s instead of 2 minutes.
- Removes `NATIVE_SIDECAR_FRAME_TIMEOUT_MS`, the `AGENTOS_SIDECAR_FRAME_TIMEOUT_MS` env override (#1641), and all `frameTimeoutMs` plumbing (spawn options, native-client, protocol-client, frame-rpc, correlation).
- Heartbeats are swallowed at the frame layer on both clients so they never reach event consumers or the bounded event buffer; the Rust client mirrors the watchdog (activity-reset reader, kill + fail-pending on silence).
- Heartbeat cadence and silence window are fixed protocol constants (no env knobs); docs updated.
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