ANDYBOT TOOL CALLING - PSEUDOCODE
==================================

RULE #1: Messages alternate: user, assistant, user, assistant (ABAB pattern)
RULE #2: petsitter sends USER messages, model sends ASSISTANT messages
RULE #3: We NEVER create assistant messages - only model does


SYSTEM PROMPT
-------------
You are an assistant. You can ask ANDYBOT to do things.

AVAILABLE COMMANDS:
- LIST_MP3S: List all MP3 files in the music library
- PLAY_MP3: Play a specific MP3 file from the library

To use a command, say:
DEAR ANDYBOT, <COMMAND_NAME>

ANDYBOT may ask you for more information. Answer briefly.


PRE_HOOK (before model sees messages)
-------------------------------------
Input: context from client, may include tool results

For each message in context:
    if message is "tool":
        content = message.content
        if content is empty:
            formatted = "OK"
        else if content is JSON list:
            formatted = join items with ", " OR "OK" if empty
        else if content is JSON object:
            formatted = JSON string
        else:
            formatted = content as-is
        
        REPLACE message with:
            role: "user"
            content: "ANDYBOT RESPONDS: <formatted>"
    
    if message is "assistant" with "tool_calls":
        STRIP tool_calls from message
        KEEP content as-is (or empty string if null)

Add system prompt at start if needed


POST_HOOK (after model responds)
--------------------------------
Input: context with model's response

last_message = context[-1]

# Pass through native tool_calls unchanged
if last_message has "tool_calls":
    return context unchanged

# Check for "DEAR ANDYBOT, <FUNCTION_NAME>"
content = last_message.content or ""
match = regex search for "DEAR ANDYBOT, (\w+)" in content (case insensitive)

if no match:
    return context unchanged

tool_name = matched function name (look up in available tools)

# Ask for ALL parameters (not just required!)
params = {}
for each parameter in tool.parameters:
    question = "ANDYBOT ASKS: <parameter description>?"
    
    # This adds a user message and gets assistant response
    context, value = get_parameter(context, question)
    
    if value is empty or "skip" or "not required":
        # Don't include this param
        continue
    
    params[parameter_name] = value

# Add tool_calls to the last assistant message
last_message.tool_calls = [{
    id: generate_random_id(),
    type: "function",
    function: {
        name: tool_name,
        arguments: JSON.stringify(params)
    }
}]

return context


GET_PARAMETER(context, question)
--------------------------------
# Add user question to context
context.append({role: "user", content: question})

# Call model
response = call_model(context)

# Add model response to context
context.append({role: "assistant", content: response})

return context, response


EXAMPLE FLOW
============

1. FIRST REQUEST
   petsitter to model:
       system: "You are an assistant..."
       user: "look at files in ~/mp3 and play the first one"
   
   model responds:
       assistant: "DEAR ANDYBOT, LIST_MP3S"
   
   post_hook detects tool call, asks for params:
       user: "ANDYBOT ASKS: path?"
       model (via callmodel_sync): "~/mp3"
   
   petsitter returns tool_calls to client:
       assistant: "" with tool_calls: {list_mp3s, path: "~/mp3"}

2. SECOND REQUEST (tool result)
   client sends:
       user: "look at files in ~/mp3..."
       tool: ["song1.mp3", "song2.mp3"]
   
   pre_hook transforms:
       user: "look at files in ~/mp3..."
       user: "ANDYBOT RESPONDS: song1.mp3, song2.mp3"
   
   model responds:
       assistant: "DEAR ANDYBOT, PLAY_MP3"
   
   post_hook asks for params:
       user: "ANDYBOT ASKS: path?"
       model: "~/mp3"
       user: "ANDYBOT ASKS: file?"
       model: "song1.mp3"
   
   petsitter returns tool_calls to client:
       assistant: "" with tool_calls: {play_mp3, path: "~/mp3", file: "song1.mp3"}

3. THIRD REQUEST (tool result)
   client sends:
       user: "look at files..."
       tool: "playing song1.mp3"
   
   pre_hook transforms:
       user: "look at files..."
       user: "ANDYBOT RESPONDS: playing song1.mp3"
   
   model responds:
       assistant: "I've started playing song1.mp3 from your ~/mp3 directory!"
   
   No tool call detected, return as-is.


COMMON MISTAKES TO AVOID
========================
1. DON'T add "Using tool..." or any extra assistant messages
2. DON'T skip optional parameters - ask for ALL of them
3. DON'T create consecutive user messages - must alternate
4. DON'T return "done" for empty results - return "OK" or actual content
5. DON'T forget to strip tool_calls from assistant messages in pre_hook