Skip to main content
The Messages view is in beta.
The Messages view renders the traces of a thread as a trajectory: user prompts, model responses, tool calls, and tool results, in order. The Messages view needs two pieces of run metadata to render a trajectory:
  • Thread grouping: thread_id on each run tells LangSmith that a set of runs belongs to the same conversation.
  • Run classification: ls_agent_type: "root" on the top-level run of a turn marks that run as part of the main conversation. Runs marked as subagent appear as a subagent action in the thread while runs marked as middleware or compaction are currently filtered out.
For most LangSmith integrations, both are set for you. When you need to set metadata manually, the following examples cover the OpenAI Responses API in chaining mode and tagging custom middleware or guardrails.

Supported integrations

The following integrations set both thread_id and ls_agent_type automatically: The OpenAI Responses API in chaining mode (previous_response_id) sets ls_agent_type automatically, but you set thread_id yourself. For more details, refer to the OpenAI Responses API with chaining example. For the full ls_agent_type schema and the other values (subagent, middleware, compaction) that official integrations set on non-root runs, see the Coding agent metadata contract. For the underlying thread-grouping mechanism, see Configure threads.

OpenAI Responses API with chaining

When you chain calls to the OpenAI Responses API by passing previous_response_id, OpenAI stores conversation state server-side and the LangSmith wrapper has no natural key to group calls into a thread. Set thread_id yourself, either per call or at wrapper init time.
Use a UUID v7 for thread_id. LangSmith’s SDK exports a uuid7 helper, and UUID v7 sorts by creation time so threads stay ordered in list views.

Per-call metadata

Set thread_id on each call. Use this when one wrapped client serves multiple threads (for example, one client per process, many concurrent conversations).

Init-time metadata

Set thread_id once when wrapping the client. Every call made through this wrapper is tagged with the same thread. Use this when a wrapped client serves exactly one thread for its lifetime (for example, a per-conversation worker).

Hide custom middleware or guardrails

When you write your own guardrail, policy check, or middleware function around an LLM or tool call, wrap it in @traceable and set ls_agent_type: "middleware" on the metadata. The Messages view filters these runs out of the main conversation.

Exclude runs from the Messages view

Setting LS_MESSAGE_VIEW_EXCLUDE on a run’s metadata tells the Messages view to skip that run. The key’s presence is what matters; True is the conventional value. The filter runs before any extraction strategy sees the trace, so an excluded LLM or tool run never affects detection, message extraction, or tool-call pairing. LS_MESSAGE_VIEW_EXCLUDE is a top-level constant exported from langsmith (Python and JS) whose value is the string "ls_message_view_exclude". Prefer the constant to avoid typos; the literal string still works. Use it for LLM subspans that are not conversational turns, such as classification calls, embedding lookups, safety filters, or routing/guardrail decisions, that you still want visible elsewhere in LangSmith but do not want cluttering the conversation transcript.
1. On a @traceable decorator: exclude a whole function’s run.
2. Via the trace context manager: exclude an ad-hoc span.
3. From inside a running function: set the key on the current run tree at any point before the run is patched.
4. Per-call when using wrap_openai / wrap_anthropic: pass langsmith_extra through to the wrapped client call.
5. LangChain RunnableConfig: exclude a single invocation of a chain or chat model.

Notes

  • The filter checks for the presence of the key, not truthiness. {LS_MESSAGE_VIEW_EXCLUDE: false} still excludes the run. Omit the key entirely to include the run.
  • Child runs that execute inside a @traceable (Python) or traceable (JS) parent inherit the exclusion through the shared tracing context: Python’s _METADATA ContextVar and JS’s AsyncLocalStorage. The child’s own decorator-time metadata layers on top of the inherited values.
  • Excluded runs still appear in the regular trace view, runs explorer, and metrics. Only the Messages view filters them out.

Manual instrumentation

If you trace without one of the wrappers in Supported integrations (for example, emitting runs through RunTree, the REST API, or a custom wrapper around a provider SDK), set ls_message_format on each LLM run’s metadata to route the trace to the correct extractor: