CodeVetter · Repo Unpack · Contributor handoff
langchain-ai/langchain
Read AGENTS.md/CLAUDE.md first — they encode the real conventions (uv-only, Conventional Commits with mandatory scope, Google docstrings, mypy strict + ruff ALL, no breaking signature changes). Work in libs/langchain_v1 for new features; libs/langchain (langchain-classic) is frozen. Re-export shims point at canonical homes: edit langchain_core or langgraph.prebuilt, not the shim. Tests must be hermetic unit tests under tests/unit_tests unless they need the docker services. Watch for: the manual structured-output model regexes, validation gaps around wrap_tool_call, and checkpointer tests that need containers.
- AGENTS.md and CLAUDE.md at repo root are the canonical contributor contract: uv for all env/dep ops (never pip/poetry), `uv sync --all-groups` before tests, make test/lint/format per package, Conventional Commits with mandatory scope, branch naming `<user>/<scope>/<desc>`.
- New features go in libs/langchain_v1 (package `langchain`); libs/langchain ships `langchain-classic` and is explicitly 'legacy, no new features' per AGENTS.md — don't add capabilities there.
- Public API stability is a hard rule: preserve signatures/positions/names, add new params keyword-only, mark experimental features with `!!! warning` docstring admonitions, and check `__init__.py` exports before touching anything public.
- Several langchain_v1 modules are backwards-compat re-export shims — e.g. langchain/tools/tool_node.py re-exports langgraph.prebuilt ToolNode/ToolCallRequest, langchain/tools/__init__.py re-exports langchain_core.tools — so edit the canonical implementation, not the shim.
- Before writing agent-loop code, read factory.py end-to-end: node names are '<middleware_name>.<hook>', edges must go through `_add_middleware_edge`/`_get_can_jump_to`, wrap handlers compose via `_chain_model_call_handlers`, and Command.goto inside wrap_model_call is unsupported.
- Test conventions: mirror source layout under tests/unit_tests, no network (pytest-socket enforced), use fixtures/mocks, determinism required; persistence tests need `make start_services` (postgres+redis) first.
- Lint bar is high: ruff `select = ["ALL"]` with google pydocstyle, single-backtick docstring code refs, banned relative imports, mypy strict with pydantic plugin and warn_unreachable; run `make lint` and `uv run --all-groups mypy .` before submitting.
- Releasing a package = bump `_version.py` + pyproject version + `uv lock`, merge, then trigger _release.yml via `gh workflow run 63880841` — never tag or create GitHub releases manually.
- Known traps: FALLBACK_MODELS_WITH_STRUCTURED_OUTPUT regexes must be updated for new model families; middleware-added tools bypass validation when wrap_tool_call exists; ModelRequest attribute mutation is deprecated (use override()); system_prompt param deprecated in favor of SystemMessage.
- Model profile data (capabilities/context windows) is generated, not hand-edited: use `uv run langchain-profiles refresh --provider <p> --data-dir <partner>/langchain_<p>/data` from libs/model-profiles.
- Every public module/function needs Google-style docstrings with Args/Returns/Raises, full type hints, and American English; tests get relaxed lint rules but still require the strict pytest config (no bare markers).