/root/code/tools_starter.py and /root/code/agent_starter.py. Copy each starter file to its working name and implement the TODOs inside.

What you’ll build
- A small agent loop that can call tools and integrate tool output into the conversation.
- Three deterministic, mocked tools:
check_calendar,search_web, andget_user_preferences. - A dispatcher to run tools and return results to the model.
- Error handling and a bounded iteration loop to avoid runaway calls.
Files and components
Tip: Keep the tool metadata (
TOOLS) and the Python handler names in sync. The model requests a function by name, and your execute_tool must map that exact name to the corresponding Python function.Step 1 — Tools: create tools.py
- Copy
tools_starter.pytotools.py. - Add three tool definitions into the
TOOLSlist:check_calendar— returns events for a date (YYYY-MM-DD) or today’s events if no date provided.search_web— returns a short summary for a search query.get_user_preferences— returns stored user preferences for a given category.
type plus a function object containing name, description, and parameters.
- Implement simple handler functions that return mocked, deterministic responses, and implement an
execute_tooldispatcher to map tool names to their Python functions and invoke them with parsed arguments.
tools.py (copy into /root/code/tools.py and fill in as shown):
Step 2 — Agent: create agent.py
- Copy
agent_starter.pytoagent.py. - Implement
run_agent(user_message: str, history: list | None = None) -> str:
run_agent:
- Build the initial
messageslist, starting with the system prompt. - Append optional conversation history, then the user’s message.
- Run a bounded loop (use
MAX_ITERATIONS) that calls the model until:- the model returns a final assistant message (finish reason
stop), or - the model requests tool calls (finish reason like
tool_callortool_calls).
- the model returns a final assistant message (finish reason
- When the model requests tools:
- Parse tool arguments (handle both dict and JSON string forms).
- Call
execute_tooland append the tool’s output as arole: "tool"message. - Continue the loop so the model can return a final answer that incorporates tool outputs.
- Provide defensive handling for different SDK shapes (object vs dict) and unknown finish reasons.
agent.py:
Important: Never hard-code your API key. Set
OPENAI_API_KEY and any OPENAI_API_BASE in your environment, and avoid committing keys to source control.Step 3 — Run the agent
From the project directory (for example/root/code) run:
__main__ block to agent.py if it’s not present, to test single-step and multi-step interactions:
check_calendar tool, received the mock schedule, and returned a natural language summary.
Step 4 — Multi-step task example
Test a multi-step query that requires the agent to call multiple tools in sequence. The agent will:- Call
search_webto summarize information about AI agents. - Call
check_calendarto check availability after 2 PM. - Combine the results into a final assistant response.
agent.py:
execute_tool, and incorporating tool outputs back into the conversation.
Troubleshooting & tips
- If the model never returns a final
stopfinish reason, the loop will eventually exit with theMAX_ITERATIONSguard to prevent infinite loops. - Ensure the
TOOLSmetadata is valid JSON-like structure (thefunctionschema) — mismatches between declared parameters and the actual handler signature can produceTypeError. - Tool argument payloads may arrive as dicts or JSON strings;
execute_toolshould defensively handle both.