Tools & Agents

Deep dive into tools, the create_agent loop, and streaming/async invocation.


Defining tools

@tool

from langchain.tools import tool

@tool
def multiply(a: int, b: int) -> int:
    """Multiply two integers."""
    return a * b

Docstrings and type hints become JSON Schema for the model.

Plain callables

Any annotated Python function with a docstring can be passed in tools=[...].

Runtime context

Tools can read agent state (e.g. user_id) via runtime APIs; middleware often writes state before tool runs.


create_agent

from langchain.agents import create_agent

agent = create_agent(
    model="openai:gpt-4.1-mini",
    tools=[multiply, search],
    system_prompt="Use tools for math and search.",
    name="assistant",
)
ParamPurpose
modelString or model instance
toolscallables / @tool / Tool objects
system_promptstr or SystemMessage
response_formatPydantic schema for final output
middlewarehook list
checkpointerpersistence
namesubgraph node name

invoke

result = agent.invoke({
    "messages": [{"role": "user", "content": "What is 12 * 7?"}]
})

State includes full messages for audit/debug.


stream

for mode, data in agent.stream(
    {"messages": [{"role": "user", "content": "Research LangGraph."}]},
    stream_mode=["messages", "updates"],
):
    print(mode, data)

async

result = await agent.ainvoke({"messages": [...]})

Use in FastAPI / asyncio services.


Multiple tools & parallelism

LangGraph may run multiple tool_calls in parallel when safe. Design read-only tools for parallelism; make writes idempotent.


Errors

Exceptions often become ToolMessage errors for the model to recover. Centralize logging in middleware.


ToolNode in LangGraph

Custom graphs use ToolNode (LangGraph Workflows); create_agent wraps this internally.


Anti-patterns

Vague docstrings, one mega-tool, non-idempotent writes on retry.


Next steps