Skip to content

Commit 14049e4

Browse files
committedMar 3, 2025·
Enhance agent tool function registration with direct function support
- 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
1 parent b966df4 commit 14049e4

File tree

8 files changed

+279
-4
lines changed

8 files changed

+279
-4
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { Agent } from 'praisonai';
2+
3+
/**
4+
* Example of a simple agent with direct function registration
5+
*
6+
* This example demonstrates how to create a simple agent that uses directly
7+
* registered functions as tools without having to define tool schemas manually
8+
* or make functions globally available.
9+
*/
10+
11+
// Define the functions directly
12+
async function getWeather(location: string) {
13+
console.log(`Getting weather for ${location}...`);
14+
return `${Math.floor(Math.random() * 30)}°C`;
15+
}
16+
17+
async function getTime(location: string) {
18+
console.log(`Getting time for ${location}...`);
19+
const now = new Date();
20+
return `${now.getHours()}:${now.getMinutes()}`;
21+
}
22+
23+
// Create an agent with directly registered functions
24+
const agent = new Agent({
25+
instructions: `You provide the current weather and time for requested locations.`,
26+
name: "DirectFunctionAgent",
27+
// Register functions directly without needing to make them global
28+
toolFunctions: {
29+
get_weather: getWeather,
30+
get_time: getTime
31+
}
32+
});
33+
34+
// Start the agent with a prompt that will trigger tool usage
35+
agent.start("What's the weather and time in Paris, France and Tokyo, Japan?");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { Agent } from 'praisonai';
2+
3+
/**
4+
* Example of a simple agent with multiple tool calling capability
5+
*
6+
* This example demonstrates how to create a simple agent that can use multiple tools
7+
* to get weather and time information for different locations.
8+
*/
9+
10+
// Define a weather tool
11+
const getWeather = {
12+
type: "function",
13+
function: {
14+
name: "get_weather",
15+
description: "Get current temperature for a given location.",
16+
parameters: {
17+
type: "object",
18+
properties: {
19+
location: {
20+
type: "string",
21+
description: "City and country e.g. Bogotá, Colombia"
22+
}
23+
},
24+
required: ["location"],
25+
additionalProperties: false
26+
},
27+
strict: true
28+
}
29+
};
30+
31+
// Define a time tool
32+
const getTime = {
33+
type: "function",
34+
function: {
35+
name: "get_time",
36+
description: "Get current time for a given location.",
37+
parameters: {
38+
type: "object",
39+
properties: {
40+
location: {
41+
type: "string",
42+
description: "City and country e.g. Bogotá, Colombia"
43+
}
44+
},
45+
required: ["location"],
46+
additionalProperties: false
47+
},
48+
strict: true
49+
}
50+
};
51+
52+
// Make the functions globally available
53+
// The agent will automatically find and use these functions
54+
(global as any).get_weather = async function(location: string) {
55+
console.log(`Getting weather for ${location}...`);
56+
return `${Math.floor(Math.random() * 30)}°C`;
57+
};
58+
59+
(global as any).get_time = async function(location: string) {
60+
console.log(`Getting time for ${location}...`);
61+
const now = new Date();
62+
return `${now.getHours()}:${now.getMinutes()}`;
63+
};
64+
65+
// Create an agent with both weather and time tools
66+
const agent = new Agent({
67+
instructions: `You provide the current weather and time for requested locations.`,
68+
name: "WeatherTimeAgent",
69+
tools: [getWeather, getTime]
70+
});
71+
72+
// Start the agent with a prompt that will trigger multiple tool calls
73+
agent.start("What's the weather and time in Paris, France and Tokyo, Japan?");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { Agent } from 'praisonai';
2+
3+
/**
4+
* Example of a simple agent with tool calling capability
5+
*
6+
* This example demonstrates how to create a simple agent that can use tools
7+
* to get weather information for a location.
8+
*/
9+
10+
// Define a weather tool
11+
const getWeather = {
12+
type: "function",
13+
function: {
14+
name: "get_weather",
15+
description: "Get current temperature for a given location.",
16+
parameters: {
17+
type: "object",
18+
properties: {
19+
location: {
20+
type: "string",
21+
description: "City and country e.g. Bogotá, Colombia"
22+
}
23+
},
24+
required: ["location"],
25+
additionalProperties: false
26+
},
27+
strict: true
28+
}
29+
};
30+
31+
// Make the function globally available
32+
// The agent will automatically find and use this function
33+
(global as any).get_weather = async function(location: string) {
34+
console.log(`Getting weather for ${location}...`);
35+
return `20°C`;
36+
};
37+
38+
// Create an agent with the weather tool
39+
const agent = new Agent({
40+
instructions: `You provide the current weather for requested locations.`,
41+
name: "WeatherAgent",
42+
tools: [getWeather]
43+
});
44+
45+
// Start the agent with a prompt that will trigger tool usage
46+
agent.start("What's the weather in Paris, France?");

‎src/praisonai-ts/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "praisonai",
3-
"version": "1.0.17",
3+
"version": "1.0.18",
44
"description": "PraisonAI TypeScript AI Agents Framework - Node.js, npm, and Javascript AI Agents Framework",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",
@@ -62,7 +62,7 @@
6262
"fast-xml-parser": "^4.5.1",
6363
"node-fetch": "^2.6.9",
6464
"openai": "^4.81.0",
65-
"praisonai": "^1.0.12"
65+
"praisonai": "^1.0.17"
6666
},
6767
"optionalDependencies": {
6868
"boxen": "^7.1.1",

‎src/praisonai-ts/src/agent/index.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export function setTaskMode(enabled: boolean) {
66
}
77

88
export { Agent, PraisonAIAgents, Task } from './proxy';
9+
export type { ProxyAgentConfig } from './proxy';
910
export type { AgentConfig } from './types';
1011
export type { TaskConfig } from './types';
11-
export type { PraisonAIAgentsConfig } from './simple';
12+
export type { PraisonAIAgentsConfig, SimpleAgentConfig } from './simple';

‎src/praisonai-ts/src/agent/proxy.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { ChatCompletionTool } from 'openai/resources/chat/completions';
66
export interface ProxyAgentConfig extends Partial<SimpleAgentConfig>, Partial<TaskAgentConfig> {
77
task?: Task;
88
tools?: any[];
9+
toolFunctions?: Record<string, Function>;
910
}
1011

1112
export class Agent {
@@ -35,7 +36,8 @@ export class Agent {
3536
verbose: config.verbose,
3637
llm: config.llm,
3738
markdown: config.markdown,
38-
tools: config.tools
39+
tools: config.tools,
40+
toolFunctions: config.toolFunctions
3941
};
4042
this.simpleAgent = new SimpleAgent(simpleConfig);
4143
}

‎src/praisonai-ts/src/agent/simple.ts

+83
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export interface SimpleAgentConfig {
1111
markdown?: boolean;
1212
stream?: boolean;
1313
tools?: any[];
14+
toolFunctions?: Record<string, Function>;
1415
}
1516

1617
export class Agent {
@@ -39,6 +40,18 @@ export class Agent {
3940
// Configure logging
4041
Logger.setVerbose(this.verbose);
4142
Logger.setPretty(this.pretty);
43+
44+
// Register directly provided tool functions if any
45+
if (config.toolFunctions) {
46+
for (const [name, func] of Object.entries(config.toolFunctions)) {
47+
this.registerToolFunction(name, func);
48+
49+
// Auto-generate tool definition if not already provided
50+
if (!this.hasToolDefinition(name)) {
51+
this.addAutoGeneratedToolDefinition(name, func);
52+
}
53+
}
54+
}
4255
}
4356

4457
private createSystemPrompt(): string {
@@ -58,6 +71,76 @@ export class Agent {
5871
this.toolFunctions[name] = fn;
5972
Logger.debug(`Registered tool function: ${name}`);
6073
}
74+
75+
/**
76+
* Check if a tool definition exists for the given function name
77+
* @param name Function name
78+
* @returns True if a tool definition exists
79+
*/
80+
private hasToolDefinition(name: string): boolean {
81+
if (!this.tools) return false;
82+
83+
return this.tools.some(tool => {
84+
if (tool.type === 'function' && tool.function) {
85+
return tool.function.name === name;
86+
}
87+
return false;
88+
});
89+
}
90+
91+
/**
92+
* Auto-generate a tool definition based on the function
93+
* @param name Function name
94+
* @param func Function implementation
95+
*/
96+
private addAutoGeneratedToolDefinition(name: string, func: Function): void {
97+
if (!this.tools) {
98+
this.tools = [];
99+
}
100+
101+
// Extract parameter names from function
102+
const funcStr = func.toString();
103+
const paramMatch = funcStr.match(/\(([^)]*)\)/);
104+
const params = paramMatch ? paramMatch[1].split(',').map(p => p.trim()).filter(p => p) : [];
105+
106+
// Create a basic tool definition
107+
const toolDef = {
108+
type: "function",
109+
function: {
110+
name,
111+
description: `Auto-generated function for ${name}`,
112+
parameters: {
113+
type: "object",
114+
properties: {},
115+
required: [] as string[]
116+
}
117+
}
118+
};
119+
120+
// Add parameters to the definition
121+
if (params.length > 0) {
122+
const properties: Record<string, any> = {};
123+
const required: string[] = [];
124+
125+
params.forEach(param => {
126+
// Remove type annotations if present
127+
const paramName = param.split(':')[0].trim();
128+
if (paramName) {
129+
properties[paramName] = {
130+
type: "string",
131+
description: `Parameter ${paramName} for function ${name}`
132+
};
133+
required.push(paramName);
134+
}
135+
});
136+
137+
toolDef.function.parameters.properties = properties;
138+
toolDef.function.parameters.required = required;
139+
}
140+
141+
this.tools.push(toolDef);
142+
Logger.debug(`Auto-generated tool definition for ${name}`);
143+
}
61144

62145
/**
63146
* Process tool calls from the model
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { Agent } from '../../../src/agent/proxy';
2+
3+
/**
4+
* Example of a simple agent with direct function registration
5+
*
6+
* This example demonstrates how to create a simple agent that uses directly
7+
* registered functions as tools without having to define tool schemas manually
8+
* or make functions globally available.
9+
*/
10+
11+
// Define the functions directly
12+
async function getWeather(location: string) {
13+
console.log(`Getting weather for ${location}...`);
14+
return `${Math.floor(Math.random() * 30)}°C`;
15+
}
16+
17+
async function getTime(location: string) {
18+
console.log(`Getting time for ${location}...`);
19+
const now = new Date();
20+
return `${now.getHours()}:${now.getMinutes()}`;
21+
}
22+
23+
// Create an agent with directly registered functions
24+
const agent = new Agent({
25+
instructions: `You provide the current weather and time for requested locations.`,
26+
name: "DirectFunctionAgent",
27+
// Register functions directly without needing to make them global
28+
toolFunctions: {
29+
get_weather: getWeather,
30+
get_time: getTime
31+
}
32+
});
33+
34+
// Start the agent with a prompt that will trigger tool usage
35+
agent.start("What's the weather and time in Paris, France and Tokyo, Japan?");

0 commit comments

Comments
 (0)
Please sign in to comment.