LangChain
Capture traces from LangChain / LangGraph via LangSmith's OTel mode
Language support
| Setup option | Python | TypeScript |
|---|---|---|
| Voxmith skill | ✓ | ✓ |
| Voxmith SDK | ✓ | ✓ |
| OpenTelemetry through LangSmith | ✓ | ✓ |
Choose a setup method
| Method | Use it when |
|---|---|
| Voxmith skill | You want your coding agent to inspect the app, make the change, and verify it. |
| Voxmith SDK | You want explicit control over the interaction boundaries and fields. |
| OpenTelemetry | The framework already emits useful spans or you operate an OTel pipeline. |
Start with one method for a call path. Combining SDK tracking with framework OpenTelemetry on the same call can create duplicate interactions.
Recommended: Voxmith skill
Recommended. Choose this path when you want your coding agent to inspect the project, select a supported transport, make the smallest instrumentation change, send a test event, and verify that it reached Voxmith.
Install the skill once in your coding-agent environment:
npx skills add Voxmith/skills --skill voxmithRun the framework-specific prompt below from the application root. Review the resulting diff before deploying it.
Use the voxmith skill to add Voxmith analytics to this LangChain or LangGraph application.
Org ID: your-org-id
Instrument the real chain, graph, or agent invocation and verify one fresh interaction.Manual setup: Voxmith SDK
pip install voxmithnpm install voxmithaiimport voxmith
voxmith.init("your-org-id")
interaction = voxmith.begin(user_id="u-42", agent_name="langchain-support", input=prompt)
try:
result = chain.invoke({"input": prompt})
interaction.end(output=str(result))
except Exception as exc:
interaction.end(output=str(exc), success=False)
raise
finally:
voxmith.shutdown()import * as voxmith from 'voxmithai';
voxmith.init('your-org-id');
const interaction = voxmith.begin({ userId: 'u-42', agentName: 'langchain-support', input: prompt });
try {
const result = await chain.invoke({ input: prompt });
interaction.end(JSON.stringify(result));
} catch (error) {
interaction.end(String(error), false);
throw error;
} finally {
await voxmith.shutdown();
}Manual setup: OpenTelemetry
LangChain emits OTel through LangSmith. Register the OTel exporter pointing at Voxmith before building chains or agents, enable LangSmith's OTel mode, then pass session_id / user_id per call.
1. Install
Already have LangSmith and an OTLP exporter installed? Skip.
No setup yet?
pip install "langsmith[otel]" langchain \
opentelemetry-sdk opentelemetry-exporter-otlp-proto-httpnpm install langsmith @opentelemetry/api @opentelemetry/context-async-hooks \
@opentelemetry/sdk-trace-base @opentelemetry/exporter-trace-otlp-proto2. Wire LangSmith OTel pointing at Voxmith
The provider must be registered before importing or constructing LangChain objects.
Already have an OTel TracerProvider? Append Voxmith as an additional span processor:
import os
from opentelemetry import trace
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
trace.get_tracer_provider().add_span_processor(
BatchSpanProcessor(
OTLPSpanExporter(
endpoint="https://otel.voxmith.com/v1/traces",
headers={"X-Voxmith-Org-ID": os.environ["VOXMITH_ORG_ID"]},
)
)
)
os.environ["LANGSMITH_OTEL_ENABLED"] = "true"
os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_OTEL_ONLY"] = "true"No OTel yet? Full setup:
import os
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
provider = TracerProvider()
provider.add_span_processor(
BatchSpanProcessor(
OTLPSpanExporter(
endpoint="https://otel.voxmith.com/v1/traces",
headers={"X-Voxmith-Org-ID": os.environ["VOXMITH_ORG_ID"]},
)
)
)
trace.set_tracer_provider(provider)
os.environ["LANGSMITH_OTEL_ENABLED"] = "true"
os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_OTEL_ONLY"] = "true"
# Import LangChain AFTER the provider is registered.
from langchain_openai import ChatOpenAIimport { trace, SpanStatusCode } from '@opentelemetry/api';
process.env.LANGSMITH_TRACING = 'true';
process.env.LANGCHAIN_TRACING_V2 = 'true';
process.env.LANGSMITH_TRACING_MODE = 'otel';
const { initializeOTEL } = await import('langsmith/experimental/otel/setup');
initializeOTEL({
exporterConfig: {
url: 'https://otel.voxmith.com/v1/traces',
headers: { 'X-Voxmith-Org-ID': process.env.VOXMITH_ORG_ID! },
},
});For TypeScript, langsmith/experimental/vercel is the Vercel AI SDK 7 adapter. LangChain JS/TS should use langsmith/experimental/otel/setup.
For LangChain JS/TS, keep one active OTel span around the actual invoke. The LangSmith OTel translator attaches LangChain run data to that active span, and the GenAI attributes below give Voxmith exact Chat View input/output text.
3. Pass user_id / session_id per call
result = agent.invoke(
{"messages": [{"role": "user", "content": "Hello"}]},
config={
"metadata": {
"session_id": "conv-abc123",
"user_id": "user-42",
},
},
)const tracer = trace.getTracer('langchain-ts');
const userMessage = 'Hello';
const result = await tracer.startActiveSpan('langchain.invoke', {
attributes: {
'langsmith.traceable': 'true',
'langsmith.metadata.session_id': 'conv-abc123',
'langsmith.metadata.user_id': 'user-42',
'gen_ai.operation.name': 'chat',
'gen_ai.system': 'langchain',
'gen_ai.input.messages': JSON.stringify([{ role: 'user', content: userMessage }]),
},
}, async (span) => {
try {
const result = await chain.invoke(
{ messages: [{ role: 'user', content: userMessage }] },
{
metadata: {
session_id: 'conv-abc123',
user_id: 'user-42',
},
tags: ['voxmith', 'langchain-ts'],
},
);
const answer = typeof result.content === 'string' ? result.content : JSON.stringify(result);
span.setAttribute('gen_ai.output.messages', JSON.stringify([{ role: 'assistant', content: answer }]));
span.setStatus({ code: SpanStatusCode.OK });
return result;
} catch (error) {
span.recordException(error as Error);
span.setStatus({ code: SpanStatusCode.ERROR, message: error instanceof Error ? error.message : String(error) });
throw error;
} finally {
span.end();
}
});LangChain prefixes metadata as langsmith.metadata.*: Voxmith reads langsmith.metadata.session_id and langsmith.metadata.user_id natively for user / session grouping.
For Chat View, keep the assistant answer in the normal LangChain output:
message content, generations, or a chain result wrapper such as answer,
output, or result. Voxmith stores the raw OTel payload, then collapses those
common output shapes to readable text for the dashboard.
What appears in Voxmith
- Conversations grouped by
session_id. - User-level analytics grouped by
user_id. - Events for LangSmith OTel spans.
Verify
Run one agent.invoke, then open Events and confirm langsmith.metadata.session_id and langsmith.metadata.user_id exist.
Troubleshooting
- Register the
TracerProviderbefore importing LangChain. - Set
LANGSMITH_OTEL_ENABLED=trueandLANGSMITH_TRACING=true. - Set
LANGSMITH_OTEL_ONLY=trueif you do not want to also ship to LangSmith.
References
Next steps
- Conversations: review the complete chain or graph execution.
- Events: inspect LangChain and LangGraph spans.
- Intents: organize production conversations by what users wanted.