---
name: Maintain Observability
slug: maintain-observability
category: DevOps
description: Maintain Observability keeps NeMo Relay event fields, exporter behavior, and binding config aligned across ATIF and typed OpenTelemetry projections. Use it when changing observability lifecycle, endpoint handling, or docs for subscriber/exporter behavior.
github: "https://github.com/NVIDIA/NeMo-Relay/tree/main/.agents/skills/maintain-observability"
language: Rust
stars: 165
forks: 67
install: "npx degit https://github.com/NVIDIA/NeMo-Relay/tree/main/.agents/skills/maintain-observability ~/.claude/skills/maintain-observability"
installs_to: ~/.claude/skills/maintain-observability
source_path: .agents/skills/maintain-observability/SKILL.md
collection_size: 25
category_size: 1075
collection_url: "https://dirskills.com/collections/NVIDIA/NeMo-Relay"
added: 2026-09-08T05:35:19.951Z
last_synced: 2026-09-08T05:35:19.951Z
canonical_url: "https://dirskills.com/skills/maintain-observability"
---

# Maintain Observability

Maintain Observability keeps NeMo Relay event fields, exporter behavior, and binding config aligned across ATIF and typed OpenTelemetry projections. Use it when changing observability lifecycle, endpoint handling, or docs for subscriber/exporter behavior.

**Install:**

```bash
npx degit https://github.com/NVIDIA/NeMo-Relay/tree/main/.agents/skills/maintain-observability ~/.claude/skills/maintain-observability
```

## README

# Maintain Observability Surfaces

## Companion Guidance

Use `karpathy-guidelines` alongside this skill for implementation or review
work. Keep changes scoped, surface assumptions, and define focused validation
before editing.

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 `just test-python`, `just test-go`, and `just test-node` when
  binding-native config or lifecycle changed.
- Update docs and examples in the same branch.

## 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`
- `validate-change`
