OpenInference#

Use the openinference section when you want NeMo Flow lifecycle events exported as OTLP trace spans with OpenInference-oriented semantics.

OpenInference export maps model-centric payloads directly into trace attributes. Scope, tool, and LLM start inputs become input.value; end outputs become output.value; LLM usage metadata maps to token-count attributes when the provider response includes usage information.

plugins.toml Example#

version = 1

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

[components.config]
version = 1

[components.config.openinference]
enabled = true
transport = "http_binary"
endpoint = "http://localhost:6006/v1/traces"
service_name = "agent-service"
service_namespace = "nemo"
service_version = "1.0.0"
instrumentation_scope = "nemo-flow-openinference"
timeout_millis = 3000

[components.config.openinference.headers]
authorization = "Bearer <token>"

[components.config.openinference.resource_attributes]
"deployment.environment" = "dev"

This configuration registers a plugin-owned OpenInference subscriber and sends OpenInference-style OTLP spans to Phoenix or another compatible backend.

Fields#

OpenInference uses the same OTLP section shape as OpenTelemetry:

Field

Default

Notes

enabled

false

Must be true to construct and register the subscriber.

transport

http_binary

http_binary or grpc.

endpoint

Exporter default

OTLP endpoint.

headers

{}

String-to-string exporter headers.

resource_attributes

{}

String-to-string OTLP resource attributes.

service_name

nemo-flow

service.name resource attribute.

service_namespace

Omitted

Optional service.namespace.

service_version

Omitted

Optional service.version.

instrumentation_scope

Omitted

Optional instrumentation scope name.

timeout_millis

3000

Export timeout.

Expected Output#

The backend should show OpenInference-oriented spans for scopes, tools, and LLM calls from the same root_uuid. LLM usage metadata appears as token counters when provider responses include usage information.

Redact sensitive event payloads with sanitize guardrails before production export.

Plugin Configuration#

Use plugin configuration when the application should let NeMo Flow own the OpenInference subscriber lifecycle.

from nemo_flow import plugin
from nemo_flow.observability import ComponentSpec, ObservabilityConfig, OtlpConfig

config = plugin.PluginConfig(
    components=[
        ComponentSpec(
            ObservabilityConfig(
                openinference=OtlpConfig(
                    enabled=True,
                    transport="http_binary",
                    endpoint="http://localhost:6006/v1/traces",
                    service_name="agent-service",
                    service_namespace="nemo",
                    service_version="1.0.0",
                    instrumentation_scope="nemo-flow-openinference",
                    resource_attributes={"deployment.environment": "dev"},
                    headers={"authorization": "Bearer <token>"},
                )
            )
        )
    ]
)

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-flow-node/plugin");
const observability = require("nemo-flow-node/observability");

await plugin.initialize({
  version: 1,
  components: [
    observability.ComponentSpec({
      version: 1,
      openinference: observability.otlpConfig({
        enabled: true,
        transport: "http_binary",
        endpoint: "http://localhost:6006/v1/traces",
        service_name: "agent-service",
        service_namespace: "nemo",
        service_version: "1.0.0",
        instrumentation_scope: "nemo-flow-openinference",
        resource_attributes: {
          "deployment.environment": "dev",
        },
        headers: {
          authorization: "Bearer <token>",
        },
      }),
    }),
  ],
});

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

let component = ComponentSpec::new(ObservabilityConfig {
    openinference: Some(OtlpSectionConfig {
        enabled: true,
        transport: "http_binary".into(),
        endpoint: Some("http://localhost:6006/v1/traces".into()),
        service_name: "agent-service".into(),
        service_namespace: Some("nemo".into()),
        service_version: Some("1.0.0".into()),
        instrumentation_scope: Some("nemo-flow-openinference".into()),
        resource_attributes: [("deployment.environment".into(), "dev".into())].into(),
        headers: [("authorization".into(), "Bearer <token>".into())].into(),
        ..OtlpSectionConfig::default()
    }),
    ..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 subscriber API when you need an explicit subscriber name or direct force_flush control.

from nemo_flow import OpenInferenceConfig, OpenInferenceSubscriber

config = OpenInferenceConfig()
config.transport = "http_binary"
config.endpoint = "http://localhost:6006/v1/traces"
config.service_name = "agent-service"
config.set_resource_attribute("deployment.environment", "dev")

subscriber = OpenInferenceSubscriber(config)
subscriber.register("openinference-exporter")

# Run instrumented application work here.

subscriber.force_flush()
subscriber.deregister("openinference-exporter")
subscriber.shutdown()
const { OpenInferenceSubscriber } = require("nemo-flow-node");

const subscriber = new OpenInferenceSubscriber({
  transport: "http_binary",
  endpoint: "http://localhost:6006/v1/traces",
  serviceName: "agent-service",
  resourceAttributes: {
    "deployment.environment": "dev",
  },
});
subscriber.register("openinference-exporter");

try {
  // Run instrumented application work here.

  subscriber.forceFlush();
} finally {
  subscriber.deregister("openinference-exporter");
  subscriber.shutdown();
}
use nemo_flow::observability::openinference::{
    OpenInferenceConfig, OpenInferenceSubscriber,
};

let config = OpenInferenceConfig::new()
    .with_service_name("agent-service")
    .with_endpoint("http://localhost:6006/v1/traces")
    .with_resource_attribute("deployment.environment", "dev");
let subscriber = OpenInferenceSubscriber::new(config)?;
subscriber.register("openinference-exporter")?;

// Run instrumented application work here.

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

Common Validation Failures#

  • transport is not http_binary or grpc.

  • Headers or resource attributes are not string-to-string maps.

  • The OpenInference feature is unavailable in the current build or target.

  • Tool and LLM calls do not use managed helpers, so spans contain only scope lifecycle data.