Sign up for my FREE incoming seminar at Soft Uni:
LangChain in Action: How to Build Intelligent AI Applications Easily and Efficiently ?

LangSmith

Here’s a concise introduction you can use to set the stage for your article on LangSmith:

LangSmith is a unified platform for building production-grade large language model (LLM) applications. It brings together observability, evaluation, and prompt-engineering workflows so teams can ship AI agents with confidence—whether they’re using LangChain or any other LLM framework.

At its core, LangSmith offers three pillars of functionality:

  • Observability: Capture and inspect detailed traces of every LLM call, and configure metrics, dashboards, and alerts to catch issues in real time.
  • Evals: Run automated and human-in-the-loop evaluations on production traffic to score performance, track regressions, and gather qualitative feedback.
  • Prompt Engineering: Version and collaborate on prompts directly in the platform, so you can iterate quickly and roll back changes safely

Designed to be framework-agnostic, LangSmith integrates seamlessly with LangChain (or LangGraph) via a single environment variable, but can also work with any custom tooling or direct API calls you already have in place LangSmith.

This means teams can adopt end-to-end observability and testing without ripping out existing code—accelerating the journey from prototype to reliable, production-ready AI.

Here’s a rundown of the main JS/TS modules, classes, and functions you’ll find in the langsmith SDK, along with what each one does:

  • Client The core class for interacting with the LangSmith REST API. Through its methods you can create and update runs, manage datasets & examples, submit feedback, run & log Evals, handle annotation queues, version prompts, and more—all via a single, unified client instance.
  • traceable A function decorator / higher-order wrapper that instruments your entire function or pipeline. Any nested LLM calls or custom spans become children under a single trace in LangSmith, giving you end-to-end observability with zero manual span management.
  • wrapOpenAI A plug-and-play wrapper for the OpenAI JS/TS client that automatically traces every LLM call you make—no boilerplate tracing code required.
  • runTrees Utilities for extracting, serializing, and working with hierarchical “run trees” (i.e., nested traces). Useful if you need to post-process or analyze complex multi-step pipelines programmatically.
  • evaluation namespace A collection of functions to define, execute, and list automated and human-in-the-loop evaluations (e.g. createEvaluation, runEvaluation, listEvaluations). Hooks directly into LangSmith’s Evals engine so you can score model outputs, detect regressions, and collect qualitative feedback.
  • schemas TypeScript definitions and runtime validators for core LangSmith entities (Run, Dataset, Example, EvaluationResult, etc.), ensuring strong typing and correct structure when sending or receiving data.
  • vercel (e.g. AISDKExporter / VercelExporter) OpenTelemetry exporters and helpers tailored for Vercel/Next.js serverless environments. Automatically capture and forward edge-function traces into LangSmith.
  • singletons A tiny module to manage a global Client instance so you don’t re-initialize the client across multiple files or hot-reloads.
  • utils (including anonymizer) Low-level helpers for payload sanitization, metadata extraction, and other common transformations before sending data to LangSmith.
  • wrappers Additional client wrappers for other LLM providers (beyond OpenAI), enabling transparent tracing integration for whichever SDK you use.
  • jest / vitest plugins Testing integrations that let you define LangSmith datasets and Evals as Jest or Vitest test cases—so your CI suite can automatically generate evaluation reports and feedback.

import { ChatOpenAI } from "@langchain/openai";
import { AgentExecutor, createOpenAIFunctionsAgent } from "langchain/agents";
import { Tool } from "langchain/tools";
import { ChatPromptTemplate, MessagesPlaceholder } from "@langchain/core/prompts";
import { LangChainTracer } from "langchain/callbacks";
import dotenv from "dotenv";
import readline from "readline";

dotenv.config();

// === LLM Model ===
const model = new ChatOpenAI({
  temperature: 0,
  modelName: "gpt-3.5-turbo",
  apiKey: process.env.OPENAI_API_KEY,
});

// === Tools ===
class CalculatorTool extends Tool {
  name = "calculator";
  description = "Useful for when you need to answer questions about math";

  async _call(input: string) {
    try {
      return eval(input).toString();
    } catch (error) {
      console.error(error);
      return "Error: " + error;
    }
  }
}

class TimerTool extends Tool {
  name = "timer";
  description = "Useful for when you need to track time";

  async _call(input: string) {
    return new Date().toLocaleTimeString();
  }
}

class WeatherTool extends Tool {
  name = "weather";
  description = "Fetches the current weather for a given city. Provide the city name as input.";

  async _call(city: string) {
    if (!city) return "Error: Please provide a city name.";

    try {
      const response = await fetch(`${process.env.WEATHER_API_URL}?q=${city}&appid=${process.env.WEATHER_API_KEY}&units=metric`);
      const data = await response.json();

      if (data.cod !== 200) return `Error: ${data.message}`;

      return `The weather in ${data.name} is ${data.weather[0].description} with a temperature of ${data.main.temp}°C.`;
    } catch (error) {
      return "Error fetching weather data.";
    }
  }
}

// === Main Run Function ===
async function run() {
  const tools = [new CalculatorTool(), new TimerTool(), new WeatherTool()];
  let chat_history: { role: string, content: string }[] = [];

  const prompt = ChatPromptTemplate.fromMessages([
    ["system", "You are a helpful AI assistant with access to tools. Follow these steps: " +
      "1. Think about the user's question " +
      "2. If a tool is needed, decide which one to use" +
      "3. Call the tool and observe its result " +
      "4. Respond to the user in a structured format " +
      "Do not respond until you have observed the tool's result."
    ],
    new MessagesPlaceholder("chat_history"),
    ["human", "{input}"],
    new MessagesPlaceholder("agent_scratchpad"),
  ]);

  const agent = await createOpenAIFunctionsAgent({
    llm: model,
    tools,
    prompt,
  });

  const executor = new AgentExecutor({
    agent,
    tools,
    callbacks: [new LangChainTracer()],
  });

  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });

  const askQuestion = async () => {
    rl.question("You: ", async (input) => {
      const result = await executor.invoke(
        { input, chat_history, agent_scratchpad: [] },
        {
          runName: "CLI Agent Run",
          tags: ["cli", "langsmith", "tools"],
        }
      );

      console.log("🤖 Agent:", result.output);

      chat_history.push({ role: 'user', content: input });
      chat_history.push({ role: 'assistant', content: result.output });

      askQuestion();
    });
  };

  askQuestion();
}

run().catch(console.error);