What a package brings
The desk runs on five pieces you wrote: a model, an embedder, a store, a saver and its middleware. Each has a counterpart you install instead.
A provider is a company that hosts models or runs a service. LangChain publishes a package per provider, named langchain- and the provider's name: langchain-openai, langchain-anthropic, langchain-chroma. There are over a thousand of them, and they are all the same shape.
The shape is this: each package holds classes that subclass the base classes you have already met. Two of the four below are packages you have never imported, and the check says the same thing about all four.
from langchain_chroma import Chroma
from langchain_core.embeddings import Embeddings
from langchain_core.language_models import BaseChatModel
from langchain_core.vectorstores import VectorStore
from langgraph.checkpoint.base import BaseCheckpointSaver
from langgraph.checkpoint.sqlite import SqliteSaver
from desk_model import DeskModel
from word_embeddings import WordEmbeddings
for cls, base in [(DeskModel, BaseChatModel), (WordEmbeddings, Embeddings),
(Chroma, VectorStore), (SqliteSaver, BaseCheckpointSaver)]:
print(f"{cls.__name__:16} is a {base.__name__}: {issubclass(cls, base)}")DeskModel and Chroma are both chat model and vector store to the same code that uses them. That is why swapping one for the other is a line: create_agent asks for the base class, not for your class.
The same function, either store
Code written against a base class does not care which one it is handed. This function is given the store you have used all along, and then one from a package you have never imported.
from langchain_chroma import Chroma
from langchain_core.vectorstores import InMemoryVectorStore
from policies import chunks
from word_embeddings import WordEmbeddings
def refund_policy(store):
store.add_documents(chunks)
found = store.similarity_search("how long does a refund take", k=1)
return f"{type(store).__name__:22} {found[0].metadata['source']}"
print(refund_policy(InMemoryVectorStore(WordEmbeddings())))
print(refund_policy(Chroma(collection_name="either-store", embedding_function=WordEmbeddings())))Same question, same document, two different stores, and refund_policy was written once. Everything in the three lessons after this is that, applied to the desk.
Which piece has which base
| What you wrote | Its base class | A real one | Package |
|---|---|---|---|
ShopModel, DeskModel | BaseChatModel | ChatOpenAI, ChatGroq | langchain-openai, langchain-groq |
WordEmbeddings | Embeddings | OpenAIEmbeddings | langchain-openai |
InMemoryVectorStore | VectorStore | Chroma, QdrantVectorStore | langchain-chroma, langchain-qdrant |
InMemorySaver | BaseCheckpointSaver | SqliteSaver, PostgresSaver | langgraph-checkpoint-sqlite, langgraph-checkpoint-postgres |
no_passwords, the desk's four | AgentMiddleware | ModelRouterMiddleware, AutoModeMiddleware | langchain-typesafe |
The last row is the one to notice. Middleware is an integration point too: langchain-typesafe calls a model named Jev that answers yes-or-no and which-one questions instead of writing sentences, so it can pick which model handles a request, or judge whether a tool call is safe to run, in the same slot your guardrail sits in. Those two are marked experimental, and the package is young.
A hosted service reads its credentials from the environment, the way lesson 1 set OPENROUTER_API_KEY in .env. The four lessons after this one take the rows in order: the model, the store, the middleware, and last the saver.
- Run the same
issubclasscheck againstInMemoryVectorStoreandInMemorySaver. - Print
Chroma.__mro__and findVectorStorein the list. - Install
langchain-qdrantand check its store againstVectorStoretoo.
Slow is fine. Stopping is the only problem.