@amitdeshmukh/ax-crew 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,17 @@ This Changelog format is based on [Keep a Changelog]
5
5
  adheres to [Semantic Versioning](https://semver.org/spec/
6
6
  v2.0.0.html).
7
7
 
8
+ ## [3.1.0] - 2024-12-10
9
+
10
+ ### Added
11
+ - Support for direct JSON object configuration in addition to configuration files
12
+ - New configuration option to pass agent configuration as a JavaScript object
13
+ - Updated documentation in README.md with examples of both configuration methods
14
+
15
+ ### Enhanced
16
+ - Configuration flexibility allowing runtime configuration modifications
17
+ - Support for dynamic agent configuration generation
18
+
8
19
  ## [3.0.0] - 2024-12-10
9
20
 
10
21
  ### Changed
package/README.md CHANGED
@@ -28,21 +28,65 @@ Refer to the [.env.example](.env.example) file for the required environment vari
28
28
  ## Usage
29
29
 
30
30
  ### Initializing a Crew
31
- A Crew is a team of agents that work together to achieve a common goal. The configuration file for a crew is a YAML file that defines the agents in the crew, along with their individual configurations.
31
+ A Crew is a team of agents that work together to achieve a common goal. You can configure your crew in two ways:
32
32
 
33
- See [agentConfig.json](agentConfig.json) for an example.
33
+ 1. Using a JSON configuration file that defines the agents in the crew, along with their individual configurations.
34
+ 2. Directly passing a JSON object with the crew configuration.
34
35
 
35
- To initialize a crew of agents, pass a config file to the `AxCrew` constructor.
36
+ #### Using a Configuration File
37
+ See [agentConfig.json](agentConfig.json) for an example configuration file.
36
38
 
37
39
  ```javascript
38
40
  // Import the AxCrew class
39
41
  import { AxCrew } from '@amitdeshmukh/ax-crew';
40
42
 
41
- // Create a new instance of AxCrew
43
+ // Create a new instance of AxCrew using a config file
42
44
  const configFilePath = './agentConfig.json';
43
45
  const crew = new AxCrew(configFilePath);
44
46
  ```
45
47
 
48
+ #### Using a Direct Configuration Object
49
+ You can also pass the configuration directly as a JSON object:
50
+
51
+ ```javascript
52
+ // Import the AxCrew class
53
+ import { AxCrew } from '@amitdeshmukh/ax-crew';
54
+
55
+ // Create the configuration object
56
+ const config = {
57
+ crew: [
58
+ {
59
+ name: "Planner",
60
+ description: "Creates a plan to complete a task",
61
+ signature: "task:string \"a task to be completed\" -> plan:string \"a plan to execute the task in 5 steps or less\"",
62
+ provider: "google-gemini",
63
+ providerKeyName: "GEMINI_API_KEY",
64
+ ai: {
65
+ model: "gemini-1.5-flash",
66
+ temperature: 0
67
+ },
68
+ options: {
69
+ debug: false
70
+ }
71
+ }
72
+ // ... more agents
73
+ ]
74
+ };
75
+
76
+ // Create a new instance of AxCrew using the config object
77
+ const crew = new AxCrew(config);
78
+ ```
79
+
80
+ Both methods support the same configuration structure and options. Choose the one that best fits your use case:
81
+ - Use a configuration file when you want to:
82
+ - Keep your configuration separate from your code
83
+ - Share configurations across different projects
84
+ - Version control your configurations
85
+ - Use a direct configuration object when you want to:
86
+ - Generate configurations dynamically
87
+ - Modify configurations at runtime
88
+ - Keep everything in one file for simpler projects
89
+
46
90
  ### Function Registry
47
91
  Functions (aka Tools) are the building blocks of agents. They are used to perform specific tasks, such as calling external APIs, databases, or other services.
48
92
 
@@ -68,56 +68,66 @@ Original error: ${error.message}`;
68
68
  return `Error parsing agent configuration: ${error.message}`;
69
69
  };
70
70
  /**
71
- * Reads the AI parameters from the YAML configuration file.
72
- * @param {string} agentConfigFilePath - The path to the agent_config.yaml file.
73
- * @returns {Object} The parsed agent configs from the config.yaml file.
74
- * @throws Will throw an error if reading the file fails.
71
+ * Reads the AI parameters from either a JSON configuration file or a direct JSON object.
72
+ * @param {AgentConfigInput} input - Either a path to the agent_config.json file or a JSON object with crew configuration.
73
+ * @returns {Object} The parsed agent configs.
74
+ * @throws Will throw an error if reading/parsing fails.
75
75
  */
76
- const parseAgentConfig = (agentConfigFilePath) => {
76
+ const parseAgentConfig = (input) => {
77
77
  try {
78
- const fileContents = fs.readFileSync(agentConfigFilePath, 'utf8');
79
- const parsedConfigs = JSON.parse(fileContents);
80
- return parsedConfigs;
78
+ if (typeof input === 'string') {
79
+ // Handle file path input
80
+ const fileContents = fs.readFileSync(input, 'utf8');
81
+ const parsedConfigs = JSON.parse(fileContents);
82
+ return parsedConfigs;
83
+ }
84
+ else {
85
+ // Handle direct JSON object input
86
+ return input;
87
+ }
81
88
  }
82
89
  catch (e) {
83
90
  if (e instanceof Error) {
84
- const formattedError = getFormattedJSONError(e, fs.readFileSync(agentConfigFilePath, 'utf8'));
85
- throw new Error(formattedError);
91
+ if (typeof input === 'string') {
92
+ const formattedError = getFormattedJSONError(e, fs.readFileSync(input, 'utf8'));
93
+ throw new Error(formattedError);
94
+ }
95
+ throw new Error(`Error parsing agent configuration: ${e.message}`);
86
96
  }
87
97
  throw e;
88
98
  }
89
99
  };
90
100
  /**
91
- * Initializes the AI agent using the specified agent name and configuration file path.
101
+ * Initializes the AI agent using the specified agent name and configuration.
92
102
  * This function parses the agent's configuration, validates the presence of the necessary API key,
93
103
  * and creates an instance of the AI agent with the appropriate settings.
94
104
  *
95
105
  * @param {string} agentName - The identifier for the AI agent to be initialized.
96
- * @param {string} agentConfigFilePath - The file path to the YAML configuration for the agent.
106
+ * @param {AgentConfigInput} agentConfig - Either a file path to the JSON configuration or a JSON object with crew configuration.
97
107
  * @param {FunctionRegistryType} functions - The functions available to the agent.
98
108
  * @param {Object} state - The state object for the agent.
99
109
  * @returns {Object} An object containing the Agents AI instance, its name, description, signature, functions and subAgentList.
100
110
  * @throws {Error} Throws an error if the agent configuration is missing, the provider is unsupported,
101
111
  * the API key is not found, or the provider key name is not specified in the configuration.
102
112
  */
103
- const getAgentConfigParams = (agentName, agentConfigFilePath, functions, state) => {
113
+ const getAgentConfigParams = (agentName, agentConfig, functions, state) => {
104
114
  try {
105
- // Retrieve the parameters for the specified AI agent from a config file in yaml format
106
- const agentConfig = parseAgentConfig(agentConfigFilePath).crew.find(agent => agent.name === agentName);
107
- if (!agentConfig) {
115
+ // Retrieve the parameters for the specified AI agent from config
116
+ const agentConfigData = parseAgentConfig(agentConfig).crew.find(agent => agent.name === agentName);
117
+ if (!agentConfigData) {
108
118
  throw new Error(`AI agent with name ${agentName} is not configured`);
109
119
  }
110
120
  // Get the constructor for the AI agent's provider
111
- const AIConstructor = AIConstructors[agentConfig.provider];
121
+ const AIConstructor = AIConstructors[agentConfigData.provider];
112
122
  if (!AIConstructor) {
113
- throw new Error(`AI provider ${agentConfig.provider} is not supported. Did you mean '${agentConfig.provider.toLowerCase()}'?`);
123
+ throw new Error(`AI provider ${agentConfigData.provider} is not supported. Did you mean '${agentConfigData.provider.toLowerCase()}'?`);
114
124
  }
115
125
  // If an API Key property is present, get the API key for the AI agent from the environment variables
116
126
  let apiKey = '';
117
- if (agentConfig.providerKeyName) {
118
- apiKey = PROVIDER_API_KEYS[agentConfig.providerKeyName] || '';
127
+ if (agentConfigData.providerKeyName) {
128
+ apiKey = PROVIDER_API_KEYS[agentConfigData.providerKeyName] || '';
119
129
  if (!apiKey) {
120
- throw new Error(`API key for provider ${agentConfig.provider} is not set in environment variables`);
130
+ throw new Error(`API key for provider ${agentConfigData.provider} is not set in environment variables`);
121
131
  }
122
132
  }
123
133
  else {
@@ -126,19 +136,19 @@ const getAgentConfigParams = (agentName, agentConfigFilePath, functions, state)
126
136
  // Create an instance of the AI agent
127
137
  const ai = new AIConstructor({
128
138
  apiKey,
129
- config: agentConfig.ai,
139
+ config: agentConfigData.ai,
130
140
  options: {
131
- debug: agentConfig.debug || false
141
+ debug: agentConfigData.debug || false
132
142
  }
133
143
  });
134
144
  // If an apiURL is provided in the agent config, set it in the AI agent
135
- if (agentConfig.apiURL) {
136
- ai.setAPIURL(agentConfig.apiURL);
145
+ if (agentConfigData.apiURL) {
146
+ ai.setAPIURL(agentConfigData.apiURL);
137
147
  }
138
148
  // Set all options from the agent configuration
139
- ai.setOptions({ ...agentConfig.options });
149
+ ai.setOptions({ ...agentConfigData.options });
140
150
  // Prepare functions for the AI agent
141
- const agentFunctions = (agentConfig.functions || [])
151
+ const agentFunctions = (agentConfigData.functions || [])
142
152
  .map(funcName => {
143
153
  const func = functions[funcName];
144
154
  if (!func) {
@@ -157,10 +167,10 @@ const getAgentConfigParams = (agentName, agentConfigFilePath, functions, state)
157
167
  return {
158
168
  ai,
159
169
  name: agentName,
160
- description: agentConfig.description,
161
- signature: agentConfig.signature,
170
+ description: agentConfigData.description,
171
+ signature: agentConfigData.signature,
162
172
  functions: agentFunctions,
163
- subAgentNames: agentConfig.agents || []
173
+ subAgentNames: agentConfigData.agents || []
164
174
  };
165
175
  }
166
176
  catch (error) {
@@ -23,11 +23,11 @@ class StatefulAxAgent extends AxAgent {
23
23
  class AxCrew {
24
24
  /**
25
25
  * Creates an instance of AxCrew.
26
- * @param {string} configFilePath - Path to the agent config file.
26
+ * @param {AgentConfigInput} agentConfig - Either a path to the agent config file or a JSON object with crew configuration.
27
27
  * @param {FunctionRegistryType} [functionsRegistry={}] - The registry of functions to use in the crew.
28
28
  * @param {string} [crewId=uuidv4()] - The unique identifier for the crew.
29
29
  */
30
- constructor(configFilePath, functionsRegistry = {}, crewId = uuidv4()) {
30
+ constructor(agentConfig, functionsRegistry = {}, crewId = uuidv4()) {
31
31
  this.functionsRegistry = {};
32
32
  /**
33
33
  * Factory function for creating an agent.
@@ -37,7 +37,7 @@ class AxCrew {
37
37
  */
38
38
  this.createAgent = (agentName) => {
39
39
  try {
40
- const agentConfigParams = getAgentConfigParams(agentName, this.configFilePath, this.functionsRegistry, this.state);
40
+ const agentConfigParams = getAgentConfigParams(agentName, this.agentConfig, this.functionsRegistry, this.state);
41
41
  // Destructure with type assertion
42
42
  const { ai, name, description, signature, functions, subAgentNames } = agentConfigParams;
43
43
  // Get subagents for the AI agent
@@ -61,7 +61,7 @@ class AxCrew {
61
61
  throw error;
62
62
  }
63
63
  };
64
- this.configFilePath = configFilePath;
64
+ this.agentConfig = agentConfig;
65
65
  this.functionsRegistry = functionsRegistry;
66
66
  this.crewId = crewId;
67
67
  this.agents = new Map();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@amitdeshmukh/ax-crew",
4
- "version": "3.0.0",
4
+ "version": "3.1.0",
5
5
  "description": "Build and launch a crew of AI agents with shared state. Built with axllm.dev",
6
6
  "main": "dist/index.js",
7
7
  "engines": {
@@ -97,33 +97,44 @@ Original error: ${error.message}`;
97
97
  return `Error parsing agent configuration: ${error.message}`;
98
98
  };
99
99
 
100
+ type AgentConfigInput = string | { crew: AgentConfig[] };
101
+
100
102
  /**
101
- * Reads the AI parameters from the YAML configuration file.
102
- * @param {string} agentConfigFilePath - The path to the agent_config.yaml file.
103
- * @returns {Object} The parsed agent configs from the config.yaml file.
104
- * @throws Will throw an error if reading the file fails.
103
+ * Reads the AI parameters from either a JSON configuration file or a direct JSON object.
104
+ * @param {AgentConfigInput} input - Either a path to the agent_config.json file or a JSON object with crew configuration.
105
+ * @returns {Object} The parsed agent configs.
106
+ * @throws Will throw an error if reading/parsing fails.
105
107
  */
106
- const parseAgentConfig = (agentConfigFilePath: string): {crew: AgentConfig[]} => {
108
+ const parseAgentConfig = (input: AgentConfigInput): { crew: AgentConfig[] } => {
107
109
  try {
108
- const fileContents = fs.readFileSync(agentConfigFilePath, 'utf8');
109
- const parsedConfigs = JSON.parse(fileContents) as { crew: AgentConfig[] };
110
- return parsedConfigs;
110
+ if (typeof input === 'string') {
111
+ // Handle file path input
112
+ const fileContents = fs.readFileSync(input, 'utf8');
113
+ const parsedConfigs = JSON.parse(fileContents) as { crew: AgentConfig[] };
114
+ return parsedConfigs;
115
+ } else {
116
+ // Handle direct JSON object input
117
+ return input;
118
+ }
111
119
  } catch (e) {
112
120
  if (e instanceof Error) {
113
- const formattedError = getFormattedJSONError(e, fs.readFileSync(agentConfigFilePath, 'utf8'));
114
- throw new Error(formattedError);
121
+ if (typeof input === 'string') {
122
+ const formattedError = getFormattedJSONError(e, fs.readFileSync(input, 'utf8'));
123
+ throw new Error(formattedError);
124
+ }
125
+ throw new Error(`Error parsing agent configuration: ${e.message}`);
115
126
  }
116
127
  throw e;
117
128
  }
118
129
  };
119
130
 
120
131
  /**
121
- * Initializes the AI agent using the specified agent name and configuration file path.
132
+ * Initializes the AI agent using the specified agent name and configuration.
122
133
  * This function parses the agent's configuration, validates the presence of the necessary API key,
123
134
  * and creates an instance of the AI agent with the appropriate settings.
124
135
  *
125
136
  * @param {string} agentName - The identifier for the AI agent to be initialized.
126
- * @param {string} agentConfigFilePath - The file path to the YAML configuration for the agent.
137
+ * @param {AgentConfigInput} agentConfig - Either a file path to the JSON configuration or a JSON object with crew configuration.
127
138
  * @param {FunctionRegistryType} functions - The functions available to the agent.
128
139
  * @param {Object} state - The state object for the agent.
129
140
  * @returns {Object} An object containing the Agents AI instance, its name, description, signature, functions and subAgentList.
@@ -132,30 +143,30 @@ const parseAgentConfig = (agentConfigFilePath: string): {crew: AgentConfig[]} =>
132
143
  */
133
144
  const getAgentConfigParams = (
134
145
  agentName: string,
135
- agentConfigFilePath: string,
146
+ agentConfig: AgentConfigInput,
136
147
  functions: FunctionRegistryType,
137
148
  state: Record<string, any>
138
149
  ) => {
139
150
  try {
140
- // Retrieve the parameters for the specified AI agent from a config file in yaml format
141
- const agentConfig = parseAgentConfig(agentConfigFilePath).crew.find(agent => agent.name === agentName);
142
- if (!agentConfig) {
151
+ // Retrieve the parameters for the specified AI agent from config
152
+ const agentConfigData = parseAgentConfig(agentConfig).crew.find(agent => agent.name === agentName);
153
+ if (!agentConfigData) {
143
154
  throw new Error(`AI agent with name ${agentName} is not configured`);
144
155
  }
145
156
 
146
157
  // Get the constructor for the AI agent's provider
147
- const AIConstructor = AIConstructors[agentConfig.provider];
158
+ const AIConstructor = AIConstructors[agentConfigData.provider];
148
159
  if (!AIConstructor) {
149
- throw new Error(`AI provider ${agentConfig.provider} is not supported. Did you mean '${agentConfig.provider.toLowerCase()}'?`);
160
+ throw new Error(`AI provider ${agentConfigData.provider} is not supported. Did you mean '${agentConfigData.provider.toLowerCase()}'?`);
150
161
  }
151
162
 
152
163
  // If an API Key property is present, get the API key for the AI agent from the environment variables
153
164
  let apiKey = '';
154
- if (agentConfig.providerKeyName) {
155
- apiKey = PROVIDER_API_KEYS[agentConfig.providerKeyName] || '';
165
+ if (agentConfigData.providerKeyName) {
166
+ apiKey = PROVIDER_API_KEYS[agentConfigData.providerKeyName] || '';
156
167
 
157
168
  if (!apiKey) {
158
- throw new Error(`API key for provider ${agentConfig.provider} is not set in environment variables`);
169
+ throw new Error(`API key for provider ${agentConfigData.provider} is not set in environment variables`);
159
170
  }
160
171
  } else {
161
172
  throw new Error(`Provider key name is missing in the agent configuration`);
@@ -164,22 +175,21 @@ const getAgentConfigParams = (
164
175
  // Create an instance of the AI agent
165
176
  const ai = new AIConstructor({
166
177
  apiKey,
167
- config: agentConfig.ai,
178
+ config: agentConfigData.ai,
168
179
  options: {
169
- debug: agentConfig.debug || false
180
+ debug: agentConfigData.debug || false
170
181
  }
171
182
  });
172
-
173
183
  // If an apiURL is provided in the agent config, set it in the AI agent
174
- if (agentConfig.apiURL) {
175
- ai.setAPIURL(agentConfig.apiURL);
184
+ if (agentConfigData.apiURL) {
185
+ ai.setAPIURL(agentConfigData.apiURL);
176
186
  }
177
187
 
178
188
  // Set all options from the agent configuration
179
- ai.setOptions({ ...agentConfig.options });
189
+ ai.setOptions({ ...agentConfigData.options });
180
190
 
181
191
  // Prepare functions for the AI agent
182
- const agentFunctions = (agentConfig.functions || [])
192
+ const agentFunctions = (agentConfigData.functions || [])
183
193
  .map(funcName => {
184
194
  const func = functions[funcName];
185
195
  if (!func) {
@@ -201,10 +211,10 @@ const getAgentConfigParams = (
201
211
  return {
202
212
  ai,
203
213
  name: agentName,
204
- description: agentConfig.description,
205
- signature: agentConfig.signature,
214
+ description: agentConfigData.description,
215
+ signature: agentConfigData.signature,
206
216
  functions: agentFunctions,
207
- subAgentNames: agentConfig.agents || []
217
+ subAgentNames: agentConfigData.agents || []
208
218
  };
209
219
  } catch (error) {
210
220
  if (error instanceof Error) {
@@ -214,4 +224,4 @@ const getAgentConfigParams = (
214
224
  }
215
225
  };
216
226
 
217
- export { getAgentConfigParams }
227
+ export { getAgentConfigParams, AgentConfigInput };
@@ -7,6 +7,7 @@ import type {
7
7
  AxProgramForwardOptions,
8
8
  } from "@ax-llm/ax";
9
9
  import { getAgentConfigParams } from "./agentConfig.js";
10
+ import type { AgentConfigInput } from "./agentConfig.js";
10
11
  import { FunctionRegistryType } from "../functions/index.js";
11
12
  import { createState, StateInstance } from "../state/index.js";
12
13
 
@@ -62,7 +63,7 @@ class StatefulAxAgent extends AxAgent<any, any> {
62
63
  * Represents a crew of agents with shared state functionality.
63
64
  */
64
65
  class AxCrew {
65
- private configFilePath: string;
66
+ private agentConfig: AgentConfigInput;
66
67
  functionsRegistry: FunctionRegistryType = {};
67
68
  crewId: string;
68
69
  agents: Map<string, StatefulAxAgent> | null;
@@ -70,16 +71,16 @@ class AxCrew {
70
71
 
71
72
  /**
72
73
  * Creates an instance of AxCrew.
73
- * @param {string} configFilePath - Path to the agent config file.
74
+ * @param {AgentConfigInput} agentConfig - Either a path to the agent config file or a JSON object with crew configuration.
74
75
  * @param {FunctionRegistryType} [functionsRegistry={}] - The registry of functions to use in the crew.
75
76
  * @param {string} [crewId=uuidv4()] - The unique identifier for the crew.
76
77
  */
77
78
  constructor(
78
- configFilePath: string,
79
+ agentConfig: AgentConfigInput,
79
80
  functionsRegistry: FunctionRegistryType = {},
80
81
  crewId: string = uuidv4()
81
82
  ) {
82
- this.configFilePath = configFilePath;
83
+ this.agentConfig = agentConfig;
83
84
  this.functionsRegistry = functionsRegistry;
84
85
  this.crewId = crewId;
85
86
  this.agents = new Map<string, StatefulAxAgent>();
@@ -96,7 +97,7 @@ class AxCrew {
96
97
  try {
97
98
  const agentConfigParams: AgentConfigParams = getAgentConfigParams(
98
99
  agentName,
99
- this.configFilePath,
100
+ this.agentConfig,
100
101
  this.functionsRegistry,
101
102
  this.state
102
103
  );
package/test1.js ADDED
@@ -0,0 +1,98 @@
1
+ import { AxCrew, AxCrewFunctions } from "./dist/index.js";
2
+
3
+ // Define the configuration object directly
4
+ const config = {
5
+ crew: [
6
+ {
7
+ name: "Planner",
8
+ description: "Creates a plan to complete a task",
9
+ signature: "task:string \"a task to be completed\" -> plan:string \"a plan to execute the task in 5 steps or less\"",
10
+ provider: "google-gemini",
11
+ providerKeyName: "GEMINI_API_KEY",
12
+ ai: {
13
+ model: "gemini-1.5-flash",
14
+ temperature: 0
15
+ },
16
+ options: {
17
+ debug: false
18
+ }
19
+ },
20
+ {
21
+ name: "Calculator",
22
+ description: "Solves math problems",
23
+ signature: "mathProblem:string \"a math problem to be solved using Python code\" -> solution:string \"the solution to the math problem\"",
24
+ provider: "google-gemini",
25
+ providerKeyName: "GEMINI_API_KEY",
26
+ ai: {
27
+ model: "gemini-1.5-pro",
28
+ temperature: 0
29
+ },
30
+ options: {
31
+ debug: true,
32
+ codeExecution: true
33
+ },
34
+ functions: ["CurrentDateTime", "DaysBetweenDates"]
35
+ },
36
+ {
37
+ name: "WebSearch",
38
+ description: "Searches the web for the latest information using Google search",
39
+ signature: "webSearchQuery:string \"a query for Google search\" -> webSearchResponse:string \"the result of the search\"",
40
+ provider: "google-gemini",
41
+ providerKeyName: "GEMINI_API_KEY",
42
+ ai: {
43
+ model: "gemini-1.5-pro",
44
+ temperature: 0
45
+ },
46
+ options: {
47
+ debug: true,
48
+ googleSearchRetrieval: true
49
+ },
50
+ functions: ["CurrentDateTime", "DaysBetweenDates"]
51
+ },
52
+ {
53
+ name: "Manager",
54
+ description: "Answers questions from the user",
55
+ signature: "question:string \"a question from a user\", plan:string \"a suggested plan to answer the question\" -> answer:string \"the answer\"",
56
+ provider: "openai",
57
+ providerKeyName: "OPENAI_API_KEY",
58
+ ai: {
59
+ model: "gpt-4o-mini",
60
+ temperature: 0
61
+ },
62
+ options: {
63
+ debug: true
64
+ },
65
+ functions: ["CurrentDateTime", "DaysBetweenDates"]
66
+ }
67
+ ]
68
+ };
69
+
70
+ // Create crew instance with the direct configuration
71
+ const crew = new AxCrew(config, AxCrewFunctions);
72
+ crew.addAgentsToCrew(["Planner", "Calculator", "WebSearch", "Manager"]);
73
+
74
+ const calculateAndPrintAgentCost = (agent, agentName) => {
75
+ const { models, modelUsage, modelInfo } = agent.axai;
76
+
77
+ const { promptTokens, completionTokens } = modelUsage;
78
+ const modelDetails = modelInfo?.find((m) => m.name === models.model);
79
+ const totalCost = ((promptTokens / 1000000) * modelDetails?.promptTokenCostPer1M) + ((completionTokens / 1000000) * modelDetails?.completionTokenCostPer1M);
80
+
81
+ console.log(`\n${agentName} Usage:\nPrompt Token Cost: $${(promptTokens / 1000000 * modelDetails?.promptTokenCostPer1M).toFixed(6)}\nCompletion Token Cost: $${(completionTokens / 1000000 * modelDetails?.completionTokenCostPer1M).toFixed(6)}\nTotal Cost: $${totalCost.toFixed(6)}\nPrompt Tokens: ${promptTokens}\nCompletion Tokens: ${completionTokens}\nTotal Tokens: ${promptTokens + completionTokens}`);
82
+ };
83
+
84
+ const userQuery = "what is the cube root of the number of days between now and Christmas";
85
+ console.log(`\n\nQuestion: ${userQuery}`);
86
+
87
+ const Planner = crew.agents.get("Planner");
88
+ const plannerResponse = await Planner.forward({ task: userQuery });
89
+ console.log(`\n\nPlanner Response: ${plannerResponse.plan}`);
90
+
91
+ const Manager = crew.agents.get("Manager");
92
+ const managerResponse = await Manager.forward({ question: userQuery, plan: plannerResponse.plan });
93
+ console.log(`\n\nManager Response: ${managerResponse.answer}`);
94
+
95
+ // const calculatorResponse = await crew.agents.get("Calculator").forward({ mathProblem: userQuery });
96
+ // calculateAndPrintAgentCost(crew.agents.get("Calculator"), "Calculator");
97
+
98
+ // console.log(`\n\nAnswer: ${calculatorResponse.solution}`);