LangChain is a framework ecosystem for composing model integrations, tools and agent behavior. Its current high-level agent entry point is create_agent; LangGraph provides the lower-level orchestration runtime beneath those agents. LangSmith is a separate tracing/evaluation product. These are related components, not interchangeable names for one mandatory stack. Current LangChain overview.
The interview question is not “how many packages can I name?” It is which behavior does an abstraction provide, and which guarantees must the application still implement?
Choose the right abstraction level
| Need | Reasonable starting point | Cost to consider |
|---|---|---|
| One model request | Provider SDK or a model integration | Additional abstraction may add little value |
| Fixed retrieval/prompt/parse pipeline | Ordinary code or composable runnables | Adapters and error/streaming behavior |
| Model-controlled tool loop | LangChain create_agent |
Middleware and tool policy must be configured |
| Explicit branches, joins and resumable waits | LangGraph | State/reducer/checkpoint design |
| More prebuilt agent capabilities | Evaluate Deep Agents | Broader behavior and dependency surface |
| Trace and evaluate any of the above | LangSmith or another compatible observability system | Instrumentation, data handling and cost |
The full langchain package is not only for prototypes or legacy retrievers. Current create_agent is a supported application entry point. Conversely, choosing LangChain does not require using every related service.
Know the package responsibilities
| Package family | Main role | Selection guidance |
|---|---|---|
langchain-core |
Shared messages, prompts, tools and Runnable interfaces | Useful when these abstractions are sufficient |
langchain |
Current high-level agent construction and middleware | Use the APIs the application actually needs |
| Provider/integration packages | Specific model, store or service connectors | Check capability, maintenance and transitive dependencies |
langgraph |
State-based graph execution and persistence interfaces | Add for the required orchestration behavior |
langchain-community |
Additional integrations | Evaluate the particular integration rather than blanket approval/rejection |
langchain-classic |
Legacy APIs retained for migration/compatibility | Isolate and migrate deliberately where warranted |
The v1 migration guide documents the current namespace and legacy moves. It also explicitly re-exports tools from langchain.tools; claiming that import is universally invalid is incorrect. Package boundaries do not establish a tiny fixed dependency count or an exclusive stability guarantee for only one package. Inspect the installed lockfile and current support policy.
Understand LCEL without treating it as magic
The LangChain Expression Language (LCEL) composes Runnables. A pipe such as a | b creates a sequence: the output of a becomes the input of b. An explicit parallel composition passes the same input to independent branches and collects their outputs.
Illustrative Python mechanics, requiring a compatible langchain-core installation:
from langchain_core.runnables import RunnableLambda, RunnableParallel
normalize = RunnableLambda(lambda text: text.strip())
describe = RunnableParallel(
original=RunnableLambda(lambda text: text),
uppercase=RunnableLambda(lambda text: text.upper()),
)
pipeline = normalize | describe
assert pipeline.invoke(" cache ") == {
"original": "cache",
"uppercase": "CACHE",
}
This example explains data flow, not why trivial string functions need a framework. For an actual RAG application, branches could fetch independent document sources before assembling one prompt.
The Runnable reference documents invocation, batching, streaming and async interfaces. Exposing astream does not prove every component streams incrementally: a buffering parser or function can delay downstream output. Async wrappers do not automatically make CPU-bound work parallel or establish a safe concurrency limit.
Set concurrency and deadlines around the actual dependencies. Two retrieval calls taking 80 ms and 120 ms can ideally complete in roughly 120 ms when independent, versus 200 ms sequentially, before orchestration overhead. They still perform two calls and can double instantaneous downstream demand.
Trace a complete pipeline
Design a documentation assistant with these requirements:
- Answer from documents the authenticated user may read.
- Return source IDs and clearly report insufficient evidence.
- Keep retrieval and generation within the response deadline.
- Preserve document, prompt and model revisions for evaluation.
- Avoid executing instructions embedded in retrieved text.
Read diagram source
flowchart LR
Q[Authenticated question] --> S[Derive permitted search scope]
S --> A[Retrieve source A]
S --> B[Retrieve source B]
A --> J[Merge, deduplicate and validate evidence]
B --> J
J --> P[Assemble bounded prompt]
P --> M[Model call]
M --> V[Validate output and cited source IDs]
V --> R[Answer or report insufficient evidence]
The framework can compose these steps. The application still defines authorization, evidence freshness, deadlines and answer validation. A retriever returning documents is not proof that the user was allowed to access them.
Failure drill: one retriever times out. Decide whether the remaining source is sufficient, whether a bounded retry fits the deadline, or whether to report incomplete evidence. Retrying the entire pipeline may unnecessarily repeat the successful retrieval and model call. Put recovery at the smallest safe boundary and account for SDK retries too.
Structured output: shape is one layer of correctness
For current agents, response_format can use a provider-native strategy or a tool-based strategy. A schema type can select a supported strategy, while current documentation requires a raw JSON Schema dictionary to be wrapped in an explicit strategy. Model/provider capability matters, particularly when combining tools with structured output. Structured-output contract.
| Layer | Example check | What it cannot prove |
|---|---|---|
| Syntax/schema | source_ids is a list of strings |
The IDs exist or support the answer |
| Domain validation | Every ID belongs to the retrieved permitted set | The answer faithfully represents its source |
| Evidence evaluation | Claims are supported by the cited text | All future requests will be correct |
| Authorization | Requested action is permitted for this principal | The action achieves the user's goal |
Schema support is method-, language- and provider-specific. Python Pydantic/TypedDict support does not imply that any JavaScript validator object is accepted by every Python method. Converting a schema can also lose custom validation semantics. Test the exported JSON Schema subset and keep application-side invariants.
For example, a positive amount_cents field can pass validation while naming the wrong customer. Structured output must never be treated as permission to create an invoice. Structured outputs and tool contracts develops this distinction.
Tools, MCP and middleware
Tools expose structured operations to the agent. A tool proposal becomes an application action only after argument validation and current authorization. Inject trusted identity at the execution boundary rather than letting the model choose an arbitrary account.
The LangChain MCP integration uses adapter packages to expose compatible MCP tools. An MCP server can also expose resources or prompts; these are not automatically all BaseTool objects. Verify adapter support for the server's negotiated protocol and transport, credentials, timeouts and lifecycle. An interoperability adapter does not provide the business permission model.
Middleware can implement application concerns such as model routing, context selection and tool-error handling. Keep one clear owner for retry and budget policies so nested wrappers do not multiply requests. Do not let an exception handler convert an uncertain payment into a harmless-looking empty string.
Make observability and portability measurable
Tracing requires configuration and coverage. Instrument custom functions, propagate correlation IDs and validate what data leaves the application. Do not promise that every custom component is automatically traced just because it appears inside a chain.
A common model interface reduces integration work; it does not make providers behaviorally interchangeable. Test message formats, tool semantics, schema support, refusal/error behavior, streaming and token accounting before switching models.
For upgrades:
- Pin a compatible dependency set and retain the lockfile.
- Identify deprecated imports and behavior changes.
- Run a representative task/evidence dataset on the old and new paths.
- Compare output validity, tool actions, latency, full cost and traces.
- Test failures, cancellations and pending persistent runs.
- Roll out within a bounded scope with rollback capability.
Do not migrate purely to remove a familiar package name. Migrate when support, security, capability or maintenance requirements justify the change.
Interview practice
Q1: When would you avoid LangChain?
When a small provider-SDK call or explicit pipeline is simpler and already satisfies the requirements. A framework should reduce relevant implementation work without obscuring critical contracts.
Q2: Does the pipe operator make every step parallel?
No. A sequence preserves dependencies. Independent branches need a parallel composition and suitable concurrency limits. Streaming also depends on the components' behavior.
Q3: What makes a lean LangChain service?
Choosing only needed abstractions and integrations, inspecting the actual dependency tree, and keeping business rules visible. It does not mean banning langchain or all community integrations without examining their role.
Q4: Why can valid structured output still be dangerous?
The shape may be correct while the referenced entity, amount, evidence or permission is wrong. Validate those independently before acting.
Q5: Does adopting MCP make the agent vendor-independent?
It can reduce tool-integration coupling, but model messages, authorization, server behavior and adapter compatibility still need handling. Protocol interoperability is one boundary, not complete application portability.
Q6: How would you justify the framework to a reviewer?
Show the specific composition, agent or persistence work it simplifies, then demonstrate equivalent task quality and acceptable cost/latency on representative failures. Keep an exit path through stable application contracts around provider and tool calls.
Final notes
Recall card: Choose abstraction → trace data flow → validate output → enforce tool authority → measure behavior → upgrade deliberately.
Next: LangGraph orchestration.