๐Ÿ”—
๐Ÿงฐ
๐Ÿ
@tool
create_agent
๐Ÿ”
๐Ÿ“ฆ
thread_id
ToolMessage
swipe โ†’
Daily Drop ยท Carousel

Build agents with LangChain

Be10x ยท Daily Drop

One question.
Three tool calls.
No script.

An agent that decides its own steps โ€” in about 20 lines of LangChain.

Swipe โ†’
01

A chain follows
your script

from langchain.chat_models import init_chat_model model = init_chat_model( "anthropic:claude-sonnet-5") chain = prompt | model | parser chain.invoke({"question": q}) # three hops. always three.

LCEL is not deprecated. For a fixed pipeline it is still exactly the right tool.

02

An agent
decides

scripted โ€” a chainprompt | model | parser
decided โ€” an agentlookup_order โ†’ search_policy โ†’ days_since

"Where is my order 4471, and can I still return it?" took three tool calls โ€” because the model chose three.

03

Three arguments.
That's the agent.

from langchain.agents import create_agent agent = create_agent( model="anthropic:claude-sonnet-5", tools=[lookup_order, search_policy, days_since], system_prompt="You are a support agent.", )

Back comes a compiled graph you call .invoke() on. And it is system_prompt=, never prompt=.

04

A tool is
a function

from langchain.tools import tool @tool def lookup_order(order_id: str) -> str: """Look up an order by its ID.""" return "Order 4471: delivered 12 Sept, โ‚น2,499"

The type hint builds the input schema. No hint, no schema, no call.

What it returns arrives as a ToolMessage.
05

The docstring is
the description

vague โ€” never called"""Order tool."""
specific โ€” called"""Look up an order's status, delivery date, item and amount by its ID."""

That one line is all the model reads before deciding your tool is worth a call.

A tool nobody picks never raises an error.
06
THE LOOP โ€” ONE TRIP AT A TIME ToolMessage call the model run the tools tool_calls no tool calls the final answer our run: 3 trips

One trip round
the loop

Ask, run what it asked for, feed the results back, ask again. It stops when the model wants no more tools.

07

Messages are
the state

1SystemMessageyour system_prompt, once at the top
2HumanMessagethe question, exactly as typed
3AIMessage.text โ€” or .tool_calls when it wants one
4ToolMessagewhat came back, tagged with tool_call_id

In and out: {"messages": [...]}

08

Memory is a
thread_id

from langgraph.checkpoint.memory import ( InMemorySaver) agent = create_agent(model=model, tools=tools, checkpointer=InMemorySaver()) config = {"configurable": {"thread_id": "customer-4471"}} agent.invoke({"messages": [...]}, config)

Same thread, and "can I still return it?" knows what it is.

New thread_id, new stranger. SqliteSaver in production.
09

Middleware,
not a rewrite

from langchain.agents.middleware import ( HumanInTheLoopMiddleware) gate = HumanInTheLoopMiddleware( interrupt_on={"issue_refund": { "allowed_decisions": ["approve", "reject"]}}) agent = create_agent(model=model, tools=tools, middleware=[gate])

The refund now waits for a human. Redaction and summaries plug in the same way.

10

Five things tutorials
get wrong

โœ•initialize_agent โ†’ create_agent
โœ•AgentExecutor โ†’ create_agent
โœ•create_react_agent โ†’ create_agent
โœ•ConversationBufferMemory โ†’ checkpointer
โœ•LLMChain โ†’ prompt | model | parser

All five still top the search results. Check the import path.

Write one tool.
Mean the docstring.

One function, one honest description, one call to create_agent โ€” and it picks the steps itself. Next drop: streaming the loop live.

Follow for daily drops โ€
Be10x ยท Eshmith Saideep
swipe ยท arrow keys ยท tap the dots
Be10x ยท Daily Drop ยท Eshmith Saideep