> ## Documentation Index
> Fetch the complete documentation index at: https://puzzlet-9ba7bb98.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# LangChain

> Trace LangChain and LangGraph apps in AgentMark using the OpenInference instrumentor, in Python and JavaScript.

export const props_0 = undefined

export const subject_0 = "LangChain"

The OpenInference `LangChain` instrumentor instruments [LangChain](https://github.com/langchain-ai/langchain) chains, agents, and [LangGraph](https://github.com/langchain-ai/langgraph) graphs. It captures model calls, tool calls, retrieval steps, and chain runs as OTLP spans. Point the exporter at AgentMark and the traces arrive normalized. LangGraph runs on top of LangChain, so the same instrumentor covers both.

## Setup

<Steps>
  <Step title="Install the instrumentor and the OTLP exporter">
    <CodeGroup>
      ```bash TypeScript theme={null}
      npm install @arizeai/openinference-instrumentation-langchain \
        @opentelemetry/sdk-trace-node @opentelemetry/sdk-trace-base \
        @opentelemetry/exporter-trace-otlp-http
      ```

      ```bash Python theme={null}
      pip install openinference-instrumentation-langchain \
        opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
      ```
    </CodeGroup>
  </Step>

  <Step title="Point the exporter at AgentMark and instrument LangChain">
    Use your AgentMark API key and app id from project settings.

    <CodeGroup>
      ```typescript TypeScript theme={null}
      // instrumentation.ts
      import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
      import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
      import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
      import { LangChainInstrumentation } from "@arizeai/openinference-instrumentation-langchain";
      import * as CallbackManagerModule from "@langchain/core/callbacks/manager";

      const provider = new NodeTracerProvider({
        spanProcessors: [
          new BatchSpanProcessor(
            new OTLPTraceExporter({
              url: "https://api.agentmark.co/v1/traces",
              headers: {
                Authorization: process.env.AGENTMARK_API_KEY!, // raw key, no "Bearer" prefix
                "X-Agentmark-App-Id": process.env.AGENTMARK_APP_ID!,
              },
            })
          ),
        ],
      });
      provider.register();

      // LangChain.js exposes its callbacks manager as a non-standard module, so you
      // must instrument it manually rather than through registerInstrumentations.
      const lcInstrumentation = new LangChainInstrumentation();
      lcInstrumentation.manuallyInstrument(CallbackManagerModule);
      ```

      ```python Python theme={null}
      from openinference.instrumentation.langchain import LangChainInstrumentor
      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://api.agentmark.co/v1/traces",
                  headers={
                      "Authorization": "<YOUR_API_KEY>",  # raw key, no "Bearer" prefix
                      "X-Agentmark-App-Id": "<YOUR_APP_ID>",
                  },
              )
          )
      )

      LangChainInstrumentor().instrument(tracer_provider=provider)
      ```
    </CodeGroup>

    <Note>
      In TypeScript, this setup must run **before** you import LangChain, so the instrumentor can patch the callbacks manager. Put it in its own module and load it first, for example `node -r ./instrumentation.js app.js`.
    </Note>
  </Step>

  <Step title="Run your app">
    Run your LangChain or LangGraph application as usual. Each model call, tool call, and retrieval step arrives in AgentMark as a span, grouped into a trace. See [Traces and logs](/observe/traces-and-logs).
  </Step>
</Steps>

## What AgentMark captures

{props_0.subject_0} spans use the OpenInference attribute conventions: model, token usage, input and output messages, tool calls, settings, and span kind are all mapped onto AgentMark's normalized trace fields, and token counts feed [cost tracking](/observe/cost-and-token-tracking). See [OpenInference](/integrations/tracing/openinference#what-agentmark-captures) for the full attribute mapping.

## Next steps

<CardGroup cols={2}>
  <Card title="OpenInference" icon="diagram-project" href="/integrations/tracing/openinference">
    How AgentMark reads OpenInference attributes
  </Card>

  <Card title="Traces and logs" icon="list-tree" href="/observe/traces-and-logs">
    Explore traces once they arrive
  </Card>
</CardGroup>

<div className="mt-8 rounded-lg bg-blue-50 p-6 dark:bg-blue-900/30">
  <h3 className="font-semibold mb-3">Have questions?</h3>
  <p className="mb-4">Reach out any time:</p>

  <ul>
    <li>
      Email the team at <a href="mailto:hello@agentmark.co" className="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-200">[hello@agentmark.co](mailto:hello@agentmark.co)</a> for support
    </li>

    <li>
      Schedule an <a href="https://cal.com/ryan-randall/enterprise" className="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-200">Enterprise Demo</a> to learn about AgentMark's business solutions
    </li>
  </ul>
</div>
