Observability Configuration

View as Markdown

Use this page when an application should install standard observability exporters from one plugin configuration document instead of manually registering each subscriber.

The plugin kind is observability. It is registered by the core runtime, so applications do not need to register a plugin implementation before validation or initialization.

For plugin file discovery, precedence, merge behavior, editor controls, and gateway conflict rules, see Plugin Configuration Files.

Observability plugin configuration uses the generic NeMo Relay plugin document shape, so field names are snake_case in every binding. This differs from Node.js runtime classes such as OpenTelemetrySubscriber, which use Node-native camelCase option names outside the plugin system.

What It Installs

Every exporter section is optional and defaults to disabled. A section is active only when it includes enabled: true.

SectionRuntime behavior
atofRegisters a global Agent Trajectory Observability Format (ATOF) JSONL exporter for raw lifecycle events.
atifRegisters one Agent Trajectory Interchange Format (ATIF) dispatcher that writes one trajectory file for each top-level agent scope.
opentelemetryRegisters a global OpenTelemetry OTLP subscriber.
openinferenceRegisters a global OpenInference OTLP subscriber.

subscriber_name is not part of this config. The runtime infers component-local subscriber names and registers them under the observability plugin namespace:

  • Agent Trajectory Observability Format (ATOF): __nemo_relay_plugin__observability__atof
  • Agent Trajectory Interchange Format (ATIF) dispatcher: __nemo_relay_plugin__observability__atif
  • Per-agent ATIF scope subscriber: __nemo_relay_plugin__observability__atif-{agent_scope_uuid}
  • OpenTelemetry: __nemo_relay_plugin__observability__opentelemetry
  • OpenInference: __nemo_relay_plugin__observability__openinference

plugins.toml Example

1version = 1
2
3[[components]]
4kind = "observability"
5enabled = true
6
7[components.config]
8version = 1
9
10[components.config.atof]
11enabled = true
12output_directory = "logs"
13filename = "events.jsonl"
14mode = "overwrite"
15
16[[components.config.atof.endpoints]]
17url = "http://localhost:8080/events"
18transport = "http_post"
19timeout_millis = 3000
20
21[components.config.atof.endpoints.headers]
22authorization = "Bearer <token>"
23
24[components.config.atif]
25enabled = true
26output_directory = "logs"
27filename_template = "trajectory-{session_id}.json"
28
29[components.config.opentelemetry]
30enabled = true
31transport = "http_binary"
32endpoint = "http://localhost:4318/v1/traces"
33service_name = "nemo-relay"
34service_namespace = "agent"
35service_version = "0.4.0"
36instrumentation_scope = "nemo-relay-observability"
37timeout_millis = 3000
38
39[components.config.opentelemetry.headers]
40authorization = "Bearer <token>"
41
42[components.config.opentelemetry.resource_attributes]
43"deployment.environment" = "dev"
44"service.instance.id" = "local"
45
46[components.config.openinference]
47enabled = true
48transport = "http_binary"
49endpoint = "http://localhost:6006/v1/traces"
50service_name = "nemo-relay"
51service_namespace = "agent"
52service_version = "0.4.0"
53instrumentation_scope = "nemo-relay-openinference"
54timeout_millis = 3000
55
56[components.config.openinference.headers]
57authorization = "Bearer <token>"
58
59[components.config.openinference.resource_attributes]
60"deployment.environment" = "dev"
61"service.instance.id" = "local"
62
63[components.config.policy]
64unknown_component = "warn"
65unknown_field = "warn"
66unsupported_value = "error"

Include only the sections you want to configure. In layered plugins.toml files, omission inherits lower-precedence values; write enabled = false to disable an inherited section.

Failure Behavior

NeMo Relay treats exporter configuration and exporter delivery failures differently. Configuration and activation failures are fail-closed for the observability setup: validation or initialization returns an error before the new plugin configuration becomes active. Runtime delivery failures are fail-open for application work: the tool, LLM, or agent run continues while the affected exporter records, logs, or reports the delivery problem.

FailureBehavior
Invalid plugins.toml, duplicate component kinds, malformed component shapes, unsupported values, unavailable exporter features, ATOF file-open failures, invalid ATOF endpoint config, unavailable ATOF streaming support, or ATOF endpoint worker startup failuresValidation or initialization fails. If a previous plugin configuration was active, NeMo Relay attempts to restore it after a failed replacement.
ATOF event serialization or file write/flush failure after activationApplication work continues. The exporter stores the failure, stops accepting later events for that file, and returns the stored error from force_flush() or shutdown().
ATOF streaming endpoint connection or send failure after activationFile output and other already-started endpoints continue. Endpoint failures are logged with the endpoint index; endpoint flush and close timeouts are logged instead of blocking shutdown indefinitely.
ATIF local file write, HTTP storage, or S3-compatible storage failureApplication work continues. The failed sink is recorded as unhealthy and skipped for later trajectories. Other configured sinks continue to receive writes.
ATIF dispatcher serialization or subscriber-management failureThe ATIF dispatcher records a fatal exporter error and stops observing later ATIF events. Other observability sections continue to run.
OpenTelemetry or OpenInference construction failurePlugin initialization fails before the subscriber is registered.
OpenTelemetry or OpenInference export failure after registrationApplication work continues. The OTLP exporter reports failures through its runtime logging and flush or shutdown path.

Missing or delayed telemetry is represented as absence of exporter output, not as synthetic success or failure events. NeMo Relay does not backfill events for subscribers that register late. If the plugin is cleared while an agent scope is still open, the ATIF dispatcher writes the partial trajectory it has already observed.

Use nemo-relay doctor to validate local ATOF and ATIF output directories, OTLP HTTP endpoints, and ATOF streaming endpoints. Validate ATIF remote storage destinations, including HTTP storage and S3-compatible storage, with exporter logs and backend-side checks because nemo-relay doctor does not probe atif.storage. For local artifact paths, verify that the running process can create the output directory and that teardown calls plugin.clear() or clear_plugin_configuration() before the process exits.

Per-Language Plugin Configuration

1import asyncio
2
3from nemo_relay import plugin, scope, ScopeType
4from nemo_relay.observability import (
5 AtifConfig,
6 AtofConfig,
7 ComponentSpec,
8 ObservabilityConfig,
9 OtlpConfig,
10)
11
12config = plugin.PluginConfig(
13 components=[
14 ComponentSpec(
15 ObservabilityConfig(
16 atof=AtofConfig(
17 enabled=True,
18 output_directory="logs",
19 filename="events.jsonl",
20 mode="overwrite",
21 ),
22 atif=AtifConfig(
23 enabled=True,
24 output_directory="logs",
25 filename_template="trajectory-{session_id}.json",
26 ),
27 opentelemetry=OtlpConfig(
28 enabled=True,
29 endpoint="http://localhost:4318/v1/traces",
30 service_name="nemo-relay",
31 service_namespace="agent",
32 service_version="0.4.0",
33 instrumentation_scope="nemo-relay-observability",
34 resource_attributes={"deployment.environment": "dev"},
35 ),
36 openinference=OtlpConfig(
37 enabled=True,
38 endpoint="http://localhost:6006/v1/traces",
39 service_name="nemo-relay",
40 service_namespace="agent",
41 service_version="0.4.0",
42 instrumentation_scope="nemo-relay-openinference",
43 resource_attributes={"deployment.environment": "dev"},
44 ),
45 )
46 )
47 ]
48)
49
50report = plugin.validate(config)
51if any(diagnostic["level"] == "error" for diagnostic in report["diagnostics"]):
52 raise RuntimeError(report["diagnostics"])
53
54async def arun():
55 async with plugin.plugin(config):
56 with scope.scope("agent", ScopeType.Agent):
57 pass
58
59asyncio.run(arun())

Validation And Teardown

Validate plugin configuration before activating it. The plugin reports unsupported transports, unsupported ATOF modes, invalid ATOF streaming endpoint URLs, non-string endpoint headers, non-positive endpoint timeouts, unsafe ATIF filename templates, unknown fields according to policy, and enabled exporters that are unavailable in the current build or target.

Call plugin.clear() or clear_plugin_configuration() during teardown. Clearing the plugin config deregisters inferred subscribers, flushes file exporters, drains and closes ATOF streaming endpoints, and shuts down owned OTLP subscribers.

Use manual subscriber/exporter APIs instead of the plugin when you need custom subscriber names, explicit per-run exporter objects, or direct control over the collection window.