Hi everyone,
I’m designing a customer-facing LangGraph-based ReAct agent for an assistant and I have a problem with the architecture.
Use case:
Like Rasa/Parlant “journeys”, I want one chat agent that can both:
Run multi-step action flows (e.g. transfer money from X to Y, configure spending alerts like “tell me when I pay > $100 on food”)
Let the user freely interrupt with other questions mid-flow (e.g. “what’s my balance?”, “show me last transactions”) and then resume.
The user can ask questions and tools will be used
Current design idea:
One ReAct LangGraph agent node = planner + router (+ final answer).
LangGraph state keeps:
active_journey: null or "TransferMoney" / "ConfigureAlert" / etc.
journey_form: dict of slots for the current journey.
messages / summary.
Rule: at most one active journey. If the user clearly starts a new journey (“open a deposit”), we drop the previous one and switch active_journey + journey_form.
The ReAct agent:
Reads the state + latest user message injected into the prompt.
Chooses tools: either a “journey tool” (that updates active_journey / journey_form and may execute actions, or other tools, e.g., RAG tool (for data-only questions), or answer directly.
The RAG tool does not reset the journey, allowing users to ask questions mid-flow and then continue.
State is persisted with a checkpointer, so each time the planner runs it sees active_journey + journey_form and continues.
Nice work! Your design is sound.
In LangGraph, the idiomatic way to support “journeys” with mid-flow questions would be to combine:
a prebuilt ReAct loop (agent + tool node)
explicit breakpoints/interrupts
and a checkpointer for durable state
Concretely:
Use the prebuilt ReAct agent and pass a checkpointer. This gives you a tool-calling loop with state persistence and optional breakpoints.
Breakpoints: You can interrupt before or after the agent or tools, which is perfect for confirmations or mid-flow clarifications (and to yield back to the user/UI).
Interrupts and resume: Within tools or nodes, call interrupt(...) to pause and bubble a breakpoint up; later resume with Command(resume=...).
Under the hood, these interrupts are first-class signals that bubble via GraphInterrupt (so they propagate reliably even when subgraphs/tools are involved)
My input for your “journeys”:
Keep active_journey and journey_form in the graph state (as you proposed). Let each journey be a subgraph (graph-as-tool). The supervisor/agent can route to the correct journey tool; mid-flow RAG queries can be served by a separate tool without clearing active_journey. After handling the side question, just resume the journey (no state reset required).
If you want user confirmations before taking actions, set interrupt_before=["tools"]. To hand control back to the UI after a tool step, consider interrupt_after=["tools"].
Always supply a thread_id and a checkpointer so all state (messages, active_journey, journey_form) is durably persisted and automatically reloaded on each turn.
Feel free to ask any questions during the implementation phase.