Skip to content

[Bug]: trajectory_context redacts structural scope metadata #528

Description

@bbednarski9

Affected area

  • Middleware or guardrails
  • Plugins
  • Observability or exporters
  • Documentation or examples

Current behavior

On the current release/0.6 branch, a composed PII-redaction profile using preset = "trajectory_context" sanitizes generic scope metadata before subscriber fan-out. String-valued classification fields that are not on the preset's analytical-key allowlist are replaced with the configured replacement.

Observed examples include:

nemo_relay.start.metadata.agent_kind = "[REDACTED]"
nemo_relay.end.metadata.agent_kind = "[REDACTED]"
nemo_relay.start.metadata.nemo_relay_scope_role = "[REDACTED]"
nemo_relay.start.metadata.hook_event_name = "[REDACTED]"

custom_mark_payload_policy = "preserve" does not affect these values because it applies only to unknown custom Mark payloads, not Scope metadata.

This conflicts with the documented trajectory_context contract, which says the preset preserves agent hierarchy while removing conversational content. Relay itself consumes nemo_relay_scope_role when classifying turn and subagent structure.

Relevant implementation:

  • Every composed profile currently enables all five sanitization surfaces in profile_as_legacy_config.
  • Enabling LLM or tool input/output installs generic scope start/end sanitizers.
  • TrajectorySanitizer::sanitize_event_fields sanitizes scope metadata with a fixed analytical-key allowlist.
  • The allowlist does not include nemo_relay_scope_role, hook_event_name, or harness-provided agent_kind.

Expected behavior

trajectory_context should preserve trusted structural and classification metadata required to reconstruct and identify a trajectory while continuing to redact LLM content, tool content, delegated instructions, history, and other content-bearing values.

At minimum:

  • Canonical Relay structural fields such as nemo_relay_scope_role remain usable after sanitization.
  • Agent hierarchy and turn/subagent classification remain reconstructable.
  • Harness identity, if exposed as a supported Relay field, uses a canonical trusted attribute that is explicitly outside content redaction.
  • Documentation accurately distinguishes trusted structural metadata from potentially content-bearing arbitrary metadata.

Steps to reproduce

  1. Use a profile-array PII configuration:

    [[components]]
    kind = "pii_redaction"
    enabled = true
    
    [components.config]
    version = 1
    codec = "openai_chat"
    
    [[components.config.profiles]]
    mode = "builtin"
    priority = 80
    
    [components.config.profiles.builtin]
    preset = "trajectory_context"
    replacement = "[REDACTED]"
    custom_mark_payload_policy = "preserve"
  2. Run a coding-agent or nested-agent trajectory that emits scope metadata containing agent_kind, nemo_relay_scope_role, or hook_event_name.

  3. Export the sanitized events through OpenTelemetry or ATIF.

  4. Observe that the metadata keys remain present but their classification values are replaced with [REDACTED].

  5. Attempt to classify the harness or recover turn/subagent roles from explicit metadata.

Environment

  • NeMo Relay branch: release/0.6
  • Commit: 239a4231ac43f0a4b82ff39fd70fec67bcc19998
  • PII configuration schema: version 1, profile-array mode
  • Preset: trajectory_context
  • Export path: OpenTelemetry/ATIF observability events
  • Providers: behavior is in the common event sanitizer and is not provider-specific

Impact

Affected deployments cannot reliably classify the originating harness or consume some Relay structural metadata after enabling trajectory_context. Falling back to span names or model names is heuristic and not a stable replacement for explicit metadata.

There is no precise declarative workaround in profile-array mode today:

  • Profiles always cover the complete pre-subscriber boundary.
  • Generic scope sanitization is coupled to the LLM/tool input and output flags.
  • trajectory_context cannot be combined with target_paths.
  • custom_mark_payload_policy does not control Scope metadata.

Raw sanitize middleware or manually maintained non-preset target-path policies are possible alternatives, but they lose the supported preset contract and are fragile across provider/event shapes.

Relates to #513 and #525.

Metadata

Metadata

Assignees

Labels

Bugissue describes bug; PR fixes bug

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions