Change NeMo Relay event fields, subscribers, ATIF output, or typed OpenTelemetry and OpenInference projections. Do not use for instrumentation examples that leave observability contracts unchanged.
Installs into .claude/skills of the current project.
Are you the author of Maintain Observability?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/nvidia-maintain-observability)
---
name: maintain-observability
description: Change NeMo Relay event fields, subscribers, ATIF output, or typed OpenTelemetry and OpenInference projections. Do not use for instrumentation examples that leave observability contracts unchanged.
license: Apache-2.0
---
# Maintain Observability Surfaces
Use this skill when changing event fields, exporter behavior, subscriber config,
or binding parity for ATIF or the `full`, `gen_ai`, and `openinference`
OpenTelemetry projections.
## Surfaces To Keep In Sync
- Core event model and emitted fields
- `crates/core/src/observability/atif.rs`
- `crates/core/src/observability/otel.rs`
- `crates/core/src/observability/openinference.rs`
- FFI and binding-native wrappers where the config or lifecycle is exposed
- Python, Go, and Node.js config objects and subscriber/exporter methods
- Observability config version 3, where one `opentelemetry` section contains
typed endpoints and OpenInference has no standalone public surface
- Docs under `docs/about-nemo-relay/concepts/subscribers.mdx` and
`docs/configure-plugins/observability/`
## Design Checklist
- [ ] Is this an event-model change, exporter-config change, or lifecycle change?
- [ ] Do all bindings expose the same logical knobs and semantics?
- [ ] Does every OpenTelemetry endpoint require a type and nonblank destination?
- [ ] Does each endpoint resolve `header_env` values at activation and reject
missing, blank, or duplicate headers?
- [ ] Do layered ATOF sink, ATIF storage, and OpenTelemetry endpoint lists
concatenate with higher-precedence entries first?
- [ ] Are OpenTelemetry and OpenInference dependencies unconditional rather
than Cargo feature-gated?
- [ ] Does `gen_ai` avoid `nemo_relay.*`, project sanitized LLM instructions
and messages into the standard content attributes, and emit minimal spans
for scopes without GenAI semantics so their parentage is preserved?
- [ ] Does `enable_full_payloads` preserve complete sanitized LLM request input
and annotations while leaving credential removal and sanitizers active?
- [ ] Does Relay derive compliant trace and span IDs consistently across typed
OpenTelemetry endpoints while preserving lifecycle parentage?
- [ ] Are mark events, start/end events, and orphan cases still handled correctly?
- [ ] Does a sanitized tool result annotation remain opaque under
`category_profile.tool_result_annotation`, ATIF observation-result
`extra.tool_result_annotation`, and the single
`nemo_relay.tool.result.annotation` attribute in `full` and
`openinference`, while `gen_ai` omits it?
- [ ] Do examples and docs use each exporter's documented flush/deregister
order before shutdown?
- [ ] Are span or trajectory fields still derived from the intended event data?
## Validation
- Run the affected Rust crate tests plus `just test-rust` if event
fields changed.
- Run only the binding suites whose exposed configuration, lifecycle, event, or
exporter contract changed.
- Update and validate docs or examples when the public workflow, documented
observability contract, or emitted output changed.
## References
- `docs/about-nemo-relay/concepts/subscribers.mdx`
- `docs/configure-plugins/observability/about.mdx`
- `docs/configure-plugins/observability/opentelemetry.mdx`
- `crates/core/src/observability/atif.rs`
- `crates/core/src/observability/otel.rs`
- `crates/core/src/observability/openinference.rs`