Course navigation
AgentsLesson 6 of 9

Creating Custom Tools

Tool Calling left lookup_html_tag at default names. Here you pick the tool name, add a list helper, and wrap lookup in StructuredTool.

Rename @tool

First arg to @tool is the name OpenAI gets. Your function can still be list_html_tags while the tool registers as html_tag_list.

Docstring is still the description. One line, say what comes back.

from langchain.tools import tool

@tool("html_tag_list")
def list_html_tags() -> str:
    """List HTML tag names available in this helper."""
    return "<a>, <title>, <h1>"

print(list_html_tags.name)  # html_tag_list, not list_html_tags

In your file

def list_html_tags():
    ...

@tool("html_tag_list")

Sent to OpenAI

name: html_tag_list
description: List HTML
  tag names…
Covered the default case in Tool Calling. Here you override the name string.

StructuredTool

For a function you already wrote without a decorator, use StructuredTool.from_function. Pass name and description in that call.

from langchain_core.tools import StructuredTool

def lookup_raw(tag_name: str) -> str:
    # your lookup logic
    return f"<{tag_name}>: ..."

html_tag_lookup = StructuredTool.from_function(
    func=lookup_raw,
    name="html_tag_lookup",
    description="Look up one HTML tag by name.",
)

Pass both to create_agent

tools=[list_html_tags, html_tag_lookup]. Same TAGS dict underneath. List question should hit html_tag_list; detail question should hit html_tag_lookup.

Two tools in the demo:

"Which tags can you look up?"
html_tag_list()
"What does <a> do?"
html_tag_lookup("a")
OpenAI matches on tool name + docstring, not your def name.
from langchain.agents import create_agent

tools = [list_html_tags, html_tag_lookup]
agent = create_agent(model="openai:gpt-4o-mini", tools=tools)

result = agent.invoke({
    "messages": [{"role": "user", "content": "Which tags can you look up?"}],
})
print(result["messages"][-1].content)

Run the demo

Venv from Project Setup. Download, then:

creating_custom_tools_demo.py

list question, then <a> question

OPENAI_API_KEY in .env, same as Tool Calling.
creating_custom_tools_demo.py
"""creating_custom_tools_demo.py"""
from langchain_core.tools import StructuredTool
# html_tag_list via @tool, lookup via StructuredTool
tools = [list_html_tags, html_tag_lookup]
python creating_custom_tools_demo.py
PowerShell — (.venv) active
(.venv) PS C:\projects\langchain-course> python creating_custom_tools_demo.py
Tools on agent:
html_tag_list: List HTML tag names…
html_tag_lookup: Look up one HTML tag…
Question: Which HTML tags can you look up? …
Answer: I can look up <a>, <title>, and <h1>.
Question: What does the <a> tag do? …
Answer: The <a> tag creates a hyperlink; use href for the URL.
Tool names print first so you can line them up with tool_calls in Agent Execution Flow.

More args later: Pydantic args_schema in Tools docs.