Install any skill in seconds. Free to start, no credit card required.
Get Started Free →jeremylongshore/langchain-reference-architecture
A reference layered architecture for production LangChain 1.0 / LangGraph 1.0 services — LLM factory with version-safe defaults, chain/graph registry, retriever and tool DI, Pydantic-validated config, per-request tenant scoping, middleware ordering, checkpointer selection per environment.
Passed 19 of 22 test cases with the skill, and 5 of 22 without it.
and 30 more in the full report
15 fixed4 passed either way2 still failing1 broke
Tokens, turns and time describe resource use, not a dollar price.
One of 15 test cases the skill fixed. Same model, same prompt, with and without the skill.
Our FastAPI application has LangChain chains hardcoded inside route handlers, shared global retrievers leaking multi-tenant data, and scattered environment variable calls. We want to refactor this into a clean multi-layer Python project structure. Please provide a step-by-step refactoring plan, a clean directory layout dividing HTTP routes, business services, third-party integrations, settings, and domain models, along with code implementations for the centralized model factory, per-tenant retriever lookup, environment config, and CI linting configuration to strictly enforce package boundaries.
| Checked | Without skill | With skill |
|---|---|---|
| The project layout uses top-level layer directories app, services, adapters, config, and domain | Missed | Passed |
| The LLM factory specifies a default timeout of 30 | Missed | Passed |
| The LLM factory specifies default max_retries of 2 | Missed | Passed |
| The static import linter configuration is placed inside pyproject.toml under tool.importlinter | Missed | Passed |
The instructions your model reads when the skill loads.
Eight months into a LangChain service, a code review surfaces the mess.
Twelve chain definitions live inlined inside FastAPI route handlers. Three
retrievers are constructed at module-global scope, one bound to
tenant_id="acme" because that was the first tenant in the pilot —
that retriever now returns Acme's documents to every other tenant, a P33
leak that has been live in production for six weeks.
max_retries=6 is hardcoded at four separate call sites. A
RunnableWithMessageHistory backed by the default
InMemoryChatMessageHistory loses every conversation on pod restart
(P22) — which is most days, because Cloud Run scales to zero.
Config is read from os.environ in three modules with three different
fallback strategies. There is no place to put a new provider without
touching seven files, and nobody remembers why the retriever is built
at import time.
The fix is not "rename a variable." The fix is an architecture that made every one of those mistakes hard to write. This skill is the target layered architecture:
app/ — FastAPI routes. Thin. Parses HTTP, calls into services,
serializes response. No chain logic, no vendor clients, no env vars.services/ — chain and graph definitions. Take dependencies through
constructor args, not module-level imports.adapters/ — vendor clients, LLM factory, retriever factory, tool
factory. This is where langchain-anthropic is imported. Nowhere else.config/ — one Pydantic Settings class. SecretStr for keys,
Literal["dev","staging","prod"] for env names, .env file loader.domain/ — Pydantic models, typed LangGraph state, enums. No I/O.Five layers, five imports deep at most. Dependency direction is
strictly downward. app imports services; services imports
adapters; adapters imports config and domain. Never the reverse.
Import-linter enforces this in CI. Pain-catalog anchors: P22 (in-memory
history loses messages — architectural fix is persistent history
injected via DI) and P33 (per-tenant vector stores leak if retriever
bound at import — architectural fix is per-request factory). Adjacent:
test cases passed, vs 5 / 22 without
More skills from the same source and nearby in the registry, with their headline benchmark lift.