Skip to content

Chapter 7 of 8

Tools, Agents, and LangGraph

Tools are how an LLM takes real action in the world. The tool decorator turns any Python function into a LangChain tool — the function's name becomes the tool's name, and its docstring becomes the description that the model reads when deciding whether to call it. You invoke the tool like any other runnable. StructuredTool.from_function is the heavier-duty variant: you supply an explicit Pydantic schema for the arguments, which gives you richer validation and a more reliable schema for the model. Both wrap the abstract BaseTool, which defines _run, _arun, args_schema, name, and description; subclassing it directly is the path for tools that need custom validation, async-only behavior, or dynamic schemas.

Once you have tools, you can either bind them to a chat model with bind_tools to get the model to emit tool_calls, or hand them to an agent. An agent is different from a chain: a chain has a predetermined sequence of steps, while an agent uses the LLM at runtime to decide which tools to call, in what order, and how many times. The legacy AgentExecutor runs an agent plus its tools in a loop with safety caps like max_iterations, a configurable early_stopping_method of force or generate, and handle_parsing_errors for malformed tool calls. Modern LangChain prefers LangGraph for agent loops: create_react_agent from langgraph.prebuilt is the canonical tool-calling agent factory that works with any chat model supporting tool calls, including OpenAI, Anthropic, Gemini, and Mistral. For OpenAI models specifically, the OpenAI Functions Agent uses native function calling rather than parsing a ReAct text trace, which is more reliable on those models.

Tool execution has its own conventions. tool_choice set to any forces the model to call a tool, while a dict value forces a specific named tool — useful for routing decisions. After the model emits an AIMessage with tool_calls, you look up each tool by name, invoke it with the parsed args, and append a ToolMessage whose tool_call_id matches the originating call. A tool with return_direct set to True returns its output to the user immediately, skipping the LLM summary step — ideal for deterministic lookups like get_current_time. To handle failures gracefully, raising ToolException inside a tool tells the agent to retry with the exception's message as feedback, and handle_tool_error on a tool does the same declaratively. A tool can also return a tuple of content and artifact so the LLM sees a clean content string while the raw artifact stays in the run state for LangSmith inspection.

For specialized workloads, the SQL Agent writes and executes queries against a SQLDatabase wrapper, the Pandas DataFrame Agent generates Python in a PythonREPL subprocess (only run in sandboxes because arbitrary code execution is a security risk), and create_stuff_documents_chain plus friends form the modern replacement for RetrievalQA. LangGraph extends the agent story into a general framework for stateful, multi-step workflows. Its core primitive is StateGraph, a directed graph where nodes are functions or runnables that read and update a shared typed state, with edges defining the flow. Conditional edges route to different nodes based on a function that inspects the current state. Checkpointers like MemorySaver, SqliteSaver, and PostgresSaver snapshot the state at each step, so you can pause, resume, rewind, and branch conversations — a thread_id passed via configurable scopes each independent conversation. For human-in-the-loop, set interrupt_before or interrupt_after on a node to pause execution for inspection and editing before resuming. To stream results, app.stream yields state deltas per node, while app.astream_events provides token-level streaming with typed events.

All chapters
  1. 1Foundations of LangChain and the Runnable Interface
  2. 2Prompts, Chat Models, and Output Parsers
  3. 3Composing Runnables and Controlling Execution
  4. 4Memory and Conversation History
  5. 5Documents, Embeddings, and Vector Stores
  6. 6RAG Pipelines and Document Processing
  7. 7Tools, Agents, and LangGraph
  8. 8Observability, Evaluation, Deployment, and Caching

Drill it

Reading is not remembering. These come from the LangChain deck:

Q

What is LangChain?

LangChain is an open-source Python framework for building applications powered by large language models (LLMs). It provides modular components for prompts, chai...

Q

What is LCEL (LangChain Expression Language)?

LCEL is a declarative syntax for composing LangChain components using the pipe operator (|). It creates RunnableSequence chains that support streaming, batching...

Q

How do you create a ChatPromptTemplate?

Use ChatPromptTemplate.from_messages() with a list of (role, template) tuples. Variables are wrapped in curly braces.from langchain_core.prompts import ChatProm...

Q

How do you invoke a ChatModel in LangChain?

Instantiate the model class and call .invoke() with a list of messages or a prompt value. The model returns an AIMessage.from langchain_openai import ChatOpenAI...