# create_react_agent -> create_agent
```python
# old (v0)
from langgraph.prebuilt import create_react_agent
agent = create_react_agent(model="...", tools=[...], prompt="...")
# new (v1)
from langchain.agents import create_agent
agent = create_agent(model="...", tools=[...], system_prompt="...")
```
## The mapping
- Import: `langgraph.prebuilt.create_react_agent` -> `langchain.agents.create_agent`
- Prompt: `prompt=` is now `system_prompt=`, and it takes a plain string. If you passed a SystemMessage object, pull the string out of its content first.
- Hooks: `pre_model_hook=`, `post_model_hook=`, `state_modifier=` are gone. Use middleware: `before_model`, `after_model`, `@wrap_model_call`, `@wrap_tool_call`. Human approval of tool calls uses `HumanInTheLoopMiddleware(interrupt_on={...})` from `langchain.agents.middleware`.
- Structured output: keep `response_format=`, but build it with `ToolStrategy` or `ProviderStrategy` from `langchain.agents.structured_output`. The old prompted tuple form is removed.
- Streaming: the node name changed from "agent" to "model". If you filter stream chunks by node name, update the filter.
- Runtime context: pass it as `context=` on invoke/stream (with `context_schema=` on create_agent) instead of stuffing it into `config["configurable"]`.
- State: prefer `langchain.agents.AgentState` over the old `langgraph.prebuilt` agent state helpers.
- Reading output: prefer `message.content_blocks` for provider-agnostic content. `message.content` still works.
## Rules
- Search the codebase for `create_react_agent`, `pre_model_hook`, `post_model_hook`, `state_modifier`, and imports from `langgraph.prebuilt` before calling a migration done. One leftover import breaks the whole module at import time.
- Invoke the same way: `agent.invoke({"messages": [{"role": "user", "content": "..."}]})`.