cli: rename langgraph.json to langsmith.json

Rename the default config filename from `langgraph.json` to
`langsmith.json` as part of the "LangGraph Platform" to "LangSmith
Deployment" rebranding.

Backward compatibility is preserved: the CLI falls back to
`langgraph.json` with a deprecation warning when `langsmith.json`
is not found. A new `_resolve_config` callback handles the
resolution logic for all `--config` click options.

Changes span libs/cli (core logic, examples, tests), libs/sdk-py
(docstrings), libs/langgraph (Makefile), and .github CI scripts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
William Fu-Hinthorn
2026-03-29 07:41:32 -07:00
co-authored by Claude Opus 4.6
parent ae76f33c6d
commit a99d733bb5
29 changed files with 125 additions and 62 deletions
+7 -7
View File
@@ -50,7 +50,7 @@ def temporary_config_folder(config_content: dict, levels: int = 0):
def test_prepare_args_and_stdin() -> None:
# this basically serves as an end-to-end test for using config and docker helpers
config_path = pathlib.Path(__file__).parent / "langgraph.json"
config_path = pathlib.Path(__file__).parent / "langsmith.json"
config = validate_config(
Config(dependencies=[".", "../../.."], graphs={"agent": "agent.py:graph"})
)
@@ -159,7 +159,7 @@ services:
develop:
watch:
- path: langgraph.json
- path: langsmith.json
action: rebuild
- path: .
action: rebuild
@@ -172,7 +172,7 @@ services:
def test_prepare_args_and_stdin_with_image() -> None:
# this basically serves as an end-to-end test for using config and docker helpers
config_path = pathlib.Path(__file__).parent / "langgraph.json"
config_path = pathlib.Path(__file__).parent / "langsmith.json"
config = validate_config(
Config(dependencies=[".", "../../.."], graphs={"agent": "agent.py:graph"})
)
@@ -263,7 +263,7 @@ services:
develop:
watch:
- path: langgraph.json
- path: langsmith.json
action: rebuild
- path: .
action: rebuild
@@ -1136,7 +1136,7 @@ def test_build_command_with_api_version_and_base_image() -> None:
def test_prepare_args_and_stdin_with_api_version() -> None:
"""Test prepare_args_and_stdin function with api_version parameter."""
config_path = pathlib.Path(__file__).parent / "langgraph.json"
config_path = pathlib.Path(__file__).parent / "langsmith.json"
config = validate_config(
Config(dependencies=["."], graphs={"agent": "agent.py:graph"})
)
@@ -1169,7 +1169,7 @@ def test_prepare_args_and_stdin_with_api_version() -> None:
def test_prepare_args_and_stdin_with_api_version_and_image() -> None:
"""Test prepare_args_and_stdin function with both api_version and image parameters."""
config_path = pathlib.Path(__file__).parent / "langgraph.json"
config_path = pathlib.Path(__file__).parent / "langsmith.json"
config = validate_config(
Config(dependencies=["."], graphs={"agent": "agent.py:graph"})
)
@@ -1298,7 +1298,7 @@ def test_dockerfile_command_distributed_with_explicit_base_image() -> None:
def test_prepare_args_and_stdin_distributed_mode() -> None:
"""Test prepare_args_and_stdin with distributed mode includes all services."""
config_path = pathlib.Path(__file__).parent / "langgraph.json"
config_path = pathlib.Path(__file__).parent / "langsmith.json"
config = validate_config(
Config(dependencies=["."], graphs={"agent": "agent.py:graph"})
)
+1 -1
View File
@@ -309,7 +309,7 @@ def test_validate_config_file():
with tempfile.TemporaryDirectory() as tmpdir:
tmpdir_path = pathlib.Path(tmpdir)
config_path = tmpdir_path / "langgraph.json"
config_path = tmpdir_path / "langsmith.json"
node_config = {"node_version": "20", "graphs": {"agent": "./agent.js:graph"}}
with open(config_path, "w") as f:
@@ -85,7 +85,7 @@ class TestNormalizeImageTag:
class TestParseEnvFromConfig:
def test_env_dict(self, tmp_path):
config_path = tmp_path / "langgraph.json"
config_path = tmp_path / "langsmith.json"
config_path.touch()
result = _parse_env_from_config({"env": {"FOO": "bar", "NUM": 42}}, config_path)
assert result == {"FOO": "bar", "NUM": "42"}
@@ -93,7 +93,7 @@ class TestParseEnvFromConfig:
def test_env_string_dotenv_file(self, tmp_path):
env_file = tmp_path / "my.env"
env_file.write_text("KEY1=val1\nKEY2=val2\n")
config_path = tmp_path / "langgraph.json"
config_path = tmp_path / "langsmith.json"
config_path.touch()
result = _parse_env_from_config({"env": "my.env"}, config_path)
assert result == {"KEY1": "val1", "KEY2": "val2"}
@@ -102,7 +102,7 @@ class TestParseEnvFromConfig:
env_file = tmp_path / ".env"
env_file.write_text("DEFAULT_KEY=default_val\n")
monkeypatch.chdir(tmp_path)
config_path = tmp_path / "langgraph.json"
config_path = tmp_path / "langsmith.json"
config_path.touch()
result = _parse_env_from_config({}, config_path)
assert result == {"DEFAULT_KEY": "default_val"}
@@ -112,14 +112,14 @@ class TestParseEnvFromConfig:
env_file = tmp_path / ".env"
env_file.write_text("MY_KEY=my_val\n")
monkeypatch.chdir(tmp_path)
config_path = tmp_path / "langgraph.json"
config_path = tmp_path / "langsmith.json"
config_path.touch()
result = _parse_env_from_config({"env": {}}, config_path)
assert result == {"MY_KEY": "my_val"}
def test_env_missing_no_dotenv_returns_empty(self, tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
config_path = tmp_path / "langgraph.json"
config_path = tmp_path / "langsmith.json"
config_path.touch()
result = _parse_env_from_config({}, config_path)
assert result == {}
@@ -128,7 +128,7 @@ class TestParseEnvFromConfig:
# Lines like "KEY=" produce empty string, lines like "KEY" produce None
env_file = tmp_path / "test.env"
env_file.write_text("GOOD=value\nEMPTY=\n")
config_path = tmp_path / "langgraph.json"
config_path = tmp_path / "langsmith.json"
config_path.touch()
result = _parse_env_from_config({"env": "test.env"}, config_path)
assert "GOOD" in result
+4 -4
View File
@@ -48,7 +48,7 @@ def test_warn_non_wolfi_distro_with_debian(capsys):
in captured.out
)
assert (
'To switch, add \'"image_distro": "wolfi"\' to your langgraph.json config file.'
'To switch, add \'"image_distro": "wolfi"\' to your langsmith.json config file.'
in captured.out
)
@@ -69,7 +69,7 @@ def test_warn_non_wolfi_distro_with_default_debian(capsys):
in captured.out
)
assert (
'To switch, add \'"image_distro": "wolfi"\' to your langgraph.json config file.'
'To switch, add \'"image_distro": "wolfi"\' to your langsmith.json config file.'
in captured.out
)
@@ -100,7 +100,7 @@ def test_warn_non_wolfi_distro_with_other_distro(capsys):
in captured.out
)
assert (
'To switch, add \'"image_distro": "wolfi"\' to your langgraph.json config file.'
'To switch, add \'"image_distro": "wolfi"\' to your langsmith.json config file.'
in captured.out
)
@@ -128,7 +128,7 @@ def test_warn_non_wolfi_distro_output_formatting():
),
(
(
' To switch, add \'"image_distro": "wolfi"\' to your langgraph.json config file.',
' To switch, add \'"image_distro": "wolfi"\' to your langsmith.json config file.',
),
{"fg": "yellow"},
),