ReflAct - Reflection-Grounded Agent Reasoning¶
Theory¶
Paper¶
Original paper
Kim, J., Rhee, S., Kim, M., et al. (2025) ReflAct: World-Grounded Decision Making in LLM Agents via Goal-State Reflection DOI: 10.48550/arXiv.2505.15182 EMNLP 2025 (Main Conference)
Concept
ReflAct extends ReAct with state‑grounded reflection. Instead of forward‑planning ("What should I do next?"), the agent reflects on its current state relative to the goal ("Where am I relative to the goal?"). This enables systematic self‑correction and better goal focus.
Architecture¶
flowchart LR
query([Query]) --> service[AgentChatService]
service --> reflact[ReflAct Mode]
reflact --> refl[REFLECTION]
refl --> action[ACTION]
action --> tool[[Tool Execute]]
tool --> obs[/OBSERVATION/]
obs --> decide{Goal reached?}
decide -->|No| refl
decide -->|Yes| final([FINAL ANSWER])
style query fill:#98d4bb,stroke:#6bbf9a,color:#000
style service fill:#a8c5e2,stroke:#7ba3c9,color:#000
style reflact fill:#88c4c8,stroke:#5fa8ad,color:#000
style refl fill:#88c4c8,stroke:#5fa8ad,color:#000
style action fill:#D1BC8A,stroke:#b8a06a,color:#000
style tool fill:#b0ca97,stroke:#8fb077,color:#000
style obs fill:#a8c5e2,stroke:#7ba3c9,color:#000
style decide fill:#9e9e9e,stroke:#757575,color:#fff
style final fill:#e8c87a,stroke:#d4a84b,color:#000
ReflAct loop: Query → REFLECTION (state‑grounded) → ACTION → Tool → OBSERVATION → (repeat or answer)
Core Concept¶
REFLECTION → ACTION → OBSERVATION → REFLECTION → ... → FINAL ANSWER
The REFLECTION step is state‑grounded:
- "Where am I relative to the goal?"
- "What do I already know?"
- "What did I just discover?"
- "What is still missing to reach the goal?"
Difference from ReACT¶
| Aspect | ReACT (THOUGHT) | ReflAct (REFLECTION) |
|---|---|---|
| Focus | Forward‑looking | State‑grounded |
| Question | "What should I do next?" | "Where am I relative to the goal?" |
| Perspective | Planning | Evaluation |
| State awareness | Partial | Full |
| Self‑correction | Possible | Systematic |
REFLECTION Structure¶
Each reflection contains three components:
REFLECTION:
1. Current state: [What I already know]
2. Latest discovery: [What was just found]
3. Goal relation: [How close am I? What is still missing?]
Advantages over ReACT¶
| Advantage | Description |
|---|---|
| Better self‑correction | Explicit state evaluation enables early error detection |
| Goal focus | Each step is measured against the goal |
| Transparency | Fully traceable reasoning process |
| Robustness | Less prone to drifting off goal |
Example¶
Query¶
ReflAct Trace¶
[Iteration 1]
REFLECTION:
Current state: The user asks for opening hours AND contact details.
I have no information yet.
Latest discovery: (None - start of task)
Goal relation: I need both pieces of information. I will search
for opening hours first.
ACTION: rag_search("opening hours DG Agentur")
OBSERVATION:
[1] Contact: Mon-Fri 9-18, Sat by appointment
[2] You can reach us at +49 911 97554990
[Iteration 2]
REFLECTION:
Current state: I have opening hours (Mon-Fri 9-18, Sat by appointment)
and a phone number (+49 911 97554990).
Latest discovery: Document [1] contains opening hours,
[2] provides the phone number.
Goal relation: Opening hours: ✓ complete
Contact details: partial (phone ✓, email missing, address missing)
ACTION: rag_search("contact email address legal notice")
OBSERVATION:
[1] Legal notice: Phone +49 911 97554990, Email office@dg-agentur.de
[2] Address: Bahnhofstraße 2, 90402 Nürnberg
[Iteration 3]
REFLECTION:
Current state: I have all required information:
- Opening hours: Mon-Fri 9-18, Sat by appointment
- Phone: +49 911 97554990
- Email: office@dg-agentur.de
- Address: Bahnhofstraße 2, 90402 Nürnberg
Latest discovery: Email and address from the legal notice.
Goal relation: GOAL REACHED - all information complete.
FINAL ANSWER: DG Agentur is open Monday to Friday 9-18,
Saturday by appointment. [1]
Contact:
- Phone: +49 911 97554990
- Email: office@dg-agentur.de
- Address: Bahnhofstraße 2, 90402 Nürnberg [2]
Response¶
DG Agentur is open Monday to Friday 9-18,
Saturday by appointment. [1]
Contact:
- Phone: +49 911 97554990
- Email: office@dg-agentur.de
- Address: Bahnhofstraße 2, 90402 Nürnberg [2]
Sources:
[1] Contact - DG Agentur
[2] Legal notice - DG Agentur
Implementation in LLARS¶
Status: Production
ReflAct is fully implemented and in production use.
Architecture¶
flowchart TB
subgraph main[chat_reflact Loop]
direction TB
start([Start]) --> refl[Generate REFLECTION]
refl --> action[Generate ACTION]
action --> parse[Parse Response]
parse --> check{FINAL ANSWER?}
check -->|No| exec[Execute Tool]
exec --> history[Add to Steps]
history --> refl
end
check -->|Yes| done([Finalize])
style start fill:#98d4bb,stroke:#6bbf9a
style refl fill:#88c4c8,stroke:#5fa8ad,color:#000
style action fill:#D1BC8A,stroke:#b8a06a,color:#000
style parse fill:#a8c5e2,stroke:#7ba3c9,color:#000
style check fill:#9e9e9e,stroke:#757575,color:#fff
style exec fill:#b0ca97,stroke:#8fb077,color:#000
style history fill:#88c4c8,stroke:#5fa8ad,color:#000
style done fill:#e8c87a,stroke:#d4a84b
style main fill:#f5f5f5,stroke:#88c4c8
System Prompt¶
# DEFAULT_REFLACT_SYSTEM_PROMPT (db/models/chatbot.py)
"""
Du bist ein ReflAct-Agent. Bei jedem Schritt reflektierst du deinen aktuellen Zustand
RELATIV zum Aufgabenziel, dann wählst du die nächste Aktion.
## ReflAct-Prinzip (basierend auf arxiv.org/abs/2505.15182):
- Nicht "Was soll ich als nächstes tun?" (vorausschauend)
- Sondern "Wo stehe ich relativ zum Ziel?" (zustandsbasiert)
## Deine Reflection muss IMMER enthalten:
1. Aktueller Zustand: Was weißt du bereits?
2. Letzte Entdeckung: Was hast du gerade erfahren?
3. Ziel-Relation: Wie nah bist du dem Ziel? Was fehlt noch?
## Verfügbare Aktionen:
- rag_search("suchbegriff") - Semantische Dokumentensuche
- lexical_search("suchbegriff") - Keyword-Suche
## Format (STRIKT einhalten!):
REFLECTION: Aktuell weiß ich [Zustand]. Die letzte Suche ergab [Ergebnis]. Dies bringt mich [näher/nicht näher] zum Ziel [X], weil [Begründung].
ACTION: rag_search("suchbegriff")
Wenn das Ziel erreicht ist:
REFLECTION: Ich habe alle nötigen Informationen: [Zusammenfassung]. Das Ziel ist erreicht.
FINAL ANSWER: [Vollständige Antwort basierend auf den gefundenen Informationen]
"""
Additionally:
- chatbot.system_prompt is prefixed.
- build_tool_availability_prompt() adds the enabled tools dynamically.
- {PROJECT_URL} placeholders are replaced before use.
Files¶
| File | Function |
|---|---|
app/services/chatbot/agent_chat_service.py |
Routing to ACT/ReAct/ReflAct |
app/services/chatbot/agent_modes/mode_reflact.py |
chat_reflact() loop + streaming |
app/services/chatbot/agent_parsers.py |
parse_reflact_response_v2() |
app/services/chatbot/agent_tools.py |
Tool execution + confidence checks |
app/db/models/chatbot.py |
DEFAULT_REFLACT_SYSTEM_PROMPT + prompt settings |
Code Snippet¶
# mode_reflact.py - chat_reflact()
for iteration in range(max_iterations):
yield {"status": "iteration", "iteration": iteration + 1, "max": max_iterations, "goal": goal}
# Stream REFLECTION + ACTION
response_text, reflection, action, final_answer = yield from _stream_reflact_response(...)
if final_answer:
yield {"status": "final_answer"}
...
return
# Execute tool
result, sources = service._tool_executor.execute_tool(action_name, action_param, message, enabled_tools)
yield {"status": "observation", "result_preview": result[:300], "iteration": iteration + 1}
Parsing¶
# agent_parsers.py - parse_reflact_response_v2()
REFLECTION_PATTERN = r"REFLECTION:\s*(.+?)(?=ACTION:|FINAL ANSWER:|THOUGHT:|GOAL:|$)"
ACTION_PATTERN = r"ACTION:\s*(.+?)(?=OBSERVATION:|REFLECTION:|FINAL ANSWER:|THOUGHT:|GOAL:|$)"
FINAL_PATTERN = r"FINAL ANSWER:\s*(.+?)(?=ACTION:|REFLECTION:|THOUGHT:|GOAL:|$)"
# Backward‑compatible: THOUGHT is interpreted as REFLECTION
THOUGHT_AS_REFLECTION = r"THOUGHT:\s*(.+?)(?=ACTION:|FINAL ANSWER:|REFLECTION:|GOAL:|$)"
Configuration¶
# ChatbotPromptSettings
agent_mode: str = "reflact"
task_type: str = "lookup" | "multihop"
agent_max_iterations: int = 5
# Multihop: max_iterations = min(agent_max_iterations + 2, 10)
tools_enabled: List[str] = ["rag_search", "lexical_search", "respond"]
web_search_enabled: bool = False
web_search_max_results: int = 5
reflact_system_prompt: str = "..." # custom prompt (optional)
Adaptive Iteration (High Confidence)¶
If the search yields high confidence, ReflAct exits early and generates a final answer immediately.
Confidence is derived from source scores (check_high_confidence).
Events (WebSocket)¶
# Streaming Events (excerpt)
yield {"status": "starting", "mode": "reflact"}
yield {"status": "iteration", "iteration": 1, "max": 7, "goal": "...", "steps": [...]}
yield {"status": "reflecting", "iteration": 1}
yield {"status": "reflection_delta", "delta": "...", "iteration": 1}
yield {"status": "reflection", "reflection": "...", "iteration": 1}
yield {"status": "action_delta", "delta": "...", "iteration": 1}
yield {"status": "action", "action": "rag_search", "param": "...", "iteration": 1}
yield {"status": "observation_delta", "delta": "...", "iteration": 1}
yield {"status": "observation", "result_preview": "...", "iteration": 1}
yield {"status": "adaptive_iteration", "iteration": 1, "reason": "high_confidence"}
yield {"status": "adaptive_response", "reason": "high_confidence_results"}
yield {"status": "max_iterations_reached"}
yield {"status": "final_answer"}
yield {"delta": "..."}
yield {"done": True, "full_response": "...", "sources": [...], "goal": "..."}
Logs¶
Comparison: ReACT vs ReflAct in LLARS¶
| Aspect | ReACT | ReflAct |
|---|---|---|
| Method | chat_react() |
chat_reflact() |
| Location | mode_react.py |
mode_reflact.py |
| Reasoning step | THOUGHT (forward) | REFLECTION (state‑grounded) |
| Parsing | parse_react_response() |
parse_reflact_response_v2() |
| State tracking | Implicit | Explicit (3‑part structure) |
| Goal evaluation | No | Yes (goal relation) |
| Tokens/iteration | ~150-300 | ~200-400 |
| Typical iterations | 2-5 | 2-5 |
| Self‑correction | Possible | Systematic |
When to use ReflAct over ReACT¶
| Use case | Recommendation |
|---|---|
| Simple lookups | ReACT or ACT |
| Multi‑hop with clear goal | ReflAct |
| Complex research | ReflAct |
| Maximum transparency | ReflAct |
| Self‑correction important | ReflAct |
| Minimal token usage | ACT or ReACT |