{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# LangGraph Integration with AgentOps\n", "\n", "This example demonstrates how to use LangGraph with AgentOps for comprehensive observability of your graph-based agent workflows.\n", "\n", "LangGraph is a framework for building stateful, multi-step applications with LLMs. AgentOps automatically instruments LangGraph to track:\n", "- Graph compilation and structure\n", "- Node executions and transitions\n", "- Tool usage within the graph\n", "- LLM calls made by agents\n", "- Complete execution flow with timing" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%pip install agentops langgraph langchain-openai python-dotenv" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup\n", "\n", "First, let's import the necessary libraries and initialize AgentOps:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import os\n", "from typing import Annotated, Literal, TypedDict\n", "from langgraph.graph import StateGraph, END\n", "from langgraph.graph.message import add_messages\n", "from langchain_openai import ChatOpenAI\n", "from langchain_core.messages import HumanMessage, ToolMessage\n", "from langchain_core.tools import tool\n", "import agentops\n", "from dotenv import load_dotenv\n", "\n", "# Load environment variables\n", "load_dotenv()\n", "\n", "# Initialize AgentOps - this enables automatic instrumentation\n", "agentops.init(os.getenv(\"AGENTOPS_API_KEY\"), auto_start_session=False)\n", "trace = agentops.start_trace(\"langgraph_example\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Define Tools\n", "\n", "Let's create some simple tools that our agent can use:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "@tool\n", "def get_weather(location: str) -> str:\n", " \"\"\"Get the weather for a given location.\"\"\"\n", " # Simulated weather data\n", " weather_data = {\n", " \"New York\": \"Sunny, 72°F\",\n", " \"London\": \"Cloudy, 60°F\",\n", " \"Tokyo\": \"Rainy, 65°F\",\n", " \"Paris\": \"Partly cloudy, 68°F\",\n", " \"Sydney\": \"Clear, 75°F\",\n", " }\n", " return weather_data.get(location, f\"Weather data not available for {location}\")\n", "\n", "\n", "@tool\n", "def calculate(expression: str) -> str:\n", " \"\"\"Evaluate a mathematical expression.\"\"\"\n", " try:\n", " result = eval(expression)\n", " return f\"The result is: {result}\"\n", " except Exception as e:\n", " return f\"Error calculating expression: {str(e)}\"\n", "\n", "\n", "# Collect tools for binding to the model\n", "tools = [get_weather, calculate]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Define Agent State\n", "\n", "In LangGraph, we need to define the state that will be passed between nodes:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class AgentState(TypedDict):\n", " messages: Annotated[list, add_messages]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Create the Model and Node Functions\n", "\n", "We'll create a model with tool binding and define the functions that will be our graph nodes:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Create model with tool binding\n", "model = ChatOpenAI(temperature=0, model=\"gpt-4o-mini\").bind_tools(tools)\n", "\n", "\n", "def should_continue(state: AgentState) -> Literal[\"tools\", \"end\"]:\n", " \"\"\"Determine if we should continue to tools or end.\"\"\"\n", " messages = state[\"messages\"]\n", " last_message = messages[-1]\n", "\n", " # If the LLM wants to use tools, continue to the tools node\n", " if hasattr(last_message, \"tool_calls\") and last_message.tool_calls:\n", " return \"tools\"\n", " # Otherwise, we're done\n", " return \"end\"\n", "\n", "\n", "def call_model(state: AgentState):\n", " \"\"\"Call the language model.\"\"\"\n", " messages = state[\"messages\"]\n", " response = model.invoke(messages)\n", " return {\"messages\": [response]}\n", "\n", "\n", "def call_tools(state: AgentState):\n", " \"\"\"Execute the tool calls requested by the model.\"\"\"\n", " messages = state[\"messages\"]\n", " last_message = messages[-1]\n", "\n", " tool_messages = []\n", " for tool_call in last_message.tool_calls:\n", " tool_name = tool_call[\"name\"]\n", " tool_args = tool_call[\"args\"]\n", "\n", " # Find and execute the requested tool\n", " for available_tool in tools:\n", " if available_tool.name == tool_name:\n", " result = available_tool.invoke(tool_args)\n", " tool_messages.append(ToolMessage(content=str(result), tool_call_id=tool_call[\"id\"]))\n", " break\n", "\n", " return {\"messages\": tool_messages}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Build the Graph\n", "\n", "Now let's construct the LangGraph workflow:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Create the graph\n", "workflow = StateGraph(AgentState)\n", "\n", "# Add nodes\n", "workflow.add_node(\"agent\", call_model)\n", "workflow.add_node(\"tools\", call_tools)\n", "\n", "# Set the entry point\n", "workflow.set_entry_point(\"agent\")\n", "\n", "# Add conditional edges\n", "workflow.add_conditional_edges(\"agent\", should_continue, {\"tools\": \"tools\", \"end\": END})\n", "\n", "# Add edge from tools back to agent\n", "workflow.add_edge(\"tools\", \"agent\")\n", "\n", "# Compile the graph\n", "app = workflow.compile()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Run Examples\n", "\n", "Let's test our agent with different queries that require tool usage:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Example 1: Weather query\n", "print(\"Example 1: Weather Query\")\n", "print(\"=\" * 50)\n", "\n", "messages = [HumanMessage(content=\"What's the weather in New York and Tokyo?\")]\n", "result = app.invoke({\"messages\": messages})\n", "\n", "final_message = result[\"messages\"][-1]\n", "print(f\"Response: {final_message.content}\\n\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Example 2: Math calculation\n", "print(\"Example 2: Math Calculation\")\n", "print(\"=\" * 50)\n", "\n", "messages = [HumanMessage(content=\"Calculate 25 * 4 + 10\")]\n", "result = app.invoke({\"messages\": messages})\n", "\n", "final_message = result[\"messages\"][-1]\n", "print(f\"Response: {final_message.content}\\n\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Example 3: Combined query\n", "print(\"Example 3: Combined Query\")\n", "print(\"=\" * 50)\n", "\n", "messages = [HumanMessage(content=\"What's the weather in Paris? Also calculate 100/5\")]\n", "result = app.invoke({\"messages\": messages})\n", "\n", "final_message = result[\"messages\"][-1]\n", "print(f\"Response: {final_message.content}\\n\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## View in AgentOps Dashboard\n", "\n", "After running this notebook, you can view the traces in your AgentOps dashboard. You'll see:\n", "\n", "1. **Graph Compilation**: The structure of your LangGraph with nodes and edges\n", "2. **Execution Flow**: How the graph executed, including:\n", " - Agent node calls\n", " - Tool node executions\n", " - State transitions\n", "3. **LLM Calls**: Each ChatGPT call with prompts and completions\n", "4. **Tool Usage**: Which tools were called and their results\n", "5. **Timing Information**: How long each step took\n", "\n", "The instrumentation captures the full context of your LangGraph application automatically!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"✅ Check your AgentOps dashboard for comprehensive traces!\")\n", "print(\"🔍 You'll see the graph structure, execution flow, and all LLM/tool calls.\")\n", "agentops.end_trace(trace)" ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.12" } }, "nbformat": 4, "nbformat_minor": 2 }