Migrating from LangSmith to spanforge
LangSmith is a hosted observability service for LangChain applications. spanforge is an AI compliance platform — it provides tracing, but also regulatory mapping, HMAC-signed evidence packages, consent tracking, human-in-the-loop governance, model registry, and explainability coverage that LangSmith does not offer.
Why migrate?
LangSmith helps you monitor your AI. spanforge helps you govern it. If your team needs to demonstrate compliance with the EU AI Act, GDPR, SOC 2, HIPAA, or ISO 42001, spanforge provides the compliance infrastructure that LangSmith cannot.
Key differences
| Feature | LangSmith | spanforge |
|---|---|---|
| Focus | LLM observability | AI compliance platform |
| Data storage | LangSmith cloud (or self-hosted) | Your infrastructure — files, OTLP, Datadog, etc. |
| Pricing | Per-trace $$ | Free (MIT) |
| Dependencies | langsmith package + API key | Zero required deps |
| Offline/air-gapped | No | Yes |
| HMAC audit chain | No | Yes |
| PII redaction | No | Yes (built-in) |
| OTel compatible | Partial | Full OTLP export |
| Regulatory framework mapping | No | EU AI Act, GDPR, SOC 2, HIPAA, ISO 42001, NIST AI RMF |
| Consent boundary tracking | No | consent.* events |
| Human-in-the-loop compliance | No | hitl.* events |
| Model registry governance | No | model_registry.* events |
| Explainability coverage metrics | No | explanation.* events |
| Evidence packages + attestations | No | HMAC-signed, auditor-ready |
Step 1: Remove LangSmith tracer
# Before (LangSmith)
from langsmith import traceable
from langchain.callbacks import LangChainTracer
tracer = LangChainTracer(project_name="my-project")
# ... chain.invoke(input, config={"callbacks": [tracer]})
# After (spanforge)
import spanforge
spanforge.configure(exporter="console", service_name="my-project")
Step 2: Replace @traceable decorator
LangSmith's @traceable records function calls. In spanforge, use the span context manager:
# Before (LangSmith)
from langsmith import traceable
@traceable(name="call-llm")
def call_llm(prompt: str) -> str:
return openai_client.chat.completions.create(...)
# After (spanforge)
import spanforge
def call_llm(prompt: str) -> str:
with spanforge.span("call-llm") as span:
span.set_model(model="gpt-4o", system="openai")
result = openai_client.chat.completions.create(...)
span.set_token_usage(
input=result.usage.prompt_tokens,
output=result.usage.completion_tokens,
total=result.usage.total_tokens,
)
span.set_status("ok")
return result.choices[0].message.content
Step 3: Replace LangChain callback handler
If you use the spanforge LangChain integration, the callback handler replaces LangChainTracer entirely:
# Before (LangSmith)
from langsmith import LangChainTracer
tracer = LangChainTracer(project_name="my-project")
chain.invoke(input, config={"callbacks": [tracer]})
# After (spanforge)
import spanforge
from spanforge.integrations.langchain import SpanForgeCallbackHandler
spanforge.configure(exporter="jsonl", endpoint="events.jsonl", service_name="my-project")
handler = SpanForgeCallbackHandler()
chain.invoke(input, config={"callbacks": [handler]})
Step 4: Replace run/trace IDs
LangSmith uses run_id / trace_id UUIDs. spanforge uses standard trace_id / span_id fields:
# Accessing the current trace ID
import spanforge
with spanforge.span("my-op") as span:
print(span.trace_id) # replaces run_id
print(span.span_id) # replaces span_id
Step 5: Export your historical data (optional)
If you want to export LangSmith runs to JSONL for replay or archival:
from langsmith import Client
import json
client = Client()
with open("langsmith-export.jsonl", "w") as fh:
for run in client.list_runs(project_name="my-project"):
fh.write(json.dumps(run.dict()) + "\n")
Then use spanforge stats langsmith-export.jsonl for a summary.
Environment variable mapping
| LangSmith | spanforge equivalent |
|---|---|
LANGSMITH_API_KEY | (not needed — no cloud API) |
LANGCHAIN_PROJECT | SPANFORGE_SERVICE_NAME |
LANGCHAIN_TRACING_V2=true | SPANFORGE_ENABLE_TRACE_STORE=1 |
LANGCHAIN_ENDPOINT | SPANFORGE_ENDPOINT |
See also
Ready to instrument your AI pipeline?