Repository navigation
LangChain Applied · Giving an agent hands without giving it the keys #13
akash-coded
started this conversation in
Exercises
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Exercise 2 - Give TravelMind Hands: the Agent
Language: Python 3.11+
Level: Intermediate
Topics:
@tool,create_agent, the reason-act-observe loop, memory withInMemorySaverandthread_id, agent debugging, Strands to LangChain conversion, diagram to agentIn Exercise 1 you controlled every step. Now the model controls the steps. You hand it tools and a goal, and it decides when to call them. Same TravelMind booking,
JX48Q2, Rao, Gold tier, BLR to DEL cancelled.Run this once so every snippet works:
Part A - Trace the loop (~4 min)
An agent alternates between reasoning and calling tools until it can answer. Read this tool and picture the loop.
A1. Put the loop steps in order for this single question:
A2. How many times does the agent call
get_bookingto answer this one question? Give the number and one line of justification.A3. Fill the message trace. What role does each message carry, start to finish?
get_bookingA4. One arrow in this loop diagram is wrong. Name it and state the correct target.
graph TD U["user"] --> M["model: reason"] M --> D{"tool needed?"} D -->|"yes"| T["call tool"] T --> D D -->|"no"| A["final answer"]Part B - Debug and fix (~5 min)
Each snippet has one bug. Name the broken line, then give a one-line fix.
B1.
B2.
B3.
For B3, name the two changes that make the second turn remember the first.
Part C - Diagram to agent (~5 min)
Turn this loop into a two-tool agent by filling the
TODOlines.graph TD U["user request"] --> M["model: reason"] M --> D{"tool needed?"} D -->|"yes"| T["call get_booking or rebook"] T --> O["observation"] O --> M D -->|"no"| A["final answer"]Boilerplate:
Watch what the model does with a request that needs two facts: it may call
get_bookingfirst to confirm the booking, thenrebook. You did not script that order. The model chose it.Part D - Convert Strands to LangChain (~5 min)
Your team has this working agent in the AWS Strands SDK. Convert it, line for line, to LangChain.
Strands version:
Use this mapping as scaffolding. Fill the right column into real code.
from strands import Agent, toolfrom langchain.agents import create_agentandfrom langchain_core.tools import tool@toolwith a docstring@toolwith the same docstringBedrockModel(model_id=..., region_name=..., temperature=...)init_chat_model(model_id, model_provider="bedrock_converse", region_name=...)Agent(model=, tools=, system_prompt=)create_agent(model, tools=, system_prompt=)agent("text")agent.invoke({"messages": [{"role": "user", "content": "text"}]})result.messageresult["messages"][-1].text()Task. Write the full LangChain equivalent.
Part E - Add memory (~4 min)
Give the Part C agent a memory so it holds the booking across turns. Fill the
TODOlines.Stretch, if time: add one middleware to guard the risky action. Import from
langchain.agents.middlewareand wraprebookso it pauses for approval before running.Definition of done
Answer key (instructor)
Part A
A1. reason about the goal, call the tool, observe the tool result, return the final answer.
A2. One call. The tier lives in a single booking record, so one
get_booking(pnr)returns everything needed.A3.
get_bookingA4. The arrow
T --> Dis wrong. After a tool runs, the observation returns to the model, so it should beT --> M.Part B
B1. Broken line: the
refunddefinition has no docstring. The model gets no description of the tool, so it cannot use it well. Fix: add a one-line docstring, for example"""Start a refund for a PNR.""".B2. Broken line:
agent.invoke("status of JX48Q2?").create_agentexpects a state dict, not a bare string. Fix:agent.invoke({"messages": [{"role": "user", "content": "status of JX48Q2?"}]}).B3. Two changes: pass
checkpointer=InMemorySaver()intocreate_agent, and passconfig={"configurable": {"thread_id": "..."}}on bothinvokecalls so they share one thread.Part C
Part D
Skeptic. Only the model construction line and the invocation line change. Strands hides the message envelope behind
agent("text"); LangChain exposes it as an explicit{"messages": [...]}state. That boundary is the point: LangChain treats the message list and its state as first-class, which is exactly what lets memory, middleware, and LangGraph plug in later.Part E
Turn 2 recalls
JX48Q2and, after aget_bookingcall, reports the cancelledBLR-DELsegment, because the sharedthread_idreplays turn 1 into the second call.All reactions