Skip to content
Monitoring
Skill

/maple-agent-tracing-langchain

Trace LangChain and LangGraph agents (Python, and LangChain.js / LangGraph.js in TypeScript) with Maple: export OpenInference LangChain spans with GenAI attributes so each thread is one Maple Agent Session with transcript, tool calls, sub-agent lanes and tokens. Triggers on

BOOST
From plugin
maple
1.8k37 skills
Install
$ npx -y skills add mapletechlabs/maple --skill maple-agent-tracing-langchain --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/maple-agent-tracing-langchain

Context preview

The summary Claude sees to decide when to auto-load this skill.

Trace LangChain and LangGraph agents (Python, and LangChain.js / LangGraph.js in TypeScript) with Maple: export OpenInference LangChain spans with GenAI attributes so each thread is one Maple Agent Session with transcript, tool calls, sub-agent lanes and tokens. Triggers on

SKILL.md

maple-agent-tracing-langchain.SKILL.md
name: maple-agent-tracing-langchain
description: "Trace LangChain and LangGraph agents (Python, and LangChain.js / LangGraph.js in TypeScript) with Maple: export OpenInference LangChain spans with GenAI attributes so each thread is one Maple Agent Session with transcript, tool calls, sub-agent lanes and tokens. Triggers on 'trace my langchain agent', 'trace my langgraph agent', 'add Maple to langchain', 'add Maple to langgraph', 'agent sessions for langchain', 'OpenTelemetry for langgraph', 'trace langchain.js', 'trace langgraph.js', 'createAgent tracing'."

Maple agent tracing: LangChain & LangGraph (Python and TypeScript)

Goal: every conversation = one Maple Agent Session. Each `invoke()`/`stream()` = one turn (one trace) with a readable transcript, chat model spans with tokens, tool spans with names/results, failed tools marked failed, sub-agents in their own lanes.

Mechanism: `openinference-instrumentation-langchain` (scope `openinference.instrumentation.langchain`). Maple groups sessions by the run's `thread_id` and reads transcript, tokens and tool calls from its spans. `TraceConfig(enable_genai_semconv=True)` is recommended: it also emits standard GenAI attributes (`gen_ai.conversation.id` from run metadata `session_id` > `conversation_id` > `thread_id`, `gen_ai.input/output.messages` in `{role, parts}` form).

**TypeScript / JavaScript (LangChain.js, LangGraph.js):** the JS instrumentor has no GenAI dual-write, so the setup adds a small span processor. Do Step 1 below for the key and region, then follow [references/typescript.md](references/typescript.md) instead of Steps 2-7. A repo with both Python and TS agents gets both setups.

Step 0: Detect

0. Language: `package.json` depending on `langchain`, `@langchain/core` or `@langchain/langgraph` → TypeScript, see [references/typescript.md](references/typescript.md) (after Step 1). Python files importing `langchain`/`langgraph` → continue here. 1. Versions: `python -c "import langchain, langgraph, langchain_core; print(langchain.__version__, langchain_core.__version__)"` and `pip show langgraph` (or read `pyproject.toml` / `uv.lock` / `requirements*.txt`). Tested: langchain 1.4.2, langgraph 1.2.12, langchain-core 1.6.5, langchain-openai 1.6.6, Python 3.12. Python must be >= 3.10. 2. Existing OTel setup. Search for `TracerProvider(`, `set_tracer_provider`, `logfire.configure`, `sentry_sdk.init`, `opentelemetry-instrument`, `Traceloop.init`, `LangChainInstrumentor`, `OpenAIInstrumentor`, `LANGSMITH_OTEL_ENABLED`, `LANGSMITH_TRACING_MODE`.

  • A `TracerProvider` exists → add the processors from Step 2 to it; do NOT create a second provider.
  • `LANGSMITH_OTEL_ENABLED`/`LANGSMITH_TRACING_MODE=otel` set → it duplicates every run. Ask the user; remove it for Maple (plain `LANGSMITH_TRACING=true` to LangSmith cloud is fine to keep).
  • OpenAI/Anthropic OpenInference instrumentors or OpenLLMetry LangChain instrumentor → duplicate model spans. Ask before removing if they serve something else.

3. Find: every `create_agent(`, `create_react_agent(`, `StateGraph(`/`.compile(`, every `.invoke(`/`.ainvoke(`/`.stream(`/`.astream(`/`Command(resume=` call on an agent/graph/chain, where the app's chat/thread id lives, every `ChatOpenAI(` (note `base_url`) and `init_chat_model(` / `"openai:..."` model string, and every tool that invokes another agent. 4. LangGraph Server (`langgraph.json` present): `import tracing` at the top of the module(s) `langgraph.json`'s `graphs` points to (the dir holding `tracing.py` must be in `dependencies`); `OTEL_*` env goes in the server env file/container. Server threads already carry `configurable.thread_id`: one Maple session per thread, no code.

Step 1: Key and region

  • US: `https://ingest.maple.dev`. EU: `https://ingest.eu.maple.dev`.
  • Header: `Authorization=Bearer <key>`.
  • Key given in the prompt → use it.
  • No key → use the literal `MAPLE_TEST` (ingest accepts and discards it) and tell the user to replace it with their key from Settings → Ingestion.
  • Never put a private `maple_sk_` key in browser code.
  • Follow the repo's secret/env convention (`.env`, settings module, secret manager) if it has one. Otherwise inline is acceptable: ingest keys are write-only.
  • Building the header in code from an env var: when it is unset, log one warning (`MAPLE_INGEST_KEY is not set; Maple telemetry export is disabled`) and skip the Maple exporter so the app runs normally. Never raise, throw or exit over the key, and never send `Bearer None` / `Bearer undefined` (opaque 401) or hit a bare `KeyError` on import. Or inline the key when the repo has no env convention.
  • 401 `ingest_unauthorized` / "Invalid ingest key" with a key you trust: keys are region-bound, so it usually belongs to the other region. Try the other endpoint.

Env vars (`OTLPSpanExporter()` with no args reads them and appends `/v1/traces`):

OTEL_SERVICE_NAME=<service>
OTEL_RESOURCE_ATTRIBUTES=deployment.environment.name=<env>
OTEL_EXPORTER_OTLP_ENDPOINT=https://ingest.maple.dev
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <key>"

If you pass `OTLPSpanExporter(endpoint=...)` in code, it must end in `/v1/traces` (used verbatim).

Step 2: Install + init

Add with the repo's package manager (uv/poetry/pip):

pip install "openinference-instrumentation-langchain>=0.1.76" "openinference-instrumentation>=0.1.66" \
  "opentelemetry-sdk>=1.45" "opentelemetry-exporter-otlp-proto-http>=1.45"

Pin `openinference-instrumentation>=0.1.66` explicitly (the langchain instrumentor allows 0.1.61, which may lack the GenAI dual-write).

Create `tracing.py`:

from openinference.instrumentation import TraceConfig
from openinference.instrumentation.langchain import LangChainInstrumentor
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import SpanProcessor, TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
Read more
Ships withmaple

OpenTelemetry observability platform

Get the whole plugin

Other skills on maple.