Solve Loop is the second phase of the dual-loop architecture, responsible for strict problem solving and answer generation. Based on knowledge collected by Analysis Loop, it uses block-based planning, step-by-step solving, and quality checking to generate high-quality final answers.
┌─────────────────────────────────────────────────────────┐
│ Solve Loop (Solution Phase) │
│ │
│ ┌──────┐ ┌─────────┐ ┌──────┐ ┌───────┐ │
│ │ Plan │ -> │ Manager │ -> │Solve │ -> │ Check │ │
│ └──────┘ └─────────┘ └──────┘ └───────┘ │
│ │ │ │
│ └───────────┘ │
│ Loop Until Complete │
│ │ │
│ ▼ │
│ ┌────────┐ │
│ │ Format │ │
│ └────────┘ │
│ │ │
│ SolveMemory │
└─────────────────────────────────────────────────────────┘
Function: Generate problem-solving plan (blocks)
Workflow:
- Analyze user question and knowledge from Analysis Loop
- Decompose problem into multiple logical blocks
- Define objectives for each block
- Save to
SolveMemory.plan
Output:
{
'num_blocks': 3,
'num_steps': 0, # Initially 0, generated by Manager
'blocks': [
{
'block_id': 'b001',
'goal': 'Understand the definition of linear convolution',
'steps': [] # Filled by Manager
}
]
}Function: Plan specific steps (steps) for each block
Workflow:
- Get next incomplete block
- Analyze block objectives
- Generate 3-5 concrete execution steps
- Save to
SolveMemory.plan.blocks[i].steps
Output:
{
'has_block': True,
'block_id': 'b001',
'steps_generated': 3,
'steps': [
{
'step_id': 's001',
'plan': 'Quote definition and explain',
'status': 'pending'
}
]
}Function: Execute each step and generate content
Workflow:
- Read current step plan
- Call tools if needed: RAG, Code Execution
- Generate step content
- Extract citations
- Return result (for Check Agent validation)
Supported Tools:
rag_search: Knowledge base retrievalrun_python_code: Python code executionquery_item: Query numbered items
Output:
{
'step_content': 'Linear convolution is defined as...',
'citations': ['[rag-1]', '[code-1]'],
'tool_logs': [
{
'tool': 'rag_search',
'status': 'success',
'elapsed_ms': 1200
}
],
'raw_llm_response': '...' # For debugging
}Function: Execute Python code (called by SolveAgent)
Features:
- Secure sandbox environment
- Support for NumPy, Matplotlib, and other common libraries
- Automatic output and error capture
- Timeout protection
Usage Example:
code_result = await code_agent.execute(
code="""
import numpy as np
x = np.array([1, 2, 3])
h = np.array([0.5, 1, 0.5])
y = np.convolve(x, h, mode='full')
print(f"Convolution result: {y}")
""",
timeout=10
)Function: Validate step quality and provide optimization suggestions
Workflow:
- Read SolveAgent output
- Check content quality:
- Logical completeness
- Citation clarity
- Calculation correctness
- Format compliance
- Provide verdict:
passorneeds_revision - If revision needed, provide specific suggestions
Verdict Standards:
pass: Content quality acceptable, proceed to next stepneeds_revision: Needs optimization with specific issues
Output:
{
'verdict': 'pass', # or 'needs_revision'
'comment': 'Content complete, citations sufficient',
'integrated_content': '...', # Optional: integrated content
'raw_response': '...' # For debugging
}Retry Mechanism:
- If
needs_revision, SolveAgent regenerates - Maximum
max_solve_correction_iterationsretries (default 3) - After max attempts, logs issue but continues
Function: Generate precise, concise answer
Features:
- Extract key information
- Generate 1-2 paragraph brief answer
- Suitable for quick reference
Configuration:
agents:
precision_answer_agent:
enabled: false # Disabled by defaultPersistent JSON memory recording the entire Solve Loop process.
Structure:
{
"user_question": "What is linear convolution?",
"plan": {
"blocks": [
{
"block_id": "b001",
"goal": "Understand the definition of linear convolution",
"steps": [
{
"step_id": "s001",
"plan": "Quote definition and explain",
"status": "completed", # pending/in_progress/completed
"content": "Linear convolution is...",
"citations": ["[rag-1]", "[code-1]"],
"tool_logs": [...]
}
]
}
]
},
"progress": {
"status": "completed", # not_started/in_progress/completed
"current_block": "b001",
"current_step": "s001",
"completed_blocks": ["b001"],
"completed_steps": ["s001", "s002"]
},
"metadata": {
"total_blocks": 3,
"total_steps": 8,
"completed_steps": 8
}
}Storage Location: {output_dir}/solve_memory.json
Global singleton managing numbering and formatting of all citations.
Features:
- Auto-assign citation numbers ([rag-1], [web-1], ...)
- Deduplication: same content gets one number
- Reset support (per task)
Usage:
from solve_loop.citation_manager import CitationManager
manager = CitationManager()
manager.reset() # Reset numbering
# Add citation
cite_id = manager.add_citation("Citation content", source="k001")
# Returns: "[rag-1]"
# Get all citations
citations = manager.get_all_citations()
# Returns: [{'id': '[rag-1]', 'content': '...', 'source': 'k001'}]Configure Solve Loop in config.yaml:
system:
max_solve_correction_iterations: 3 # Max retries per step
agents:
plan_agent:
enabled: true
model: "gpt-4o"
temperature: 0.3
manager_agent:
enabled: true
model: "gpt-4o"
temperature: 0.3
solve_agent:
enabled: true
model: "gpt-4o"
temperature: 0.4
code_agent:
enabled: true
timeout: 10 # Code execution timeout (seconds)
check_agent:
enabled: true
model: "gpt-4o"
temperature: 0.3
precision_answer_agent:
enabled: false # Optional
model: "gpt-4o"
temperature: 0.2from solve_agents.memory import SolveMemory, InvestigateMemory
from solve_agents.solve_loop import (
PlanAgent,
ManagerAgent,
SolveAgent,
CheckAgent,
)
# Load Analysis Loop results
investigate_memory = InvestigateMemory.load(output_dir)
# Create Solve memory
solve_memory = SolveMemory.load_or_create(
output_dir="./output",
user_question="What is linear convolution?"
)
# Initialize Agents
plan_agent = PlanAgent(config, api_key, base_url)
manager_agent = ManagerAgent(config, api_key, base_url)
solve_agent = SolveAgent(config, api_key, base_url)
check_agent = CheckAgent(config, api_key, base_url)
# 1. Plan: Generate blocks
plan_result = await plan_agent.process(
question=question,
investigate_memory=investigate_memory,
solve_memory=solve_memory
)
# 2. Solve Loop
while solve_memory.progress.status != "completed":
# Manager: Generate steps
manager_result = await manager_agent.process(
question=question,
solve_memory=solve_memory,
investigate_memory=investigate_memory
)
if not manager_result['has_block']:
break
# Solve + Check loop
current_step = solve_memory.get_current_step()
for attempt in range(max_retries):
# Solve: Execute step
solve_result = await solve_agent.process(
question=question,
current_step=current_step,
solve_memory=solve_memory,
investigate_memory=investigate_memory,
kb_name="ai_textbook",
output_dir="./output"
)
# Check: Validate quality
check_result = await check_agent.process(
question=question,
current_step_result=solve_result,
solve_memory=solve_memory,
investigate_memory=investigate_memory
)
if check_result['verdict'] == 'pass':
# Mark as complete
solve_memory.complete_step(
step_id=current_step.step_id,
content=solve_result['step_content'],
citations=solve_result['citations'],
tool_logs=solve_result['tool_logs']
)
break
# Save
solve_memory.save()
with open(f"{output_dir}/final_answer.md", 'w') as f:
f.write(format_result['final_answer'])Question: "What is linear convolution?"
Plan Phase: Generate 3 blocks:
b001: Understand linear convolution definitionb002: Master calculation methodsb003: Learn application scenarios
Block 1 (b001):
- Manager: Generate 3 steps
s001: Quote definition and explains002: Explain mathematical expressions003: Provide examples
- Solve + Check: Execute stepwise
s001: Pass (1 attempt)s002: Needs revision (pass on 2nd attempt)s003: Pass (1 attempt)
Block 2 (b002):
- Manager: Generate 2 steps
s004: Explain calculation stepss005: Demonstrate with code
- Solve + Check: Execute stepwise
s004: Passs005: Call CodeAgent for execution, pass
Block 3 (b003):
- Manager: Generate 2 steps
s006: List application domainss007: Summarize pros and cons
- Solve + Check: Execute stepwise
s006: Passs007: Pass
Format Phase: Integrate all steps, generate final answer, format 5 citations
- Decompose complex problems into multiple blocks
- Each block has clear objectives
- Supports parallel thinking (though sequential execution)
- Each block decomposes into concrete steps
- Execute sequentially, accumulate context
- Support tool calls (RAG, code execution)
- Check Agent cyclically validates
- Automatic error correction
- Maximum 3 retries
- Auto-assign numbering
- Deduplication handling
- Formatted output
- JSON format storage
- Supports checkpoint resumption
- Facilitates debugging and review
cat output/solve_memory.json | jq .Logs display detailed information for each step:
--- Step 1: s001 ---
Plan: Quote definition and explain
[Solve] Generating content...
[Check] Verdict: pass
✓ Step s001 completed
metadata = solve_memory.metadata
print(f"Total blocks: {metadata['total_blocks']}")
print(f"Total steps: {metadata['total_steps']}")
print(f"Completed: {metadata['completed_steps']}")from solve_loop.citation_manager import CitationManager
manager = CitationManager()
citations = manager.get_all_citations()
for cite in citations:
print(f"{cite['id']}: {cite['content'][:50]}...")Q: How to adjust maximum retries per step?
Set in config.yaml:
system:
max_solve_correction_iterations: 3 # Default 3Q: How to enable precision answer?
agents:
precision_answer_agent:
enabled: trueQ: Code execution timeout, what to do?
Increase timeout:
agents:
code_agent:
timeout: 20 # Increase to 20 secondsQ: How to view Check Agent feedback?
Check logs for [Check] section or inspect tool_logs in solve_memory.json.
Q: How to manually reset CitationManager?
from solve_loop.citation_manager import CitationManager
manager = CitationManager()
manager.reset()Related Documentation: