Autonomous Tool-Calling Loop (ReAct Pattern)
An original reference implementation of the ReAct reasoning + acting loop that inspects tool calls returned by an LLM, executes local Python functions with error sandboxing, and returns observations.
import json
from typing import Dict, Any, Callable
def run_agent_loop(
client: Any,
model: str,
messages: list,
tools: list,
tool_map: Dict[str, Callable],
max_turns: int = 6
) -> str:
"""
Executes an autonomous tool-calling reasoning loop until the model
produces a terminal response or reaches max_turns.
"""
for turn in range(max_turns):
response = client.chat.completions.create(
model=model,
messages=messages,
tools=tools,
tool_choice="auto"
)
msg = response.choices[0].message
messages.append(msg)
# Terminal state reached if no tool calls requested
if not msg.tool_calls:
return msg.content or ""
# Dispatch each requested tool execution
for tool_call in msg.tool_calls:
fn_name = tool_call.function.name
try:
fn_args = json.loads(tool_call.function.arguments)
if fn_name in tool_map:
result = tool_map[fn_name](**fn_args)
else:
result = {"error": f"Tool '{fn_name}' not registered."}
except Exception as e:
result = {"error": f"Tool execution failed: {str(e)}"}
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result)
})
return "Agent execution stopped: Maximum conversation turns reached."