Skip to content

Latest commit

 

History

History
141 lines (103 loc) · 3.67 KB

File metadata and controls

141 lines (103 loc) · 3.67 KB

Agent Tools

Tools are Python functions that the LangGraph agent can call. They can read and update agent state, fetch data, and perform any server-side logic.

Creating a Tool

Use the @tool decorator from LangChain:

from langchain.tools import tool, ToolRuntime

@tool
def my_tool(arg1: str, arg2: int, runtime: ToolRuntime):
    """Description of what this tool does. The agent reads this to decide when to call it."""
    return f"Result: {arg1} x {arg2}"
  • The docstring tells the agent when and how to use the tool
  • runtime: ToolRuntime gives access to agent state (optional parameter)
  • Return value is sent back to the agent as the tool result

Reading State

Access current agent state via runtime.state:

# apps/agent/src/todos.py

@tool
def get_todos(runtime: ToolRuntime):
    """Get the current todos."""
    return runtime.state.get("todos", [])

Updating State

Return a Command with an update dict to modify agent state:

from langgraph.types import Command
from langchain.messages import ToolMessage

@tool
def manage_todos(todos: list[Todo], runtime: ToolRuntime) -> Command:
    """Manage the current todos."""
    # Ensure all todos have unique IDs
    for todo in todos:
        if "id" not in todo or not todo["id"]:
            todo["id"] = str(uuid.uuid4())

    return Command(update={
        "todos": todos,
        "messages": [
            ToolMessage(
                content="Successfully updated todos",
                tool_call_id=runtime.tool_call_id
            )
        ]
    })

Key points:

  • Command(update={...}) merges the update into agent state
  • Include a ToolMessage in the messages list to acknowledge the tool call
  • Use runtime.tool_call_id for the message's tool_call_id

Returning Data (No State Update)

For tools that just return data without modifying state, return the value directly:

# apps/agent/src/query.py

import csv
from pathlib import Path
from langchain.tools import tool

# Load data at module init
_data = []
with open(Path(__file__).parent / "db.csv") as f:
    _data = list(csv.DictReader(f))

@tool
def query_data(query: str):
    """Query the financial transactions database. Call this before creating charts."""
    return _data

Registering Tools with the Agent

Add tools to the agent's tools list in apps/agent/main.py:

from src.todos import todo_tools  # [manage_todos, get_todos]
from src.query import query_data
from src.plan import plan_visualization

agent = create_deep_agent(
    model=ChatOpenAI(model="gpt-5.4-2026-03-05"),
    tools=[query_data, plan_visualization, *todo_tools],
    middleware=[CopilotKitMiddleware()],
    context_schema=AgentState,
    ...
)

You can pass individual tools or spread a list of tools.

Example: Adding a New Tool

Say you want to add a tool that fetches weather data:

1. Create the tool (apps/agent/src/weather.py):

from langchain.tools import tool

@tool
def get_weather(city: str):
    """Get the current weather for a city."""
    # Your implementation here
    return {"city": city, "temp": 72, "condition": "sunny"}

2. Register it in apps/agent/main.py:

from src.weather import get_weather

agent = create_deep_agent(
    tools=[query_data, plan_visualization, *todo_tools, get_weather],
    ...
)

The agent can now call get_weather when a user asks about weather. If you want a custom UI for the result, register a useRenderTool on the frontend (see Generative UI).

Next Steps

  • Agent State — How state sync works between tools and the frontend
  • Generative UI — Render custom UI for tool results