# LCEL
```python
from langchain.chat_models import init_chat_model
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_template("Tell me a joke about {topic}")
model = init_chat_model("gpt-5.4-mini")
chain = prompt | model | StrOutputParser()
chain.invoke({"topic": "bears"})
```
## Rules
- For new code, use LCEL (`prompt | model | parser`). Do not reach for LLMChain in new code; it lives in langchain-classic now and only exists for old codebases.
- LCEL runnables get `.invoke`, `.batch`, `.stream`, `.astream_events`, `.with_retry`, and `.with_fallbacks` for free. If you are hand-rolling retry loops around a chain, you are reimplementing built-ins.
- Prefer create_agent over chains for anything with tools. Chains are for straight pipelines; the moment the model needs to decide, that is an agent.