Observability

Migrate From the Legacy Recorder

Move an agent from the legacy recorder to OpenTelemetry in the current SDK releases (Python 0.8.17, TypeScript 0.8.23). Learn what was removed, what to change, and why there is no runtime fallback to the old path.

This guide is for developers and operators who run an ArmorIQ SDK that still uses the legacy recorder (ObservabilityRecorder). You get the list of removed APIs, the steps to move to OpenTelemetry, and a clear rule about what the SDK will and will not do if something fails.

Migration support and runtime fallback are different things

These two ideas are easy to confuse.

Migration supportRuntime fallback
What it isThe ArmorIQ backend keeps an old route open for a limited time, so an older client that you have not upgraded yet still delivers data.The SDK changes to another path on its own when the main path fails.
Who does itThe backendThe SDK
Does it exist?Yes, for a limited time.No. The current SDKs have none.
Which routePOST /observability/spans (old JSON route)Not applicable
Is it permanent?No. ArmorIQ plans to remove the old route after all clients have migrated.Not applicable

Migration support. The backend still accepts POST /observability/spans from older SDK clients. This gives you time to upgrade. Do not build anything new on that route. ArmorIQ plans to remove it after all consumers move to the current SDK, and it will not bring it back as a rollback path. Old traces that are already stored stay readable.

No runtime fallback. The current SDK sends traces one way only: OTLP to POST /v1/traces, or to the OTLP endpoint or provider that you choose. It never sends to the old route. The SDK has no pipeline setting and no mixed mode. If a destination is missing, rejected, or not reachable, the SDK exports nothing and the agent continues. It does not pick another destination, another transport, or local storage. A test in each SDK checks that the production code contains no reference to the old route.

What changed

The current releases (Python 0.8.17, TypeScript 0.8.23) break compatibility with the legacy recorder. If your version range does not include them, change it when you are ready to move.

RemovedUse instead
The in-memory recorder and shipper: ObservabilityRecorder, ObservabilityShipper, and the recorder handle functions (the functions that started and ended traces and spans by hand)The SDK builds an OpenTelemetry span tree for each session by itself. You call nothing.
ObservabilityConfig (Python) and defaultObservabilityConfig and ObservabilityConfig (TypeScript)ObservabilityOptions on the client, and the per-session switch below
Python: ShipperConfig, TraceSummary, the JSON schemas, and the session members observability_recorder and active_plan_trace_contextNothing. The SDK handles these inside the session.
TypeScript: the schema and trace-summary exports, and ArmorIQSession.observabilityRecorder and ArmorIQSession.activePlanTraceContextsession.otelSession
ObservabilityOptions.pipeline, the pipeline mode type, and ARMORIQ_OTEL_PIPELINENothing. OpenTelemetry is the only path.
ObservabilityConfig.enabled (Python)SessionOptions(observability_enabled=False)
The old environment variables ARMORIQ_OBSERVABILITY_ENDPOINT and ARMORIQ_OBSERVABILITY_PRODUCTThe SDK no longer reads them. ArmorIQ takes your organization and product from your API key. To send elsewhere, use ARMORIQ_OTEL_EXPORTER and the standard OTEL_EXPORTER_OTLP_* variables.
The Python model price table: MODEL_PRICES, ModelPrice, and compute_cost_usdArmorIQ prices model usage when it receives a span. Pass cost_usd only when your provider reports a cost.
POST /observability/spansPOST /v1/traces

Two things look different in the dashboard after you move. The SDK now makes one trace for each session. Its root span is armoriq.agent.run, and its plan is a child span named armoriq.intent.plan. Trace IDs are standard OpenTelemetry IDs, which have 32 hexadecimal characters.

Move your agent

  1. Upgrade the SDK. For Python install armoriq-sdk==0.8.17. For TypeScript install @armoriq/sdk@0.8.23. Change any version range that excludes these versions.
  2. Delete recorder code. Remove every use of the recorder, the shipper, the handle functions, and the trace summary. Remove manual start, end, and flush calls for traces and spans. If you call session.record_generation(...) in Python, you can keep it. It now adds a model span.
  3. Move your settings.
    • To turn tracing off for one session in Python, use SessionOptions(observability_enabled=False).
    • To turn tracing off for one session in TypeScript, use startSession({ observability: { enabled: false } }).
    • To send traces to your own endpoint, use the settings in Choose who exports your traces.
  4. Keep your session close. The close that ends your session also ends the trace. Framework adapters do it for you. See Set up tracing.
  5. Check the first trace. Run the agent once. Open Observability and confirm that the trace has your policy and tool spans. Read What data is captured so that you know what is stored in your organization capture mode.
  6. Check your own tooling. If a script reads traces from the API, read the API reference. Spans now have OpenTelemetry names such as gen_ai.chat and armoriq.tool. Group operations by the armoriq.operation.category attribute, not by span name. See the data model.

What does not change

  • Policy decisions and enforcement. They never depend on telemetry.
  • Your API key and organization. ArmorIQ reads both from the key.
  • Old traces. They stay in ArmorIQ and stay readable.
  • The fail-open rule. A tracing error never changes the result of your agent.

ArmorClaude and ArmorCodex

ArmorClaude and ArmorCodex builds that bundle an older SDK still send each turn to the old route. Builds that bundle the current SDK send over OTLP. Check which SDK your plugin build uses. See ArmorCodex and ArmorClaude.

Roll back

The safe way to roll back is to turn tracing off. Set ARMORIQ_OBSERVABILITY=off, or use the per-session switch above. Policy enforcement keeps working. Your organization can also set the capture mode to off in Settings > Observability. See Organization controls.

You can also keep your older SDK for now. That works only while the backend still accepts the old route, so treat it as a short-term step. The SDK will not fall back to the old route for you.

Next steps

On this page