my biggest code smell is debugging. Trying to step through the code is slow because of how much the debugger has to keep track off and it's a lot of step into / jumps until you get to the piece you actually care about. Then you also see stuff like "if langchain_v2: <branch> elif langchain_v3: <branch> else ...." ... breaking changes are ok! I feel like at this point they're hopelessly spaghettied and need a more opinionated approach to clean up a lot of the mess.
Since others are asking: My current goto is pydantic ai and it's been doing pretty well for my use cases.