Skip to content

Commit

Permalink
Enhance agent tool function registration with direct function support
Browse files Browse the repository at this point in the history
- Added support for directly registering tool functions without global declaration
- Implemented auto-generation of tool definitions for registered functions
- Created new example scripts demonstrating direct function tool registration
- Updated package version to 1.0.18
- Expanded Agent configuration to support `toolFunctions` property
- Added type exports for improved type safety
  • Loading branch information
MervinPraison committed Mar 3, 2025
1 parent b966df4 commit 14049e4
Show file tree
Hide file tree
Showing 8 changed files with 279 additions and 4 deletions.
35 changes: 35 additions & 0 deletions src/praisonai-ts/examples/simple/direct-function-tools.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Agent } from 'praisonai';

/**
* Example of a simple agent with direct function registration
*
* This example demonstrates how to create a simple agent that uses directly
* registered functions as tools without having to define tool schemas manually
* or make functions globally available.
*/

// Define the functions directly
async function getWeather(location: string) {
console.log(`Getting weather for ${location}...`);
return `${Math.floor(Math.random() * 30)}°C`;
}

async function getTime(location: string) {
console.log(`Getting time for ${location}...`);
const now = new Date();
return `${now.getHours()}:${now.getMinutes()}`;
}

// Create an agent with directly registered functions
const agent = new Agent({
instructions: `You provide the current weather and time for requested locations.`,
name: "DirectFunctionAgent",
// Register functions directly without needing to make them global
toolFunctions: {
get_weather: getWeather,
get_time: getTime
}
});

// Start the agent with a prompt that will trigger tool usage
agent.start("What's the weather and time in Paris, France and Tokyo, Japan?");
73 changes: 73 additions & 0 deletions src/praisonai-ts/examples/simple/multi-tool-call.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { Agent } from 'praisonai';

/**
* Example of a simple agent with multiple tool calling capability
*
* This example demonstrates how to create a simple agent that can use multiple tools
* to get weather and time information for different locations.
*/

// Define a weather tool
const getWeather = {
type: "function",
function: {
name: "get_weather",
description: "Get current temperature for a given location.",
parameters: {
type: "object",
properties: {
location: {
type: "string",
description: "City and country e.g. Bogotá, Colombia"
}
},
required: ["location"],
additionalProperties: false
},
strict: true
}
};

// Define a time tool
const getTime = {
type: "function",
function: {
name: "get_time",
description: "Get current time for a given location.",
parameters: {
type: "object",
properties: {
location: {
type: "string",
description: "City and country e.g. Bogotá, Colombia"
}
},
required: ["location"],
additionalProperties: false
},
strict: true
}
};

// Make the functions globally available
// The agent will automatically find and use these functions
(global as any).get_weather = async function(location: string) {
console.log(`Getting weather for ${location}...`);
return `${Math.floor(Math.random() * 30)}°C`;
};

(global as any).get_time = async function(location: string) {
console.log(`Getting time for ${location}...`);
const now = new Date();
return `${now.getHours()}:${now.getMinutes()}`;
};

// Create an agent with both weather and time tools
const agent = new Agent({
instructions: `You provide the current weather and time for requested locations.`,
name: "WeatherTimeAgent",
tools: [getWeather, getTime]
});

// Start the agent with a prompt that will trigger multiple tool calls
agent.start("What's the weather and time in Paris, France and Tokyo, Japan?");
46 changes: 46 additions & 0 deletions src/praisonai-ts/examples/simple/single-agent-tool-call.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Agent } from 'praisonai';

/**
* Example of a simple agent with tool calling capability
*
* This example demonstrates how to create a simple agent that can use tools
* to get weather information for a location.
*/

// Define a weather tool
const getWeather = {
type: "function",
function: {
name: "get_weather",
description: "Get current temperature for a given location.",
parameters: {
type: "object",
properties: {
location: {
type: "string",
description: "City and country e.g. Bogotá, Colombia"
}
},
required: ["location"],
additionalProperties: false
},
strict: true
}
};

// Make the function globally available
// The agent will automatically find and use this function
(global as any).get_weather = async function(location: string) {
console.log(`Getting weather for ${location}...`);
return `20°C`;
};

// Create an agent with the weather tool
const agent = new Agent({
instructions: `You provide the current weather for requested locations.`,
name: "WeatherAgent",
tools: [getWeather]
});

// Start the agent with a prompt that will trigger tool usage
agent.start("What's the weather in Paris, France?");
4 changes: 2 additions & 2 deletions src/praisonai-ts/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "praisonai",
"version": "1.0.17",
"version": "1.0.18",
"description": "PraisonAI TypeScript AI Agents Framework - Node.js, npm, and Javascript AI Agents Framework",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down Expand Up @@ -62,7 +62,7 @@
"fast-xml-parser": "^4.5.1",
"node-fetch": "^2.6.9",
"openai": "^4.81.0",
"praisonai": "^1.0.12"
"praisonai": "^1.0.17"
},
"optionalDependencies": {
"boxen": "^7.1.1",
Expand Down
3 changes: 2 additions & 1 deletion src/praisonai-ts/src/agent/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export function setTaskMode(enabled: boolean) {
}

export { Agent, PraisonAIAgents, Task } from './proxy';
export type { ProxyAgentConfig } from './proxy';
export type { AgentConfig } from './types';
export type { TaskConfig } from './types';
export type { PraisonAIAgentsConfig } from './simple';
export type { PraisonAIAgentsConfig, SimpleAgentConfig } from './simple';
4 changes: 3 additions & 1 deletion src/praisonai-ts/src/agent/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { ChatCompletionTool } from 'openai/resources/chat/completions';
export interface ProxyAgentConfig extends Partial<SimpleAgentConfig>, Partial<TaskAgentConfig> {
task?: Task;
tools?: any[];
toolFunctions?: Record<string, Function>;
}

export class Agent {
Expand Down Expand Up @@ -35,7 +36,8 @@ export class Agent {
verbose: config.verbose,
llm: config.llm,
markdown: config.markdown,
tools: config.tools
tools: config.tools,
toolFunctions: config.toolFunctions
};
this.simpleAgent = new SimpleAgent(simpleConfig);
}
Expand Down
83 changes: 83 additions & 0 deletions src/praisonai-ts/src/agent/simple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface SimpleAgentConfig {
markdown?: boolean;
stream?: boolean;
tools?: any[];
toolFunctions?: Record<string, Function>;
}

export class Agent {
Expand Down Expand Up @@ -39,6 +40,18 @@ export class Agent {
// Configure logging
Logger.setVerbose(this.verbose);
Logger.setPretty(this.pretty);

// Register directly provided tool functions if any
if (config.toolFunctions) {
for (const [name, func] of Object.entries(config.toolFunctions)) {
this.registerToolFunction(name, func);

// Auto-generate tool definition if not already provided
if (!this.hasToolDefinition(name)) {
this.addAutoGeneratedToolDefinition(name, func);
}
}
}
}

private createSystemPrompt(): string {
Expand All @@ -58,6 +71,76 @@ export class Agent {
this.toolFunctions[name] = fn;
Logger.debug(`Registered tool function: ${name}`);
}

/**
* Check if a tool definition exists for the given function name
* @param name Function name
* @returns True if a tool definition exists
*/
private hasToolDefinition(name: string): boolean {
if (!this.tools) return false;

return this.tools.some(tool => {
if (tool.type === 'function' && tool.function) {
return tool.function.name === name;
}
return false;
});
}

/**
* Auto-generate a tool definition based on the function
* @param name Function name
* @param func Function implementation
*/
private addAutoGeneratedToolDefinition(name: string, func: Function): void {
if (!this.tools) {
this.tools = [];
}

// Extract parameter names from function
const funcStr = func.toString();
const paramMatch = funcStr.match(/\(([^)]*)\)/);
const params = paramMatch ? paramMatch[1].split(',').map(p => p.trim()).filter(p => p) : [];

// Create a basic tool definition
const toolDef = {
type: "function",
function: {
name,
description: `Auto-generated function for ${name}`,
parameters: {
type: "object",
properties: {},
required: [] as string[]
}
}
};

// Add parameters to the definition
if (params.length > 0) {
const properties: Record<string, any> = {};
const required: string[] = [];

params.forEach(param => {
// Remove type annotations if present
const paramName = param.split(':')[0].trim();
if (paramName) {
properties[paramName] = {
type: "string",
description: `Parameter ${paramName} for function ${name}`
};
required.push(paramName);
}
});

toolDef.function.parameters.properties = properties;
toolDef.function.parameters.required = required;
}

this.tools.push(toolDef);
Logger.debug(`Auto-generated tool definition for ${name}`);
}

/**
* Process tool calls from the model
Expand Down
35 changes: 35 additions & 0 deletions src/praisonai-ts/tests/development/simple/direct-function-tools.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Agent } from '../../../src/agent/proxy';

/**
* Example of a simple agent with direct function registration
*
* This example demonstrates how to create a simple agent that uses directly
* registered functions as tools without having to define tool schemas manually
* or make functions globally available.
*/

// Define the functions directly
async function getWeather(location: string) {
console.log(`Getting weather for ${location}...`);
return `${Math.floor(Math.random() * 30)}°C`;
}

async function getTime(location: string) {
console.log(`Getting time for ${location}...`);
const now = new Date();
return `${now.getHours()}:${now.getMinutes()}`;
}

// Create an agent with directly registered functions
const agent = new Agent({
instructions: `You provide the current weather and time for requested locations.`,
name: "DirectFunctionAgent",
// Register functions directly without needing to make them global
toolFunctions: {
get_weather: getWeather,
get_time: getTime
}
});

// Start the agent with a prompt that will trigger tool usage
agent.start("What's the weather and time in Paris, France and Tokyo, Japan?");

0 comments on commit 14049e4

Please sign in to comment.