Merge branch 'main' into vb/fix-command-messages

This commit is contained in:
Nuno Campos
2025-04-11 14:27:26 -07:00
committed by GitHub
11 changed files with 32 additions and 75 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
# How to Deploy to Cloud SaaS
# How to Deploy to Cloud SaaS (Beta)
Before deploying, review the [conceptual guide for the Cloud SaaS](../../concepts/langgraph_cloud.md) deployment option.
@@ -1,4 +1,4 @@
# How to Deploy Self-Hosted Control Plane
# How to Deploy Self-Hosted Control Plane (Beta)
Before deploying, review the [conceptual guide for the Self-Hosted Control Plane](../../concepts/langgraph_self_hosted_control_plane.md) deployment option.
@@ -1,4 +1,4 @@
# How to Deploy Self-Hosted Data Plane
# How to Deploy Self-Hosted Data Plane (Beta)
Before deploying, review the [conceptual guide for the Self-Hosted Data Plane](../../concepts/langgraph_self_hosted_data_plane.md) deployment option.
+3 -3
View File
@@ -10,11 +10,11 @@
There are 4 main options for deploying with the LangGraph Platform:
1. **[Cloud SaaS](#cloud-saas)**: Available for **Plus** and **Enterprise** plans.
1. **<a href="#cloud-saas">Cloud SaaS<sup>(Beta)</sup></a>**: Available for **Plus** and **Enterprise** plans.
1. **[Self-Hosted Data Plane](#self-hosted-data-plane)**: Available for the **Enterprise** plan.
1. **<a href="#self-hosted-data-plane">Self-Hosted Data Plane<sup>(Beta)</sup></a>**: Available for the **Enterprise** plan.
1. **[Self-Hosted Control Plane](#self-hosted-control-plane)**: Available for the **Enterprise** plan.
1. **<a href="#self-hosted-control-plane">Self-Hosted Control Plane<sup>(Beta)</sup></a>**: Available for the **Enterprise** plan.
1. **[Standalone Container](#standalone-container)**: Available for all plans.
+1 -1
View File
@@ -1,4 +1,4 @@
# Cloud SaaS
# Cloud SaaS (Beta)
To deploy a [LangGraph Server](../concepts/langgraph_server.md), follow the how-to guide for [how to deploy to Cloud SaaS](../cloud/deployment/cloud.md).
+4
View File
@@ -5,6 +5,10 @@ search:
# LangGraph Platform
Watch this 4-minute overview of LangGraph Platform to see how it helps you build, deploy, and evaluate agentic applications.
<iframe width="560" height="315" src="https://www.youtube.com/embed/pfAQxBS5z88?si=XGS6Chydn6lhSO1S" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
## Overview
LangGraph Platform is a commercial solution for deploying agentic applications to production, built on the open-source [LangGraph framework](./high_level.md).
@@ -1,4 +1,4 @@
# Self-Hosted Control Plane
# Self-Hosted Control Plane (Beta)
To deploy a [LangGraph Server](../concepts/langgraph_server.md), follow the how-to guide for [how to deploy the Self-Hosted Control Plane](../cloud/deployment/self_hosted_control_plane.md).
@@ -1,4 +1,4 @@
# Self-Hosted Data Plane
# Self-Hosted Data Plane (Beta)
To deploy a [LangGraph Server](../concepts/langgraph_server.md), follow the how-to guide for [how to deploy the Self-Hosted Data Plane](../cloud/deployment/self_hosted_data_plane.md).
+3 -3
View File
@@ -17,9 +17,9 @@ Get started deploying your LangGraph applications locally or on the cloud with
## Deployment Options
- [Cloud SaaS](../concepts/langgraph_cloud.md): Connect to your GitHub repositories and deploy LangGraph Servers to LangChain's cloud. We manage everything.
- [Self-Hosted Data Plane](../concepts/langgraph_self_hosted_data_plane.md): Create deployments from the [Control Plane UI](../concepts/langgraph_control_plane.md#control-plane-ui) and deploy LangGraph Servers to your cloud. We manage the [control plane](../concepts/langgraph_control_plane.md), you manage the deployments.
- [Self-Hosted Control Plane](../concepts/langgraph_self_hosted_control_plane.md#control-plane-ui): Create deployments from a self-hosted [Control Plane UI](../concepts/langgraph_control_plane.md) and deploy LangGraph Servers to your cloud. You manage everything.
- <a href="../../concepts/langgraph_cloud/">Cloud SaaS<sup>(Beta)</sup></a>: Connect to your GitHub repositories and deploy LangGraph Servers to LangChain's cloud. We manage everything.
- <a href="../../concepts/langgraph_self_hosted_data_plane/">Self-Hosted Data Plane<sup>(Beta)</sup></a>: Create deployments from the [Control Plane UI](../concepts/langgraph_control_plane.md#control-plane-ui) and deploy LangGraph Servers to your cloud. We manage the [control plane](../concepts/langgraph_control_plane.md), you manage the deployments.
- <a href="../../concepts/langgraph_self_hosted_control_plane/">Self-Hosted Control Plane<sup>(Beta)</sup></a>: Create deployments from a self-hosted [Control Plane UI](../concepts/langgraph_control_plane.md#control-plane-ui) and deploy LangGraph Servers to your cloud. You manage everything.
- [Standalone Container](../concepts/langgraph_standalone_container.md): Deploy LangGraph Server Docker images however you like.
A quick comparison...
+12 -59
View File
@@ -44,6 +44,7 @@ from langgraph.constants import (
NS_END,
NS_SEP,
TAG_HIDDEN,
TASKS,
)
from langgraph.errors import (
ErrorCode,
@@ -78,7 +79,7 @@ from langgraph.store.base import BaseStore
from langgraph.types import All, Checkpointer, Command, RetryPolicy
from langgraph.utils.fields import get_field_default
from langgraph.utils.pydantic import create_model
from langgraph.utils.runnable import RunnableCallable, RunnableLike, coerce_to_runnable
from langgraph.utils.runnable import RunnableLike, coerce_to_runnable
logger = logging.getLogger(__name__)
@@ -670,10 +671,6 @@ class StateGraph(Graph):
for key, node in self.nodes.items():
compiled.attach_node(key, node)
compiled.nodes[START].writers.append(CONTROL_BRANCH_PATH)
for key in self.nodes:
compiled.nodes[key].writers.append(CONTROL_BRANCH_PATH)
for start, end in self.edges:
compiled.attach_edge(start, end)
@@ -802,6 +799,7 @@ class CompiledStateGraph(CompiledGraph):
ChannelWriteTupleEntry(
mapper=_get_root if output_keys == ["__root__"] else _get_updates
),
ChannelWriteTupleEntry(mapper=_control_branch),
)
# add node and output channel
@@ -936,7 +934,7 @@ class CompiledStateGraph(CompiledGraph):
if end != END:
self.nodes[end].writers.append(
ChannelWrite(
[ChannelWriteEntry(channel_name, end)], tags=[TAG_HIDDEN]
(ChannelWriteEntry(channel_name, end),), tags=[TAG_HIDDEN]
)
)
@@ -1062,10 +1060,9 @@ def _coerce_state(schema: Type[Any], input: dict[str, Any]) -> dict[str, Any]:
return schema(**input)
def _control_branch(value: Any, config: RunnableConfig) -> Any:
def _control_branch(value: Any) -> Sequence[tuple[str, Any]]:
if isinstance(value, Send):
ChannelWrite.do_write(config, (value,))
return value
return ((TASKS, value),)
commands: list[Command] = []
if isinstance(value, Command):
commands.append(value)
@@ -1073,66 +1070,22 @@ def _control_branch(value: Any, config: RunnableConfig) -> Any:
for cmd in value:
if isinstance(cmd, Command):
commands.append(cmd)
rtn: list[Union[ChannelWriteEntry, Send]] = []
rtn: list[tuple[str, Any]] = []
for command in commands:
if command.graph == Command.PARENT:
raise ParentCommand(command)
if isinstance(command.goto, Send):
rtn.append(command.goto)
rtn.append((TASKS, command.goto))
elif isinstance(command.goto, str):
rtn.append(ChannelWriteEntry(CHANNEL_BRANCH_TO.format(command.goto), None))
rtn.append((CHANNEL_BRANCH_TO.format(command.goto), None))
else:
rtn.extend(
go
(TASKS, go)
if isinstance(go, Send)
else ChannelWriteEntry(CHANNEL_BRANCH_TO.format(go), None)
else (CHANNEL_BRANCH_TO.format(go), None)
for go in command.goto
)
if rtn:
ChannelWrite.do_write(config, rtn)
return value
async def _acontrol_branch(value: Any, config: RunnableConfig) -> Any:
if isinstance(value, Send):
ChannelWrite.do_write(config, (value,))
return value
commands: list[Command] = []
if isinstance(value, Command):
commands.append(value)
elif isinstance(value, (list, tuple)):
for cmd in value:
if isinstance(cmd, Command):
commands.append(cmd)
rtn: list[Union[ChannelWriteEntry, Send]] = []
for command in commands:
if command.graph == Command.PARENT:
raise ParentCommand(command)
if isinstance(command.goto, Send):
rtn.append(command.goto)
elif isinstance(command.goto, str):
rtn.append(ChannelWriteEntry(CHANNEL_BRANCH_TO.format(command.goto), None))
else:
rtn.extend(
go
if isinstance(go, Send)
else ChannelWriteEntry(CHANNEL_BRANCH_TO.format(go), None)
for go in command.goto
)
if rtn:
ChannelWrite.do_write(config, rtn)
return value
CONTROL_BRANCH_PATH = RunnableCallable(
_control_branch,
_acontrol_branch,
tags=[TAG_HIDDEN],
trace=False,
recurse=False,
set_context=False,
func_accepts_config=True,
)
return rtn
def _get_root(input: Any) -> Optional[Sequence[tuple[str, Any]]]:
+4 -4
View File
@@ -4660,7 +4660,7 @@ def test_root_graph(
content="result for query",
name="search_api",
tool_call_id="tool_call123",
id="00000000-0000-4000-8000-000000000040",
id="00000000-0000-4000-8000-000000000033",
)
]
},
@@ -4683,7 +4683,7 @@ def test_root_graph(
content="result for another",
name="search_api",
tool_call_id="tool_call456",
id="00000000-0000-4000-8000-000000000049",
id="00000000-0000-4000-8000-000000000041",
)
]
},
@@ -5387,7 +5387,7 @@ def test_root_graph(
"__root__": [
HumanMessage(
content="what is weather in sf",
id="00000000-0000-4000-8000-000000000083",
id="00000000-0000-4000-8000-000000000070",
),
AIMessage(
content="",
@@ -5407,7 +5407,7 @@ def test_root_graph(
),
AIMessage(content="answer", id="ai2"),
AIMessage(
content="an extra message", id="00000000-0000-4000-8000-000000000107"
content="an extra message", id="00000000-0000-4000-8000-000000000091"
),
HumanMessage(content="what is weather in la"),
],