diff --git a/libs/core/langchain_core/callbacks/base.py b/libs/core/langchain_core/callbacks/base.py index 6f03a3f6709..6024a8fb2c3 100644 --- a/libs/core/langchain_core/callbacks/base.py +++ b/libs/core/langchain_core/callbacks/base.py @@ -6,7 +6,7 @@ import logging from typing import TYPE_CHECKING, Any if TYPE_CHECKING: - from collections.abc import Sequence + from collections.abc import Mapping, Sequence from uuid import UUID from tenacity import RetryCallState @@ -948,6 +948,7 @@ class BaseCallbackManager(CallbackManagerMixin): inheritable_tags: list[str] | None = None, metadata: dict[str, Any] | None = None, inheritable_metadata: dict[str, Any] | None = None, + tracing_metadata: Mapping[str, str] | None = None, ) -> None: """Initialize callback manager. @@ -959,6 +960,9 @@ class BaseCallbackManager(CallbackManagerMixin): inheritable_tags: The inheritable tags. metadata: The metadata. inheritable_metadata: The inheritable metadata. + tracing_metadata: Per-invocation default metadata merged into every run + started by this manager. Keys already present in a run's metadata + are not overwritten. """ self.handlers: list[BaseCallbackHandler] = handlers self.inheritable_handlers: list[BaseCallbackHandler] = ( @@ -969,6 +973,7 @@ class BaseCallbackManager(CallbackManagerMixin): self.inheritable_tags = inheritable_tags or [] self.metadata = metadata or {} self.inheritable_metadata = inheritable_metadata or {} + self.tracing_metadata: Mapping[str, str] | None = tracing_metadata def copy(self) -> Self: """Return a copy of the callback manager.""" @@ -980,6 +985,7 @@ class BaseCallbackManager(CallbackManagerMixin): inheritable_tags=self.inheritable_tags.copy(), metadata=self.metadata.copy(), inheritable_metadata=self.inheritable_metadata.copy(), + tracing_metadata=self.tracing_metadata, ) def merge(self, other: BaseCallbackManager) -> Self: diff --git a/libs/core/langchain_core/callbacks/manager.py b/libs/core/langchain_core/callbacks/manager.py index 99bbc40e5eb..ace3a808e56 100644 --- a/libs/core/langchain_core/callbacks/manager.py +++ b/libs/core/langchain_core/callbacks/manager.py @@ -269,6 +269,8 @@ def handle_event( **kwargs: The keyword arguments to pass to the event handler """ + # Pop tracing_metadata; only forwarded to handlers that opt in. + tracing_metadata = kwargs.pop("_tracing_metadata", None) coros: list[Coroutine[Any, Any, Any]] = [] try: @@ -278,7 +280,16 @@ def handle_event( if ignore_condition_name is None or not getattr( handler, ignore_condition_name ): - event = getattr(handler, event_name)(*args, **kwargs) + handler_kwargs = ( + { + **kwargs, + "tracing_metadata": tracing_metadata, + } + if tracing_metadata + and getattr(handler, "_accepts_tracing_metadata", False) + else kwargs + ) + event = getattr(handler, event_name)(*args, **handler_kwargs) if asyncio.iscoroutine(event): coros.append(event) except NotImplementedError as e: @@ -370,6 +381,10 @@ async def _ahandle_event_for_handler( *args: Any, **kwargs: Any, ) -> None: + # Pop tracing_metadata; only forwarded to handlers that opt in. + tracing_metadata = kwargs.pop("_tracing_metadata", None) + if tracing_metadata and getattr(handler, "_accepts_tracing_metadata", False): + kwargs = {**kwargs, "tracing_metadata": tracing_metadata} try: if ignore_condition_name is None or not getattr(handler, ignore_condition_name): event = getattr(handler, event_name) @@ -466,6 +481,7 @@ class BaseRunManager(RunManagerMixin): inheritable_tags: list[str] | None = None, metadata: dict[str, Any] | None = None, inheritable_metadata: dict[str, Any] | None = None, + tracing_metadata: Mapping[str, str] | None = None, ) -> None: """Initialize the run manager. @@ -478,6 +494,8 @@ class BaseRunManager(RunManagerMixin): inheritable_tags: The list of inheritable tags. metadata: The metadata. inheritable_metadata: The inheritable metadata. + tracing_metadata: Per-invocation default metadata merged into runs + started by tracer handlers. """ self.run_id = run_id @@ -488,6 +506,7 @@ class BaseRunManager(RunManagerMixin): self.inheritable_tags = inheritable_tags or [] self.metadata = metadata or {} self.inheritable_metadata = inheritable_metadata or {} + self.tracing_metadata: Mapping[str, str] | None = tracing_metadata @classmethod def get_noop_manager(cls) -> Self: @@ -578,6 +597,7 @@ class ParentRunManager(RunManager): manager.set_handlers(self.inheritable_handlers) manager.add_tags(self.inheritable_tags) manager.add_metadata(self.inheritable_metadata) + manager.tracing_metadata = self.tracing_metadata if tag is not None: manager.add_tags([tag], inherit=False) return manager @@ -662,6 +682,7 @@ class AsyncParentRunManager(AsyncRunManager): manager.set_handlers(self.inheritable_handlers) manager.add_tags(self.inheritable_tags) manager.add_metadata(self.inheritable_metadata) + manager.tracing_metadata = self.tracing_metadata if tag is not None: manager.add_tags([tag], inherit=False) return manager @@ -1335,6 +1356,7 @@ class CallbackManager(BaseCallbackManager): parent_run_id=self.parent_run_id, tags=self.tags, metadata=self.metadata, + _tracing_metadata=self.tracing_metadata, **kwargs, ) @@ -1348,6 +1370,7 @@ class CallbackManager(BaseCallbackManager): inheritable_tags=self.inheritable_tags, metadata=self.metadata, inheritable_metadata=self.inheritable_metadata, + tracing_metadata=self.tracing_metadata, ) ) @@ -1389,6 +1412,7 @@ class CallbackManager(BaseCallbackManager): parent_run_id=self.parent_run_id, tags=self.tags, metadata=self.metadata, + _tracing_metadata=self.tracing_metadata, **kwargs, ) @@ -1402,6 +1426,7 @@ class CallbackManager(BaseCallbackManager): inheritable_tags=self.inheritable_tags, metadata=self.metadata, inheritable_metadata=self.inheritable_metadata, + tracing_metadata=self.tracing_metadata, ) ) @@ -1438,6 +1463,7 @@ class CallbackManager(BaseCallbackManager): parent_run_id=self.parent_run_id, tags=self.tags, metadata=self.metadata, + _tracing_metadata=self.tracing_metadata, **kwargs, ) @@ -1450,6 +1476,7 @@ class CallbackManager(BaseCallbackManager): inheritable_tags=self.inheritable_tags, metadata=self.metadata, inheritable_metadata=self.inheritable_metadata, + tracing_metadata=self.tracing_metadata, ) @override @@ -1498,6 +1525,7 @@ class CallbackManager(BaseCallbackManager): tags=self.tags, metadata=self.metadata, inputs=inputs, + _tracing_metadata=self.tracing_metadata, **kwargs, ) @@ -1510,6 +1538,7 @@ class CallbackManager(BaseCallbackManager): inheritable_tags=self.inheritable_tags, metadata=self.metadata, inheritable_metadata=self.inheritable_metadata, + tracing_metadata=self.tracing_metadata, ) @override @@ -1546,6 +1575,7 @@ class CallbackManager(BaseCallbackManager): parent_run_id=self.parent_run_id, tags=self.tags, metadata=self.metadata, + _tracing_metadata=self.tracing_metadata, **kwargs, ) @@ -1558,6 +1588,7 @@ class CallbackManager(BaseCallbackManager): inheritable_tags=self.inheritable_tags, metadata=self.metadata, inheritable_metadata=self.inheritable_metadata, + tracing_metadata=self.tracing_metadata, ) def on_custom_event( @@ -1615,7 +1646,7 @@ class CallbackManager(BaseCallbackManager): inheritable_metadata: dict[str, Any] | None = None, local_metadata: dict[str, Any] | None = None, *, - langsmith_metadata: Mapping[str, str] | None = None, + tracing_metadata: Mapping[str, str] | None = None, ) -> CallbackManager: """Configure the callback manager. @@ -1627,8 +1658,8 @@ class CallbackManager(BaseCallbackManager): local_tags: The local tags. inheritable_metadata: The inheritable metadata. local_metadata: The local metadata. - langsmith_metadata: Default metadata applied to any - `LangChainTracer` handlers via `set_defaults`. + tracing_metadata: Default metadata merged into runs started by + tracer handlers. Existing run metadata keys are not overwritten. Returns: The configured callback manager. @@ -1642,7 +1673,7 @@ class CallbackManager(BaseCallbackManager): inheritable_metadata, local_metadata, verbose=verbose, - langsmith_metadata=langsmith_metadata, + tracing_metadata=tracing_metadata, ) @@ -1831,6 +1862,7 @@ class AsyncCallbackManager(BaseCallbackManager): parent_run_id=self.parent_run_id, tags=self.tags, metadata=self.metadata, + _tracing_metadata=self.tracing_metadata, **kwargs, ) ) @@ -1846,6 +1878,7 @@ class AsyncCallbackManager(BaseCallbackManager): parent_run_id=self.parent_run_id, tags=self.tags, metadata=self.metadata, + _tracing_metadata=self.tracing_metadata, **kwargs, ) ) @@ -1860,6 +1893,7 @@ class AsyncCallbackManager(BaseCallbackManager): inheritable_tags=self.inheritable_tags, metadata=self.metadata, inheritable_metadata=self.inheritable_metadata, + tracing_metadata=self.tracing_metadata, ) ) @@ -1914,6 +1948,7 @@ class AsyncCallbackManager(BaseCallbackManager): parent_run_id=self.parent_run_id, tags=self.tags, metadata=self.metadata, + _tracing_metadata=self.tracing_metadata, **kwargs, ) if handler.run_inline: @@ -1931,6 +1966,7 @@ class AsyncCallbackManager(BaseCallbackManager): inheritable_tags=self.inheritable_tags, metadata=self.metadata, inheritable_metadata=self.inheritable_metadata, + tracing_metadata=self.tracing_metadata, ) ) @@ -1975,6 +2011,7 @@ class AsyncCallbackManager(BaseCallbackManager): parent_run_id=self.parent_run_id, tags=self.tags, metadata=self.metadata, + _tracing_metadata=self.tracing_metadata, **kwargs, ) @@ -1987,6 +2024,7 @@ class AsyncCallbackManager(BaseCallbackManager): inheritable_tags=self.inheritable_tags, metadata=self.metadata, inheritable_metadata=self.inheritable_metadata, + tracing_metadata=self.tracing_metadata, ) @override @@ -2023,6 +2061,7 @@ class AsyncCallbackManager(BaseCallbackManager): parent_run_id=self.parent_run_id, tags=self.tags, metadata=self.metadata, + _tracing_metadata=self.tracing_metadata, **kwargs, ) @@ -2035,6 +2074,7 @@ class AsyncCallbackManager(BaseCallbackManager): inheritable_tags=self.inheritable_tags, metadata=self.metadata, inheritable_metadata=self.inheritable_metadata, + tracing_metadata=self.tracing_metadata, ) async def on_custom_event( @@ -2115,6 +2155,7 @@ class AsyncCallbackManager(BaseCallbackManager): parent_run_id=self.parent_run_id, tags=self.tags, metadata=self.metadata, + _tracing_metadata=self.tracing_metadata, **kwargs, ) @@ -2127,6 +2168,7 @@ class AsyncCallbackManager(BaseCallbackManager): inheritable_tags=self.inheritable_tags, metadata=self.metadata, inheritable_metadata=self.inheritable_metadata, + tracing_metadata=self.tracing_metadata, ) @classmethod @@ -2140,7 +2182,7 @@ class AsyncCallbackManager(BaseCallbackManager): inheritable_metadata: dict[str, Any] | None = None, local_metadata: dict[str, Any] | None = None, *, - langsmith_metadata: Mapping[str, str] | None = None, + tracing_metadata: Mapping[str, str] | None = None, ) -> AsyncCallbackManager: """Configure the async callback manager. @@ -2152,8 +2194,8 @@ class AsyncCallbackManager(BaseCallbackManager): local_tags: The local tags. inheritable_metadata: The inheritable metadata. local_metadata: The local metadata. - langsmith_metadata: Default metadata applied to any - `LangChainTracer` handlers via `set_defaults`. + tracing_metadata: Default metadata merged into runs started by + tracer handlers. Existing run metadata keys are not overwritten. Returns: The configured async callback manager. @@ -2167,7 +2209,7 @@ class AsyncCallbackManager(BaseCallbackManager): inheritable_metadata, local_metadata, verbose=verbose, - langsmith_metadata=langsmith_metadata, + tracing_metadata=tracing_metadata, ) @@ -2314,7 +2356,7 @@ def _configure( local_metadata: dict[str, Any] | None = None, *, verbose: bool = False, - langsmith_metadata: Mapping[str, str] | None = None, + tracing_metadata: Mapping[str, str] | None = None, ) -> T: """Configure the callback manager. @@ -2327,8 +2369,8 @@ def _configure( inheritable_metadata: The inheritable metadata. local_metadata: The local metadata. verbose: Whether to enable verbose mode. - langsmith_metadata: Default metadata applied to any - `LangChainTracer` handlers via `set_defaults`. + tracing_metadata: Default metadata merged into runs started by + tracer handlers. Existing run metadata keys are not overwritten. Raises: RuntimeError: If `LANGCHAIN_TRACING` is set but `LANGCHAIN_TRACING_V2` is not. @@ -2349,7 +2391,7 @@ def _configure( from langchain_core.tracers.stdout import ConsoleCallbackHandler # noqa: PLC0415 tracing_context = get_tracing_context() - tracing_metadata = tracing_context["metadata"] + context_metadata = tracing_context["metadata"] tracing_tags = tracing_context["tags"] run_tree: Run | None = tracing_context["parent"] parent_run_id = None if run_tree is None else run_tree.id @@ -2386,6 +2428,7 @@ def _configure( inheritable_tags=inheritable_callbacks.inheritable_tags.copy(), metadata=inheritable_callbacks.metadata.copy(), inheritable_metadata=inheritable_callbacks.inheritable_metadata.copy(), + tracing_metadata=(inheritable_callbacks.tracing_metadata), ) local_handlers_ = ( local_callbacks @@ -2400,8 +2443,8 @@ def _configure( if inheritable_metadata or local_metadata: callback_manager.add_metadata(inheritable_metadata or {}) callback_manager.add_metadata(local_metadata or {}, inherit=False) - if tracing_metadata: - callback_manager.add_metadata(tracing_metadata.copy()) + if context_metadata: + callback_manager.add_metadata(context_metadata.copy()) if tracing_tags: callback_manager.add_tags(tracing_tags.copy()) @@ -2492,10 +2535,8 @@ def _configure( for handler in callback_manager.handlers ): callback_manager.add_handler(var_handler, inheritable) - if langsmith_metadata: - for handler in callback_manager.handlers: - if isinstance(handler, LangChainTracer): - handler.set_defaults(metadata=langsmith_metadata) + if tracing_metadata: + callback_manager.tracing_metadata = tracing_metadata return callback_manager diff --git a/libs/core/langchain_core/tracers/base.py b/libs/core/langchain_core/tracers/base.py index eaf9c04359f..4e4a5535256 100644 --- a/libs/core/langchain_core/tracers/base.py +++ b/libs/core/langchain_core/tracers/base.py @@ -33,6 +33,9 @@ logger = logging.getLogger(__name__) class BaseTracer(_TracerCore, BaseCallbackHandler, ABC): """Base interface for tracers.""" + # Opt in to receiving per-invocation tracing_metadata via handle_event. + _accepts_tracing_metadata = True + @abstractmethod def _persist_run(self, run: Run) -> None: """Persist a run.""" @@ -59,6 +62,7 @@ class BaseTracer(_TracerCore, BaseCallbackHandler, ABC): parent_run_id: UUID | None = None, metadata: dict[str, Any] | None = None, name: str | None = None, + tracing_metadata: dict[str, str] | None = None, **kwargs: Any, ) -> Run: """Start a trace for a chat model run. @@ -77,6 +81,8 @@ class BaseTracer(_TracerCore, BaseCallbackHandler, ABC): parent_run_id: The parent run ID. metadata: The metadata for the run. name: The name of the run. + tracing_metadata: Per-invocation default metadata to merge + into the run. Existing run metadata keys are not overwritten. **kwargs: Additional arguments. Returns: @@ -92,6 +98,9 @@ class BaseTracer(_TracerCore, BaseCallbackHandler, ABC): name=name, **kwargs, ) + if tracing_metadata: + existing = chat_model_run.extra.get("metadata") or {} + chat_model_run.extra["metadata"] = {**tracing_metadata, **existing} self._start_trace(chat_model_run) self._on_chat_model_start(chat_model_run) return chat_model_run @@ -106,6 +115,7 @@ class BaseTracer(_TracerCore, BaseCallbackHandler, ABC): parent_run_id: UUID | None = None, metadata: dict[str, Any] | None = None, name: str | None = None, + tracing_metadata: dict[str, str] | None = None, **kwargs: Any, ) -> Run: """Start a trace for an LLM run. @@ -118,6 +128,8 @@ class BaseTracer(_TracerCore, BaseCallbackHandler, ABC): parent_run_id: The parent run ID. metadata: The metadata for the run. name: The name of the run. + tracing_metadata: Per-invocation default metadata to merge + into the run. Existing run metadata keys are not overwritten. **kwargs: Additional arguments. Returns: @@ -133,6 +145,9 @@ class BaseTracer(_TracerCore, BaseCallbackHandler, ABC): name=name, **kwargs, ) + if tracing_metadata: + existing = llm_run.extra.get("metadata") or {} + llm_run.extra["metadata"] = {**tracing_metadata, **existing} self._start_trace(llm_run) self._on_llm_start(llm_run) return llm_run @@ -260,6 +275,7 @@ class BaseTracer(_TracerCore, BaseCallbackHandler, ABC): metadata: dict[str, Any] | None = None, run_type: str | None = None, name: str | None = None, + tracing_metadata: dict[str, str] | None = None, **kwargs: Any, ) -> Run: """Start a trace for a chain run. @@ -273,6 +289,8 @@ class BaseTracer(_TracerCore, BaseCallbackHandler, ABC): metadata: The metadata for the run. run_type: The type of the run. name: The name of the run. + tracing_metadata: Per-invocation default metadata to merge + into the run. Existing run metadata keys are not overwritten. **kwargs: Additional arguments. Returns: @@ -289,6 +307,9 @@ class BaseTracer(_TracerCore, BaseCallbackHandler, ABC): name=name, **kwargs, ) + if tracing_metadata: + existing = chain_run.extra.get("metadata") or {} + chain_run.extra["metadata"] = {**tracing_metadata, **existing} self._start_trace(chain_run) self._on_chain_start(chain_run) return chain_run @@ -362,6 +383,7 @@ class BaseTracer(_TracerCore, BaseCallbackHandler, ABC): metadata: dict[str, Any] | None = None, name: str | None = None, inputs: dict[str, Any] | None = None, + tracing_metadata: dict[str, str] | None = None, **kwargs: Any, ) -> Run: """Start a trace for a tool run. @@ -375,6 +397,8 @@ class BaseTracer(_TracerCore, BaseCallbackHandler, ABC): metadata: The metadata for the run. name: The name of the run. inputs: The inputs for the tool. + tracing_metadata: Per-invocation default metadata to merge + into the run. Existing run metadata keys are not overwritten. **kwargs: Additional arguments. Returns: @@ -391,6 +415,9 @@ class BaseTracer(_TracerCore, BaseCallbackHandler, ABC): inputs=inputs, **kwargs, ) + if tracing_metadata: + existing = tool_run.extra.get("metadata") or {} + tool_run.extra["metadata"] = {**tracing_metadata, **existing} self._start_trace(tool_run) self._on_tool_start(tool_run) return tool_run @@ -451,6 +478,7 @@ class BaseTracer(_TracerCore, BaseCallbackHandler, ABC): tags: list[str] | None = None, metadata: dict[str, Any] | None = None, name: str | None = None, + tracing_metadata: dict[str, str] | None = None, **kwargs: Any, ) -> Run: """Run when the `Retriever` starts running. @@ -463,6 +491,8 @@ class BaseTracer(_TracerCore, BaseCallbackHandler, ABC): tags: The tags for the run. metadata: The metadata for the run. name: The name of the run. + tracing_metadata: Per-invocation default metadata to merge + into the run. Existing run metadata keys are not overwritten. **kwargs: Additional arguments. Returns: @@ -478,6 +508,9 @@ class BaseTracer(_TracerCore, BaseCallbackHandler, ABC): name=name, **kwargs, ) + if tracing_metadata: + existing = retrieval_run.extra.get("metadata") or {} + retrieval_run.extra["metadata"] = {**tracing_metadata, **existing} self._start_trace(retrieval_run) self._on_retriever_start(retrieval_run) return retrieval_run diff --git a/libs/core/langchain_core/tracers/langchain.py b/libs/core/langchain_core/tracers/langchain.py index b8242a27b49..77c108893bf 100644 --- a/libs/core/langchain_core/tracers/langchain.py +++ b/libs/core/langchain_core/tracers/langchain.py @@ -201,6 +201,7 @@ class LangChainTracer(BaseTracer): parent_run_id: UUID | None = None, metadata: dict[str, Any] | None = None, name: str | None = None, + tracing_metadata: dict[str, str] | None = None, **kwargs: Any, ) -> Run: """Start a trace for an LLM run. @@ -213,6 +214,7 @@ class LangChainTracer(BaseTracer): parent_run_id: The parent run ID. metadata: The metadata. name: The name. + tracing_metadata: Per-invocation default metadata. **kwargs: Additional keyword arguments. Returns: @@ -233,6 +235,9 @@ class LangChainTracer(BaseTracer): tags=tags, name=name, ) + if tracing_metadata: + existing = chat_model_run.extra.get("metadata") or {} + chat_model_run.extra["metadata"] = {**tracing_metadata, **existing} self._start_trace(chat_model_run) self._on_chat_model_start(chat_model_run) return chat_model_run @@ -427,6 +432,7 @@ class LangChainTracer(BaseTracer): def _patch_missing_metadata(self: LangChainTracer, run: Run) -> None: + # Apply constructor-set tracing_metadata as defaults (fill-not-overwrite). if not self.tracing_metadata: return metadata = run.metadata diff --git a/libs/core/tests/unit_tests/runnables/test_tracing_interops.py b/libs/core/tests/unit_tests/runnables/test_tracing_interops.py index 2e5fdc77a29..0dd9f0bc2f3 100644 --- a/libs/core/tests/unit_tests/runnables/test_tracing_interops.py +++ b/libs/core/tests/unit_tests/runnables/test_tracing_interops.py @@ -681,42 +681,44 @@ class TestTracerMetadataThroughInvoke: assert md["config_key"] == "config_val" -class TestLangsmithMetadataInConfigure: - """Tests for `langsmith_metadata` parameter in `CallbackManager.configure()`.""" +class TestTracingMetadataInConfigure: + """Tests for `tracing_metadata` parameter in `CallbackManager.configure()`.""" - def test_langsmith_metadata_applied_via_configure(self) -> None: - """langsmith_metadata flows through configure to LangChainTracer.""" + def test_tracing_metadata_applied_via_configure(self) -> None: + """tracing_metadata flows through configure to the CallbackManager.""" tracer = _create_tracer_with_mocked_client() cm = CallbackManager.configure( inheritable_callbacks=[tracer], - langsmith_metadata={"env": "prod", "service": "api"}, + tracing_metadata={"env": "prod", "service": "api"}, ) - # The tracer should have set_defaults called with the metadata - lc_tracers = [h for h in cm.handlers if isinstance(h, LangChainTracer)] - assert len(lc_tracers) == 1 - assert lc_tracers[0].tracing_metadata == {"env": "prod", "service": "api"} + # Metadata is stored on the manager, not mutated on the shared tracer. + assert cm.tracing_metadata == {"env": "prod", "service": "api"} + # The shared tracer instance is NOT mutated. + assert tracer.tracing_metadata is None - def test_langsmith_metadata_does_not_overwrite_tracer_metadata(self) -> None: - """Tracer's own metadata takes precedence over langsmith_metadata.""" + def test_tracing_metadata_does_not_overwrite_tracer_metadata(self) -> None: + """Tracer's own metadata takes precedence over tracing_metadata.""" tracer = _create_tracer_with_mocked_client(metadata={"env": "staging"}) - CallbackManager.configure( + cm = CallbackManager.configure( inheritable_callbacks=[tracer], - langsmith_metadata={"env": "prod", "service": "api"}, + tracing_metadata={"env": "prod", "service": "api"}, ) - assert tracer.tracing_metadata == {"env": "staging", "service": "api"} + # The shared tracer instance is NOT mutated. + assert tracer.tracing_metadata == {"env": "staging"} + # Per-invocation defaults are on the manager. + assert cm.tracing_metadata == {"env": "prod", "service": "api"} - def test_langsmith_metadata_end_to_end(self) -> None: - """langsmith_metadata in configure propagates to posted runs.""" + def test_tracing_metadata_end_to_end(self) -> None: + """tracing_metadata in configure propagates to posted runs.""" tracer = _create_tracer_with_mocked_client() @RunnableLambda def my_func(x: int) -> int: return x - # Use langsmith_metadata through the config callbacks path cm = CallbackManager.configure( inheritable_callbacks=[tracer], - langsmith_metadata={"env": "prod"}, + tracing_metadata={"env": "prod"}, ) my_func.invoke(1, {"callbacks": cm}) @@ -725,8 +727,8 @@ class TestLangsmithMetadataInConfigure: md = posts[0].get("extra", {}).get("metadata", {}) assert md["env"] == "prod" - def test_langsmith_metadata_does_not_affect_non_tracer_handlers(self) -> None: - """langsmith_metadata only applies to LangChainTracer, not other handlers.""" + def test_tracing_metadata_does_not_affect_non_tracer_handlers(self) -> None: + """tracing_metadata only applies to tracer handlers, not other handlers.""" tracer = _create_tracer_with_mocked_client() received_metadata: list[dict[str, Any]] = [] @@ -738,7 +740,7 @@ class TestLangsmithMetadataInConfigure: capture = MetadataCapture() cm = CallbackManager.configure( inheritable_callbacks=[tracer, capture], - langsmith_metadata={"tracer_only": "yes"}, + tracing_metadata={"tracer_only": "yes"}, ) @RunnableLambda @@ -747,7 +749,7 @@ class TestLangsmithMetadataInConfigure: my_func.invoke(1, {"callbacks": cm}) - # Non-tracer handler should NOT see langsmith_metadata + # Non-tracer handler should NOT see tracing_metadata assert len(received_metadata) >= 1 for md in received_metadata: assert "tracer_only" not in md @@ -759,11 +761,11 @@ class TestLangsmithMetadataInConfigure: post_md = post.get("extra", {}).get("metadata", {}) assert post_md["tracer_only"] == "yes" - def test_no_langsmith_metadata_is_noop(self) -> None: - """Passing langsmith_metadata=None does not alter tracer state.""" + def test_no_tracing_metadata_is_noop(self) -> None: + """Passing tracing_metadata=None does not alter tracer state.""" tracer = _create_tracer_with_mocked_client() CallbackManager.configure( inheritable_callbacks=[tracer], - langsmith_metadata=None, + tracing_metadata=None, ) assert tracer.tracing_metadata is None