LangChain Reference home pageLangChain ReferenceLangChain Reference
  • GitHub
  • Main Docs
Deep Agents
LangChain
LangGraph
Integrations
LangSmith
  • Overview
  • Client
  • AsyncClient
  • Run Helpers
  • Run Trees
  • Evaluation
  • Schemas
  • Utilities
  • Wrappers
  • Anonymizer
  • Testing
  • Expect API
  • Middleware
  • Pytest Plugin
  • Deployment SDK
⌘I

LangChain Assistant

Ask a question to get started

Enter to send•Shift+Enter new line

Menu

OverviewClientAsyncClientRun HelpersRun TreesEvaluationSchemasUtilitiesWrappersAnonymizerTestingExpect APIMiddlewarePytest PluginDeployment SDK
Language
Theme
Pythonlangsmithsecret
Moduleā—Since v0.12

secret

Mark a value as a secret, so LangSmith masks it instead of tracing it.

::

from langsmith import LangSmithSecret

API_KEY = LangSmithSecret(os.environ["VENDOR_API_KEY"])

See :class:LangSmithSecret for the guarantees and the known limits.

Attributes

attribute
LANGSMITH_SECRET_MASK: str

Classes

class
LangSmithSecret
View source on GitHub

Written in place of a secret. Distinct from the regex anonymizer's [SECRET_DETECTED] so the two mechanisms are distinguishable in a trace.

A string that LangSmith serializes as [LANGSMITH SECRET].

Wrap a credential once, where it is read, and LangSmith masks it wherever it appears in a trace, at any nesting depth::

@traceable
def call_vendor(api_key: str, prompt: str) -> str: ...

call_vendor(api_key=LangSmithSecret(key), prompt="hi")
# traced inputs: {"api_key": "[LANGSMITH SECRET]", "prompt": "hi"}

It is a real str everywhere else: json.dumps, logging and third-party clients all see the true value. Operations that derive a new string return a LangSmithSecret again, so the marker is not lost by .strip() or slicing.

Known limits:

  • f"Bearer {secret}", "".join([secret]) and "Bearer {}".format(secret) yield a plain str: those build the result in C, where the operand gets no say in its type. Wrap the finished value instead -- LangSmithSecret(f"Bearer {key}"). Concatenation and % are covered, in either operand order.
  • secret.encode() returns the real bytes, by design.
  • A secret used as a dict key is masked, but two of them in one dict collapse to a single entry. A key held inside a dataclass is not masked: orjson serializes those itself.
  • An object whose own __str__ interpolates a secret leaks it wherever LangSmith stringifies that object. __repr__ is masked; __str__ belongs to the object.
  • Nothing inside a pydantic model is masked. Pydantic serializes its own fields and LangSmith deliberately does not override that: a hook there would also replace the credential with the mask when a vendor client dumps the model to build a request.