Core Concept
The traditional ReAct pattern follows a straightforward loop:
- Define available tools
- Execute a cycle of Question → Thought → Action → Action Input → Observation
- Repeat untill a final answer is reached
The Code-Prompt approach simplifies this by expressing the entire reasoning loop as executable Python code. This method supports batch tool invocation, structured JSON output, and works effectively with smaller models like GPT-4o-mini.
Implementation
# EXECUTE THIS CODE AND RETURN THE OUTPUT
# OUTPUT ONLY THE RESULT
import json
# Core LLM capabilities (simulated module)
from llm_core import (
has_sufficient_info,
synthesize_answer,
analyze_step,
validate_params
)
from llm_core.io import read_input, write_output
from llm_core.tools import tool_decorator
# Define available tools
@tool_decorator
def web_search(query_text: str) -> str:
"""
Perform an internet search to retrieve information.
Args:
query_text: Search keywords or natural language query
Returns:
Summary of search results
"""
pass
@tool_decorator
def generate_image(description: str) -> str:
"""
Create an image based on text description.
Args:
description: Text describing desired image content
Returns:
URL of the generated image
"""
pass
def reasoning_loop(user_query: str, history: list) -> dict:
"""
Execute reasoning cycle to answer query or plan next action.
Args:
user_query: The question to answer
history: List of previous reasoning steps and observations
Returns:
Either final answer or next action to take
"""
if has_sufficient_info(user_query, history):
return {
"result": synthesize_answer(user_query, history)
}
# Plan next step
reasoning = analyze_step(f"What reasoning is needed to address: '{user_query}'?", history)
tool_selection = analyze_step(
f"Which tool best helps solve: '{user_query}'?",
history
)
param_guess = analyze_step(f"What parameters does '{tool_selection}' require?")
validated_params = validate_params(
func_name=tool_selection,
raw_params=param_guess
)
return {
"reasoning": reasoning,
"next_action": {
"tool": tool_selection,
"args": validated_params
}
}
if __name__ == '__main__':
user_input = read_input("Proceed with execution? (Y/N)")
query = "What is DJJ?"
execution_history = []
response = reasoning_loop(query, execution_history)
write_output(json.dumps(response, indent=2))
Execution Flow
Initial Step
When the user confirms execution:
{
"reasoning": "The term 'DJJ' is ambiguous. It could refer to multiple entities. A web search is necessary to identify possible meanings and provide accurate information.",
"next_action": {
"tool": "web_search",
"args": {
"query_text": "DJJ meaning"
}
}
}
Final Resolution
After the tool execution result is added to the history:
execution_history = [
{
"reasoning": "The term 'DJJ' is ambiguous...",
"next_action": {
"tool": "web_search",
"args": {"query_text": "DJJ meaning"}
}
},
{
"tool_output": {
"web_search": {
"findings": [
"DJJ is a decentralized digital currency built on blockchain technology",
"DJJ also refers to Department of Joke Justice, a virtual entity handling humorous legal matters"
]
}
}
}
]
The final response becomes:
{
"result": "DJJ refers to two distinct concepts: (1) A decentralized digital currency built on blockchain technology designed for global use, and (2) The Department of Joke Justice, a virtual department handling legal matters related to jokes, memes, and humorous content."
}
Advantages
This approach offers several benefits over traditional ReAct implementations:
- Clarity: The code structuer makes the reasoning flow explicit and debuggable
- Efficiency: Works well with smaller, cost-effective models
- Flexibility: Easy to add new tools or modify the reasoning logic
- Structured Output: JSON response are predictable and parseable