Skip to Content

Migrate from LangSmith to Rius

LangSmith traces LangChain and LangGraph apps through LangChain’s callback system, and any other code through @traceable and its client wrappers. Rius takes OpenTelemetry traces, and the Rius SDK hooks the same LangChain callbacks, so for most apps the migration is a dependency and a few lines of setup, not a rewrite. This guide maps the concepts, walks the migration paths, and ends with a cutover checklist. Run both backends in parallel during the evaluation; nothing here requires a hard switch.

TL;DR: For a LangChain or LangGraph app, install the Rius SDK with the langchain extra and call rius.init() (Path A). For @traceable, wrap_openai and wrap_anthropic, swap them for @rius.observe and the Rius integrations (Path B). If you cannot change code yet, LangSmith’s own OpenTelemetry export can send to Rius (Path C), with gaps listed below.

Why migrate from LangSmith to Rius

Rius is agent observability built on OpenTelemetry: traces arrive over plain OTLP, so the same instrumentation works with any backend. On top of the traces you get session and user grouping, server-side cost, alerts, and an MCP server so your coding agent can query production traces. With the Rius SDK you also see which agent processes are alive, and, with partial spans turned on, runs still in progress. LangSmith features with no Rius equivalent are listed in what does not carry over.

Concept mapping: LangSmith vs Rius

LangSmithRiusNotes
ProjectAgent (named by service.name)Rius groups traces by agent, named by service.name (service_name in rius.init()). Give each environment (production, staging) its own workspace and API key.
TraceTraceSame tree of nested steps.
RunSpanEach step of a trace is an OpenTelemetry span.
Run type (llm, chain, tool, retriever, embedding)Span kind (LLM, CHAIN, TOOL, RETRIEVER, EMBEDDING, AGENT)Set with kind= on @rius.observe; integrations set it for you.
LLM runGenerationA span with model, tokens, and cost. Rius computes cost server-side from model and tokens.
Thread (thread_id or session_id metadata)Sessionwith rius.session(thread_id): stamps session.id on every span in scope, child spans included.
MetadataSpan attributesSee Path B.
TagsSpan attributesNo separate tag concept; use an attribute.
FeedbackNot availableSee what does not carry over.
Datasets, experiments, evaluatorsNot availableSee what does not carry over.
Prompt Hub and PlaygroundNot availableSee what does not carry over.

Choose your path

Path A: LangChain and LangGraph apps

The Rius SDK’s langchain integration hooks LangChain’s callback system, the same hook LangSmith uses, so anything that runs through it is traced: LCEL chains, agents built with create_agent, and LangGraph nodes.

pip install "glassflow-rius[langchain]"

Then replace the LangSmith environment with one init() call at startup:

# Before: LangSmith export LANGSMITH_TRACING=true export LANGSMITH_API_KEY="lsv2_..." export LANGSMITH_PROJECT="my-agent" # After: Rius export RIUS_API_KEY="ri_..."
import rius client = rius.init(service_name="my-agent") # build and run your chains, agents and graphs exactly as before from langchain.agents import create_agent agent = create_agent("openai:gpt-4o-mini", tools=[get_weather]) agent.invoke({"messages": [{"role": "user", "content": "Weather in Lisbon?"}]})

In a short-lived Python script, call client.flush() before it exits so every call is counted once; see Count the call once.

The trace shows the graph as nested spans: the agent run, each model step and tool step, with the model call as a generation carrying the model, token counts, and cost. Unset LANGSMITH_TRACING once you no longer want LangSmith’s callback tracer to run alongside.

For LangChain.js, the TypeScript SDK does the same; see the LangChain integration for the install line.

Without the Rius SDK

To use your own OpenTelemetry setup instead of the SDK, install openinference-instrumentation-langchain from OpenInference, an open-source set of OpenTelemetry instrumentations for LLM libraries. Wire an OTLP exporter to Rius as shown on the OpenInference page, swapping OpenAIInstrumentor for LangChainInstrumentor:

from openinference.instrumentation.langchain import LangChainInstrumentor LangChainInstrumentor().instrument(tracer_provider=provider)

Raise the span attribute limit, for example with OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT=4096, as that page describes. Without the SDK you get no view of which agent processes are alive or of runs in progress (liveness).

Path B: swap @traceable and the client wrappers for the Rius SDK

For code instrumented with the LangSmith SDK, the Rius SDK has direct equivalents. The client wrappers become nothing at all: rius.init() instruments the OpenAI and Anthropic libraries process-wide, so every client you create is traced.

pip install "glassflow-rius[openai,anthropic]"
LangSmith (Python)Rius (Python)
LANGSMITH_TRACING=true, LANGSMITH_API_KEY, LANGSMITH_PROJECTRIUS_API_KEY plus rius.init(service_name="my-agent")
wrap_openai(OpenAI())OpenAI(), traced by the OpenAI integration
wrap_anthropic(Anthropic())Anthropic(), traced by the Anthropic integration
@traceable@rius.observe
@traceable(name="Chat Pipeline")@rius.observe(name="Chat Pipeline")
@traceable(run_type="tool")@rius.observe(kind=rius.SpanKind.TOOL)
@traceable(run_type="retriever")@rius.observe(kind=rius.SpanKind.RETRIEVER)
@traceable(run_type="llm") around a call you trace by handrius.start_as_current_generation(model=..., provider=...) with set_usage(); see generations
with trace("name", "chain", inputs=...)with rius.start_as_current_span("name") as span: then span.set_input(...)
metadata={"thread_id": thread_id}with rius.session(thread_id): around the call
metadata={...}, tags=[...]span.set_attribute(key, value) inside rius.start_as_current_span(...), or opentelemetry.trace.get_current_span().set_attribute(key, value) inside an @rius.observe function

A pipeline, before and after:

# LangSmith from langsmith import traceable from langsmith.wrappers import wrap_openai from openai import OpenAI client = wrap_openai(OpenAI()) @traceable(run_type="tool") def retrieve(question: str) -> str: return search(question) @traceable(name="Chat Pipeline", metadata={"thread_id": thread_id}) def pipeline(question: str) -> str: context = retrieve(question) return client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "system", "content": f"Context: {context}"}, {"role": "user", "content": question}], ).choices[0].message.content pipeline("What does Rius ingest?")
# Rius import rius from openai import OpenAI rius.init(service_name="my-agent") client = OpenAI() # no wrapper: init() instruments the library @rius.observe(kind=rius.SpanKind.TOOL) def retrieve(question: str) -> str: return search(question) @rius.observe(name="Chat Pipeline") def pipeline(question: str) -> str: context = retrieve(question) return client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "system", "content": f"Context: {context}"}, {"role": "user", "content": question}], ).choices[0].message.content with rius.session(thread_id): pipeline("What does Rius ingest?")

Two differences worth knowing before you start:

  • Threads are a scope, not metadata. LangSmith asks you to put thread_id on every run, child runs included. rius.session() is a context manager that stamps every span started inside it, including spans from auto-instrumentation, so you set it once per request. observe takes no session argument for the same reason.
  • Process-wide instrumentation. Calling rius.init() before you create clients is enough; there is no per-client wrapper to forget. If you trace some calls by hand today with run_type="llm", check the integrations list first: you may be able to drop the manual code.

The TypeScript SDK has the same shape (observe as a wrapper function, withSession); see the tracing guide.

Path C: point LangSmith’s OpenTelemetry export at Rius

The LangSmith SDK can export its runs as OpenTelemetry spans to any OTLP endpoint, including Rius, through the standard OTEL_EXPORTER_OTLP_* variables. It needs no code change, for LangChain apps and @traceable code alike:

pip install "langsmith[otel]" export LANGSMITH_TRACING=true export LANGSMITH_OTEL_ENABLED=true export LANGSMITH_OTEL_ONLY=true # send only to the OTLP endpoint below export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.eu.console.rius-glassflow.com" export OTEL_EXPORTER_OTLP_HEADERS="authorization=Bearer <your API key>" export OTEL_SERVICE_NAME="my-agent" # LangSmith defaults it to "langsmith"

This needs langsmith 0.4.25 or newer. No LangSmith API key is needed. Recent langsmith releases also accept LANGSMITH_TRACING_MODE=otel in place of the two LANGSMITH_OTEL_* variables.

What arrives in Rius:

  • The trace tree, with LangSmith’s run names: the graph, each model and tool step, and your @traceable functions.
  • Model calls as generations with model, token counts and cost.
  • Tool runs as tool spans. Chain runs arrive without a span kind, and langchain appears as a provider (with zero tokens) in provider breakdowns.

What does not:

  • Inputs, outputs and messages: the trace view shows no content for these spans.
  • Threads. A thread_id or session_id in run metadata arrives as langsmith.metadata.thread_id, not as session.id, so traces are not grouped into sessions. Other metadata arrives the same way, as langsmith.metadata.* span attributes.
  • Live views. Seeing which agent processes are alive and, with partial spans turned on, runs still in progress needs the Rius SDK. LangSmith’s exporter sends neither.

Treat Path C as a bridge for the evaluation period, then move to Path A or B for content and sessions.

Side by side during the evaluation

Pick whichever matches your path:

  • Path A or B: run the Rius SDK in one service, or one environment, while the rest keep reporting to LangSmith. Both can also run in the same process: leaving LANGSMITH_TRACING=true set keeps LangSmith’s callback tracer running next to Rius for LangChain apps.
  • Path C: hybrid mode, LANGSMITH_OTEL_ENABLED=true without LANGSMITH_OTEL_ONLY, sends runs to LangSmith and spans to the OTLP endpoint at once. For more than one OTLP destination, use an OpenTelemetry Collector:
exporters: otlphttp/langsmith: traces_endpoint: https://api.smith.langchain.com/otel/v1/traces headers: x-api-key: ${env:LANGSMITH_API_KEY} Langsmith-Project: my_project otlphttp/rius: endpoint: https://ingest.eu.console.rius-glassflow.com encoding: proto compression: gzip headers: authorization: Bearer ${env:RIUS_API_KEY} service: pipelines: traces: receivers: [otlp] processors: [batch] exporters: [otlphttp/langsmith, otlphttp/rius]

The Collector page covers the Rius exporter, including why it must be otlphttp and not otlp.

What does not carry over from LangSmith

LangSmith is a tracing, evaluation, prompt engineering and deployment platform. Rius is agent observability, and today it has no equivalent for:

  • Evaluation: no datasets, experiments, offline or online evaluators, pairwise comparisons, or LLM-as-judge. Keep these in LangSmith or a dedicated eval tool.
  • Feedback and annotation queues: no feedback scores on runs and no human review queues.
  • Prompt Hub and Playground: no versioned prompts, prompt commits, or playground. Prompt content on spans is captured and inspectable, but there is no registry.
  • LangSmith Deployment (formerly LangGraph Platform) and LangSmith Studio: Rius does not host or run agents. It observes them wherever they run, including on LangSmith Deployment, as long as they can export OTLP.
  • Self-hosting: Rius is a hosted service only. LangSmith offers a self-hosted edition as an add-on to its Enterprise plan.
  • Historical data: existing traces stay in LangSmith; Rius starts from the first span you send it.

What you keep: trace inspection with the same nested structure, sessions and users, token and server-side cost analytics, and alerts.

If evaluations, datasets or annotation queues are load-bearing in your workflow, run both backends and keep LangSmith for those pieces rather than cutting over completely.

LangSmith to Rius cutover checklist

  1. Create a Rius workspace and API key (quickstart). New organizations start with a free trial (30 days or 500,000 spans, whichever comes first), then a paid plan; see Plans and billing.
  2. Pick your path: LangChain and LangGraph, @traceable and wrappers, or, to start without code changes, LangSmith’s OTel export.
  3. Run both backends side by side for one service or environment (how).
  4. Verify one traced request end to end: the trace tree matches what you see in LangSmith, each model call is a generation with model and token counts, and cost appears.
  5. Map threads to sessions: wrap each conversation turn in rius.session(thread_id) and check that the turns group in the sessions view.
  6. Compare both backends on real traffic for a few days: trace counts, token totals, cost.
  7. Move anything that reads from LangSmith (dashboards, alerts, internal tools) to their Rius equivalents, or deliberately leave them behind.
  8. Unset LANGSMITH_TRACING, remove @traceable and the wrappers, and revoke the LangSmith keys once nothing sends to them.

Frequently asked questions

Do I have to rewrite my LangChain or LangGraph app?

No. The Rius SDK hooks LangChain’s callbacks, the same mechanism LangSmith uses, so your chains, agents and graphs stay as they are. You add rius.init() and install the langchain extra.

Can I run LangSmith and Rius at the same time?

Yes. With the Rius SDK, leave LANGSMITH_TRACING=true set and both receive traces from the same process. With LangSmith’s OTel export, its hybrid mode or an OpenTelemetry Collector fans out to both. The migration is reversible until you remove LangSmith from your code and revoke its keys.

Is Rius compatible with the LangSmith SDK?

Partly. Rius does not accept LangSmith’s native run API, but the LangSmith SDK’s OpenTelemetry export can target Rius (Path C). Model, tokens and cost come through that way, but content and threads do not. Swap @traceable and the wrappers for the Rius SDK to get those; the mapping is one to one.

Can I import my existing LangSmith traces?

No. Rius has no importer for LangSmith runs. Keep LangSmith available for looking up history until it ages out of your retention window.

Last updated on