From 0d9071888f53e438b386bd7addd655c71eb0abbe Mon Sep 17 00:00:00 2001 From: mnajafian-nv Date: Wed, 7 Oct 2026 18:43:45 -0700 Subject: [PATCH 1/5] feat: add shared Relay correlation metadata helper In-process adapters attach NeMo Fabric IDs to their Relay root scope so telemetry consumers can join Relay events back to a Fabric runtime, invocation, and request. Each adapter currently spells the metadata keys inline, and the set of keys differs between adapters. Define the three reserved key names once in the common adapter package and add relay_correlation_metadata(), which builds the mapping from the invocation's RuntimeContext. relay_request_context() now uses the same request key constant; its behavior is unchanged. Signed-off-by: mnajafian-nv --- .../src/nemo_fabric_adapters/common/utils.py | 19 +++++++++++++- tests/adapters/test_adapaters_common_utils.py | 25 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/adapters/python/common/src/nemo_fabric_adapters/common/utils.py b/adapters/python/common/src/nemo_fabric_adapters/common/utils.py index c3f3718df..ba4603819 100644 --- a/adapters/python/common/src/nemo_fabric_adapters/common/utils.py +++ b/adapters/python/common/src/nemo_fabric_adapters/common/utils.py @@ -16,10 +16,17 @@ from typing import Any from nemo_fabric_adapter_contract.codec import JsonValue +from nemo_fabric_adapter_contract.models import RuntimeContext _FIELD_NAME = re.compile(r"[!#$%&'*+\-.^_`|~0-9A-Za-z]+") +# Reserved Relay metadata keys that join Relay telemetry to NeMo Fabric IDs. +# Consumers match these names literally, so treat them as a stable contract. +RELAY_REQUEST_ID_METADATA_KEY = "nemo_fabric_request_id" +RELAY_INVOCATION_ID_METADATA_KEY = "nemo_fabric_invocation_id" +RELAY_RUNTIME_ID_METADATA_KEY = "nemo_fabric_runtime_id" + def normalize_user_input(value: JsonValue) -> str: """Return user input as text, serializing structured values deterministically.""" @@ -278,7 +285,7 @@ def relay_request_context( ) -> tuple[Any, dict[str, str]]: """Root Relay at a usable session root, else a UUID request ID; preserve metadata.""" - metadata = {"nemo_fabric_request_id": request_id} + metadata = {RELAY_REQUEST_ID_METADATA_KEY: request_id} request_uuid = _uuid_or_none(request_id) session_uuid = _uuid_or_none(session_root) @@ -297,6 +304,16 @@ def relay_request_context( return use_scope_stack(stack), metadata +def relay_correlation_metadata(context: RuntimeContext) -> dict[str, str]: + """Return the NeMo Fabric IDs to attach to an invocation's Relay root scope.""" + + return { + RELAY_REQUEST_ID_METADATA_KEY: context.request_id, + RELAY_INVOCATION_ID_METADATA_KEY: context.invocation_id, + RELAY_RUNTIME_ID_METADATA_KEY: context.runtime_id, + } + + def ambient_relay_plugin_config_paths() -> list[Path]: """Return ambient user or project Relay plugin configs visible to Python.""" diff --git a/tests/adapters/test_adapaters_common_utils.py b/tests/adapters/test_adapaters_common_utils.py index 3a09ae7de..4b824defb 100644 --- a/tests/adapters/test_adapaters_common_utils.py +++ b/tests/adapters/test_adapaters_common_utils.py @@ -25,6 +25,7 @@ from nemo_fabric import ModelConfig from nemo_fabric import RelayAtifConfig from nemo_fabric import RelayObservabilityConfig +from nemo_fabric_adapter_contract.models import RuntimeContext ROOT = Path(__file__).resolve().parents[2] @@ -187,6 +188,30 @@ def test_two_requests_share_one_session_root(monkeypatch: pytest.MonkeyPatch): ] +def test_relay_correlation_metadata_returns_reserved_fabric_ids(tmp_path: Path): + context = RuntimeContext.from_mapping( + { + "runtime_id": "runtime-1", + "invocation_id": "invocation-1", + "request_id": "request-1", + "environment": { + "environment_id": "test-environment", + "provider": "test", + "control_location": "in_env_control", + "workspace": str(tmp_path), + "ownership": "caller_owned", + }, + "artifacts": {}, + } + ) + + assert common_utils.relay_correlation_metadata(context) == { + "nemo_fabric_request_id": "request-1", + "nemo_fabric_invocation_id": "invocation-1", + "nemo_fabric_runtime_id": "runtime-1", + } + + @pytest.mark.parametrize( ("value", "expected"), [ From d1a36152326da6b908a5c4c97aca857dc6308f0f Mon Sep 17 00:00:00 2001 From: mnajafian-nv Date: Wed, 7 Oct 2026 18:46:49 -0700 Subject: [PATCH 2/5] feat: add runtime ID to Deep Agents and mini-SWE-agent Relay scopes The OO Agents adapter already tags its per-invocation Relay Agent scope with the NeMo Fabric runtime, invocation, and request IDs, but the Deep Agents and mini-SWE-agent adapters omit the runtime ID. Without it, a telemetry consumer cannot group invocations that ran on the same retained runtime, and the reserved keys differ by adapter. Build the root scope metadata with the shared relay_correlation_metadata() helper so both adapters emit all three keys. relay_request_context() still owns the UUID propagation root. The Deep Agents telemetry path now receives the RuntimeContext instead of separate ID arguments. Signed-off-by: mnajafian-nv --- .../deepagents/adapter.py | 13 +++--- adapters/python/mini-swe-agent/README.md | 10 ++--- .../mini_swe_agent/adapter.py | 2 +- tests/adapters/test_deepagents.py | 6 +++ tests/adapters/test_mini_swe_agent.py | 3 ++ tests/integrations/test_relay_scope_leak.py | 42 ++++++++++++++++--- 6 files changed, 56 insertions(+), 20 deletions(-) diff --git a/adapters/python/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py b/adapters/python/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py index e053bffd2..b726e8f70 100644 --- a/adapters/python/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py +++ b/adapters/python/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py @@ -724,7 +724,6 @@ async def invoke( ) user_message = common_utils.normalize_user_input(request.input) - request_id = runtime_context.request_id resumed = self._completed_invocations > 0 inherited_quarantine = self._telemetry_quarantine is not None @@ -733,8 +732,7 @@ async def invoke( else: outcome = await self._invoke_with_telemetry( user_message, - request_id, - runtime_context.invocation_id, + runtime_context, request.relay_session_root, ) @@ -806,8 +804,7 @@ async def invoke( async def _invoke_with_telemetry( self, user_message: str, - request_id: str, - invocation_id: str, + runtime_context: RuntimeContext, session_root: str | None, ) -> TurnOutcome: """Run one turn inside the Relay plugin/scope, isolating telemetry faults. @@ -838,9 +835,11 @@ async def _invoke_with_telemetry( # turn, which would lose one of the two. try: request_context, metadata = common_utils.relay_request_context( - request_id, session_root + runtime_context.request_id, session_root + ) + metadata.update( + common_utils.relay_correlation_metadata(runtime_context) ) - metadata["nemo_fabric_invocation_id"] = invocation_id with request_context: with self._relay_scope.scope( "deepagents-request", diff --git a/adapters/python/mini-swe-agent/README.md b/adapters/python/mini-swe-agent/README.md index 608a7f15e..28ff55d01 100644 --- a/adapters/python/mini-swe-agent/README.md +++ b/adapters/python/mini-swe-agent/README.md @@ -153,20 +153,18 @@ hierarchy without requiring upstream changes. ### Correlation IDs The top-level `mini-swe-agent.request` Agent scope stores the NeMo Fabric -request and invocation IDs, and a caller-supplied session root, as Relay -metadata: +request, invocation, and runtime IDs, and a caller-supplied session root, as +Relay metadata: | NeMo Fabric ID | Relay metadata key | Meaning | | --- | --- | --- | | `request_id` | `nemo_fabric_request_id` | Correlates the caller's logical request. A caller can provide the same value when it wants to correlate retries or related processing. | | `invocation_id` | `nemo_fabric_invocation_id` | Identifies one concrete invocation attempt. NeMo Fabric assigns a new value to each invocation. | +| `runtime_id` | `nemo_fabric_runtime_id` | Identifies the longer-lived retained runtime that can process multiple invocations. | | `RunRequest.relay_session_root` | `nemo_fabric_session_root` | Groups invocations into one Relay session. A UUID string Relay accepts becomes the propagated Relay root; a UUID `request_id` stays the parent, otherwise the session root is also the parent. Absent when the value is missing or unusable; the invocation proceeds without an error. | Nested step, LLM, and `bash` tool events are correlated through the Relay scope -hierarchy; they do not repeat these metadata fields. The `runtime_id` -identifies the longer-lived retained runtime that can process multiple -invocations, but the mini-SWE-agent adapter does not currently add it to Relay -scope metadata. +hierarchy; they do not repeat these metadata fields. Install both the harness and Relay: diff --git a/adapters/python/mini-swe-agent/src/nemo_fabric_adapters/mini_swe_agent/adapter.py b/adapters/python/mini-swe-agent/src/nemo_fabric_adapters/mini_swe_agent/adapter.py index 916aed0fd..15df4f5c4 100644 --- a/adapters/python/mini-swe-agent/src/nemo_fabric_adapters/mini_swe_agent/adapter.py +++ b/adapters/python/mini-swe-agent/src/nemo_fabric_adapters/mini_swe_agent/adapter.py @@ -213,7 +213,7 @@ async def _run_with_relay( request_context, metadata = common_utils.relay_request_context( context.request_id, session_root ) - metadata["nemo_fabric_invocation_id"] = context.invocation_id + metadata.update(common_utils.relay_correlation_metadata(context)) with ( request_context, self._relay_scope.scope( diff --git a/tests/adapters/test_deepagents.py b/tests/adapters/test_deepagents.py index 25e42e28f..9dbd08db2 100644 --- a/tests/adapters/test_deepagents.py +++ b/tests/adapters/test_deepagents.py @@ -740,6 +740,7 @@ async def test_relay_telemetry_wraps_agent_and_reports_artifacts( { "nemo_fabric_request_id": "request-1", "nemo_fabric_invocation_id": "inv-1", + "nemo_fabric_runtime_id": "run-1", } ] # the Deep Agents callback handler is added to the LangGraph run config so @@ -758,6 +759,7 @@ async def test_relay_telemetry_wraps_agent_and_reports_artifacts( { "nemo_fabric_request_id": "018f47a4-3af7-7d94-8e61-9f0f89b5d312", "nemo_fabric_invocation_id": "inv-1", + "nemo_fabric_runtime_id": "run-1", }, ), ( @@ -766,6 +768,7 @@ async def test_relay_telemetry_wraps_agent_and_reports_artifacts( { "nemo_fabric_request_id": "request-1", "nemo_fabric_invocation_id": "inv-1", + "nemo_fabric_runtime_id": "run-1", }, ), ], @@ -1411,6 +1414,7 @@ async def test_native_telemetry_exports_without_artifacts( { "nemo_fabric_request_id": "request-1", "nemo_fabric_invocation_id": "inv-1", + "nemo_fabric_runtime_id": "run-1", } ] assert fake_relay["callback_handler"] in (fake_sdks["config"] or {}).get( @@ -2216,10 +2220,12 @@ async def test_persistent_runtime_scopes_relay_per_invocation( { "nemo_fabric_request_id": "request-1", "nemo_fabric_invocation_id": "inv-1", + "nemo_fabric_runtime_id": "run-relay-persistent", }, { "nemo_fabric_request_id": "request-1", "nemo_fabric_invocation_id": "inv-2", + "nemo_fabric_runtime_id": "run-relay-persistent", }, ] assert fake_sdks["saver_exits"] == 1 diff --git a/tests/adapters/test_mini_swe_agent.py b/tests/adapters/test_mini_swe_agent.py index e4de390aa..285ffe24c 100644 --- a/tests/adapters/test_mini_swe_agent.py +++ b/tests/adapters/test_mini_swe_agent.py @@ -422,6 +422,7 @@ async def test_relay_enabled_uses_instrumented_subclass_and_reports_artifacts( assert request_scope[2]["metadata"] == { "nemo_fabric_request_id": "mini-request", "nemo_fabric_invocation_id": "mini-invocation", + "nemo_fabric_runtime_id": "mini-runtime", } assert mock_relay["step_starts"][0][2]["handle"] is mock_relay["request_handle"] assert mock_relay["llm_starts"][0][2]["handle"] is mock_relay["step_handle"] @@ -463,6 +464,7 @@ async def test_uuid_request_id_seeds_relay_propagation( assert mock_relay["request_scopes"][0][2]["metadata"] == { "nemo_fabric_request_id": request_id, "nemo_fabric_invocation_id": "mini-invocation", + "nemo_fabric_runtime_id": "mini-runtime", } @@ -502,6 +504,7 @@ async def test_typed_session_root_roots_relay_propagation( "nemo_fabric_request_id": request_id, "nemo_fabric_session_root": SESSION_ROOT, "nemo_fabric_invocation_id": "mini-invocation", + "nemo_fabric_runtime_id": "mini-runtime", } diff --git a/tests/integrations/test_relay_scope_leak.py b/tests/integrations/test_relay_scope_leak.py index c395c538e..9dabfdcd5 100644 --- a/tests/integrations/test_relay_scope_leak.py +++ b/tests/integrations/test_relay_scope_leak.py @@ -14,10 +14,12 @@ import contextlib import os import uuid +from collections.abc import Callable from pathlib import Path from types import SimpleNamespace import pytest +from nemo_fabric_adapter_contract.models import RuntimeContext from nemo_fabric_adapters.deepagents import adapter from nemo_fabric_adapters.common.utils import relay_request_context @@ -41,6 +43,30 @@ def isolated_scope_stack(monkeypatch: pytest.MonkeyPatch, tmp_path: Path): nemo_relay._scope_stack_var.reset(token) +@pytest.fixture(name="make_runtime_context") +def make_runtime_context_fixture( + tmp_path: Path, +) -> Callable[[str, str], RuntimeContext]: + def make(request_id: str, invocation_id: str) -> RuntimeContext: + return RuntimeContext.from_mapping( + { + "runtime_id": "runtime-1", + "invocation_id": invocation_id, + "request_id": request_id, + "environment": { + "environment_id": "test-environment", + "provider": "test", + "control_location": "in_env_control", + "workspace": str(tmp_path), + "ownership": "caller_owned", + }, + "artifacts": {}, + } + ) + + return make + + async def _overlapping_chain_runs(handler: NemoRelayCallbackHandler) -> None: """Close two sibling chain runs out of LIFO order, as LangGraph's tasks do.""" @@ -138,7 +164,9 @@ async def activate(self, config: object): ) -async def test_uuid_request_id_seeds_real_relay_parent(monkeypatch): +async def test_uuid_request_id_seeds_real_relay_parent( + monkeypatch, make_runtime_context +): async def fake_invoke(agent, user_message, thread_id, callbacks=None): return {"messages": []}, [], [] @@ -157,8 +185,7 @@ async def fake_invoke(agent, user_message, thread_id, callbacks=None): outcome = await runtime._invoke_with_telemetry( "hello", - request_id, - "invocation-1", + make_runtime_context(request_id, "invocation-1"), None, ) @@ -169,12 +196,15 @@ async def fake_invoke(agent, user_message, thread_id, callbacks=None): { "nemo_fabric_request_id": request_id, "nemo_fabric_invocation_id": "invocation-1", + "nemo_fabric_runtime_id": "runtime-1", } ] assert nemo_relay.scope.get_handle().uuid == baseline.uuid -async def test_overlapping_turns_stay_telemetry_clean(monkeypatch): +async def test_overlapping_turns_stay_telemetry_clean( + monkeypatch, make_runtime_context +): """Two ordered turns end to end: real scope, real callback, real stack.""" async def fake_invoke(agent, user_message, thread_id, callbacks=None): @@ -193,10 +223,10 @@ async def fake_invoke(agent, user_message, thread_id, callbacks=None): runtime._callback_handler_type = NemoRelayCallbackHandler first = await runtime._invoke_with_telemetry( - "hello", "request-1", "invocation-1", None + "hello", make_runtime_context("request-1", "invocation-1"), None ) second = await runtime._invoke_with_telemetry( - "hello again", "request-2", "invocation-2", None + "hello again", make_runtime_context("request-2", "invocation-2"), None ) assert (first.error, first.telemetry_error) == (None, None) From 0dd4e6fcc8e86359471df83d514d4d8de48f6d56 Mon Sep 17 00:00:00 2001 From: mnajafian-nv Date: Wed, 7 Oct 2026 18:47:48 -0700 Subject: [PATCH 3/5] refactor: build NOOA Relay scope metadata with the shared helper The NOOA adapter spelled the three reserved NeMo Fabric correlation keys inline. Use relay_correlation_metadata() so every in-process adapter emits the keys from one definition and cannot drift. The emitted keys and values are unchanged, and the adapter still does not seed a Relay propagation root from the request ID. Signed-off-by: mnajafian-nv --- .../python/nooa/src/nemo_fabric_adapters/nooa/telemetry.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/adapters/python/nooa/src/nemo_fabric_adapters/nooa/telemetry.py b/adapters/python/nooa/src/nemo_fabric_adapters/nooa/telemetry.py index 28d95e2bd..afd185666 100644 --- a/adapters/python/nooa/src/nemo_fabric_adapters/nooa/telemetry.py +++ b/adapters/python/nooa/src/nemo_fabric_adapters/nooa/telemetry.py @@ -259,11 +259,7 @@ async def invoke( common_utils.reject_inherited_relay_plugin_config(activation.report) uninstall = install_nemo_relay_compat(agent.event_manager) try: - metadata = { - "nemo_fabric_request_id": runtime_context.request_id, - "nemo_fabric_invocation_id": runtime_context.invocation_id, - "nemo_fabric_runtime_id": runtime_context.runtime_id, - } + metadata = common_utils.relay_correlation_metadata(runtime_context) try: with scope.scope( self._scope_name, From 51f374c6605d713882ea8e9b61b2758cd9980873 Mon Sep 17 00:00:00 2001 From: mnajafian-nv Date: Wed, 7 Oct 2026 18:51:32 -0700 Subject: [PATCH 4/5] docs: document reserved NeMo Fabric Relay correlation keys Adapter authors had no single description of which Relay metadata keys carry NeMo Fabric IDs, and consumers could not tell which adapters emit them or how to export them to OpenTelemetry. Describe the three reserved keys and the helper pattern in the common adapter README, state that the CLI gateway adapters and the Hermes Agent plugin path do not attach them yet, and show the promote_metadata_prefixes endpoint setting that exports them as span attributes. Keep the adapter-building skill in parity with the new helper. Signed-off-by: mnajafian-nv --- adapters/python/common/README.md | 66 +++++++++++++++++++++++ skills/nemo-fabric-build-adapter/SKILL.md | 8 ++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/adapters/python/common/README.md b/adapters/python/common/README.md index 4e2576b3a..17e537cd5 100644 --- a/adapters/python/common/README.md +++ b/adapters/python/common/README.md @@ -148,3 +148,69 @@ This helper does not apply to adapters that send telemetry through an external Relay gateway or whose upstream integration creates an isolated scope context. Those adapters retain their native session correlation until their Relay boundary accepts a per-turn propagation context. + +### Correlation Metadata Keys + +Adapters that own their invocation-level Agent scope attach NeMo Fabric IDs to +that root scope as Relay metadata. The following metadata keys are reserved for +this purpose, and telemetry consumers match them literally: + +| Relay metadata key | `RuntimeContext` field | Meaning | +| --- | --- | --- | +| `nemo_fabric_request_id` | `request_id` | Correlates the caller's logical request. A caller can reuse the value across retries, so several invocations can share it. | +| `nemo_fabric_invocation_id` | `invocation_id` | Identifies one invocation. NeMo Fabric assigns a new value to every invocation, so this key joins Relay telemetry to exactly one `RunResult`. | +| `nemo_fabric_runtime_id` | `runtime_id` | Identifies the runtime that processed the invocation. One runtime can process multiple invocations. | + +Build the keys with +`nemo_fabric_adapters.common.utils.relay_correlation_metadata()` and merge them +into the metadata that `relay_request_context()` returns, as in the following +example. Merging rather than replacing keeps any key that +`relay_request_context()` adds, such as `nemo_fabric_session_root`. + +```python +import nemo_fabric_adapters.common.utils as common_utils +from nemo_relay import ScopeType +from nemo_relay import scope + +request_context, metadata = common_utils.relay_request_context( + context.request_id, request.relay_session_root +) +metadata.update(common_utils.relay_correlation_metadata(context)) +with ( + request_context, + scope.scope("my-adapter.request", ScopeType.Agent, metadata=metadata), +): + ... +``` + +Nested scopes do not repeat the keys because the Relay scope hierarchy already +links them to the root scope. The LangChain Deep Agents, mini-SWE-agent, and +NOOA adapters attach all three keys. NOOA calls only +`relay_correlation_metadata()`, so its request ID does not become the +propagated Relay root. + +Claude, Codex, and Pi send telemetry through an external Relay gateway and do +not yet carry per-invocation NeMo Fabric IDs into Relay. Hermes Agent emits +Relay telemetry through its own plugin, so its adapter does not attach these +keys either. Remote Agent forwards only `nemo_fabric_request_id`, in the remote +API request body. + +ATOF records carry these keys in the root scope's event metadata. To export +them as OpenTelemetry span attributes, add the `nemo_fabric_` prefix to +`promote_metadata_prefixes` on the trace endpoint. NeMo Fabric passes the field +to Relay unchanged: + +```python +from nemo_fabric import RelayOpenTelemetryEndpointConfig + +endpoint = RelayOpenTelemetryEndpointConfig( + type="gen_ai", + endpoint="http://localhost:4318/v1/traces", + promote_metadata_prefixes=["nemo_fabric_"], +) +``` + +Relay promotes the keys onto the invocation's root Agent span; child spans +share that span's trace. Refer to "Event Metadata Promotion" in the +[NeMo Relay OpenTelemetry documentation](https://github.com/NVIDIA/NeMo-Relay/blob/0.9.3/docs/configure-plugins/observability/opentelemetry.mdx) +for prefix syntax and collision rules. diff --git a/skills/nemo-fabric-build-adapter/SKILL.md b/skills/nemo-fabric-build-adapter/SKILL.md index 523a6feec..6cd4e6c7a 100644 --- a/skills/nemo-fabric-build-adapter/SKILL.md +++ b/skills/nemo-fabric-build-adapter/SKILL.md @@ -247,7 +247,13 @@ instead, a UUID request ID stays the parent (otherwise the session root is), and `nemo_fabric_session_root` is added to the metadata, so the caller's invocations share one Relay session. Context keys do not control propagation. An unusable session root falls back to a usable UUID request ID without raising; if neither -value is usable, the helper returns `nullcontext()` without setting propagation. Do not apply this pattern to an external Relay gateway or an +value is usable, the helper returns `nullcontext()` without setting propagation. Merge +`nemo_fabric_adapters.common.utils.relay_correlation_metadata(context)` into +that metadata with `metadata.update(...)` rather than replacing it, so keys +from `relay_request_context()` reach the scope. `relay_correlation_metadata()` +returns the reserved `nemo_fabric_request_id`, `nemo_fabric_invocation_id`, and +`nemo_fabric_runtime_id` keys that consumers use to join Relay telemetry to a +NeMo Fabric result. Do not apply this pattern to an external Relay gateway or an upstream integration that creates an isolated scope context unless its boundary accepts a per-turn propagation context. From 929752440aa87c9510b79434fcf62def8dbfde50 Mon Sep 17 00:00:00 2001 From: mnajafian-nv Date: Thu, 8 Oct 2026 00:07:56 -0700 Subject: [PATCH 5/5] refactor: build LangGraph example Relay metadata with the shared helper The LangGraph custom-agent example, which the adapter-building skill points authors to, still spelled nemo_fabric_runtime_id and nemo_fabric_invocation_id by hand. Merge relay_correlation_metadata() into the relay_request_context() metadata instead, so the example and the first-party adapters build the reserved keys from one definition. The emitted keys and values are unchanged. Signed-off-by: mnajafian-nv --- examples/langgraph_custom_agent/adapter/telemetry.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/examples/langgraph_custom_agent/adapter/telemetry.py b/examples/langgraph_custom_agent/adapter/telemetry.py index 785e7b125..1f1e688f2 100644 --- a/examples/langgraph_custom_agent/adapter/telemetry.py +++ b/examples/langgraph_custom_agent/adapter/telemetry.py @@ -135,12 +135,7 @@ async def observe_invocation( request_context, metadata = common_utils.relay_request_context( context.request_id, session_root ) - metadata.update( - { - "nemo_fabric_runtime_id": context.runtime_id, - "nemo_fabric_invocation_id": context.invocation_id, - } - ) + metadata.update(common_utils.relay_correlation_metadata(context)) with ( request_context, scope.scope(