Building AI Agents with LangChain and LangGraph: Part 2 › Reply Agent Implementation

Michael BrenndoerferAugust 2, 20252 min read
Building AI Agents with LangChain and LangGraph: Part 2 › Reply Agent ImplementationOne section · Sections in this article8 / 9 ↓
Reading tools Definitions & inline links

Toggle tooltip visibility. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Let's combine everything we've learned into a simple reply agent that demonstrates all the key concepts:

  • Workflow orchestration with conditional logic
  • Tool integration with proper error handling
  • Clean architecture for maintainability
  • Extensible design for adding more tools and capabilities

This serves as a template for building real-world agentic systems.

In[19]:
Code
# reply_agent.py
from typing import Literal
from langchain.chat_models import init_chat_model
from langchain.tools import tool
from langgraph.graph import MessagesState, StateGraph, END, START


@tool
def draft_customer_reply(customer_name: str, request_category: str, reply: str) -> str:
    """Draft a reply to a customer."""
    return f"I am drafting a reply to {customer_name} in the category {request_category}.\n Content: {reply}"


llm = init_chat_model("google_vertexai:gemini-2.0-flash", temperature=0)
model_with_tools = llm.bind_tools([draft_customer_reply], tool_choice="any")


def call_llm(state: MessagesState) -> MessagesState:
    """Run LLM"""

    output = model_with_tools.invoke(state["messages"])
    return {"messages": [output]}


def run_tool(state: MessagesState) -> MessagesState:
    """Performs the tool call"""

    result = []
    for tool_call in state["messages"][-1].tool_calls:
        observation = draft_customer_reply.invoke(tool_call["args"])
        result.append(
            {"role": "tool", "content": observation, "tool_call_id": tool_call["id"]}
        )
    return {"messages": result}


def should_continue(state: MessagesState) -> Literal["run_tool", "__end__"]:
    """Route to tool handler, or end if Done tool called"""

    # Get the last message
    messages = state["messages"]
    last_message = messages[-1]

    # If the last message is a tool call, check if it's a Done tool call
    if last_message.tool_calls:
        return "run_tool"
    # Otherwise, we stop (reply to the user)
    return END


# Create the workflow
workflow = StateGraph(MessagesState)

# Nodes
workflow.add_node("call_llm", call_llm)
workflow.add_node("run_tool", run_tool)

# Edges
workflow.add_edge(START, "call_llm")
workflow.add_conditional_edges(
    "call_llm", should_continue, {"run_tool": "run_tool", END: END}
)
workflow.add_edge("run_tool", END)

# Compile the workflow
app = workflow.compile()

Running Your Production Agent

To deploy this agent, save the code above as reply_agent.py and run it from your terminal:

python reply_agent.py

The agent will process your request through the complete workflow, demonstrating how all the concepts work together in a real application.

Example Usage and Output

Here's what happens when you run the agent:

Input: "Inform Jeremy about his delivery status being in-progres"

Processing:

  1. LLM analyzes the request
  2. Determines appropriate tool and parameters
  3. Executes the reply tool
  4. Returns formatted result

Output: Complete reply with correct classification

In[20]:
Code
# Demonstration of the complete workflow
result = app.invoke(
    {
        "messages": [
            {
                "role": "user",
                "content": "Inform Jeremy about his delivery status being in-progres.",
            }
        ]
    }
)

print("=== Agent Workflow Result ===")
for message in result["messages"]:
    message.pretty_print()
Out[20]:
Console
=== Agent Workflow Result ===
================================ Human Message =================================

Inform Jeremy about his delivery status being in-progres.
================================== Ai Message ==================================
Tool Calls:
  draft_customer_reply (e1122d59-7c36-41b3-a8fe-d1f235c79a98)
 Call ID: e1122d59-7c36-41b3-a8fe-d1f235c79a98
  Args:
    request_category: Delivery Status
    customer_name: Jeremy
    reply: Your delivery is in progress.
================================= Tool Message =================================

I am drafting a reply to Jeremy in the category Delivery Status.
 Content: Your delivery is in progress.