Dynamic Tool Selection in ReAct Agents
A production ReAct agent must dynamically select the right tool based on the current thought.
Task
Implement DynamicReActAgent that:
- Builds a system prompt describing all available tools.
- Parses LLM output to extract tool name and arguments.
- Executes the selected tool and feeds observation back.
- Returns a complete execution trace with steps and final answer.
Constraints
- LLM output format:
Thought: ... Action: tool_name Args: {json args} - Gracefully handle malformed LLM output.
- Trace each step: thought, action, args, observation.
- Support
finishas a special action to return the answer.
Examples
Example 1:
Input:
tools = [Tool('calc', 'Calculate math', eval, {})]
llm = lambda msgs: 'Thought: calc needed\nAction: calc\nArgs: {"expr": "2+2"}'
agent = DynamicReActAgent(tools, llm)
agent.run('What is 2+2?')Output:
{'answer': '4', 'steps': 1, 'trace': [...]}Explanation: Agent selects 'calc', runs eval('2+2')=4, returns answer.
Starter Code
from typing import Any, Dict, List, Optional
import json
class Tool:
def __init__(self, name: str, description: str, fn: callable, schema: Dict):
self.name = name
self.description = description
self.fn = fn
self.schema = schema
class DynamicReActAgent:
def __init__(self, tools: List[Tool], llm_fn: callable):
self.tools = {t.name: t for t in tools}
self.llm_fn = llm_fn # fn(messages: List[Dict]) -> str
self.trace: List[Dict] = []
def _select_tool(self, thought: str) -> Optional[str]:
# TODO: Parse tool name from thought or call LLM for selection
pass
def _parse_args(self, thought: str, tool_name: str) -> Dict:
# TODO: Extract arguments from thought
pass
def _build_system_prompt(self) -> str:
# TODO: Build system prompt with tool descriptions
pass
def run(self, task: str, max_steps: int = 10) -> Dict:
# TODO: Full ReAct loop returning trace + final answer
pass
Python3
ReadyLines: 1Characters: 0
Ready