gemini/agents/genai-experience-concierge/langgraph-demo/backend/notebooks/langgraph-agent.ipynb (397 lines of code) (raw):
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"id": "f705f4be70e9"
},
"outputs": [],
"source": [
"# Copyright 2025 Google LLC\n",
"#\n",
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
"# you may not use this file except in compliance with the License.\n",
"# You may obtain a copy of the License at\n",
"#\n",
"# https://www.apache.org/licenses/LICENSE-2.0\n",
"#\n",
"# Unless required by applicable law or agreed to in writing, software\n",
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
"# See the License for the specific language governing permissions and\n",
"# limitations under the License."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "40503295d0ef"
},
"source": [
"# Constructing a LangGraphAgent"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "56af7aaf9a84"
},
"source": [
"<table align=\"left\">\n",
" <td style=\"text-align: center\">\n",
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/generative-ai/blob/main/gemini/agents/genai-experience-concierge/langgraph-demo/backend/notebooks/langgraph-agent.ipynb\">\n",
" <img width=\"32px\" src=\"https://www.gstatic.com/pantheon/images/bigquery/welcome_page/colab-logo.svg\" alt=\"Google Colaboratory logo\"><br> Open in Colab\n",
" </a>\n",
" </td>\n",
" <td style=\"text-align: center\">\n",
" <a href=\"https://console.cloud.google.com/vertex-ai/colab/import/https:%2F%2Fraw.githubusercontent.com%2FGoogleCloudPlatform%2Fgenerative-ai%2Fmain%2Fgemini%2Fagents%2Fgenai-experience-concierge%2Flanggraph-demo%2Fbackend%2Fnotebooks%2Flanggraph-agent.ipynb\">\n",
" <img width=\"32px\" src=\"https://lh3.googleusercontent.com/JmcxdQi-qOpctIvWKgPtrzZdJJK-J3sWE1RsfjZNwshCFgE_9fULcNpuXYTilIR2hjwN\" alt=\"Google Cloud Colab Enterprise logo\"><br> Open in Colab Enterprise\n",
" </a>\n",
" </td>\n",
" <td style=\"text-align: center\">\n",
" <a href=\"https://console.cloud.google.com/vertex-ai/workbench/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/generative-ai/main/gemini/agents/genai-experience-concierge/langgraph-demo/backend/notebooks/langgraph-agent.ipynb\">\n",
" <img src=\"https://www.gstatic.com/images/branding/gcpiconscolors/vertexai/v1/32px.svg\" alt=\"Vertex AI logo\"><br> Open in Vertex AI Workbench\n",
" </a>\n",
" </td>\n",
" <td style=\"text-align: center\">\n",
" <a href=\"https://github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/agents/genai-experience-concierge/langgraph-demo/backend/notebooks/langgraph-agent.ipynb\">\n",
" <img width=\"32px\" src=\"https://www.svgrepo.com/download/217753/github.svg\" alt=\"GitHub logo\"><br> View on GitHub\n",
" </a>\n",
" </td>\n",
"</table>\n",
"\n",
"<div style=\"clear: both;\"></div>\n",
"\n",
"<b>Share to:</b>\n",
"\n",
"<a href=\"https://www.linkedin.com/sharing/share-offsite/?url=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/agents/genai-experience-concierge/langgraph-demo/backend/notebooks/langgraph-agent.ipynb\" target=\"_blank\">\n",
" <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/8/81/LinkedIn_icon.svg\" alt=\"LinkedIn logo\">\n",
"</a>\n",
"\n",
"<a href=\"https://bsky.app/intent/compose?text=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/agents/genai-experience-concierge/langgraph-demo/backend/notebooks/langgraph-agent.ipynb\" target=\"_blank\">\n",
" <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/7/7a/Bluesky_Logo.svg\" alt=\"Bluesky logo\">\n",
"</a>\n",
"\n",
"<a href=\"https://twitter.com/intent/tweet?url=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/agents/genai-experience-concierge/langgraph-demo/backend/notebooks/langgraph-agent.ipynb\" target=\"_blank\">\n",
" <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/5/5a/X_icon_2.svg\" alt=\"X logo\">\n",
"</a>\n",
"\n",
"<a href=\"https://reddit.com/submit?url=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/agents/genai-experience-concierge/langgraph-demo/backend/notebooks/langgraph-agent.ipynb\" target=\"_blank\">\n",
" <img width=\"20px\" src=\"https://redditinc.com/hubfs/Reddit%20Inc/Brand/Reddit_Logo.png\" alt=\"Reddit logo\">\n",
"</a>\n",
"\n",
"<a href=\"https://www.facebook.com/sharer/sharer.php?u=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/agents/genai-experience-concierge/langgraph-demo/backend/notebooks/langgraph-agent.ipynb\" target=\"_blank\">\n",
" <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/5/51/Facebook_f_logo_%282019%29.svg\" alt=\"Facebook logo\">\n",
"</a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "dbfe0a3c85ab"
},
"source": [
"| | |\n",
"|-|-|\n",
"|Author(s) | [Pablo Gaeta](https://github.com/pablofgaeta) |"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "80df1bbc5c57"
},
"source": [
"## Overview\n",
"\n",
"This notebook demonstrates the necessary code to transform any LangGraph graph into a `LangGraphAgent` using the `concierge.langgraph_server` module.\n",
"\n",
"This is a useful interactive way to develop agents before deploying them on a server."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "faca4bb1709f"
},
"source": [
"## Import dependencies"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"id": "d376d236bf4b"
},
"outputs": [],
"source": [
"import asyncio\n",
"from typing import TypedDict\n",
"import uuid\n",
"\n",
"from concierge.langgraph_server import langgraph_agent, schemas\n",
"from langgraph import graph, types"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "fd56ca055bc6"
},
"source": [
"## Define graph state schema and simple graph implementation"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"id": "9c8f32748aa9"
},
"outputs": [],
"source": [
"# State schema\n",
"\n",
"\n",
"class State(TypedDict, total=False):\n",
" id: str\n",
"\n",
"\n",
"# Node functions\n",
"\n",
"\n",
"async def set_id(state: State):\n",
" new_id = state.get(\"id\")\n",
" assert new_id is not None, \"must set ID\"\n",
"\n",
" await asyncio.sleep(1)\n",
" return types.Command(update=State(id=new_id), goto=\"REVERSE_ID\")\n",
"\n",
"\n",
"async def reverse_id(state: State):\n",
" new_id = state.get(\"id\")\n",
" assert new_id is not None, \"ID must be set before reversing\"\n",
"\n",
" await asyncio.sleep(1)\n",
" return types.Command(update=State(id=new_id[::-1]))\n",
"\n",
"\n",
"# Graph\n",
"\n",
"state_graph = graph.StateGraph(state_schema=State)\n",
"state_graph.add_node(\"SET_ID\", set_id)\n",
"state_graph.add_node(\"REVERSE_ID\", reverse_id)\n",
"state_graph.set_entry_point(\"SET_ID\");"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "7cb6adb34f11"
},
"source": [
"## Build a _stateful_ agent"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"id": "a49509c54b29"
},
"outputs": [],
"source": [
"basic_agent = langgraph_agent.LangGraphAgent(\n",
" state_graph=state_graph,\n",
" checkpointer_config=schemas.MemoryBackendConfig(),\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "01c2cd4651a5"
},
"source": [
"**Test**: Run a query in debug stream mode"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"id": "7b0721483f62"
},
"outputs": [],
"source": [
"async for chunk in basic_agent.stream(\n",
" input=State(id=\"hello\"),\n",
" config={\"configurable\": {\"thread_id\": uuid.uuid4().hex}},\n",
" stream_mode=\"debug\",\n",
"):\n",
" print(chunk)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "6cee145a454e"
},
"source": [
"**Test**: Run a query in values mode (full state returned each time)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"id": "c368bf3c6b63"
},
"outputs": [],
"source": [
"async for chunk in basic_agent.stream(\n",
" input=State(id=\"hello\"),\n",
" config={\"configurable\": {\"thread_id\": uuid.uuid4().hex}},\n",
" stream_mode=\"values\",\n",
"):\n",
" print(\"complete state\", \"=\", chunk)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "b42173c19c6b"
},
"source": [
"**Test**: Run a query in updates mode (only state updates returned by each node)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"id": "5702fb63eb29"
},
"outputs": [],
"source": [
"async for chunk in basic_agent.stream(\n",
" input=State(id=\"hello\"),\n",
" config={\"configurable\": {\"thread_id\": uuid.uuid4().hex}},\n",
" stream_mode=\"updates\",\n",
"):\n",
" print(\"updates\", \"->\", chunk)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "e65e2a213b30"
},
"source": [
"**Test**: Run a query with a list of stream modes (yields stream mode and chunk data)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"id": "c30db9a8a393"
},
"outputs": [],
"source": [
"async for stream_mode, chunk in basic_agent.stream(\n",
" input=State(id=\"hello\"),\n",
" config={\"configurable\": {\"thread_id\": uuid.uuid4().hex}},\n",
" stream_mode=[\"updates\"],\n",
"):\n",
" print(stream_mode, \"->\", chunk)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "34b3574a9425"
},
"source": [
"**Test**: Attempt a stateless query, fails since checkpointer requires thread ID. To run stateless queries, must build a stateless agent like the example in the next section."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"id": "b91f9f8497a2"
},
"outputs": [],
"source": [
"async for stream_mode, chunk in basic_agent.stream(\n",
" input=State(id=\"hello\"),\n",
" config={\"configurable\": {\"thread_id\": uuid.uuid4().hex}},\n",
" stream_mode=[\"updates\"],\n",
"):\n",
" print(stream_mode, \"->\", chunk)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "c78f7af99ca9"
},
"source": [
"## Build a _stateless_ agent"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"id": "693b95986c1a"
},
"outputs": [],
"source": [
"stateless_basic_agent = langgraph_agent.LangGraphAgent(\n",
" state_graph=state_graph,\n",
" checkpointer_config=None, # no checkpointer means it will only work with stateless requests\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "397beba9ee29"
},
"source": [
"**Test**: Run stateless run without threads"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"id": "9f02207bea72"
},
"outputs": [],
"source": [
"async for chunk in stateless_basic_agent.stream(\n",
" input=State(id=\"hello\"),\n",
" stream_mode=\"updates\",\n",
"):\n",
" print(\"complete state\", \"=\", chunk)"
]
}
],
"metadata": {
"colab": {
"name": "langgraph-agent.ipynb",
"toc_visible": true
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
}
},
"nbformat": 4,
"nbformat_minor": 0
}