How to define a tool in LangChain

An agent can choose application actions only when each action has a clear name, typed inputs, and a result it can pass back to the model. LangChain represents that contract as a tool, keeping the callable behavior in Python while exposing only the fields the model needs.

The @tool decorator converts a function into a BaseTool object. A Pydantic model supplies field descriptions, defaults, and allowed values for the model-facing schema, while the decorator description explains when the action applies.

A direct invocation can validate the tool contract without an API key or agent loop. The completed program prints the exposed name and schema details, then calls the tool with a support-ticket payload so the returned value depends on the supplied inputs.

Steps to define a LangChain tool:

  1. Open an activated Python project environment that already contains LangChain.
  2. Start define_langchain_tool.py with the imports and Pydantic input schema.
    define_langchain_tool.py
    from typing import Literal
     
    from langchain.tools import tool
    from pydantic import BaseModel, Field
     
     
    class TicketSummaryInput(BaseModel):
        """Input fields for a support-ticket summary."""
     
        title: str = Field(description="Short title from the support queue")
        priority: Literal["low", "normal", "high"] = Field(
            default="normal",
            description="Escalation priority for the routing summary",
        )
        requester: str = Field(description="Name or team that opened the ticket")
  3. Add the decorated summarize_ticket() function below the input schema.
    @tool(
        "summarize_ticket",
        args_schema=TicketSummaryInput,
        description="Create a routing summary for a support ticket.",
    )
    def summarize_ticket(
        title: str,
        requester: str,
        priority: str = "normal",
    ) -> str:
        return f"[{priority}] {title} - requester: {requester}"

    snake_case tool names have broad provider compatibility. Side effects such as ticket updates or database writes still need narrow input schemas and application-level authorization checks.

  4. Append schema inspection and direct invocation below the tool function.
    schema = summarize_ticket.tool_call_schema.model_json_schema()
    print(f"Tool name: {summarize_ticket.name}")
    print(f"Required inputs: {', '.join(schema['required'])}")
    print(
        "Priority choices: "
        + ", ".join(schema["properties"]["priority"]["enum"])
    )
     
    result = summarize_ticket.invoke(
        {
            "title": "Database backup failed",
            "priority": "high",
            "requester": "Platform Operations",
        }
    )
    print(f"Tool result: {result}")
  5. Review the completed define_langchain_tool.py file before execution.
    define_langchain_tool.py
    from typing import Literal
     
    from langchain.tools import tool
    from pydantic import BaseModel, Field
     
     
    class TicketSummaryInput(BaseModel):
        """Input fields for a support-ticket summary."""
     
        title: str = Field(description="Short title from the support queue")
        priority: Literal["low", "normal", "high"] = Field(
            default="normal",
            description="Escalation priority for the routing summary",
        )
        requester: str = Field(description="Name or team that opened the ticket")
     
     
    @tool(
        "summarize_ticket",
        args_schema=TicketSummaryInput,
        description="Create a routing summary for a support ticket.",
    )
    def summarize_ticket(
        title: str,
        requester: str,
        priority: str = "normal",
    ) -> str:
        return f"[{priority}] {title} - requester: {requester}"
     
     
    schema = summarize_ticket.tool_call_schema.model_json_schema()
    print(f"Tool name: {summarize_ticket.name}")
    print(f"Required inputs: {', '.join(schema['required'])}")
    print(
        "Priority choices: "
        + ", ".join(schema["properties"]["priority"]["enum"])
    )
     
    result = summarize_ticket.invoke(
        {
            "title": "Database backup failed",
            "priority": "high",
            "requester": "Platform Operations",
        }
    )
    print(f"Tool result: {result}")
  6. Run define_langchain_tool.py to confirm the exposed schema and callable result.
    $ python3 define_langchain_tool.py
    Tool name: summarize_ticket
    Required inputs: title, requester
    Priority choices: low, normal, high
    Tool result: [high] Database backup failed - requester: Platform Operations