Conversational Patterns & Agentic Tools
Multi-turn memory, instruction persistence and safe tools.
Conversational Patterns & Agentic Tools is a free Claude Architect lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Claude Architect learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
The Stateless Truth
Scenario 7 of the exam is Conversational AI Architecture Patterns. The first thing it tests is whether you understand that the Claude API is stateless: the model keeps no memory between requests.
Every turn you send the full message history in the messages array. "Memory" in a conversational app is something you engineer client-side, not a server session the model holds for you.
systemcarries persistent instructionsmessagescarries the entire turn-by-turn history, every request
import anthropic
client = anthropic.Anthropic()
# Memory = the list YOU maintain and resend each turn
history = [
{"role": "user", "content": "My order id is 8842."},
{"role": "assistant", "content": "Got it, order 8842."},
{"role": "user", "content": "When does it ship?"},
]
resp = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
system="You are a concise support agent.",
messages=history, # FULL history, every single turn
)Instruction Persistence Lives in system
In multi-turn chat, instructions that must hold for the entire session belong in the system field, not buried in a user turn 20 messages ago.
Why this matters: models exhibit lost-in-the-middle behavior, attending more to the start and end of the context than the middle. An instruction wedged in turn 7 of a 40-turn chat is the easiest thing for the model to drift away from.
The system prompt is re-supplied verbatim on every request, so it is the most reliable home for persistent rules: tone, role, refusal policy, output constraints.
Reading the Stop Reason
Conversational turns end on a stop_reason. You drive your control flow off this signal, never by scanning the assistant's text for words like "done" or "finished."
end_turn— the model completed its replytool_use— the model wants a tool run before continuingmax_tokens— output was truncatedstop_sequence— a configured stop sequence fired
Parsing text for completion signals is a classic exam anti-pattern and almost always a wrong answer.
resp = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
system=SYSTEM,
messages=history,
tools=TOOLS,
)
if resp.stop_reason == "tool_use":
run_tools_and_append(resp, history) # then loop again
elif resp.stop_reason == "end_turn":
deliver(resp) # turn is complete
elif resp.stop_reason == "max_tokens":
handle_truncation(resp) # continue / raise budgetThe Agentic Loop
Agentic tools turn a chat into an actor. The loop is fixed and simple:
- send the request
- inspect
stop_reason - if
tool_use: run the tool(s), append the results to history, send again - repeat until
end_turn
Decisions are model-driven. An iteration cap is a safety net to prevent runaway loops — never your primary stop mechanism. You terminate on the stop reason; the cap only catches pathological cases.
MAX_ITERS = 10 # SAFETY NET only, not the real stop condition
for _ in range(MAX_ITERS):
resp = client.messages.create(
model="claude-sonnet-4-5", max_tokens=1024,
system=SYSTEM, messages=history, tools=TOOLS,
)
history.append({"role": "assistant", "content": resp.content})
if resp.stop_reason != "tool_use":
break # end_turn -> we are genuinely done
results = execute_tool_calls(resp.content)
history.append({"role": "user", "content": results})Tool Results Re-enter as Context
When you run a tool, its result is appended back to messages as a tool_result block carrying the matching tool_use_id. The model reads that result on the next request and continues reasoning.
Reliability tip from the exam: trim verbose tool output to the relevant fields before appending. Dumping a 5,000-token raw API payload into history wastes the window, worsens lost-in-the-middle, and dilutes attention. Keep the fields the model actually needs to act.
Descriptions Select Tools
For safe agentic tools, the description is the primary selection mechanism — not the tool name. The model routes by reading descriptions, so write them like a contract:
- purpose — what it does and when to use it
- return values — what comes back
- input formats with examples
- edge cases and applicability boundaries
Overlapping or ambiguous descriptions cause misrouting. Aim for 4-5 tools per agent; past ~18 tools, selection reliability degrades sharply. Scope tools tightly to the role.
lookup_order = {
"name": "lookup_order",
"description": (
"Fetch the status of ONE order by its numeric id. "
"Returns {order_id, status, ships_on}. "
"Input: order_id as an integer, e.g. 8842. "
"Use ONLY after the customer identity is verified. "
"Returns an empty result (not an error) if the id does not exist."
),
"input_schema": {
"type": "object",
"properties": {"order_id": {"type": "integer"}},
"required": ["order_id"],
},
}Steering with tool_choice
tool_choice controls whether and how the model uses tools on a given turn:
"auto"— the model decides between answering in text or calling a tool (the conversational default)"any"— the model must call some tool; this guarantees structured output{"type":"tool","name":"X"}— force a specific tool
In open conversation you usually want "auto" so Claude can chat or act as appropriate. Reach for "any" or a forced tool when you need a structured, schema-validated result rather than free text.
# Conversational default: let Claude talk OR act
resp = client.messages.create(
model="claude-sonnet-4-5", max_tokens=1024,
system=SYSTEM, messages=history, tools=TOOLS,
tool_choice={"type": "auto"},
)
# Force a structured extraction instead of prose
resp = client.messages.create(
model="claude-sonnet-4-5", max_tokens=1024,
system=SYSTEM, messages=history, tools=[extract_tool],
tool_choice={"type": "any"},
)Handling Ambiguous Input
Real conversations are messy. When the user's request is ambiguous, the safe pattern is to ask for more identifiers — never guess.
Classic exam case: a lookup returns multiple customer matches. The correct behavior is to request a disambiguating identifier (email, order id), not to silently pick the first row. Guessing risks acting on the wrong account.
For emotional or frustrated users the pattern is: acknowledge the emotion, propose a concrete solution, and escalate only if the request is reiterated.
Safe Tools: Preconditions and Hooks
"Safe tools" means a sensitive action cannot fire without its guarantees met. Two layers do this:
- Programmatic preconditions — e.g. block
process_refunduntilget_customerreturns a verified id. This is a deterministic guarantee prompt guidance cannot give. - Hooks —
PostToolUseintercepts results before the model sees them; outgoing-call hooks block policy-violating actions (e.g. refund > $500).
Hooks are 100% deterministic; prompts are ~90% probabilistic. Enforce critical rules with hooks/preconditions whenever failure has financial, legal, or safety consequences. Enforcing such rules with prompts alone is an anti-pattern.
def process_refund(amount, customer):
# Deterministic precondition — not a polite prompt request
if not customer.get("verified_id"):
raise PermissionError("Identity not verified")
if amount > 500:
# Out-of-prompt enforcement; hook blocks this path too
return escalate_to_human(reason="refund_over_limit",
amount=amount)
return issue_refund(customer["id"], amount)Structured Errors Over Generic Failures
An agent recovers only as well as its errors let it. A generic "Operation failed" blocks recovery; a structured error enables intelligent routing.
Distinguish an access failure (maybe retry) from a valid empty result (no matches — do not retry). Structured fields to surface:
errorCategory— transient / validation / business / permissionisRetryableattempted_queryand anypartial_results
Recover transient faults locally in the subagent; escalate non-recoverable failures with partial results. Never silently suppress an error, and never abort the whole conversation over one failed tool call.
{
"isError": true,
"errorCategory": "transient",
"isRetryable": true,
"message": "Order service timed out",
"attempted_query": {"order_id": 8842},
"partial_results": []
}Keeping Long Conversations Reliable
As a chat grows, you must manage the context window without losing facts. Progressive summarization compresses old turns — but it makes numbers, percentages, and dates vague.
The fix: pull transactional facts (order ids, amounts, dates, verified identity) into a separate "case facts" block kept verbatim, outside the summary. Summarize the chatter; never summarize the facts the agent must act on.
Combined with trimming verbose tool output and placing persistent rules in system, this keeps multi-turn agents accurate across long sessions.
Quick Check: Stopping the Agentic Loop
A scenario-based decision from Scenario 8 (Agentic AI Tools).
Recap: Conversational Patterns & Agentic Tools
Lock these in for the exam:
- Stateless model — you resend full
messageshistory every turn; "memory" is engineered client-side. - Persistent instructions live in
system; mid-history rules get lost in the middle. - Stop reasons drive control flow — loop on
tool_use, finish onend_turn; never parse text for "done". - Caps are safety nets, not the primary stop.
- Tool descriptions (not names) select tools; 4-5 per agent, scoped to role.
tool_choice:autoto chat-or-act,anyto guarantee structured output, forced for a specific tool.- Ambiguity → ask for more identifiers, never guess.
- Safe tools = preconditions + hooks (deterministic) for financial/legal/safety rules — not prompts alone.
- Structured errors enable recovery; keep case facts verbatim outside summaries.
Frequently asked questions
Is the “Conversational Patterns & Agentic Tools” lesson free?
Yes — the full text of “Conversational Patterns & Agentic Tools” is free to read here on the web, and the Claude Architect course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Claude Architect course, upgrade to CoddyKit PRO.
What will I learn in “Conversational Patterns & Agentic Tools”?
Multi-turn memory, instruction persistence and safe tools. You practise Claude Architect with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Claude Architect?
No prior experience is required. Claude Architect on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Conversational Patterns & Agentic Tools” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Claude Architect lesson?
Yes. Every Claude Architect lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Support Agent & Multi-Agent Research
- Code Gen & Developer Productivity
- CI/CD & Structured Extraction
- Conversational Patterns & Agentic Tools