diff --git a/docs/docs/concepts/low_level.md b/docs/docs/concepts/low_level.md index 26b5e9ff8..c8e05ec31 100644 --- a/docs/docs/concepts/low_level.md +++ b/docs/docs/concepts/low_level.md @@ -359,6 +359,25 @@ Use `Command` when you need to **both** update the graph state **and** route to Use [conditional edges](#conditional-edges) to route between nodes conditionally without updating the state. +### Navigating to a node in a parent graph + +If you are using [subgraphs](#subgraphs), you might want to navigate from a node a subgraph to a different subgraph (i.e. a different node in the parent graph). To do so, you can specify `graph=Command.PARENT` in `Command`: + +```python +def my_node(state: State) -> Command[Literal["my_other_node"]]: + return Command( + update={"foo": "bar"}, + goto="other_subgraph", # where `other_subgraph` is a node in the parent graph + graph=Command.PARENT + ) +``` + +!!! note + + Setting `graph` to `Command.PARENT` will navigate to the closest parent graph. + +This is particularly useful when implementing [multi-agent handoffs](./multi_agent.md#handoffs). + ### Using inside tools A common use case is updating graph state from inside a tool. For example, in a customer support application you might want to look up customer information based on their account number or ID in the beginning of the conversation. To update the graph state from the tool, you can return `Command(update={"my_custom_key": "foo", "messages": [...]})` from the tool: diff --git a/docs/docs/how-tos/command.ipynb b/docs/docs/how-tos/command.ipynb index acc9ff2b4..fe947a80b 100644 --- a/docs/docs/how-tos/command.ipynb +++ b/docs/docs/how-tos/command.ipynb @@ -33,6 +33,17 @@ " )\n", "```\n", "\n", + "If you are using [subgraphs](#subgraphs), you might want to navigate from a node a subgraph to a different subgraph (i.e. a different node in the parent graph). To do so, you can specify `graph=Command.PARENT` in `Command`:\n", + "\n", + "```python\n", + "def my_node(state: State) -> Command[Literal[\"my_other_node\"]]:\n", + " return Command(\n", + " update={\"foo\": \"bar\"},\n", + " goto=\"other_subgraph\", # where `other_subgraph` is a node in the parent graph\n", + " graph=Command.PARENT\n", + " )\n", + "```\n", + "\n", "This guide shows how you can do use `Command` to add dynamic control flow in your LangGraph app." ] }, @@ -83,7 +94,7 @@ "id": "6a08d957-b3d2-4538-bf4a-68ef90a51b98", "metadata": {}, "source": [ - "## Define graph" + "## Basic usage" ] }, { @@ -126,9 +137,6 @@ " )\n", "\n", "\n", - "# Nodes B and C are unchanged\n", - "\n", - "\n", "def node_b(state: State):\n", " print(\"Called B\")\n", " return {\"foo\": state[\"foo\"] + \"b\"}\n", @@ -182,7 +190,7 @@ "outputs": [ { "data": { - "image/jpeg": "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", + "image/png": "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", "text/plain": [ "" ] @@ -210,6 +218,109 @@ "execution_count": 5, "id": "d88a5d9b-ee08-4ed4-9c65-6e868210bfac", "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Called A\n", + "Called B\n" + ] + }, + { + "data": { + "text/plain": [ + "{'foo': 'ab'}" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "graph.invoke({\"foo\": \"\"})" + ] + }, + { + "cell_type": "markdown", + "id": "68986cc4-97ec-43a1-b95d-5273d7ffc25a", + "metadata": {}, + "source": [ + "## Navigating to a node in a parent graph" + ] + }, + { + "cell_type": "markdown", + "id": "02ccddf2-978c-41bf-b2eb-2d0c4b3f5d81", + "metadata": {}, + "source": [ + "Now let's demonstrate how you can navigate from inside a subgraph to a different node in a parent graph. We'll do so by changing `node_a` in the above example into a single-node graph that we'll add as a subgraph to our parent graph." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "91351541-67af-4c73-9437-426599dcf81e", + "metadata": {}, + "outputs": [], + "source": [ + "# Define the nodes\n", + "\n", + "\n", + "def node_a(state: State):\n", + " print(\"Called A\")\n", + " value = random.choice([\"a\", \"b\"])\n", + " # this is a replacement for a conditional edge function\n", + " if value == \"a\":\n", + " goto = \"node_b\"\n", + " else:\n", + " goto = \"node_c\"\n", + "\n", + " # note how Command allows you to BOTH update the graph state AND route to the next node\n", + " return Command(\n", + " update={\"foo\": value},\n", + " goto=goto,\n", + " # this tells LangGraph to navigate to node_b or node_c in the parent graph\n", + " # NOTE: this will navigate to the closest parent graph relative to the subgraph\n", + " graph=Command.PARENT,\n", + " )\n", + "\n", + "\n", + "subgraph = StateGraph(State).add_node(node_a).add_edge(START, \"node_a\").compile()\n", + "\n", + "\n", + "def node_b(state: State):\n", + " print(\"Called B\")\n", + " return {\"foo\": state[\"foo\"] + \"b\"}\n", + "\n", + "\n", + "def node_c(state: State):\n", + " print(\"Called C\")\n", + " return {\"foo\": state[\"foo\"] + \"c\"}" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "beb61d02-c868-4c2b-b83f-1dfd280f1c8e", + "metadata": {}, + "outputs": [], + "source": [ + "builder = StateGraph(State)\n", + "builder.add_edge(START, \"subgraph\")\n", + "builder.add_node(\"subgraph\", subgraph)\n", + "builder.add_node(node_b)\n", + "builder.add_node(node_c)\n", + "\n", + "graph = builder.compile()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "3f07b704-1fe2-48a3-ad40-c9bc7698cb1c", + "metadata": {}, "outputs": [ { "name": "stdout", @@ -225,7 +336,7 @@ "{'foo': 'bc'}" ] }, - "execution_count": 5, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" }