Use LangChain components without hiding your product logic.
LangChain supplies a ready agent harness around models, tools, and prompts.
Learners know what create_agent owns and what the app still owns.
Why this matters: This prevents treating LangChain as a substitute for product policy.
Problem anchor: a support triage app needs a model, KB search, structured triage output, and a ticket-draft tool. LangChain can connect these pieces quickly through model interfaces, tools, prompts, and middleware.
The app still owns permissions, data freshness, approvals, and evals. LangChain can call tools; it does not decide whether a refund draft should be approved.
The agent uses a KB retriever tool and a ticket-draft tool. The system prompt says to cite retrieved notes and return structured triage fields. Middleware blocks external send until approval.
This is a good LangChain fit because the hard work is integration and middleware, not a custom graph topology.
The tool contract is the app boundary.
Learners design reliable LangChain tool contracts.
Why this matters: Vague tools and free-form outputs make agent apps hard to test.
Tools can be Python callables, LangChain tools, or dictionaries, but the runtime pattern is the same: the model requests a tool, the app validates and executes, and the result returns to context.
Structured output is useful when the final result feeds UI, workflow, or tests. Do not rely on prose when downstream code needs fields such as priority, category, citation IDs, or needs_human_review.
| Option | Contract | Use when | Risk | When to choose | Cost | Complexity |
|---|---|---|---|---|---|---|
| Function tool | Expose narrow callable with schema/docstring. | Model needs application action or lookup. | Broad tool can create excessive agency. | Use for bounded operations. | Low | Medium |
| Structured output | Return validated fields. | UI/workflow/tests need data. | Schema support differs by provider. | Use for product outputs. | Low | Medium |
| Free-form prose | Natural-language answer only. | Human-only response. | Hard to validate and route. | Use for low-risk chat. | Low | Low |
Middleware is powerful because it mutates the agent loop.
Learners understand LangChain middleware as product logic.
Why this matters: Middleware can become hidden application behavior if unobserved.
LangChain middleware can summarize context, retry model/tool calls, filter tools, require human review, redact PII, apply guardrails, and emit traces. These are production behaviors and should be versioned and tested.
Middleware interactions can surprise teams: a summarizer might remove a constraint; a retry wrapper might repeat a non-idempotent tool; a tool filter might hide the only valid operation.
A support agent may draft a ticket update automatically, but middleware interrupts before posting to the customer. The approval packet includes recipient, body, sources, and risk.
If the reviewer edits the response, the trace records the edit and the final posted text.
The first run should be traceable before it is polished.
Learners connect create_agent syntax to product checks.
Why this matters: Concrete code reveals where tool execution and output validation happen.
A LangChain example should show the model, tools, instructions, and invocation shape. For teaching, a harmless KB lookup tool is enough; production tools add policy and approvals.
Spaced recall: from function calling, model-selected tool calls still execute in application code. The framework loop does not remove validation.
from langchain.agents import create_agent def search_kb(query: str) -> str: """Search approved lesson notes. Use for KB-specific questions.""" return "LangGraph is useful for explicit state, checkpoints, and interrupts. Source: langgraph.md" agent = create_agent( model="provider:model-name", tools=[search_kb], system_prompt="Answer as a careful tutor. Cite KB sources when using search_kb.", ) result = agent.invoke({"messages": [{"role": "user", "content": "When should I use LangGraph?"}]}) print(result)
The KB search tool should be considered because the question asks for framework guidance grounded in lesson notes.
LangChain apps need the same eval discipline as any agent system.
Learners finish with production checks for LangChain apps.
Why this matters: A demo run does not prove long conversation, retries, or approvals behave correctly.
LangChain smooths over providers and tools, but provider behavior differs around streaming, structured output, tool calls, and context windows. Pin versions and test the exact model/tool path you ship.
Traces should show messages, retrieved context, tool calls, middleware decisions, model outputs, costs, and errors. Regression tests should include tool-use, no-tool, approval, and failure cases.
Read the trace with the answer.
Retrieval prompt: rebuild LangChain agents by naming create_agent, model, tools, system prompt, structured output, middleware, runtime config, tracing, and tests.
Design a LangChain support agent with one retriever, one safe ticket tool, structured output, middleware for approval, and three trace assertions. Next rung: LangGraph for explicit branching.
A create_agent loop keeps calling tools and re-prompting the model until it decides to stop. Which role does YOUR application code play in this loop?
The framework owns the loop; your application owns authority — the tool contracts and descriptions that shape what the model can choose from.
In your own words: why should a tool description be narrow rather than broad, and what risk does a vague description create?
Tight tool contracts prevent mis-selection and force you to treat every tool result as untrusted context that must be validated before use.
You add a middleware layer that rewrites the system prompt based on the user's subscription tier before the agent runs. Which production concern does this middleware address?
Middleware that modifies the prompt (or the available tool list) based on user identity is enforcing authorization — a classic production concern that lives outside the model loop itself.
You write a test for your agent and want to assert that the KB (knowledge-base) tool is called when the user asks a factual product question, but NOT called for a simple greeting. What is the most reliable way to make this assertion?
Trace-level assertions on tool-call events are the direct, reliable signal; surface-level output checks can pass even when the wrong tool (or no tool) was used.
After tracing several agent runs you notice the model occasionally skips a tool you expected it to use. Before blaming the model, what should you check first according to the lesson's tracing guidance?
Pinning provider and package versions is the first line of defense — silent upgrades to LangChain's default prompts or the provider's model can change tool-selection behavior without any code change on your part.