70 Commits

Author SHA1 Message Date
Victor Kyriazakos d607f0cafb fix(relay): bound native scope lifecycle operations so a wedged pipeline cannot block the agent
The NeMo Relay native binding's scope.pop/push are synchronous and
unbounded ('returns after the scope is closed successfully'). When the
native pipeline cannot make progress, the session coordinator's turn and
session finalization block forever inside run_conversation: delegated
children finish their turns but never return, and delegation batches die
on the stall watchdog. Proven live 2026-08-10 on the staging fleet — a
falsification probe (plugin disabled, identical config) completed the
same delegation batch that wedged with the plugin active.

Bound every scope lifecycle operation that gates turn/session completion
(session push, turn push, turn pop, logical-LLM pops, session pop,
subscriber flush) by running the native call on a shared
DaemonThreadPoolExecutor and honoring a 10s result timeout. On breach a
TimeoutError propagates into each call site's existing exception
handling — warn, retain the unclosed-prefix diagnostics, continue — so
the worst case is one lost span, never a blocked agent. timeout=None
preserves byte-identical synchronous behavior for all other callers, and
interpreter-shutdown paths fall back to the synchronous call so the
atexit flush still exports.

Observability must never block the product.
2026-08-12 19:19:54 -07:00
Teknium 961f7481a7 fix(relay): bypass managed execution for nested calls inside managed callbacks
The native Relay pipeline binds its Futures to the event loop that
entered run_in_session_async. While a managed tool callback executes,
that loop is blocked until the callback returns — so a nested managed
relay call made from inside the callback (vision_analyze's auxiliary
LLM call on a worker-thread loop) awaits a Future that can never
complete: 'RuntimeError: Future attached to a different loop', or a
deadlock, plus 'Event loop is closed' at shutdown when the orphaned
future completes late. (#77244)

Fix: managed_callback_guard, a ContextVar depth marker set around every
Hermes callback the relay adapters hand to the native pipeline
(relay_tools.execute invoke, relay_llm execute/execute_async invoke,
ManagedLlmStream run_callback). resolve_execution_context returns the
no-relay triple while the marker is set, so nested calls run unmanaged.
The marker propagates through contextvars.copy_context() into the
worker threads tools use for their internal async work.

Top-level turn LLM calls and tool wraps stay fully managed — verified
live: vision_analyze works under active shared metrics while the main
turn still records managed llm.execute events.

Alternative fixes considered and rejected: removing
retain_managed_execution (kills the shared-metrics managed pipeline)
and gating on main-thread identity (managed tool wraps legitimately
run on the run_agent thread, so that gate disables relay everywhere).
2026-08-08 23:46:17 -07:00
Bryan Bednarski e1caa611bf fix(relay): preserve skipped turn context
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
2026-08-03 13:43:17 -06:00
Bryan Bednarski a2a08fe147 fix(relay): gate skipped turn metrics
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
2026-08-03 13:43:17 -06:00
Bryan Bednarski 9a9b670e29 fix(relay): avoid concurrent turn scope corruption
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
2026-08-03 13:43:16 -06:00
Alex Fournier 3b55419cb1 fix(relay): close logical calls in stack order
Signed-off-by: Alex Fournier <afournier@nvidia.com>
2026-07-28 10:19:53 -07:00
Alex Fournier 14bed44c8c Reapply "feat(observability): integrate NeMo Relay runtime and shared metrics"
Signed-off-by: Alex Fournier <afournier@nvidia.com>
2026-07-27 21:10:51 -07:00
Jeffrey Quesnelle 841a5a744a Revert "feat(observability): integrate NeMo Relay runtime and shared metrics" 2026-07-27 22:28:08 -04:00
Alex Fournier 8699ff58ed fix(relay): close child sessions inside turn ownership
Signed-off-by: Alex Fournier <afournier@nvidia.com>
2026-07-27 08:20:05 -07:00
Alex Fournier bc597571fe perf(relay): bypass inactive execution adapters
Signed-off-by: Alex Fournier <afournier@nvidia.com>
2026-07-27 08:14:50 -07:00
Alex Fournier 502e4d63a2 perf(relay): avoid disabled mark initialization
Signed-off-by: Alex Fournier <afournier@nvidia.com>
2026-07-23 14:31:12 -07:00
Alex Fournier 4788994bd2 fix(relay): preserve managed callback context
Signed-off-by: Alex Fournier <afournier@nvidia.com>
2026-07-23 13:53:59 -07:00
Alex Fournier ea171c947a perf(relay): bypass inactive tool interception
Signed-off-by: Alex Fournier <afournier@nvidia.com>
2026-07-23 13:38:49 -07:00
Alex Fournier 591ba267d2 fix(relay): release session lock before callbacks
Signed-off-by: Alex Fournier <afournier@nvidia.com>
2026-07-23 13:33:41 -07:00
Alex Fournier a6fbff1d7e fix(relay): retain active child sessions
Signed-off-by: Alex Fournier <afournier@nvidia.com>
2026-07-23 13:22:50 -07:00
Alex Fournier df892a08f6 test(runtime): retain direct Relay interceptor coverage
Signed-off-by: Alex Fournier <afournier@nvidia.com>
2026-07-21 09:28:47 -07:00
Alex Fournier 6efc5fe0af fix(runtime): preserve provider payloads through Relay
Signed-off-by: Alex Fournier <afournier@nvidia.com>
2026-07-21 09:25:22 -07:00
Alex Fournier 55b7903cf7 fix(observability): harden Relay terminal lifecycle metrics
Signed-off-by: Alex Fournier <afournier@nvidia.com>
2026-07-19 08:59:42 -04:00
Alex Fournier 4dedaa4237 refactor(runtime): consolidate Relay lifecycle ownership
Signed-off-by: Alex Fournier <afournier@nvidia.com>
2026-07-19 08:59:06 -04:00
Alex Fournier 9bc521b138 refactor(runtime): manage Relay LLM tool and subagent execution
Signed-off-by: Alex Fournier <afournier@nvidia.com>
2026-07-19 08:57:38 -04:00