Agent Trajectory Observability Format (ATOF)#

Use the atof section when you want the raw Agent Trajectory Observability Format (ATOF) 0.1 event stream written as JSONL.

ATOF JSONL export is useful for local debugging, offline inspection, and preserving the canonical event stream before it is translated into another format.

plugins.toml Example#

version = 1

[[components]]
kind = "observability"
enabled = true

[components.config]
version = 1

[components.config.atof]
enabled = true
output_directory = "logs"
filename = "events.jsonl"
mode = "overwrite"

This configuration registers the plugin-managed ATOF exporter and writes one JSON object per lifecycle event to logs/events.jsonl.

Fields#

Field

Default

Notes

enabled

false

Must be true to write events.

output_directory

Current working directory

Directory containing the JSONL file.

filename

Timestamped nemo-relay-events-*.jsonl

Explicit output filename.

mode

append

append or overwrite.

Expected Output#

Each emitted scope, tool, LLM, middleware, or mark event is written as one ATOF JSON object per line. For event field semantics, see Events.

Register the plugin before instrumented work starts and clear it during shutdown so file handles flush.

Plugin Configuration#

Use plugin configuration when the application should let NeMo Relay own the ATOF exporter lifecycle.

from nemo_relay import plugin
from nemo_relay.observability import AtofConfig, ComponentSpec, ObservabilityConfig

config = plugin.PluginConfig(
    components=[
        ComponentSpec(
            ObservabilityConfig(
                atof=AtofConfig(
                    enabled=True,
                    output_directory="logs",
                    filename="events.jsonl",
                    mode="overwrite",
                )
            )
        )
    ]
)

report = plugin.validate(config)
if any(diagnostic["level"] == "error" for diagnostic in report["diagnostics"]):
    raise RuntimeError(report["diagnostics"])

await plugin.initialize(config)
try:
    # Run instrumented application work here.
    pass
finally:
    plugin.clear()
const plugin = require("nemo-relay-node/plugin");
const observability = require("nemo-relay-node/observability");

await plugin.initialize({
  version: 1,
  components: [
    observability.ComponentSpec({
      version: 1,
      atof: observability.atofConfig({
        enabled: true,
        output_directory: "logs",
        filename: "events.jsonl",
        mode: "overwrite",
      }),
    }),
  ],
});

try {
  // Run instrumented application work here.
} finally {
  plugin.clear();
}
use nemo_relay::observability::plugin_component::{
    AtofSectionConfig, ComponentSpec, ObservabilityConfig,
};
use nemo_relay::plugin::{initialize_plugins, validate_plugin_config, PluginConfig};

let component = ComponentSpec::new(ObservabilityConfig {
    atof: Some(AtofSectionConfig {
        enabled: true,
        output_directory: Some("logs".into()),
        filename: Some("events.jsonl".into()),
        mode: "overwrite".into(),
    }),
    ..ObservabilityConfig::default()
});

let config = PluginConfig {
    version: 1,
    components: vec![component.into()],
    policy: Default::default(),
};

let report = validate_plugin_config(&config);
assert!(!report.has_errors());

let active = initialize_plugins(config).await?;

Manual API#

Use the manual AtofExporter API when a test or script needs a custom subscriber name or explicit registration window.

from nemo_relay import AtofExporter, AtofExporterConfig, AtofExporterMode

config = AtofExporterConfig()
config.output_directory = "logs"
config.filename = "events.jsonl"
config.mode = AtofExporterMode.Overwrite

exporter = AtofExporter(config)
exporter.register("atof-exporter")

# Run instrumented application work here.

exporter.force_flush()
exporter.deregister("atof-exporter")
exporter.shutdown()
const { AtofExporter } = require("nemo-relay-node");

const exporter = new AtofExporter({
  outputDirectory: "logs",
  filename: "events.jsonl",
  mode: "overwrite",
});
exporter.register("atof-exporter");

try {
  // Run instrumented application work here.

  exporter.forceFlush();
} finally {
  exporter.deregister("atof-exporter");
  exporter.shutdown();
}
use nemo_relay::observability::atof::{
    AtofExporter, AtofExporterConfig, AtofExporterMode,
};

let config = AtofExporterConfig::new()
    .with_output_directory("logs")
    .with_filename("events.jsonl")
    .with_mode(AtofExporterMode::Overwrite);
let exporter = AtofExporter::new(config)?;
exporter.register("atof-exporter")?;

// Run instrumented application work here.

exporter.force_flush()?;
let _ = exporter.deregister("atof-exporter")?;
exporter.shutdown()?;

Common Validation Failures#

  • mode is not append or overwrite.

  • The output directory is not writable at runtime.

  • ATOF is enabled in a target that cannot access the native filesystem.