PowerShell Requires Chilkat v11.4.0+
PowerShell
Streaming AI with Manual AI Tool Function Calling
See more AI Examples
Demonstrates how to get AI responses in streaming mode, including manual tool function calls.Chilkat PowerShell Downloads
Add-Type -Path "C:\chilkat\ChilkatDotNet47-x64\ChilkatDotNet47.dll"
$success = $false
# Create the following JSON to define tool functions available for the AI to use.
# Note: You'll use the following JSON format regardless of the AI provider, whether
# it be ChatGPT, Gemini, Claude, Grok, etc. Chilkat automatically converts to the required
# format needed for a given AI provider.
# In this example, the application is providing a single function the AI may choose to call.
# {
# "tools": [
# {
# "name": "get_horoscope",
# "description": "Get today's horoscope for an astrological sign.",
# "parameters": {
# "properties": {
# "sign": {
# "type": "string",
# "description": "An astrological sign like Taurus or Aquarius"
# }
# }
# }
# }
# ]
# }
$jsonTools = New-Object Chilkat.JsonObject
$toolIdx = 0
$jsonTools.I = $toolIdx
$jsonTools.UpdateString("tools[i].name","get_horoscope")
$jsonTools.UpdateString("tools[i].description","Get today's horoscope for an astrological sign.")
$jsonTools.UpdateString("tools[i].parameters.properties.sign.type","string")
$jsonTools.UpdateString("tools[i].parameters.properties.sign.description","An astrological sign like Taurus or Aquarius")
# More tools can be added as desired..
$jsonTools.EmitCompact = $false
$($jsonTools.Emit())
$ai = New-Object Chilkat.Ai
# Register the tools that will be made available to the AI.
$ai.RegisterManualTools($jsonTools)
# The provider can be "openai", "google", "claude", "grok", "mistral", "custom", etc.
$ai.Provider = "openai"
# Use your provider's API key.
$ai.ApiKey = "MY_API_KEY"
# Choose a model.
$ai.Model = "gpt-5.6-luna"
# Tool function calling must always occur within a conversation.
$conversation_name = "convo_astrology"
$sysMessage = "You are a helpful astrologer"
$devMessage = "Respond only with markdown."
$ai.NewConvo($conversation_name,$sysMessage,$devMessage)
# Provide inputs
$ai.InputAddText("What is my horoscope? I am an Aquarius.")
# Get the response in streaming mode.
$ai.Streaming = $true
# In streaming mode, if we receive an AI event that is a request for tool use,
# we'll need to make the call to the JavaScript and then continue with a followup Ask,
# until the final response is received.
$sbEventName = New-Object Chilkat.StringBuilder
$sbDelta = New-Object Chilkat.StringBuilder
$sbFullResponse = New-Object Chilkat.StringBuilder
# When PollAi returns with an event, it's highly unlikely the
# call to NextAiEvent does not immediately return. Setting a max
# timeout is just a precaution..
$maxWaitMs = 5000
$jsonFn = New-Object Chilkat.JsonObject
$finished = $false
$numAsks = 0
# Set a max # of followup Asks to prevent any unexpected infinite looping.
while (!$finished -and ($numAsks -lt 10)) {
# Send the request to the AI model.
$success = $ai.Ask("text")
if ($success -eq $false) {
$($ai.LastErrorText)
exit
}
$madeFunctionCalls = $false
$streamingDone = $false
while (!$streamingDone) {
$result = $ai.PollAi($false)
if ($result -lt 0) {
$($ai.LastErrorText)
$("Failed.")
exit
}
if ($result -gt 0) {
# We have an event..
$success = $ai.NextAiEvent($maxWaitMs,$sbEventName,$sbDelta)
if ($success -eq $false) {
$($ai.LastErrorText)
exit
}
# Is this an event where the AI is requesting a function call?
if ($sbEventName.ContentsEqual("function_call",$true)) {
$jsonFn.LoadSb($sbDelta)
# Note: Chilkat will convert responses from all AI providers to this format:
# {
# "function_call": [
# {
# "name": "get_horoscope",
# "call_id": "call_RYmeysYQFocFc7Z2ofkv61dW",
# "arguments": "{\"sign\":\"Aquarius\"}",
# "args": {
# "sign": "Aquarius"
# }
# }
# ]
# }
$numFnCalls = $jsonFn.SizeOfArray("function_call")
$fn_idx = 0
while (($fn_idx -lt $numFnCalls)) {
$jsonFn.I = $fn_idx
$sbFnName = New-Object Chilkat.StringBuilder
$jsonFn.StringOfSb("function_call[i].name",$sbFnName)
$callId = $jsonFn.StringOf("function_call[i].call_id")
if ($sbFnName.ContentsEqual("get_horoscope",$true) -eq $true) {
# The get_horoscope function (as defined above) has one argument named "sign".
$zodiac_sign = $jsonFn.StringOf("function_call[i].args.sign")
$("zodiac_sign = " + $zodiac_sign)
# Insert application code here to call your app's get_horoscope function, passing the zodiac_sign to it..
# For this example, we'll pretend the app's get_horoscope function returned the following:
$applicationFnCallResult = "Aquarius: Next Tuesday you will befriend a baby otter."
# Provide the tool call result as an input for the followup Ask.
$ai.InputAddFnResult($callId,$applicationFnCallResult)
$madeFunctionCalls = $true
}
# Your application would add code to check for and handle each possible function call.
$fn_idx = $fn_idx + 1
}
}
else {
if (!$sbEventName.ContentsEqual("empty",$true)) {
$sbFullResponse.AppendSb($sbDelta)
if ($sbEventName.ContentsEqual("null_terminator",$true)) {
$streamingDone = $true
}
}
}
}
else {
# No event arrived, so wait a short time rather than spin in a loop..
$ai.SleepMs(100)
}
}
if (!$madeFunctionCalls) {
$finished = $true
}
$numAsks = $numAsks + 1
}
$("Full Response:")
$($sbFullResponse.GetAsString())