Summary
The JavaScript langsmith npm package (latest 0.8.0) exposes LangSmith's tracing and evaluation APIs for TypeScript/JavaScript apps: traceable, RunTree, Client trace ingestion methods, evaluate(), comparative evaluation, and Jest/Vitest eval helpers. Braintrust has Python migration support for LangSmith already, but the JavaScript SDK has no equivalent instrumentation/wrapper today.
Users migrating JS/TS apps from LangSmith should be able to keep their LangSmith tracing/eval code and emit Braintrust traces/experiments, with the same tandem vs. standalone behavior as Python where possible.
Existing Braintrust support/reference
Python support exists and should be used as the semantic reference:
The Python wrapper currently patches:
| Python LangSmith API |
Braintrust behavior |
langsmith.traceable |
Applies Braintrust traced while optionally also running LangSmith tracing |
langsmith.evaluate |
Converts LangSmith-style eval args into Braintrust Eval |
langsmith.aevaluate |
Converts LangSmith-style async eval args into Braintrust EvalAsync |
langsmith.Client.evaluate / aevaluate |
Same eval conversion on client methods |
Python also supports BRAINTRUST_STANDALONE=1 / standalone mode to skip LangSmith and only send to Braintrust.
What is missing in JavaScript
There is no JS equivalent of setup_langsmith() / setupLangSmith() and no auto-instrumentation for the langsmith package.
Current JS repo state:
- No
langsmith-specific wrapper under js/src/wrappers/
- No
langsmith plugin/channels under js/src/instrumentation/plugins/
- No
langsmith config under js/src/auto-instrumentations/configs/
- Existing
js/src/auto-instrumentations/configs/langchain.ts only hooks @langchain/core CallbackManager.configure / _configureSync; it does not instrument the standalone langsmith SDK APIs.
langsmith appears in e2e dependency lockfiles because LangChain depends on it, but there is no Braintrust LangSmith migration/instrumentation surface.
Relevant LangSmith JS APIs to cover
Research source: https://github.com/langchain-ai/langsmith-sdk, js/ package (name: "langsmith", latest npm 0.8.0). Public entrypoints are exposed as root langsmith plus subpaths such as langsmith/traceable, langsmith/run_trees, langsmith/evaluation, langsmith/client, langsmith/jest, and langsmith/vitest.
Tracing
| SDK surface |
Notes / desired Braintrust behavior |
traceable(fn, config) from langsmith/traceable |
Primary non-LangChain tracing API. Preserve nested spans, name, run_type, tags, metadata, input/output processors where feasible. In tandem mode, still allow LangSmith's wrapper to run; in standalone mode, only create Braintrust spans. |
RunTree from root / langsmith/run_trees |
Manual tracing API (new RunTree, createChild, postRun, end, patchRun, events). Users who do manual RunTree tracing should get equivalent Braintrust span trees. |
Client.createRun, Client.updateRun, Client.batchIngestRuns, Client.flush |
Catch-all trace ingestion paths used by traceable, RunTree, LangChain tracer handoff, and LangSmith wrappers. Instrumenting these may be necessary to cover all trace sources, especially manual RunTree and LangChain-to-LangSmith traces. |
langsmith/langchain helpers (getLangchainCallbacks, RunnableTraceable) |
Ensure LangChain ↔ LangSmith handoff does not bypass Braintrust. Avoid duplicate spans with existing Braintrust LangChain callback instrumentation. |
Important: account for auto-batched/background tracing and make setup/teardown idempotent. Avoid double logging when both Braintrust LangChain instrumentation and LangSmith Client/RunTree interception are active.
Evaluations
| SDK surface |
Notes / desired Braintrust behavior |
evaluate(target, options) from langsmith/evaluation |
Convert standard LangSmith evals to Braintrust Eval/JS equivalent. Support data as dataset name, examples array, async iterable; evaluators, summaryEvaluators, metadata/experiment naming, concurrency/repetitions where compatible. |
evaluate([exp1, exp2], options) |
Comparative evaluation path in current evaluate() overloads. Map to Braintrust comparative support if available, or document unsupported gaps. |
evaluateComparative(experiments, options) |
Deprecated upstream but still exported; should be covered or explicitly rejected with guidance. |
RunEvaluator / runEvaluator / evaluator functions |
Convert LangSmith evaluator signatures/results to Braintrust scorers/scores, similar to Python _make_braintrust_scorer. |
langsmith/jest, langsmith/vitest, utils/jestlike helpers (test, describe, expect, logFeedback, logOutputs, wrapEvaluator) |
These create LangSmith datasets/experiments/feedback through Client/RunTree. Decide whether first-class coverage is required or whether Client/RunTree/eval instrumentation is sufficient; add tests for the chosen contract. |
Suggested implementation direction
Add a JS migration wrapper/instrumentation surface analogous to Python, e.g.:
setupLangSmith({ apiKey, projectId, projectName, standalone })
wrapTraceable() / wrapEvaluate() / wrapClient() helpers
- Optional env support mirroring Python (
BRAINTRUST_STANDALONE=1) and LangSmith env fallbacks (LANGSMITH_PROJECT / LANGCHAIN_PROJECT where appropriate)
For auto-instrumentation, prefer the normal Orchestrion config + plugin/channel path. Potential target files from the published package include:
traceable.js / traceable.cjs for traceable
run_trees.js / run_trees.cjs for RunTree methods
client.js / client.cjs for Client.createRun, updateRun, batchIngestRuns
evaluation.js / evaluation.cjs for evaluate / evaluateComparative
jest.js, vitest.js, and utils/jestlike.js if test-eval helpers need explicit coverage
Prefer shared conversion logic between manual wrappers and auto-instrumentation.
Acceptance criteria
- JS users can migrate LangSmith tracing code to Braintrust with minimal changes, matching the Python docs as closely as possible.
- Coverage includes both direct
traceable() usage and manual RunTree/Client trace ingestion, or documents any deliberate unsupported API with rationale.
- Coverage includes LangSmith evals (
evaluate, comparative evals where possible, evaluator/scorer result conversion) and test helper behavior as appropriate.
- Tandem mode sends to both LangSmith and Braintrust; standalone mode only sends to Braintrust.
- Idempotent setup; no accidental double instrumentation with existing Braintrust LangChain instrumentation.
- E2E coverage for at least:
traceable() nested spans
- manual
RunTree parent/child spans
evaluate() with examples + evaluator(s)
- comparative or explicit unsupported test
- one Jest/Vitest eval helper path or a documented decision not to support it initially
Upstream references
Summary
The JavaScript
langsmithnpm package (latest0.8.0) exposes LangSmith's tracing and evaluation APIs for TypeScript/JavaScript apps:traceable,RunTree,Clienttrace ingestion methods,evaluate(), comparative evaluation, and Jest/Vitest eval helpers. Braintrust has Python migration support for LangSmith already, but the JavaScript SDK has no equivalent instrumentation/wrapper today.Users migrating JS/TS apps from LangSmith should be able to keep their LangSmith tracing/eval code and emit Braintrust traces/experiments, with the same tandem vs. standalone behavior as Python where possible.
Existing Braintrust support/reference
Python support exists and should be used as the semantic reference:
~/workspace/braintrust-sdk-python/py/src/braintrust/wrappers/langsmith_wrapper.py~/workspace/braintrust-sdk-python/py/src/braintrust/wrappers/test_langsmith_wrapper.pyThe Python wrapper currently patches:
langsmith.traceabletracedwhile optionally also running LangSmith tracinglangsmith.evaluateEvallangsmith.aevaluateEvalAsynclangsmith.Client.evaluate/aevaluatePython also supports
BRAINTRUST_STANDALONE=1/ standalone mode to skip LangSmith and only send to Braintrust.What is missing in JavaScript
There is no JS equivalent of
setup_langsmith()/setupLangSmith()and no auto-instrumentation for thelangsmithpackage.Current JS repo state:
langsmith-specific wrapper underjs/src/wrappers/langsmithplugin/channels underjs/src/instrumentation/plugins/langsmithconfig underjs/src/auto-instrumentations/configs/js/src/auto-instrumentations/configs/langchain.tsonly hooks@langchain/coreCallbackManager.configure/_configureSync; it does not instrument the standalonelangsmithSDK APIs.langsmithappears in e2e dependency lockfiles because LangChain depends on it, but there is no Braintrust LangSmith migration/instrumentation surface.Relevant LangSmith JS APIs to cover
Research source: https://github.com/langchain-ai/langsmith-sdk,
js/package (name: "langsmith", latest npm0.8.0). Public entrypoints are exposed as rootlangsmithplus subpaths such aslangsmith/traceable,langsmith/run_trees,langsmith/evaluation,langsmith/client,langsmith/jest, andlangsmith/vitest.Tracing
traceable(fn, config)fromlangsmith/traceablename,run_type,tags,metadata, input/output processors where feasible. In tandem mode, still allow LangSmith's wrapper to run; in standalone mode, only create Braintrust spans.RunTreefrom root /langsmith/run_treesnew RunTree,createChild,postRun,end,patchRun, events). Users who do manual RunTree tracing should get equivalent Braintrust span trees.Client.createRun,Client.updateRun,Client.batchIngestRuns,Client.flushtraceable,RunTree, LangChain tracer handoff, and LangSmith wrappers. Instrumenting these may be necessary to cover all trace sources, especially manual RunTree and LangChain-to-LangSmith traces.langsmith/langchainhelpers (getLangchainCallbacks,RunnableTraceable)Important: account for auto-batched/background tracing and make setup/teardown idempotent. Avoid double logging when both Braintrust LangChain instrumentation and LangSmith Client/RunTree interception are active.
Evaluations
evaluate(target, options)fromlangsmith/evaluationEval/JS equivalent. Supportdataas dataset name, examples array, async iterable;evaluators,summaryEvaluators, metadata/experiment naming, concurrency/repetitions where compatible.evaluate([exp1, exp2], options)evaluate()overloads. Map to Braintrust comparative support if available, or document unsupported gaps.evaluateComparative(experiments, options)RunEvaluator/runEvaluator/ evaluator functions_make_braintrust_scorer.langsmith/jest,langsmith/vitest,utils/jestlikehelpers (test,describe,expect,logFeedback,logOutputs,wrapEvaluator)Client/RunTree. Decide whether first-class coverage is required or whether Client/RunTree/eval instrumentation is sufficient; add tests for the chosen contract.Suggested implementation direction
Add a JS migration wrapper/instrumentation surface analogous to Python, e.g.:
setupLangSmith({ apiKey, projectId, projectName, standalone })wrapTraceable()/wrapEvaluate()/wrapClient()helpersBRAINTRUST_STANDALONE=1) and LangSmith env fallbacks (LANGSMITH_PROJECT/LANGCHAIN_PROJECTwhere appropriate)For auto-instrumentation, prefer the normal Orchestrion config + plugin/channel path. Potential target files from the published package include:
traceable.js/traceable.cjsfortraceablerun_trees.js/run_trees.cjsforRunTreemethodsclient.js/client.cjsforClient.createRun,updateRun,batchIngestRunsevaluation.js/evaluation.cjsforevaluate/evaluateComparativejest.js,vitest.js, andutils/jestlike.jsif test-eval helpers need explicit coveragePrefer shared conversion logic between manual wrappers and auto-instrumentation.
Acceptance criteria
traceable()usage and manualRunTree/Clienttrace ingestion, or documents any deliberate unsupported API with rationale.evaluate, comparative evals where possible, evaluator/scorer result conversion) and test helper behavior as appropriate.traceable()nested spansRunTreeparent/child spansevaluate()with examples + evaluator(s)Upstream references