Compare commits

...
Author SHA1 Message Date
William Fu-Hinthorn 7d86336927 Bump 2025-09-09 14:28:42 -07:00
William FH 4adbcbc13e chore(langgraph): Omit other keys from metadata by default (#6047)
Right now we include configuration as metadata (which is later passed to
tracing callbacks).

Right now we include any key that doesn't have a dunder prefix and whose
value is a string or int.

This PR proposes to also exclude keys with certain substrings (key,
secret, token).

I would also be in favor of dropping support for forwarding configurable
values to metadata entirely, but this is a smaller, less controversial
change.

Add a test.
2025-09-09 14:28:33 -07:00
5 changed files with 46 additions and 17 deletions
+18 -7
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
from collections import ChainMap
from collections.abc import Sequence
from collections.abc import Mapping, Sequence
from os import getenv
from typing import Any, cast
@@ -312,11 +312,22 @@ def ensure_config(*configs: RunnableConfig | None) -> RunnableConfig:
for k, v in config.items():
if _is_not_empty(v) and k not in CONFIG_KEYS:
empty[CONF][k] = v
_empty_metadata = empty["metadata"]
for key, value in empty[CONF].items():
if (
not key.startswith("__")
and isinstance(value, (str, int, float, bool))
and key not in empty["metadata"]
):
empty["metadata"][key] = value
if _exclude_as_metadata(key, value, _empty_metadata):
continue
_empty_metadata[key] = value
return empty
_OMIT = ("key", "token", "secret", "password", "auth")
def _exclude_as_metadata(key: str, value: Any, metadata: Mapping[str, Any]) -> bool:
key_lower = key.casefold()
return (
key.startswith("__")
or not isinstance(value, (str, int, float, bool))
or key in metadata
or any(substr in key_lower for substr in _OMIT)
)
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "langgraph"
version = "0.6.7"
version = "0.6.8"
description = "Building stateful, multi-actor applications with LLMs"
authors = []
requires-python = ">=3.9"
+23 -5
View File
@@ -17,16 +17,13 @@ import langsmith
import pytest
from typing_extensions import NotRequired, Required, TypedDict
from langgraph._internal._config import _is_not_empty
from langgraph._internal._config import _is_not_empty, ensure_config
from langgraph._internal._fields import (
_is_optional_type,
get_enhanced_type_hints,
get_field_default,
)
from langgraph._internal._runnable import (
is_async_callable,
is_async_generator,
)
from langgraph._internal._runnable import is_async_callable, is_async_generator
from langgraph.constants import END
from langgraph.graph import StateGraph
from langgraph.graph.state import CompiledStateGraph
@@ -301,3 +298,24 @@ def test_is_not_empty() -> None:
assert not _is_not_empty([])
assert not _is_not_empty(())
assert not _is_not_empty({})
def test_configurable_metadata():
config = {
"configurable": {
"a-key": "foo",
"somesecretval": "bar",
"sometoken": "thetoken",
"__dontinclude": "bar",
"includeme": "hi",
"andme": 42,
"nested": {"foo": "bar"},
"nooverride": -2,
},
"metadata": {"nooverride": 18},
}
expected = {"includeme", "andme", "nooverride"}
merged = ensure_config(config)
metadata = merged["metadata"]
assert metadata.keys() == expected
assert metadata["nooverride"] == 18
+2 -2
View File
@@ -1,5 +1,5 @@
version = 1
revision = 2
revision = 3
requires-python = ">=3.9"
resolution-markers = [
"python_full_version >= '3.14'",
@@ -1269,7 +1269,7 @@ wheels = [
[[package]]
name = "langgraph"
version = "0.6.7"
version = "0.6.8"
source = { editable = "." }
dependencies = [
{ name = "langchain-core" },
+2 -2
View File
@@ -1,5 +1,5 @@
version = 1
revision = 2
revision = 3
requires-python = ">=3.9"
[[package]]
@@ -316,7 +316,7 @@ wheels = [
[[package]]
name = "langgraph"
version = "0.6.7"
version = "0.6.8"
source = { editable = "../langgraph" }
dependencies = [
{ name = "langchain-core" },