OpenAI Agents SDK via PowerShell

After figuring out how to use functions

It is time to play with Agents

Key idea here is that we can not pass bazillion of tools into the model, and need to find some way to split them into chunks.

There is an customer_service example which does exactly this

If you play little bit with code and put few print statements here and ther, you may get full log of requests which will be something like this

How does it work?

At the top level we have Triage Agent its job is to decide to which other agent user message should be sent

We are achieving this by passing corresponding instructions and tool definitions

Here is an brief exapmle:

$headers = @{ Authorization = "Bearer $env:OPENAI_API_KEY" }

$baseInstructions = @"
# System context

You are part of a multi-agent system called the Agents SDK, designed to make agent coordination and execution easy.

Agents uses two primary abstraction: **Agents** and **Handoffs**.

An agent encompasses instructions and tools and can hand off a conversation to another agent when appropriate.

Handoffs are achieved by calling a handoff function, generally named `transfer_to_<agent_name>`.

Transfers between agents are handled seamlessly in the background; do not mention or draw attention to these transfers in your conversation with the user.
"@

$triageAgentInstructions = @"
$baseInstructions

You are a helpful triaging agent. You can use your tools to delegate questions to other appropriate agents.
"@

# note: tools here, are kind of fake functions to switch between available agents
$triageAgentTools = @(
  @{
    name        = "transfer_to_faq_agent"
    parameters  = @{
      additionalProperties = $false
      type                 = "object"
      properties           = @{}
      required             = @()
    }
    strict      = $true
    type        = "function"
    description = "Handoff to the FAQ Agent agent to handle the request. A helpful agent that can answer questions about the airline."
  }
  @{
    name        = "transfer_to_seat_booking_agent"
    parameters  = @{
      additionalProperties = $false
      type                 = "object"
      properties           = @{}
      required             = @()
    }
    strict      = $true
    type        = "function"
    description = "Handoff to the Seat Booking Agent agent to handle the request. A helpful agent that can update a seat on a flight."
  }
)


$res = Invoke-RestMethod -Method Post -Uri "https://api.openai.com/v1/responses" -Headers $headers -ContentType "application/json; charset=utf-8" -Body (ConvertTo-Json -Depth 100 -InputObject @{
    input        = @(
      @{
        role    = "user"
        content = "lets book a seat"
      }
    )
    model        = "gpt-4o"
    include      = @()
    instructions = $triageAgentInstructions
    stream       = $false
    tools        = $triageAgentTools
  })

$res.output | ConvertTo-Json -Depth 100

which will respond like so:

{
  "type": "function_call",
  "id": "fc_67dd8bce982481929f5f2d56f88799aa08e37110f459307f",
  "call_id": "call_goIRf9LIVdFCGVPEtL1gnVKs",
  "name": "transfer_to_seat_booking_agent",
  "arguments": "{}",
  "status": "completed"
}

So, our triage agent decided to switch context to seat booking agent based on user input, and asks us to call corresponding function.

There is no transfer_to_seat_booking_agent function, but, the key here is that:

  1. we will append this response as is to conversation
  2. we will append fake response like this {"type": "function_call_output", "call_id": "call_VbNO0xX5vd4a6RfonLs1A0nw", "output": "{"assistant": "Seat Booking Agent"}"}
  3. change instructions and tools definition to ones belong to seat booking agent
  4. pass all this back to OpenAI

e.g.: subsequent request will be:

$headers = @{ Authorization = "Bearer $env:OPENAI_API_KEY" }

$baseInstructions = @"
# System context

You are part of a multi-agent system called the Agents SDK, designed to make agent coordination and execution easy.

Agents uses two primary abstraction: **Agents** and **Handoffs**.

An agent encompasses instructions and tools and can hand off a conversation to another agent when appropriate.

Handoffs are achieved by calling a handoff function, generally named `transfer_to_<agent_name>`.

Transfers between agents are handled seamlessly in the background; do not mention or draw attention to these transfers in your conversation with the user.
"@

$seatBookingAgentInstructions = @"
$baseInstructions

You are a seat booking agent. If you are speaking to a customer, you probably were transferred to from the triage agent.

Use the following routine to support the customer.

# Routine

1. Ask for their confirmation number.
2. Ask the customer what their desired seat number is.
3. Use the update seat tool to update the seat on the flight.

If the customer asks a question that is not related to the routine, transfer back to the triage agent. """,
"@

$seatBookingAgentTools = @(
  # real function, that is supposed to update seat by calling external API
  @{
    name        = "update_seat"
    parameters  = @{
      properties           = @{
        confirmation_number = @{
          description = "The confirmation number for the flight."
          title       = "Confirmation Number"
          type        = "string"
        }
        new_seat            = @{
          description = "The new seat to update to."
          title       = "New Seat"
          type        = "string"
        }
      }
      required             = @("confirmation_number", "new_seat")
      title                = "update_seat_args"
      type                 = "object"
      additionalProperties = $false
    }
    strict      = $true
    type        = "function"
    description = "Update the seat for a given confirmation number."
  },
  # fake function, to switch back to triage agent
  @{
    name        = "transfer_to_triage_agent"
    parameters  = @{
      additionalProperties = $false
      type                 = "object"
      properties           = @{}
      required             = @()
    }
    strict      = $true
    type        = "function"
    description = "Handoff to the Triage Agent agent to handle the request. A triage agent that can delegate a customer's request to the appropriate agent."
  }
)


$res = Invoke-RestMethod -Method Post -Uri "https://api.openai.com/v1/responses" -Headers $headers -ContentType "application/json; charset=utf-8" -Body (ConvertTo-Json -Depth 100 -InputObject @{
    input        = @(
      @{
        role    = "user"
        content = "lets book a seat"
      },
      # append previous response as is
      @{
        type      = "function_call"
        id        = "fc_67dd8bce982481929f5f2d56f88799aa08e37110f459307f"
        call_id   = "call_goIRf9LIVdFCGVPEtL1gnVKs"
        name      = "transfer_to_seat_booking_agent"
        arguments = "{}"
        status    = "completed"
      },
      # as well as our fake function call result
      @{
        type    = "function_call_output"
        call_id = "call_goIRf9LIVdFCGVPEtL1gnVKs"
        output  = "{`"assistant`": `"Seat Booking Agent`"}"
      }
    )
    model        = "gpt-4o"
    include      = @()
    instructions = $seatBookingAgentInstructions # note: we are using seat booking agent instructions now
    stream       = $false
    tools        = $seatBookingAgentTools # note: we are using seat booking agent tools now
  })

$res.output | ConvertTo-Json -Depth 100

which will respond with:

{
  "type": "message",
  "id": "msg_67dd8e004e208192b3ea40b3a369b8a108e37110f459307f",
  "status": "completed",
  "role": "assistant",
  "content": [
    {
      "type": "output_text",
      "text": "Sure! Please provide your confirmation number.",
      "annotations": []
    }
  ]
}

user will enter his confirmation number and we will call model with current instructions and tools still set to seat booking agent, which will then ask for seat number and at the end call update seat function

whenever user asks for something that current agent can not recognize - it will fallback to triage agent which will decide what to do

PowerShell customer support agent

here is full example of commands ran one by one:

$headers = @{ Authorization = "Bearer $env:OPENAI_API_KEY" }

$baseInstructions = @"
# System context

You are part of a multi-agent system called the Agents SDK, designed to make agent coordination and execution easy. 

Agents uses two primary abstraction: **Agents** and **Handoffs**.

An agent encompasses instructions and tools and can hand off a conversation to another agent when appropriate.

Handoffs are achieved by calling a handoff function, generally named `transfer_to_<agent_name>`.

Transfers between agents are handled seamlessly in the background; do not mention or draw attention to these transfers in your conversation with the user.
"@

$triageAgentInstructions = @"
$baseInstructions

You are a helpful triaging agent. You can use your tools to delegate questions to other appropriate agents.
"@

# note: tools here, are kind of fake functions to switch between available agents
$triageAgentTools = @(
  @{
    name        = "transfer_to_faq_agent"
    parameters  = @{
      additionalProperties = $false
      type                 = "object"
      properties           = @{}
      required             = @()
    }
    strict      = $true
    type        = "function"
    description = "Handoff to the FAQ Agent agent to handle the request. A helpful agent that can answer questions about the airline."
  }
  @{
    name        = "transfer_to_seat_booking_agent"
    parameters  = @{
      additionalProperties = $false
      type                 = "object"
      properties           = @{}
      required             = @()
    }
    strict      = $true
    type        = "function"
    description = "Handoff to the Seat Booking Agent agent to handle the request. A helpful agent that can update a seat on a flight."
  }
)

$seatBookingAgentInstructions = @"
$baseInstructions

You are a seat booking agent. If you are speaking to a customer, you probably were transferred to from the triage agent.

Use the following routine to support the customer.

# Routine

1. Ask for their confirmation number.
2. Ask the customer what their desired seat number is.
3. Use the update seat tool to update the seat on the flight.

If the customer asks a question that is not related to the routine, transfer back to the triage agent. """,
"@

$seatBookingAgentTools = @(
  # real function, that is supposed to update seat by calling external API
  @{
    name        = "update_seat"
    parameters  = @{
      properties           = @{
        confirmation_number = @{
          description = "The confirmation number for the flight."
          title       = "Confirmation Number"
          type        = "string"
        }
        new_seat            = @{
          description = "The new seat to update to."
          title       = "New Seat"
          type        = "string"
        }
      }
      required             = @("confirmation_number", "new_seat")
      title                = "update_seat_args"
      type                 = "object"
      additionalProperties = $false
    }
    strict      = $true
    type        = "function"
    description = "Update the seat for a given confirmation number."
  },
  # fake function, to switch back to triage agent
  @{
    name        = "transfer_to_triage_agent"
    parameters  = @{
      additionalProperties = $false
      type                 = "object"
      properties           = @{}
      required             = @()
    }
    strict      = $true
    type        = "function"
    description = "Handoff to the Triage Agent agent to handle the request. A triage agent that can delegate a customer's request to the appropriate agent."
  }
)

$faqAgentInstructions = @"
$baseInstructions

You are an FAQ agent. If you are speaking to a customer, you probably were transferred to from the triage agent.

Use the following routine to support the customer.

# Routine

1. Identify the last question asked by the customer.
2. Use the faq lookup tool to answer the question. Do not rely on your own knowledge.
3. If you cannot answer the question, transfer back to the triage agent.
"@

$faqAgentTools = @(
  # real function, that is supposed to update seat by calling external API
  @{
    name        = "faq_lookup_tool"
    parameters  = @{
      properties           = @{
        question = @{
          title = "Question"
          type  = "string"
        }
      }
      required             = @("question")
      title                = "faq_lookup_tool_args"
      type                 = "object"
      additionalProperties = $false
    }
    strict      = $true
    type        = "function"
    description = "Lookup frequently asked questions."
  },
  # fake function, to switch back to triage agent
  @{
    name        = "transfer_to_triage_agent"
    parameters  = @{
      additionalProperties = $false
      type                 = "object"
      properties           = @{}
      required             = @()
    }
    strict      = $true
    type        = "function"
    description = "Handoff to the Triage Agent agent to handle the request. A triage agent that can delegate a customer's request to the appropriate agent."
  }
)

# ---------------------------------

$currentInstructions = $triageAgentInstructions
$currentTools = $triageAgentTools
$conversation = @()

# ---------------------------------

$conversation += @{
  role    = "user"
  content = "lets book a seat"
}

$res = Invoke-RestMethod -Method Post -Uri "https://api.openai.com/v1/responses" -Headers $headers -ContentType "application/json; charset=utf-8" -Body (ConvertTo-Json -Depth 100 -InputObject @{
    input        = $conversation
    model        = "gpt-4o"
    include      = @()
    instructions = $currentInstructions
    stream       = $false
    tools        = $currentTools
  })
  
$conversation += $res.output  
$res.output | ConvertTo-Json -Depth 100
<#
{
  "type": "function_call",
  "id": "fc_67dd5c1dca848192a9fb5db5b763c9c10bcefeefee80cd8b",
  "call_id": "call_Pg1xsRsU5f97E44Bvu8079jW",
  "name": "transfer_to_seat_booking_agent",
  "arguments": "{}",
  "status": "completed"
}
#>

# because switch is a face function, append result as well
$conversation += @{
  call_id = $res.output.call_id
  output  = "{`"assistant`": `"Seat Booking Agent`"}"
  type    = "function_call_output"
}
# and switch agent
$currentInstructions = $seatBookingAgentInstructions
$currentTools = $seatBookingAgentTools

# and make new request with corresponding context
$res = Invoke-RestMethod -Method Post -Uri "https://api.openai.com/v1/responses" -Headers $headers -ContentType "application/json; charset=utf-8" -Body (ConvertTo-Json -Depth 100 -InputObject @{
    input        = $conversation
    model        = "gpt-4o"
    include      = @()
    instructions = $currentInstructions
    stream       = $false
    tools        = $currentTools
  })

$conversation += $res.output  
$res.output | ConvertTo-Json -Depth 100
<#
{
  "type": "message",
  "id": "msg_67dd5c2e38b08192a09a0901b6c7e89b0bcefeefee80cd8b",
  "status": "completed",
  "role": "assistant",
  "content": [
    {
      "type": "output_text",
      "text": "I can help you with that! Could you please provide your confirmation number?",
      "annotations": []
    }
  ]
}
#>

# pass user response
$conversation += @{
  role    = "user"
  content = "123"
}

$res = Invoke-RestMethod -Method Post -Uri "https://api.openai.com/v1/responses" -Headers $headers -ContentType "application/json; charset=utf-8" -Body (ConvertTo-Json -Depth 100 -InputObject @{
    input        = $conversation
    model        = "gpt-4o"
    include      = @()
    instructions = $currentInstructions
    stream       = $false
    tools        = $currentTools
  })

$conversation += $res.output  
$res.output | ConvertTo-Json -Depth 100
<#
{
  "type": "message",
  "id": "msg_67dd5c43402c81928454a86c0c7ff3190bcefeefee80cd8b",
  "status": "completed",
  "role": "assistant",
  "content": [
    {
      "type": "output_text",
      "text": "Great, what seat number would you like to book?",
      "annotations": []
    }
  ]
}
#>

# pass user response
$conversation += @{
  role    = "user"
  content = "2B"
}

$res = Invoke-RestMethod -Method Post -Uri "https://api.openai.com/v1/responses" -Headers $headers -ContentType "application/json; charset=utf-8" -Body (ConvertTo-Json -Depth 100 -InputObject @{
    input        = $conversation
    model        = "gpt-4o"
    include      = @()
    instructions = $currentInstructions
    stream       = $false
    tools        = $currentTools
  })

$conversation += $res.output  
$res.output | ConvertTo-Json -Depth 100
<#
{
  "type": "function_call",
  "id": "fc_67dd5c55f3588192af24286b4363433d0bcefeefee80cd8b",
  "call_id": "call_bJ8UmdANmEUdQArUvSHPdAvE",
  "name": "update_seat",
  "arguments": "{\"confirmation_number\":\"123\",\"new_seat\":\"2B\"}",
  "status": "completed"
}
#>

# pretend we have called external API to update seat and add response
$conversation += @{
  call_id = $res.output.call_id
  output  = "Updated seat to 2B for confirmation number 123"
  type    = "function_call_output"
}

$res = Invoke-RestMethod -Method Post -Uri "https://api.openai.com/v1/responses" -Headers $headers -ContentType "application/json; charset=utf-8" -Body (ConvertTo-Json -Depth 100 -InputObject @{
    input        = $conversation
    model        = "gpt-4o"
    include      = @()
    instructions = $currentInstructions
    stream       = $false
    tools        = $currentTools
  })

$conversation += $res.output  
$res.output | ConvertTo-Json -Depth 100
<#
{
  "type": "message",
  "id": "msg_67dd5c7ed324819285f0b8da049a1a970bcefeefee80cd8b",
  "status": "completed",
  "role": "assistant",
  "content": [
    {
      "type": "output_text",
      "text": "Your seat has been successfully updated to 2B. Safe travels! If you have any more questions, feel free to ask.",
      "annotations": []
    }
  ]
}
#>

# here, our flow is completed


# ---------------------------------
# Starting sencond request, asking about allowed bags

$conversation += @{
  role    = "user"
  content = "how many bags can i bring?"
}

# note: we are still in the context of seat booking agent, so we will make a request with the same context
$res = Invoke-RestMethod -Method Post -Uri "https://api.openai.com/v1/responses" -Headers $headers -ContentType "application/json; charset=utf-8" -Body (ConvertTo-Json -Depth 100 -InputObject @{
    input        = $conversation
    model        = "gpt-4o"
    include      = @()
    instructions = $currentInstructions
    stream       = $false
    tools        = $currentTools
  })

$conversation += $res.output  
$res.output | ConvertTo-Json -Depth 100
<#
{
  "type": "function_call",
  "id": "fc_67dd5ccd27448192b2cf2bf6127001560bcefeefee80cd8b",
  "call_id": "call_1D61UAqL2RsEUGop9lrgo3X5",
  "name": "transfer_to_triage_agent",
  "arguments": "{}",
  "status": "completed"
}
#>

# note: because this request can not be handled by seat booking agent, and there is `transfer_to_triage_agent` model chooses to call it
# transfer_to_triage_agent is an fake function, that will switch to triage agent
# so add fake function call results to conversation as if we switched agent
$conversation += @{
  call_id = $res.output.call_id
  output  = "{`"assistant`": `"Triage Agent`"}"
  type    = "function_call_output"
}
# and switch agent
$currentInstructions = $triageAgentInstructions
$currentTools = $triageAgentTools

$res = Invoke-RestMethod -Method Post -Uri "https://api.openai.com/v1/responses" -Headers $headers -ContentType "application/json; charset=utf-8" -Body (ConvertTo-Json -Depth 100 -InputObject @{
    input        = $conversation
    model        = "gpt-4o"
    include      = @()
    instructions = $currentInstructions
    stream       = $false
    tools        = $currentTools
  })

$conversation += $res.output  
$res.output | ConvertTo-Json -Depth 100
<#
{
  "type": "function_call",
  "id": "fc_67dd5d286c808192b2ca7304a6a51ae70bcefeefee80cd8b",
  "call_id": "call_Ak9B4malozIwVSlyzTChMHZo",
  "name": "transfer_to_faq_agent",
  "arguments": "{}",
  "status": "completed"
}
#>

# note: triage agent desided to switch us to faq agent
# add fake function call response as if we have switched agent
$conversation += @{
  call_id = $res.output.call_id
  output  = "{`"assistant`": `"FAQ Agent`"}"
  type    = "function_call_output"
}
# and switch agent
$currentInstructions = $faqAgentInstructions
$currentTools = $faqAgentTools

$res = Invoke-RestMethod -Method Post -Uri "https://api.openai.com/v1/responses" -Headers $headers -ContentType "application/json; charset=utf-8" -Body (ConvertTo-Json -Depth 100 -InputObject @{
    input        = $conversation
    model        = "gpt-4o"
    include      = @()
    instructions = $currentInstructions
    stream       = $false
    tools        = $currentTools
  })

$conversation += $res.output  
$res.output | ConvertTo-Json -Depth 100
<#
{
  "type": "function_call",
  "id": "fc_67dd5d63537481928089fbfa8aca47da0bcefeefee80cd8b",
  "call_id": "call_zuYpDRDCzKf4NC0Fb3khSIdv",
  "name": "faq_lookup_tool",
  "arguments": "{\"question\":\"how many bags can i bring\"}",
  "status": "completed"
}
#>

# note: because of tools, our model recognized call to faq lookup and tries to cal that function

# after calling faq lookup, we will receive response with answer which we pass back to the model
# append function call result to conversation
$conversation += @{
  call_id = $res.output.call_id
  output  = "You are allowed to bring one bag on the plane, which must be under 50 pounds and 22 inches x 14 inches x 9 inches in size. If you have more questions, feel free to ask!"
  type    = "function_call_output"
}

$res = Invoke-RestMethod -Method Post -Uri "https://api.openai.com/v1/responses" -Headers $headers -ContentType "application/json; charset=utf-8" -Body (ConvertTo-Json -Depth 100 -InputObject @{
    input        = $conversation
    model        = "gpt-4o"
    include      = @()
    instructions = $currentInstructions
    stream       = $false
    tools        = $currentTools
  })

$conversation += $res.output  
$res.output | ConvertTo-Json -Depth 100
<#
{
  "type": "message",
  "id": "msg_67dd5dc85a908192bfe87df417a897430bcefeefee80cd8b",
  "status": "completed",
  "role": "assistant",
  "content": [
    {
      "type": "output_text",
      "text": "You are allowed to bring one bag on the plane, which must be under 50 pounds and 22 inches x 14 inches x 9 inches in size. If you have more questions, feel free to ask!",
      "annotations": []
    }
  ]
}
#>

# note: having the response from function call, model uses it to respond to user

and the same but with everything inlined

Interactive sample

of course we do want something interactive, so here is combined script

$headers = @{ Authorization = "Bearer $env:OPENAI_API_KEY" }

$baseInstructions = @"
# System context

You are part of a multi-agent system called the Agents SDK, designed to make agent coordination and execution easy. 

Agents uses two primary abstraction: **Agents** and **Handoffs**.

An agent encompasses instructions and tools and can hand off a conversation to another agent when appropriate.

Handoffs are achieved by calling a handoff function, generally named `transfer_to_<agent_name>`.

Transfers between agents are handled seamlessly in the background; do not mention or draw attention to these transfers in your conversation with the user.
"@

$triageAgentInstructions = @"
$baseInstructions

You are a helpful triaging agent. You can use your tools to delegate questions to other appropriate agents.
"@

# note: tools here, are kind of fake functions to switch between available agents
$triageAgentTools = @(
  @{
    name        = "transfer_to_faq_agent"
    parameters  = @{
      additionalProperties = $false
      type                 = "object"
      properties           = @{}
      required             = @()
    }
    strict      = $true
    type        = "function"
    description = "Handoff to the FAQ Agent agent to handle the request. A helpful agent that can answer questions about the airline."
  }
  @{
    name        = "transfer_to_seat_booking_agent"
    parameters  = @{
      additionalProperties = $false
      type                 = "object"
      properties           = @{}
      required             = @()
    }
    strict      = $true
    type        = "function"
    description = "Handoff to the Seat Booking Agent agent to handle the request. A helpful agent that can update a seat on a flight."
  }
)

$seatBookingAgentInstructions = @"
$baseInstructions

You are a seat booking agent. If you are speaking to a customer, you probably were transferred to from the triage agent.

Use the following routine to support the customer.

# Routine

1. Ask for their confirmation number.
2. Ask the customer what their desired seat number is.
3. Use the update seat tool to update the seat on the flight.

If the customer asks a question that is not related to the routine, transfer back to the triage agent. """,
"@

$seatBookingAgentTools = @(
  # real function, that is supposed to update seat by calling external API
  @{
    name        = "update_seat"
    parameters  = @{
      properties           = @{
        confirmation_number = @{
          description = "The confirmation number for the flight."
          title       = "Confirmation Number"
          type        = "string"
        }
        new_seat            = @{
          description = "The new seat to update to."
          title       = "New Seat"
          type        = "string"
        }
      }
      required             = @("confirmation_number", "new_seat")
      title                = "update_seat_args"
      type                 = "object"
      additionalProperties = $false
    }
    strict      = $true
    type        = "function"
    description = "Update the seat for a given confirmation number."
  },
  # fake function, to switch back to triage agent
  @{
    name        = "transfer_to_triage_agent"
    parameters  = @{
      additionalProperties = $false
      type                 = "object"
      properties           = @{}
      required             = @()
    }
    strict      = $true
    type        = "function"
    description = "Handoff to the Triage Agent agent to handle the request. A triage agent that can delegate a customer's request to the appropriate agent."
  }
)

$faqAgentInstructions = @"
$baseInstructions

You are an FAQ agent. If you are speaking to a customer, you probably were transferred to from the triage agent.

Use the following routine to support the customer.

# Routine

1. Identify the last question asked by the customer.
2. Use the faq lookup tool to answer the question. Do not rely on your own knowledge.
3. If you cannot answer the question, transfer back to the triage agent.
"@

$faqAgentTools = @(
  # real function, that is supposed to update seat by calling external API
  @{
    name        = "faq_lookup_tool"
    parameters  = @{
      properties           = @{
        question = @{
          title = "Question"
          type  = "string"
        }
      }
      required             = @("question")
      title                = "faq_lookup_tool_args"
      type                 = "object"
      additionalProperties = $false
    }
    strict      = $true
    type        = "function"
    description = "Lookup frequently asked questions."
  },
  # fake function, to switch back to triage agent
  @{
    name        = "transfer_to_triage_agent"
    parameters  = @{
      additionalProperties = $false
      type                 = "object"
      properties           = @{}
      required             = @()
    }
    strict      = $true
    type        = "function"
    description = "Handoff to the Triage Agent agent to handle the request. A triage agent that can delegate a customer's request to the appropriate agent."
  }
)

# ---------------------------------

$currentInstructions = $triageAgentInstructions
$currentTools = $triageAgentTools
$conversation = @()
$prompt = $true

while ($true) {
  if ($prompt) {
    $message = Read-Host "Enter your message"
    if (-not $message -or $message.ToLower() -eq "exit" -or $message.ToLower() -eq "quit") {
      Write-Host "Bye!"
      break
    }
    $conversation += @{
      role    = "user"
      content = $message
    }

    $res = Invoke-RestMethod -Method Post -Uri "https://api.openai.com/v1/responses" -Headers $headers -ContentType "application/json; charset=utf-8" -Body (ConvertTo-Json -Depth 100 -InputObject @{
        input        = $conversation
        model        = "gpt-4o"
        include      = @()
        instructions = $currentInstructions
        stream       = $false
        tools        = $currentTools
      })
  
    $conversation += $res.output
    $prompt = $false
  }
  
  if ($res.output.type -eq "message") {
    Write-Host $res.output.content[0].text
    $prompt = $true
  }
  elseif ($res.output.type -eq "function_call" -and $res.output.name -eq "transfer_to_seat_booking_agent") {
    $conversation += @{
      call_id = $res.output.call_id
      output  = "{`"assistant`": `"Seat Booking Agent`"}"
      type    = "function_call_output"
    }
    $currentInstructions = $seatBookingAgentInstructions
    $currentTools = $seatBookingAgentTools
    $res = Invoke-RestMethod -Method Post -Uri "https://api.openai.com/v1/responses" -Headers $headers -ContentType "application/json; charset=utf-8" -Body (ConvertTo-Json -Depth 100 -InputObject @{
        input        = $conversation
        model        = "gpt-4o"
        include      = @()
        instructions = $currentInstructions
        stream       = $false
        tools        = $currentTools
      })
  
    $conversation += $res.output
  }
  elseif ($res.output.type -eq "function_call" -and $res.output.name -eq "transfer_to_faq_agent") {
    $conversation += @{
      call_id = $res.output.call_id
      output  = "{`"assistant`": `"FAQ Agent`"}"
      type    = "function_call_output"
    }
    $currentInstructions = $faqAgentInstructions
    $currentTools = $faqAgentTools
    $res = Invoke-RestMethod -Method Post -Uri "https://api.openai.com/v1/responses" -Headers $headers -ContentType "application/json; charset=utf-8" -Body (ConvertTo-Json -Depth 100 -InputObject @{
        input        = $conversation
        model        = "gpt-4o"
        include      = @()
        instructions = $currentInstructions
        stream       = $false
        tools        = $currentTools
      })

    $conversation += $res.output
  }
  elseif ($res.output.type -eq "function_call" -and $res.output.name -eq "transfer_to_triage_agent") {
    $conversation += @{
      call_id = $res.output.call_id
      output  = "{`"assistant`": `"Triage Agent`"}"
      type    = "function_call_output"
    }
    $currentInstructions = $triageAgentInstructions
    $currentTools = $triageAgentTools
    $res = Invoke-RestMethod -Method Post -Uri "https://api.openai.com/v1/responses" -Headers $headers -ContentType "application/json; charset=utf-8" -Body (ConvertTo-Json -Depth 100 -InputObject @{
        input        = $conversation
        model        = "gpt-4o"
        include      = @()
        instructions = $currentInstructions
        stream       = $false
        tools        = $currentTools
      })

    $conversation += $res.output
  }
  elseif ($res.output.type -eq "function_call" -and $res.output.name -eq "update_seat") {
    # pretend we have called external API to update seat and add response
    $conversation += @{
      call_id = $res.output.call_id
      output  = "Updated seat to $($res.output.arguments.new_seat) for confirmation number $($res.output.arguments.confirmation_number)"
      type    = "function_call_output"
    }
    $res = Invoke-RestMethod -Method Post -Uri "https://api.openai.com/v1/responses" -Headers $headers -ContentType "application/json; charset=utf-8" -Body (ConvertTo-Json -Depth 100 -InputObject @{
        input        = $conversation
        model        = "gpt-4o"
        include      = @()
        instructions = $currentInstructions
        stream       = $false
        tools        = $currentTools
      })

    $conversation += $res.output
  }
  elseif ($res.output.type -eq "function_call" -and $res.output.name -eq "faq_lookup_tool") {
    # pretend we have called external API to update seat and add response
    $question = $res.output.arguments | ConvertFrom-Json | Select-Object -ExpandProperty question
    $answer = "I'm sorry, I don't know the answer to that question."
    if ($question.ToLower().Contains("bag")) {
      $answer = "You are allowed to bring one bag on the plane. It must be under 50 pounds and 22 inches x 14 inches x 9 inches."
    }
    elseif ($question.ToLower().Contains("seats") -or $question.ToLower().Contains("plane")) {
      $answer = "There are 120 seats on the plane. There are 22 business class seats and 98 economy seats. Exit rows are rows 4 and 16. Rows 5-8 are Economy Plus, with extra legroom. "
    }
    elseif ($question.ToLower().Contains("wifi") -or $question.ToLower().Contains("wi-fi") -or $question.ToLower().Contains("internet")) {
      $answer = "We have free wifi on the plane, join Airline-Wifi"
    }
    $conversation += @{
      call_id = $res.output.call_id
      output  = $answer
      type    = "function_call_output"
    }
    $res = Invoke-RestMethod -Method Post -Uri "https://api.openai.com/v1/responses" -Headers $headers -ContentType "application/json; charset=utf-8" -Body (ConvertTo-Json -Depth 100 -InputObject @{
        input        = $conversation
        model        = "gpt-4o"
        include      = @()
        instructions = $currentInstructions
        stream       = $false
        tools        = $currentTools
      })

    $conversation += $res.output
  }
}

and its transcript:

Enter your message: lets book a seat
Could you please provide your confirmation number?
Enter your message: 123
What seat number would you like to book?
Enter your message: 2B
Your seat has been successfully updated to 2B. Safe travels! If you need further assistance, feel free to ask.
Enter your message: how much bags can i bring?
You are allowed to bring one bag on the plane, and it must be under 50 pounds with dimensions not exceeding 22 inches x 14 inches x 9 inches.

So, key idea here is that we may have many different agents definted, with specific instructions and tools and can reuse/combine them and at the top level we will have this triage agent to choose correct agent to pass request to