Completions V1 is Deprecated: This tutorial now uses the V2 API. If you’re using V1 (
/ai/v1/chat/completions), please migrate to V2 for better performance and intelligent routing.View V2 Guide | Migration StepsPrerequisites
Before starting, ensure you have:- A Gloo AI Studio account
- Your Client ID and Client Secret from the API Credentials page
- Authentication setup - Complete the Authentication Tutorial first
The Completions API with tool use requires Bearer token authentication. If you haven’t set up authentication yet, follow the Authentication Tutorial to learn how to exchange your credentials for access tokens and manage token expiration.
Step 1: Define Your Tool Schema
The first step is to define a function schema that describes the structured output you want. This tells the AI exactly what format to return:{
"tools": [
{
"type": "function",
"function": {
"name": "create_growth_plan",
"description": "Creates a structured personal growth plan with a title and a series of actionable steps.",
"parameters": {
"type": "object",
"properties": {
"goal_title": {
"type": "string",
"description": "A concise, encouraging title for the user's goal."
},
"steps": {
"type": "array",
"description": "A list of concrete steps the user should take.",
"items": {
"type": "object",
"properties": {
"step_number": { "type": "integer" },
"action": {
"type": "string",
"description": "The specific, actionable task for this step."
},
"timeline": {
"type": "string",
"description": "A suggested timeframe for this step (e.g., 'Week 1-2')."
}
},
"required": ["step_number", "action", "timeline"]
}
}
},
"required": ["goal_title", "steps"]
}
}
}
]
}
Step 2: Make the API Call
Now make the API request with the tool definition and settool_choice: "required" to force the AI to use your tool:
{
"auto_routing": true,
"messages": [
{
"role": "user",
"content": "I want to grow in my faith."
}
],
"tools": [
// ... The tool definition from Step 1 goes here ...
],
"tool_choice": "required"
}
Auto-Routing: Setting
auto_routing: true lets Gloo AI automatically select the optimal model for your tool use request. This is the recommended V2 approach. You can also specify a direct model like "model": "gloo-anthropic-claude-sonnet-4.5" if you need explicit control.Example Response
The API will return structured data in thetool_calls array:
{
"id": "chatcmpl-ecc49558",
"choices": [
{
"finish_reason": "tool_calls",
"index": 0,
"message": {
"content": null,
"role": "assistant",
"tool_calls": [
{
"id": "tooluse_c0lmjtOJSlOYQZPBsp4biQ",
"function": {
"arguments": "{\"goal_title\": \"Growing Deeper in Faith\", \"steps\": [{\"step_number\": 1, \"action\": \"Establish a consistent daily quiet time with God through prayer and Bible reading, starting with 10-15 minutes each morning\", \"timeline\": \"Week 1-2\"}, {\"step_number\": 2, \"action\": \"Choose a Bible reading plan or devotional to provide structure for your study time\", \"timeline\": \"Week 2-3\"}, {\"step_number\": 3, \"action\": \"Find a local church community or small group where you can worship, learn, and build relationships with other believers\", \"timeline\": \"Week 3-4\"}, {\"step_number\": 4, \"action\": \"Begin journaling your prayers, thoughts, and insights from Scripture to track your spiritual growth\", \"timeline\": \"Week 4-5\"}, {\"step_number\": 5, \"action\": \"Look for opportunities to serve others in your community or church as a way to live out your faith\", \"timeline\": \"Month 2\"}, {\"step_number\": 6, \"action\": \"Seek out a mentor or accountability partner who can encourage you and help you grow in your walk with God\", \"timeline\": \"Month 2-3\"}]}",
"name": "create_growth_plan"
},
"type": "function"
}
]
}
}
],
"created": 1755118870,
"model": "gloo-anthropic-claude-sonnet-4.5",
"object": "chat.completion",
"usage": {
"completion_tokens": 391,
"prompt_tokens": 1631,
"total_tokens": 2022
}
}
arguments field contains a JSON string that matches your tool schema perfectly!
Complete Examples
The following examples combine token retrieval, expiration checking, making the API call with tool use, and parsing the structured response into a complete, runnable script for each language. You’ll want to first set up your environment variables in either an.env file:
GLOO_CLIENT_ID=YOUR_CLIENT_ID
GLOO_CLIENT_SECRET=YOUR_CLIENT_SECRET
export GLOO_CLIENT_ID="your_actual_client_id_here"
export GLOO_CLIENT_SECRET="your_actual_client_secret_here"
import requests
import time
import json
import os
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
# --- Configuration ---
# It's recommended to load credentials from environment variables
CLIENT_ID = os.getenv("GLOO_CLIENT_ID", "YOUR_CLIENT_ID")
CLIENT_SECRET = os.getenv("GLOO_CLIENT_SECRET", "YOUR_CLIENT_SECRET")
TOKEN_URL = "https://platform.ai.gloo.com/oauth2/token"
API_URL = "https://platform.ai.gloo.com/ai/v2/chat/completions"
# --- State Management ---
# In a real application, you would persist this token information
access_token_info = {}
def get_access_token():
"""Retrieves a new access token."""
headers = {"Content-Type": "application/x-www-form-urlencoded"}
data = {"grant_type": "client_credentials", "scope": "api/access"}
response = requests.post(TOKEN_URL, headers=headers, data=data, auth=(CLIENT_ID, CLIENT_SECRET))
response.raise_for_status()
token_data = response.json()
token_data['expires_at'] = int(time.time()) + token_data['expires_in']
return token_data
def is_token_expired(token_info):
"""Checks if the token is expired or close to expiring."""
if not token_info or 'expires_at' not in token_info:
return True
return time.time() > (token_info['expires_at'] - 60)
def create_goal_setting_request(user_goal):
"""Creates a goal-setting request with tool use."""
global access_token_info
if is_token_expired(access_token_info):
print("Token is expired or missing. Fetching a new one...")
access_token_info = get_access_token()
headers = {
"Authorization": f"Bearer {access_token_info['access_token']}",
"Content-Type": "application/json"
}
payload = {
"auto_routing": True,
"messages": [{"role": "user", "content": user_goal}],
"tools": [
{
"type": "function",
"function": {
"name": "create_growth_plan",
"description": "Creates a structured personal growth plan with a title and a series of actionable steps.",
"parameters": {
"type": "object",
"properties": {
"goal_title": {
"type": "string",
"description": "A concise, encouraging title for the user's goal."
},
"steps": {
"type": "array",
"description": "A list of concrete steps the user should take.",
"items": {
"type": "object",
"properties": {
"step_number": {"type": "integer"},
"action": {
"type": "string",
"description": "The specific, actionable task for this step."
},
"timeline": {
"type": "string",
"description": "A suggested timeframe for this step (e.g., 'Week 1-2')."
}
},
"required": ["step_number", "action", "timeline"]
}
}
},
"required": ["goal_title", "steps"]
}
}
}
],
"tool_choice": "required"
}
response = requests.post(API_URL, headers=headers, json=payload)
response.raise_for_status()
return response.json()
def parse_growth_plan(api_response):
"""Parses the API response and extracts the structured growth plan."""
try:
tool_call = api_response['choices'][0]['message']['tool_calls'][0]
function_args = json.loads(tool_call['function']['arguments'])
return function_args
except (KeyError, IndexError, json.JSONDecodeError) as e:
raise ValueError(f"Failed to parse growth plan: {e}")
def display_growth_plan(growth_plan):
"""Displays the growth plan in a user-friendly format."""
print(f"\n🎯 {growth_plan['goal_title']}")
print("=" * (len(growth_plan['goal_title']) + 4))
for step in growth_plan['steps']:
print(f"\n{step['step_number']}. {step['action']}")
print(f" ⏰ Timeline: {step['timeline']}")
# --- Main Execution ---
if __name__ == "__main__":
try:
user_goal = "I want to grow in my faith."
print(f"Creating growth plan for: '{user_goal}'")
# Make API call with tool use
response = create_goal_setting_request(user_goal)
# Parse the structured response
growth_plan = parse_growth_plan(response)
# Display the results
display_growth_plan(growth_plan)
# Also show raw JSON for developers
print(f"\n📊 Raw JSON output:")
print(json.dumps(growth_plan, indent=2))
except requests.exceptions.HTTPError as err:
print(f"An HTTP error occurred: {err}")
except Exception as err:
print(f"An error occurred: {err}")
// Load environment variables from .env file
require('dotenv').config();
const axios = require('axios');
// --- Configuration ---
const CLIENT_ID = process.env.GLOO_CLIENT_ID || "YOUR_CLIENT_ID";
const CLIENT_SECRET = process.env.GLOO_CLIENT_SECRET || "YOUR_CLIENT_SECRET";
const TOKEN_URL = "https://platform.ai.gloo.com/oauth2/token";
const API_URL = "https://platform.ai.gloo.com/ai/v2/chat/completions";
// --- State Management ---
let tokenInfo = {};
async function getAccessToken() {
const body = 'grant_type=client_credentials&scope=api/access';
const response = await axios.post(TOKEN_URL, body, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
auth: { username: CLIENT_ID, password: CLIENT_SECRET }
});
const tokenData = response.data;
tokenData.expires_at = Math.floor(Date.now() / 1000) + tokenData.expires_in;
return tokenData;
}
function isTokenExpired(token) {
if (!token || !token.expires_at) return true;
return (Date.now() / 1000) > (token.expires_at - 60);
}
async function createGoalSettingRequest(userGoal) {
if (isTokenExpired(tokenInfo)) {
console.log("Token is expired or missing. Fetching a new one...");
tokenInfo = await getAccessToken();
}
const payload = {
auto_routing: true,
messages: [{ role: "user", content: userGoal }],
tools: [
{
type: "function",
function: {
name: "create_growth_plan",
description: "Creates a structured personal growth plan with a title and a series of actionable steps.",
parameters: {
type: "object",
properties: {
goal_title: {
type: "string",
description: "A concise, encouraging title for the user's goal."
},
steps: {
type: "array",
description: "A list of concrete steps the user should take.",
items: {
type: "object",
properties: {
step_number: { type: "integer" },
action: {
type: "string",
description: "The specific, actionable task for this step."
},
timeline: {
type: "string",
description: "A suggested timeframe for this step (e.g., 'Week 1-2')."
}
},
required: ["step_number", "action", "timeline"]
}
}
},
required: ["goal_title", "steps"]
}
}
}
],
tool_choice: "required"
};
const response = await axios.post(API_URL, payload, {
headers: {
'Authorization': `Bearer ${tokenInfo.access_token}`,
'Content-Type': 'application/json',
},
});
return response.data;
}
function parseGrowthPlan(apiResponse) {
try {
const toolCall = apiResponse.choices[0].message.tool_calls[0];
return JSON.parse(toolCall.function.arguments);
} catch (error) {
throw new Error(`Failed to parse growth plan: ${error.message}`);
}
}
function displayGrowthPlan(growthPlan) {
console.log(`\n🎯 ${growthPlan.goal_title}`);
console.log("=".repeat(growthPlan.goal_title.length + 4));
growthPlan.steps.forEach(step => {
console.log(`\n${step.step_number}. ${step.action}`);
console.log(` ⏰ Timeline: ${step.timeline}`);
});
}
// --- Main Execution ---
async function main() {
try {
const userGoal = "I want to grow in my faith.";
console.log(`Creating growth plan for: '${userGoal}'`);
// Make API call with tool use
const response = await createGoalSettingRequest(userGoal);
// Parse the structured response
const growthPlan = parseGrowthPlan(response);
// Display the results
displayGrowthPlan(growthPlan);
// Also show raw JSON for developers
console.log(`\n📊 Raw JSON output:`);
console.log(JSON.stringify(growthPlan, null, 2));
} catch (error) {
console.error("An error occurred:", error.response ? error.response.data : error.message);
}
}
main();
import axios from 'axios';
import * as dotenv from 'dotenv';
// Load environment variables from .env file
dotenv.config();
// Type definitions
interface TokenInfo {
access_token: string;
expires_in: number;
expires_at: number;
token_type: string;
}
interface GrowthStep {
step_number: number;
action: string;
timeline: string;
}
interface GrowthPlan {
goal_title: string;
steps: GrowthStep[];
}
interface ToolCall {
id: string;
type: string;
function: {
name: string;
arguments: string;
};
}
interface ApiResponse {
choices: Array<{
message: {
tool_calls: ToolCall[];
};
}>;
}
// --- Configuration ---
const CLIENT_ID = process.env.GLOO_CLIENT_ID || "YOUR_CLIENT_ID";
const CLIENT_SECRET = process.env.GLOO_CLIENT_SECRET || "YOUR_CLIENT_SECRET";
const TOKEN_URL = "https://platform.ai.gloo.com/oauth2/token";
const API_URL = "https://platform.ai.gloo.com/ai/v2/chat/completions";
// --- State Management ---
let tokenInfo: TokenInfo | null = null;
async function getAccessToken(): Promise<TokenInfo> {
const body = 'grant_type=client_credentials&scope=api/access';
const response = await axios.post<TokenInfo>(TOKEN_URL, body, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
auth: { username: CLIENT_ID, password: CLIENT_SECRET }
});
const tokenData = response.data;
(tokenData as any).expires_at = Math.floor(Date.now() / 1000) + tokenData.expires_in;
return tokenData;
}
function isTokenExpired(token: TokenInfo | null): boolean {
if (!token || !(token as any).expires_at) return true;
return (Date.now() / 1000) > ((token as any).expires_at - 60);
}
async function createGoalSettingRequest(userGoal: string): Promise<ApiResponse> {
if (isTokenExpired(tokenInfo)) {
console.log("Token is expired or missing. Fetching a new one...");
tokenInfo = await getAccessToken();
}
const payload = {
auto_routing: true,
messages: [{ role: "user", content: userGoal }],
tools: [
{
type: "function",
function: {
name: "create_growth_plan",
description: "Creates a structured personal growth plan with a title and a series of actionable steps.",
parameters: {
type: "object",
properties: {
goal_title: {
type: "string",
description: "A concise, encouraging title for the user's goal."
},
steps: {
type: "array",
description: "A list of concrete steps the user should take.",
items: {
type: "object",
properties: {
step_number: { type: "integer" },
action: {
type: "string",
description: "The specific, actionable task for this step."
},
timeline: {
type: "string",
description: "A suggested timeframe for this step (e.g., 'Week 1-2')."
}
},
required: ["step_number", "action", "timeline"]
}
}
},
required: ["goal_title", "steps"]
}
}
}
],
tool_choice: "required"
};
const response = await axios.post<ApiResponse>(API_URL, payload, {
headers: {
'Authorization': `Bearer ${tokenInfo!.access_token}`,
'Content-Type': 'application/json',
},
});
return response.data;
}
function parseGrowthPlan(apiResponse: ApiResponse): GrowthPlan {
try {
const toolCall = apiResponse.choices[0].message.tool_calls[0];
return JSON.parse(toolCall.function.arguments) as GrowthPlan;
} catch (error: any) {
throw new Error(`Failed to parse growth plan: ${error.message}`);
}
}
function displayGrowthPlan(growthPlan: GrowthPlan): void {
console.log(`\n🎯 ${growthPlan.goal_title}`);
console.log("=".repeat(growthPlan.goal_title.length + 4));
growthPlan.steps.forEach(step => {
console.log(`\n${step.step_number}. ${step.action}`);
console.log(` ⏰ Timeline: ${step.timeline}`);
});
}
// --- Main Execution ---
async function main(): Promise<void> {
try {
const userGoal = "I want to grow in my faith.";
console.log(`Creating growth plan for: '${userGoal}'`);
// Make API call with tool use
const response = await createGoalSettingRequest(userGoal);
// Parse the structured response
const growthPlan = parseGrowthPlan(response);
// Display the results
displayGrowthPlan(growthPlan);
// Also show raw JSON for developers
console.log(`\n📊 Raw JSON output:`);
console.log(JSON.stringify(growthPlan, null, 2));
} catch (error: any) {
console.error("An error occurred:", error.response ? error.response.data : error.message);
}
}
main();
<?php
require_once 'vendor/autoload.php';
// Load environment variables from .env file
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();
// --- Configuration ---
$CLIENT_ID = $_ENV['GLOO_CLIENT_ID'] ?? 'YOUR_CLIENT_ID';
$CLIENT_SECRET = $_ENV['GLOO_CLIENT_SECRET'] ?? 'YOUR_CLIENT_SECRET';
$TOKEN_URL = 'https://platform.ai.gloo.com/oauth2/token';
$API_URL = 'https://platform.ai.gloo.com/ai/v2/chat/completions';
// Validate credentials
if ($CLIENT_ID === 'YOUR_CLIENT_ID' || $CLIENT_SECRET === 'YOUR_CLIENT_SECRET' ||
empty($CLIENT_ID) || empty($CLIENT_SECRET)) {
echo "Error: GLOO_CLIENT_ID and GLOO_CLIENT_SECRET must be set\n";
echo "Either:\n";
echo "1. Create a .env file with your credentials:\n";
echo " GLOO_CLIENT_ID=your_client_id_here\n";
echo " GLOO_CLIENT_SECRET=your_client_secret_here\n";
echo "2. Export them as environment variables:\n";
echo " export GLOO_CLIENT_ID=\"your_client_id_here\"\n";
echo " export GLOO_CLIENT_SECRET=\"your_client_secret_here\"\n";
exit(1);
}
// --- State Management ---
$tokenInfo = [];
function getAccessToken($clientId, $clientSecret, $tokenUrl) {
$postData = 'grant_type=client_credentials&scope=api/access';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $tokenUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_USERPWD, $clientId . ':' . $clientSecret);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);
$result = curl_exec($ch);
if (curl_errno($ch)) throw new Exception(curl_error($ch));
curl_close($ch);
$tokenData = json_decode($result, true);
$tokenData['expires_at'] = time() + $tokenData['expires_in'];
return $tokenData;
}
function isTokenExpired($token) {
if (empty($token) || !isset($token['expires_at'])) return true;
return time() > ($token['expires_at'] - 60);
}
function createGoalSettingRequest($userGoal, $apiUrl, &$tokenInfo, $clientId, $clientSecret, $tokenUrl) {
if (isTokenExpired($tokenInfo)) {
echo "Token is expired or missing. Fetching a new one...\n";
$tokenInfo = getAccessToken($clientId, $clientSecret, $tokenUrl);
}
$tools = [
[
'type' => 'function',
'function' => [
'name' => 'create_growth_plan',
'description' => 'Creates a structured personal growth plan with a title and a series of actionable steps.',
'parameters' => [
'type' => 'object',
'properties' => [
'goal_title' => [
'type' => 'string',
'description' => 'A concise, encouraging title for the user\'s goal.'
],
'steps' => [
'type' => 'array',
'description' => 'A list of concrete steps the user should take.',
'items' => [
'type' => 'object',
'properties' => [
'step_number' => ['type' => 'integer'],
'action' => [
'type' => 'string',
'description' => 'The specific, actionable task for this step.'
],
'timeline' => [
'type' => 'string',
'description' => 'A suggested timeframe for this step (e.g., \'Week 1-2\').'
]
],
'required' => ['step_number', 'action', 'timeline']
]
]
],
'required' => ['goal_title', 'steps']
]
]
]
];
$payload = json_encode([
'auto_routing' => true,
'messages' => [['role' => 'user', 'content' => $userGoal]],
'tools' => $tools,
'tool_choice' => 'required'
]);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Bearer ' . $tokenInfo['access_token'],
]);
$result = curl_exec($ch);
if (curl_errno($ch)) throw new Exception(curl_error($ch));
curl_close($ch);
return json_decode($result, true);
}
function parseGrowthPlan($apiResponse) {
try {
$toolCall = $apiResponse['choices'][0]['message']['tool_calls'][0];
return json_decode($toolCall['function']['arguments'], true);
} catch (Exception $e) {
throw new Exception("Failed to parse growth plan: " . $e->getMessage());
}
}
function displayGrowthPlan($growthPlan) {
echo "\n🎯 " . $growthPlan['goal_title'] . "\n";
echo str_repeat("=", strlen($growthPlan['goal_title']) + 4) . "\n";
foreach ($growthPlan['steps'] as $step) {
echo "\n" . $step['step_number'] . ". " . $step['action'] . "\n";
echo " ⏰ Timeline: " . $step['timeline'] . "\n";
}
}
// --- Main Execution ---
try {
$userGoal = "I want to grow in my faith.";
echo "Creating growth plan for: '$userGoal'\n";
// Make API call with tool use
$response = createGoalSettingRequest($userGoal, $API_URL, $tokenInfo, $CLIENT_ID, $CLIENT_SECRET, $TOKEN_URL);
// Parse the structured response
$growthPlan = parseGrowthPlan($response);
// Display the results
displayGrowthPlan($growthPlan);
// Also show raw JSON for developers
echo "\n📊 Raw JSON output:\n";
echo json_encode($growthPlan, JSON_PRETTY_PRINT) . "\n";
} catch (Exception $e) {
echo 'Error: ' . $e->getMessage() . "\n";
}
?>
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"strings"
"time"
"github.com/joho/godotenv"
)
// --- Configuration ---
var (
clientID string
clientSecret string
tokenURL = "https://platform.ai.gloo.com/oauth2/token"
apiURL = "https://platform.ai.gloo.com/ai/v2/chat/completions"
)
// --- State Management ---
var tokenInfo *TokenInfo
// --- Data Structures ---
type TokenInfo struct {
AccessToken string `json:"access_token"`
ExpiresIn int `json:"expires_in"`
ExpiresAt int64 `json:"expires_at"`
TokenType string `json:"token_type"`
}
type GrowthStep struct {
StepNumber int `json:"step_number"`
Action string `json:"action"`
Timeline string `json:"timeline"`
}
type GrowthPlan struct {
GoalTitle string `json:"goal_title"`
Steps []GrowthStep `json:"steps"`
}
type ToolCall struct {
ID string `json:"id"`
Type string `json:"type"`
Function struct {
Name string `json:"name"`
Arguments string `json:"arguments"`
} `json:"function"`
}
type ApiResponse struct {
Choices []struct {
Message struct {
ToolCalls []ToolCall `json:"tool_calls"`
} `json:"message"`
} `json:"choices"`
}
// --- Function Definitions ---
func getAccessToken() (*TokenInfo, error) {
data := strings.NewReader("grant_type=client_credentials&scope=api/access")
req, err := http.NewRequest("POST", tokenURL, data)
if err != nil {
return nil, err
}
req.SetBasicAuth(clientID, clientSecret)
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
bodyBytes, _ := ioutil.ReadAll(resp.Body)
return nil, fmt.Errorf("failed to get token: %s - %s", resp.Status, string(bodyBytes))
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var localTokenInfo TokenInfo
if err := json.Unmarshal(body, &localTokenInfo); err != nil {
return nil, err
}
localTokenInfo.ExpiresAt = time.Now().Unix() + int64(localTokenInfo.ExpiresIn)
return &localTokenInfo, nil
}
func isTokenExpired(token *TokenInfo) bool {
if token == nil || token.ExpiresAt == 0 {
return true
}
return time.Now().Unix() > (token.ExpiresAt - 60)
}
func createGoalSettingRequest(userGoal string) (*ApiResponse, error) {
var err error
if isTokenExpired(tokenInfo) {
fmt.Println("Token is expired or missing. Fetching a new one...")
tokenInfo, err = getAccessToken()
if err != nil {
return nil, err
}
}
tools := []map[string]interface{}{
{
"type": "function",
"function": map[string]interface{}{
"name": "create_growth_plan",
"description": "Creates a structured personal growth plan with a title and a series of actionable steps.",
"parameters": map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"goal_title": map[string]interface{}{
"type": "string",
"description": "A concise, encouraging title for the user's goal.",
},
"steps": map[string]interface{}{
"type": "array",
"description": "A list of concrete steps the user should take.",
"items": map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"step_number": map[string]string{"type": "integer"},
"action": map[string]string{
"type": "string",
"description": "The specific, actionable task for this step.",
},
"timeline": map[string]string{
"type": "string",
"description": "A suggested timeframe for this step (e.g., 'Week 1-2').",
},
},
"required": []string{"step_number", "action", "timeline"},
},
},
},
"required": []string{"goal_title", "steps"},
},
},
},
}
payload := map[string]interface{}{
"auto_routing": true,
"messages": []map[string]string{{"role": "user", "content": userGoal}},
"tools": tools,
"tool_choice": "required",
}
jsonPayload, _ := json.Marshal(payload)
req, err := http.NewRequest("POST", apiURL, bytes.NewBuffer(jsonPayload))
if err != nil {
return nil, err
}
req.Header.Add("Authorization", "Bearer "+tokenInfo.AccessToken)
req.Header.Add("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("API call failed: %s - %s", resp.Status, string(body))
}
var result ApiResponse
json.Unmarshal(body, &result)
return &result, nil
}
func parseGrowthPlan(apiResponse *ApiResponse) (*GrowthPlan, error) {
if len(apiResponse.Choices) == 0 || len(apiResponse.Choices[0].Message.ToolCalls) == 0 {
return nil, fmt.Errorf("no tool calls found in response")
}
toolCall := apiResponse.Choices[0].Message.ToolCalls[0]
var growthPlan GrowthPlan
if err := json.Unmarshal([]byte(toolCall.Function.Arguments), &growthPlan); err != nil {
return nil, fmt.Errorf("failed to parse growth plan: %v", err)
}
return &growthPlan, nil
}
func displayGrowthPlan(growthPlan *GrowthPlan) {
fmt.Printf("\n🎯 %s\n", growthPlan.GoalTitle)
fmt.Printf("%s\n", strings.Repeat("=", len(growthPlan.GoalTitle)+4))
for _, step := range growthPlan.Steps {
fmt.Printf("\n%d. %s\n", step.StepNumber, step.Action)
fmt.Printf(" ⏰ Timeline: %s\n", step.Timeline)
}
}
// Helper to get environment variables
func getEnv(key, fallback string) string {
if value, ok := os.LookupEnv(key); ok {
return value
}
return fallback
}
// Initialize loads environment variables and validates configuration
func init() {
// Load environment variables from .env file if it exists
_ = godotenv.Load()
// Get credentials from environment
clientID = getEnv("GLOO_CLIENT_ID", "")
clientSecret = getEnv("GLOO_CLIENT_SECRET", "")
// Validate that credentials are provided
if clientID == "" || clientSecret == "" {
fmt.Println("Error: GLOO_CLIENT_ID and GLOO_CLIENT_SECRET must be set")
fmt.Println("Either:")
fmt.Println("1. Create a .env file with your credentials:")
fmt.Println(" GLOO_CLIENT_ID=your_client_id_here")
fmt.Println(" GLOO_CLIENT_SECRET=your_client_secret_here")
fmt.Println("2. Export them as environment variables:")
fmt.Println(" export GLOO_CLIENT_ID=\"your_client_id_here\"")
fmt.Println(" export GLOO_CLIENT_SECRET=\"your_client_secret_here\"")
os.Exit(1)
}
}
// --- Main Execution ---
func main() {
userGoal := "I want to grow in my faith."
fmt.Printf("Creating growth plan for: '%s'\n", userGoal)
// Make API call with tool use
response, err := createGoalSettingRequest(userGoal)
if err != nil {
fmt.Printf("Error creating growth plan: %v\n", err)
return
}
// Parse the structured response
growthPlan, err := parseGrowthPlan(response)
if err != nil {
fmt.Printf("Error parsing growth plan: %v\n", err)
return
}
// Display the results
displayGrowthPlan(growthPlan)
// Also show raw JSON for developers
fmt.Printf("\n📊 Raw JSON output:\n")
jsonBytes, _ := json.MarshalIndent(growthPlan, "", " ")
fmt.Printf("%s\n", string(jsonBytes))
}
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonArray;
import io.github.cdimascio.dotenv.Dotenv;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Instant;
import java.util.Base64;
import java.util.List;
// --- Main Application Class ---
public class Main {
public static void main(String[] args) {
// Validate credentials before proceeding
if (!CompletionsToolUse.validateCredentials()) {
System.exit(1);
}
CompletionsToolUse toolUse = new CompletionsToolUse();
try {
String userGoal = "I want to grow in my faith.";
System.out.println("Creating growth plan for: '" + userGoal + "'");
// Make API call with tool use
ApiResponse response = toolUse.createGoalSettingRequest(userGoal);
// Parse the structured response
GrowthPlan growthPlan = toolUse.parseGrowthPlan(response);
// Display the results
toolUse.displayGrowthPlan(growthPlan);
// Also show raw JSON for developers
System.out.println("\n📊 Raw JSON output:");
System.out.println(toolUse.gson.toJson(growthPlan));
} catch (Exception e) {
e.printStackTrace();
}
}
}
// --- Completions Tool Use Class ---
class CompletionsToolUse {
// Load environment variables from .env file if it exists
private static final Dotenv dotenv = Dotenv.configure()
.ignoreIfMissing()
.load();
private static final String CLIENT_ID = dotenv.get("GLOO_CLIENT_ID", "YOUR_CLIENT_ID");
private static final String CLIENT_SECRET = dotenv.get("GLOO_CLIENT_SECRET", "YOUR_CLIENT_SECRET");
private static final String TOKEN_URL = "https://platform.ai.gloo.com/oauth2/token";
private static final String API_URL = "https://platform.ai.gloo.com/ai/v2/chat/completions";
private TokenInfo tokenInfo;
private final HttpClient httpClient = HttpClient.newHttpClient();
public final Gson gson = new Gson();
// Validate that credentials are provided
public static boolean validateCredentials() {
if ("YOUR_CLIENT_ID".equals(CLIENT_ID) || CLIENT_ID == null || CLIENT_ID.trim().isEmpty() ||
"YOUR_CLIENT_SECRET".equals(CLIENT_SECRET) || CLIENT_SECRET == null || CLIENT_SECRET.trim().isEmpty()) {
System.err.println("Error: GLOO_CLIENT_ID and GLOO_CLIENT_SECRET must be set");
System.err.println("Either:");
System.err.println("1. Create a .env file with your credentials:");
System.err.println(" GLOO_CLIENT_ID=your_client_id_here");
System.err.println(" GLOO_CLIENT_SECRET=your_client_secret_here");
System.err.println("2. Export them as environment variables:");
System.err.println(" export GLOO_CLIENT_ID=\"your_client_id_here\"");
System.err.println(" export GLOO_CLIENT_SECRET=\"your_client_secret_here\"");
return false;
}
return true;
}
// --- Data Classes ---
static class TokenInfo {
String access_token;
int expires_in;
long expires_at;
}
static class GrowthStep {
int step_number;
String action;
String timeline;
}
static class GrowthPlan {
String goal_title;
List<GrowthStep> steps;
}
static class ToolCall {
String id;
String type;
Function function;
static class Function {
String name;
String arguments;
}
}
static class ApiResponse {
List<Choice> choices;
static class Choice {
Message message;
static class Message {
List<ToolCall> tool_calls;
}
}
}
// --- Token Management ---
private void fetchAccessToken() throws IOException, InterruptedException {
String auth = CLIENT_ID + ":" + CLIENT_SECRET;
String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
String requestBody = "grant_type=client_credentials&scope=api/access";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(TOKEN_URL))
.header("Content-Type", "application/x-www-form-urlencoded")
.header("Authorization", "Basic " + encodedAuth)
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new IOException("Failed to get token: " + response.body());
}
this.tokenInfo = gson.fromJson(response.body(), TokenInfo.class);
this.tokenInfo.expires_at = Instant.now().getEpochSecond() + this.tokenInfo.expires_in;
}
private boolean isTokenExpired() {
if (this.tokenInfo == null || this.tokenInfo.expires_at == 0) return true;
return Instant.now().getEpochSecond() > (this.tokenInfo.expires_at - 60);
}
// --- API Methods ---
public ApiResponse createGoalSettingRequest(String userGoal) throws IOException, InterruptedException {
if (isTokenExpired()) {
System.out.println("Token is expired or missing. Fetching a new one...");
fetchAccessToken();
}
// Create the tool definition using JsonObject for proper structure
JsonObject toolSchema = new JsonObject();
toolSchema.addProperty("type", "function");
JsonObject function = new JsonObject();
function.addProperty("name", "create_growth_plan");
function.addProperty("description", "Creates a structured personal growth plan with a title and a series of actionable steps.");
JsonObject parameters = new JsonObject();
parameters.addProperty("type", "object");
JsonObject properties = new JsonObject();
JsonObject goalTitle = new JsonObject();
goalTitle.addProperty("type", "string");
goalTitle.addProperty("description", "A concise, encouraging title for the user's goal.");
properties.add("goal_title", goalTitle);
JsonObject steps = new JsonObject();
steps.addProperty("type", "array");
steps.addProperty("description", "A list of concrete steps the user should take.");
JsonObject items = new JsonObject();
items.addProperty("type", "object");
JsonObject itemProperties = new JsonObject();
JsonObject stepNumber = new JsonObject();
stepNumber.addProperty("type", "integer");
itemProperties.add("step_number", stepNumber);
JsonObject action = new JsonObject();
action.addProperty("type", "string");
action.addProperty("description", "The specific, actionable task for this step.");
itemProperties.add("action", action);
JsonObject timeline = new JsonObject();
timeline.addProperty("type", "string");
timeline.addProperty("description", "A suggested timeframe for this step (e.g., 'Week 1-2').");
itemProperties.add("timeline", timeline);
items.add("properties", itemProperties);
JsonArray required = new JsonArray();
required.add("step_number");
required.add("action");
required.add("timeline");
items.add("required", required);
steps.add("items", items);
properties.add("steps", steps);
parameters.add("properties", properties);
JsonArray requiredParams = new JsonArray();
requiredParams.add("goal_title");
requiredParams.add("steps");
parameters.add("required", requiredParams);
function.add("parameters", parameters);
toolSchema.add("function", function);
JsonArray tools = new JsonArray();
tools.add(toolSchema);
JsonObject message = new JsonObject();
message.addProperty("role", "user");
message.addProperty("content", userGoal);
JsonArray messages = new JsonArray();
messages.add(message);
JsonObject payload = new JsonObject();
payload.addProperty("auto_routing", true);
payload.add("messages", messages);
payload.add("tools", tools);
payload.addProperty("tool_choice", "required");
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(API_URL))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer " + this.tokenInfo.access_token)
.POST(HttpRequest.BodyPublishers.ofString(gson.toJson(payload)))
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new IOException("API call failed: " + response.body());
}
return gson.fromJson(response.body(), ApiResponse.class);
}
public GrowthPlan parseGrowthPlan(ApiResponse apiResponse) {
try {
ToolCall toolCall = apiResponse.choices.get(0).message.tool_calls.get(0);
return gson.fromJson(toolCall.function.arguments, GrowthPlan.class);
} catch (Exception e) {
throw new RuntimeException("Failed to parse growth plan: " + e.getMessage(), e);
}
}
public void displayGrowthPlan(GrowthPlan growthPlan) {
System.out.println("\n🎯 " + growthPlan.goal_title);
System.out.println("=".repeat(growthPlan.goal_title.length() + 4));
for (GrowthStep step : growthPlan.steps) {
System.out.println("\n" + step.step_number + ". " + step.action);
System.out.println(" ⏰ Timeline: " + step.timeline);
}
}
}
Testing Your Implementation
To test any of the complete examples:- Set up your environment variables with your actual Gloo AI credentials
- Install dependencies according to each language’s requirements
- Run the script and observe the structured output
- Automatically handle token retrieval and expiration
- Make a tool-use API call with the goal “I want to grow in my faith”
- Parse the JSON response into a structured format
- Display the growth plan in a user-friendly format
- Show the raw JSON for developers
Key Benefits
This approach provides several advantages over simple chat completions:- Predictable Structure: The response always follows your defined schema
- Machine-Readable: Easy to parse and use in applications
- Type Safety: Clear data types for each field
- Validation: The API enforces your schema requirements
- Flexibility: Can adapt to any structured output needs
Working Code Sample
View Complete Code
Clone or browse the complete working examples for all 6 languages (JavaScript, TypeScript, Python, PHP, Go, Java) with setup instructions.
Next Steps
Now that you understand how to use tool use for structured output with V2, consider exploring:- Completions V2 Guide - Learn about auto-routing and model selection options
- Tool Use Guide - For more advanced tool use patterns and multi-step workflows
- Completions API Reference - Full API documentation
- Custom Schemas - Adapt this pattern for your specific use cases

