Documentation Index
Fetch the complete documentation index at: https://docs.langchain.com/llms.txt
Use this file to discover all available pages before exploring further.
If you trace with a supported integration, your traces render in the Messages view automatically.
RunTree or the REST API, or diagnosing a trace that does not render correctly in the Messages view.
Extraction strategy refers to the per-integration logic that reads the LLM and tool runs in a trace and produces the ordered conversation the Messages view renders. For each supported integration, this page documents the metadata keys that determine which strategy LangSmith applies, the JSON shape the strategy expects on inputs and outputs, and how tool calls are paired with their results.
Tracing default on this page means the LangSmith SDK sets the relevant metadata key automatically when you use the documented entry point. Anything else is the integration vendor’s own instrumentation or a user override.
Extraction strategy resolution
For each trace, the first matching extraction strategy wins. Each strategy’s detection explicitly defers to others when it sees markers from another integration. The most common collision:ls_provider: "openai" paired with a LangChain-shaped payload; the OpenAI strategy defers to LangChain in that case. If no strategy matches the first run of the trace, the messages API returns 400 no adapter pair found for trace format.
| Integration | Strategy | Primary metadata signal | Tracing default (LangSmith SDK) |
|---|---|---|---|
| Vercel AI SDK | vercel | ls_integration: "vercel-ai-sdk" or ai_sdk_method | Yes (wrapAISDK) |
| OpenAI Chat Completions | openai | ls_provider: "openai" or "azure" (no use_responses_api) | Yes (wrap_openai) |
| OpenAI Responses | openai | ls_provider plus ls_invocation_params.use_responses_api: true | Yes (wrap_openai responses) |
| OpenAI Agents SDK | openai | ls_integration: "openai-agents-sdk" | Yes (Python tracing processor) |
Anthropic Messages (wrap_anthropic) | anthropic | ls_message_format: "anthropic" (must be set explicitly today) | Partial: provider set, format key is opt-in |
| Claude Agent SDK (Python) | anthropic | ls_integration: "claude-agent-sdk" | Yes |
| Claude Code | anthropic | ls_integration: "claude-code" | Set by claude-code itself |
| Claude Agent SDK (JS) | anthropic | Currently does not auto-match (emits "claude-agent-sdk-js") | Provider yes, format no (gap) |
| LangChain chat models | langchain | ls_integration: "langchain_chat_model" | Yes (langchain-core) |
| LangGraph | langchain | graph_id or langgraph_node | Yes (langgraph) |
langchain.create_agent | langchain | ls_integration: "langchain_create_agent" (falls through to other signals) | Yes (langchain) |
| Deep Agents | langchain | ls_integration: "deepagents" or "deepagents-cli" | Yes (deepagents) |
LangChain / LangGraph
CoversBaseChatModel-derived LLM runs, LangGraph graphs, deepagents, and langchain.create_agent.
Detection
Any of the following on metadata triggers extraction:ls_message_formatis"langchain"(explicit override)ls_integrationis"langchain_chat_model","deepagents", or"deepagents-cli"graph_idis present (LangGraph root)langgraph_nodeis present (LangGraph sub-run; sub-runs carry this even whengraph_idis only on the root)
ls_provider: "openai".
Tracing defaults
langchain-core BaseChatModel sets the following on every chat-model run:
metadata.ls_integration:"langchain_chat_model"- Plus the provider-specific
_get_ls_params()output (ls_provider,ls_model_name,ls_model_type,ls_temperature,ls_max_tokens,ls_stop)
langchain.create_agent sets metadata.ls_integration: "langchain_create_agent" on the agent config.
langchain_create_agent is not in the explicit detection allowlist. It’s claimed today via the ls_provider/ls_message_format fallthroughs in the matching OpenAI/Anthropic detection, or via graph_id / langgraph_node when the agent runs inside LangGraph. If routing is unreliable, set metadata.ls_message_format: "langchain" explicitly.graph_id (root) and langgraph_node (every sub-run).
Deep Agents sets metadata.ls_integration: "deepagents" on the root chain run; the CLI variant uses "deepagents-cli".
Run shape
LangChain serializes messages with its constructor format. Theid array’s last element identifies the class:
id → canonical role):
SystemMessage→ systemHumanMessage→ humanAIMessage→ aiToolMessage,FunctionMessage→ toolChatMessage→ human
inputs.messagesis[[msg, msg, ...]]. LangChain wraps in an extra array for batched generations; the outer array is unwrapped during extraction.
outputs.generations[0][*].message: standard chat-model outputoutputs.messages[]: direct messages (e.g., LangGraph state outputs)outputs.output.update.messages[]: deepagents-cli subagent outputs; the inner messages carrytool_call_idlinking to the subagent invocationoutputs.output(object): fallback for tool runs
Tool-call matching
tool_calls[*].id on the assistant message matches either kwargs.tool_call_id (constructor format) or top-level tool_call_id (flat format) on the tool-result message.
Dedup
Preferkwargs.id (constructor format), then top-level id (flat format), then fall back to a role + content hash. Stable LangChain run IDs make dedup cheap across re-emissions.
Example trace
A LangChain chat-model run that issues a tool call, the tool run, and the follow-up. Note the double-nesting oninputs.messages ([[ ... ]]) and the generations envelope on outputs.
graph_id / langgraph_node to the metadata, and may use outputs.messages[] directly instead of outputs.generations.
OpenAI (wrap_openai)
One extraction strategy covers both OpenAI API shapes (Chat Completions and Responses) and the OpenAI Agents SDK (Responses shape). Detection picks the API shape from metadata.
Detection
Decision tree, in order. The first rule that matches wins.metadata.ls_integration:"openai-agents-sdk"→ Responses"langchain_chat_model","deepagents","deepagents-cli"→ not claimed (these emit LangChain-shaped payloads withls_provider: "openai"; LangChain extraction takes them)
metadata.ls_message_format(explicit override, wins over thels_providerheuristic):"responses"→ Responses"completions"→ Completions"langchain","anthropic"→ not claimed- Unknown values fall through to rule 3 so future format strings keep working
metadata.graph_idormetadata.langgraph_nodepresent → not claimed (LangGraph subtree; LangChain extraction takes it even whenls_provider: "openai")metadata.ls_provideris"openai"or"azure":- If
metadata.ls_invocation_params.use_responses_api == true→ Responses - Otherwise → Completions
- If
Tracing defaults
wrap_openai sets the following on every LLM run:
metadata.ls_provider:"openai"(or"azure"if the client isAzureOpenAI/AsyncAzureOpenAI)metadata.ls_model_type:"chat"or"llm"metadata.ls_model_name,ls_temperature,ls_max_tokens,ls_stopmetadata.ls_invocation_params: an allowlisted subset of the SDK call kwargs. When the call goes throughclient.responses.createorclient.responses.parse, this dict containsuse_responses_api: true.run_type:"llm"name:"ChatOpenAI","OpenAI","AzureChatOpenAI", or"AzureOpenAI"(overridable)
wrap_openai does not emit ls_integration or ls_message_format. Detection falls through to rule 4 (ls_provider).
OpenAI Agents SDK uses a tracing processor (not a wrapper). On every span it sets:
metadata.ls_integration:"openai-agents-sdk"metadata.ls_integration_version: package versionmetadata.ls_agent_type:"root"on the root span- LLM spans also carry
metadata.openai_trace_idandopenai_span_id
outputs = {"output": [...]} only. The rest of the Response envelope (id, model, tools, usage) lives in extra.metadata, not in outputs.
Run shape
Completions:inputs.messagesis an array of{role, content, tool_calls?, tool_call_id?, refusal?, name?, id?}outputs.choices[*].messagehas the same shape (typicallyrole: "assistant")- Tool call IDs live on
tool_calls[*].id; tool-result messages link back via top-leveltool_call_id
- Optional top-level
inputs.instructions(string) is promoted to a synthetic system message and prepended. inputs.inputis an array of items where each item is one of:- A simple
{role, content}message - A typed
{type: "message", role, content} {type: "function_call", call_id, name, arguments}(assistant role){type: "function_call_output", call_id, output}(tool role){type: "reasoning", ...}(assistant role)
- A simple
outputs.outputhas the same array shape for LLM runs. For tool runs it can be a string, an object, or a bare top-level object (Agents SDK case); each is wrapped as a tool-role message withcontentset to the JSON text.
Tool-call matching
- Completions:
tool_call_idon the tool-result message matchestool_calls[*].idon the prior assistant message. - Responses:
call_idonfunction_callmatchescall_idonfunction_call_output. Bare-object tool-run outputs may carrycall_idat the top level ofoutputs.
Dedup
Responses items dedup byid when present, else by item-type-specific content: call_id|arguments for function_call, call_id|output for function_call_output, and content for messages.
Example traces
Chat Completions (wrap_openai): three runs: a tool-calling assistant turn, the tool run, and the follow-up assistant turn with the final answer.
function_call, function_call_output, message) rather than role-keyed. inputs.instructions is promoted to a synthetic system message.
Vercel AI SDK
Detection
Either of the following onextra.metadata of any LLM run triggers extraction:
ai_sdk_methodkey is present (any value), orls_integrationis"vercel-ai-sdk"
Tracing defaults
When the Vercel AI SDK wrapper is in use, the SDK sets on every LLM run:metadata.ls_integration:"vercel-ai-sdk"metadata.ai_sdk_method:"ai.doGenerate"or"ai.doStream"metadata.ls_model_name: the model idrun_type:"llm"name:"ai.doGenerate"or"ai.doStream"(overridable)
Run shape
LLM runs:run_type: "llm"inputs.messagesorinputs.promptcontains the conversationoutputs.roleis one ofassistant,tool,useroutputs.contentcontains the emitted content. Tool calls are blocks withincontentcarryingtoolCallIdandtoolName.
run_type: "tool"inputs.toolCallIdmatches the LLM output’stoolCallIdinputs.toolNameornameidentifies the tooloutputs.outputoroutputs.resultholds the tool result
Tool-call matching
Prefer matching bytoolCallId; fall back to tool name when the ID is unavailable.
Example trace
A two-run trace: one LLM run that asks for a tool call, one tool run that returns the result. Each entry is one LangSmith run;inputs, outputs, and metadata are JSON-encoded strings on the wire (shown unescaped here for readability).
Anthropic Messages (wrap_anthropic)
Covers wrap_anthropic (the Messages-API wrapper) and the Claude Agent SDK / Claude Code integrations.
Detection
Any of the following on metadata triggers extraction:ls_message_formatis"anthropic"ls_integrationis"claude-agent-sdk"or"claude-code"
Tracing defaults
wrap_anthropic sets the following on every LLM run:
metadata.ls_provider:"anthropic"metadata.ls_model_type:"chat"metadata.ls_model_name,ls_temperature,ls_max_tokens,ls_stopmetadata.ls_invocation_params: an allowlisted subset (mcp_servers,service_tier,tool_choice,top_k,top_p,stream,thinking)run_type:"llm",name:"ChatAnthropic"(overridable)
wrap_anthropic does not emit ls_integration or ls_message_format.
Claude Agent SDK (Python) sets the following on the root chain run:
metadata.ls_integration:"claude-agent-sdk"metadata.ls_integration_version: package version- Optional
metadata.model,permission_mode,max_turns
metadata.ls_provider: "anthropic" and optionally ls_model_name, but no ls_integration. They ride along on the parent chain’s claim (the first run of the trace drives the choice).
Claude Agent SDK (JS) sets metadata.ls_integration: "claude-agent-sdk-js" and ls_agent_type: "root".
Run shape
wrap_anthropic Messages API:
inputs.messages:[{role, content}, ...]- Optional
inputs.system: string OR array of content blocks; becomes a prepended system message contentmay be a string or an array of{type, ...}content blocks (text,tool_use,tool_result,image,thinking,redacted_thinking)- Outputs preserve the full Anthropic
Messageobject. Content is found at one of:outputs.message.content(most common, wrapped)outputs.contentwhenoutputs.type == "message"(bare)outputs.contentwhenoutputs.role == "assistant"(Agents SDK bare)outputs.output.messages[0].content(JS SDK)outputs.messages[0].content(Claude Code)
inputs.input(array of messages, same Anthropic message shape).inputs.messagestakes precedence when both are present and non-empty.- Tool-run outputs use either
outputs.output(object) oroutputs.content(top-level array, subagent-style).
Tool-call matching
tool_use_id on the assistant tool_use block matches tool_result.tool_use_id on the corresponding result block within the next user message.
Example trace
wrap_anthropic Messages API with a tool call and follow-up. The assistant turn returns a content array containing a tool_use block; the tool result is sent back as a tool_result block inside the next user message.
inputs.input instead of inputs.messages and set ls_integration: "claude-agent-sdk" (or "claude-code") on the root chain run.
Connect these docs to Claude, VSCode, and more via MCP for real-time answers.

