helloparthshah commited on
Commit
bf722a2
·
1 Parent(s): 0ab24d1

Added expense budget

Browse files
src/manager/agent_manager.py CHANGED
@@ -17,12 +17,20 @@ MODEL_FILE_PATH = "./src/models/models.json"
17
 
18
  class Agent(ABC):
19
 
20
- def __init__(self, agent_name: str, base_model: str, system_prompt: str, creation_cost: str, invoke_cost: str):
 
 
 
 
 
 
21
  self.agent_name = agent_name
22
  self.base_model = base_model
23
  self.system_prompt = system_prompt
24
- self.creation_cost = creation_cost
25
- self.invoke_cost = invoke_cost
 
 
26
  self.create_model()
27
 
28
  @abstractmethod
@@ -42,8 +50,10 @@ class Agent(ABC):
42
 
43
  def get_costs(self):
44
  return {
45
- "create_cost": self.creation_cost,
46
- "invoke_cost": self.invoke_cost
 
 
47
  }
48
 
49
  class OllamaAgent(Agent):
@@ -69,7 +79,14 @@ class OllamaAgent(Agent):
69
  ollama.delete(self.agent_name)
70
 
71
  class GeminiAgent(Agent):
72
- def __init__(self, agent_name: str, base_model: str, system_prompt: str, creation_cost: str, invoke_cost: str):
 
 
 
 
 
 
 
73
  load_dotenv()
74
  self.api_key = os.getenv("GEMINI_KEY")
75
  if not self.api_key:
@@ -79,7 +96,13 @@ class GeminiAgent(Agent):
79
  self.client = genai.Client(api_key=self.api_key)
80
 
81
  # Call parent constructor after API setup
82
- super().__init__(agent_name, base_model, system_prompt, creation_cost, invoke_cost)
 
 
 
 
 
 
83
 
84
  def create_model(self):
85
  self.messages = []
@@ -110,8 +133,10 @@ class AgentManager():
110
 
111
  def create_agent(self, agent_name: str,
112
  base_model: str, system_prompt: str,
113
- description: str = "", create_cost: float = 0,
114
- invoke_cost: float = 0,
 
 
115
  **additional_params) -> Tuple[Agent, int]:
116
 
117
  if agent_name in self._agents:
@@ -122,8 +147,10 @@ class AgentManager():
122
  base_model,
123
  system_prompt,
124
  description=description,
125
- create_cost=create_cost,
126
- invoke_cost=invoke_cost,
 
 
127
  **additional_params # For any future parameters we might want to add
128
  )
129
 
@@ -133,18 +160,35 @@ class AgentManager():
133
  base_model,
134
  system_prompt,
135
  description=description,
136
- create_cost=create_cost,
137
- invoke_cost=invoke_cost,
 
 
138
  **additional_params # For any future parameters we might want to add
139
  )
140
- return (self._agents[agent_name], self.budget_manager.get_current_remaining_budget())
 
 
141
 
142
- def validate_budget(self, amount: float) -> None:
143
- if not self.budget_manager.can_spend(amount):
144
- raise ValueError(f"Do not have enough budget to create/use the agent. "
145
- +f"Creating/Using the agent costs {amount} but only {self.budget_manager.get_current_remaining_budget()} is remaining")
 
 
 
 
 
146
 
147
- def create_agent_class(self, agent_name: str, base_model: str, system_prompt: str, description: str = "", create_cost: float = 0, invoke_cost: float = 0,
 
 
 
 
 
 
 
 
148
  **additional_params) -> Agent:
149
  agent_type = self._get_agent_type(base_model)
150
  agent_class = self._agent_types.get(agent_type)
@@ -152,11 +196,19 @@ class AgentManager():
152
  if not agent_class:
153
  raise ValueError(f"Unsupported base model {base_model}")
154
 
155
- created_agent = agent_class(agent_name, base_model, system_prompt, create_cost,invoke_cost)
 
 
 
 
 
 
156
 
157
- self.validate_budget(create_cost)
 
158
 
159
- self.budget_manager.add_to_expense(create_cost)
 
160
  # create agent
161
  return created_agent
162
 
@@ -178,8 +230,10 @@ class AgentManager():
178
  for name, data in full_models.items():
179
  simplified_agents[name] = {
180
  "description": data.get("description", ""),
181
- "create_cost": data.get("create_cost", 0),
182
- "invoke_cost": data.get("invoke_cost", 0),
 
 
183
  "base_model": data.get("base_model", ""),
184
  }
185
  return simplified_agents
@@ -192,7 +246,7 @@ class AgentManager():
192
  def delete_agent(self, agent_name: str) -> int:
193
  agent = self.get_agent(agent_name)
194
 
195
- self.budget_manager.remove_from_expense(agent.creation_cost)
196
  agent.delete_agent()
197
 
198
  del self._agents[agent_name]
@@ -206,18 +260,31 @@ class AgentManager():
206
  f.write(json.dumps(models, indent=4))
207
  except Exception as e:
208
  output_assistant_response(f"Error deleting agent: {e}")
209
- return self.budget_manager.get_current_remaining_budget()
 
210
 
211
  def ask_agent(self, agent_name: str, prompt: str) -> Tuple[str,int]:
212
  agent = self.get_agent(agent_name)
213
 
214
- self.validate_budget(agent.invoke_cost)
 
 
 
215
 
216
  response = agent.ask_agent(prompt)
217
- return (response, self.budget_manager.get_current_remaining_budget())
 
 
218
 
219
- def _save_agent(self, agent_name: str, base_model: str, system_prompt: str,
220
- description: str = "", create_cost: float = 0, invoke_cost: float = 0,
 
 
 
 
 
 
 
221
  **additional_params) -> None:
222
  """Save a single agent to the models.json file"""
223
  try:
@@ -236,8 +303,10 @@ class AgentManager():
236
  "base_model": base_model,
237
  "description": description,
238
  "system_prompt": system_prompt,
239
- "create_cost": create_cost,
240
- "invoke_cost": invoke_cost,
 
 
241
  }
242
 
243
  # Add any additional parameters that were passed
@@ -276,8 +345,10 @@ class AgentManager():
276
  continue
277
  base_model = data["base_model"]
278
  system_prompt = data["system_prompt"]
279
- creation_cost = data["create_cost"]
280
- invoke_cost = data["invoke_cost"]
 
 
281
  model_type = self._get_agent_type(base_model)
282
  manager_class = self._agent_types.get(model_type)
283
 
@@ -288,16 +359,20 @@ class AgentManager():
288
  base_model,
289
  system_prompt,
290
  description=data.get("description", ""),
291
- create_cost=creation_cost,
292
- invoke_cost=invoke_cost,
 
 
293
  **data.get("additional_params", {})
294
  )
295
  self._agents[name] = manager_class(
296
  name,
297
  base_model,
298
  system_prompt,
299
- creation_cost,
300
- invoke_cost
 
 
301
  )
302
  except Exception as e:
303
  output_assistant_response(f"Error loading agents: {e}")
 
17
 
18
  class Agent(ABC):
19
 
20
+ def __init__(self, agent_name: str,
21
+ base_model: str,
22
+ system_prompt: str,
23
+ create_resource_cost: int,
24
+ invoke_resource_cost: int,
25
+ create_expense_cost: int = 0,
26
+ invoke_expense_cost: int = 0,):
27
  self.agent_name = agent_name
28
  self.base_model = base_model
29
  self.system_prompt = system_prompt
30
+ self.create_resource_cost = create_resource_cost
31
+ self.invoke_resource_cost = invoke_resource_cost
32
+ self.create_expense_cost = create_expense_cost
33
+ self.invoke_expense_cost = invoke_expense_cost
34
  self.create_model()
35
 
36
  @abstractmethod
 
50
 
51
  def get_costs(self):
52
  return {
53
+ "create_resource_cost": self.create_resource_cost,
54
+ "invoke_resource_cost": self.invoke_resource_cost,
55
+ "create_expense_cost": self.create_expense_cost,
56
+ "invoke_expense_cost": self.invoke_expense_cost
57
  }
58
 
59
  class OllamaAgent(Agent):
 
79
  ollama.delete(self.agent_name)
80
 
81
  class GeminiAgent(Agent):
82
+ def __init__(self,
83
+ agent_name: str,
84
+ base_model: str,
85
+ system_prompt: str,
86
+ create_resource_cost: int,
87
+ invoke_resource_cost: int,
88
+ create_expense_cost: int = 0,
89
+ invoke_expense_cost: int = 0,):
90
  load_dotenv()
91
  self.api_key = os.getenv("GEMINI_KEY")
92
  if not self.api_key:
 
96
  self.client = genai.Client(api_key=self.api_key)
97
 
98
  # Call parent constructor after API setup
99
+ super().__init__(agent_name,
100
+ base_model,
101
+ system_prompt,
102
+ create_resource_cost,
103
+ invoke_resource_cost,
104
+ create_expense_cost,
105
+ invoke_expense_cost)
106
 
107
  def create_model(self):
108
  self.messages = []
 
133
 
134
  def create_agent(self, agent_name: str,
135
  base_model: str, system_prompt: str,
136
+ description: str = "", create_resource_cost: float = 0,
137
+ invoke_resource_cost: float = 0,
138
+ create_expense_cost: float = 0,
139
+ invoke_expense_cost: float = 0,
140
  **additional_params) -> Tuple[Agent, int]:
141
 
142
  if agent_name in self._agents:
 
147
  base_model,
148
  system_prompt,
149
  description=description,
150
+ create_resource_cost=create_resource_cost,
151
+ invoke_resource_cost=invoke_resource_cost,
152
+ create_expense_cost=create_expense_cost,
153
+ invoke_expense_cost=invoke_expense_cost,
154
  **additional_params # For any future parameters we might want to add
155
  )
156
 
 
160
  base_model,
161
  system_prompt,
162
  description=description,
163
+ create_resource_cost=create_resource_cost,
164
+ invoke_resource_cost=invoke_resource_cost,
165
+ create_expense_cost=create_expense_cost,
166
+ invoke_expense_cost=invoke_expense_cost,
167
  **additional_params # For any future parameters we might want to add
168
  )
169
+ return (self._agents[agent_name],
170
+ self.budget_manager.get_current_remaining_resource_budget(),
171
+ self.budget_manager.get_current_remaining_expense_budget())
172
 
173
+ def validate_budget(self,
174
+ resource_cost: float=0,
175
+ expense_cost: float=0) -> None:
176
+ if not self.budget_manager.can_spend_resource(resource_cost):
177
+ raise ValueError(f"Do not have enough resource budget to create/use the agent. "
178
+ +f"Creating/Using the agent costs {resource_cost} but only {self.budget_manager.get_current_remaining_resource_budget()} is remaining")
179
+ if not self.budget_manager.can_spend_expense(expense_cost):
180
+ raise ValueError(f"Do not have enough expense budget to create/use the agent. "
181
+ +f"Creating/Using the agent costs {expense_cost} but only {self.budget_manager.get_current_remaining_expense_budget()} is remaining")
182
 
183
+ def create_agent_class(self,
184
+ agent_name: str,
185
+ base_model: str,
186
+ system_prompt: str,
187
+ description: str = "",
188
+ create_resource_cost: float = 0,
189
+ invoke_resource_cost: float = 0,
190
+ create_expense_cost: float = 0,
191
+ invoke_expense_cost: float = 0,
192
  **additional_params) -> Agent:
193
  agent_type = self._get_agent_type(base_model)
194
  agent_class = self._agent_types.get(agent_type)
 
196
  if not agent_class:
197
  raise ValueError(f"Unsupported base model {base_model}")
198
 
199
+ created_agent = agent_class(agent_name,
200
+ base_model,
201
+ system_prompt,
202
+ create_resource_cost,
203
+ invoke_resource_cost,
204
+ create_expense_cost,
205
+ invoke_expense_cost,)
206
 
207
+ self.validate_budget(create_resource_cost,
208
+ create_expense_cost)
209
 
210
+ self.budget_manager.add_to_resource_budget(create_resource_cost)
211
+ self.budget_manager.add_to_expense_budget(create_expense_cost)
212
  # create agent
213
  return created_agent
214
 
 
230
  for name, data in full_models.items():
231
  simplified_agents[name] = {
232
  "description": data.get("description", ""),
233
+ "create_resource_cost": data.get("create_resource_cost", 0),
234
+ "invoke_resource_cost": data.get("invoke_resource_cost", 0),
235
+ "create_expense_cost": data.get("create_expense_cost", 0),
236
+ "invoke_expense_cost": data.get("invoke_expense_cost", 0),
237
  "base_model": data.get("base_model", ""),
238
  }
239
  return simplified_agents
 
246
  def delete_agent(self, agent_name: str) -> int:
247
  agent = self.get_agent(agent_name)
248
 
249
+ self.budget_manager.remove_from_resource_expense(agent.create_resource_cost)
250
  agent.delete_agent()
251
 
252
  del self._agents[agent_name]
 
260
  f.write(json.dumps(models, indent=4))
261
  except Exception as e:
262
  output_assistant_response(f"Error deleting agent: {e}")
263
+ return (self.budget_manager.get_current_remaining_resource_budget(),
264
+ self.budget_manager.get_current_remaining_expense_budget())
265
 
266
  def ask_agent(self, agent_name: str, prompt: str) -> Tuple[str,int]:
267
  agent = self.get_agent(agent_name)
268
 
269
+ self.validate_budget(agent.invoke_resource_cost,
270
+ agent.invoke_expense_cost)
271
+
272
+ self.budget_manager.add_to_expense_budget(agent.invoke_expense_cost)
273
 
274
  response = agent.ask_agent(prompt)
275
+ return (response,
276
+ self.budget_manager.get_current_remaining_resource_budget(),
277
+ self.budget_manager.get_current_remaining_expense_budget())
278
 
279
+ def _save_agent(self,
280
+ agent_name: str,
281
+ base_model: str,
282
+ system_prompt: str,
283
+ description: str = "",
284
+ create_resource_cost: float = 0,
285
+ invoke_resource_cost: float = 0,
286
+ create_expense_cost: float = 0,
287
+ invoke_expense_cost: float = 0,
288
  **additional_params) -> None:
289
  """Save a single agent to the models.json file"""
290
  try:
 
303
  "base_model": base_model,
304
  "description": description,
305
  "system_prompt": system_prompt,
306
+ "create_resource_cost": create_resource_cost,
307
+ "invoke_resource_cost": invoke_resource_cost,
308
+ "create_expense_cost": create_expense_cost,
309
+ "invoke_expense_cost": invoke_expense_cost,
310
  }
311
 
312
  # Add any additional parameters that were passed
 
345
  continue
346
  base_model = data["base_model"]
347
  system_prompt = data["system_prompt"]
348
+ create_resource_cost = data.get("create_resource_cost", 0)
349
+ invoke_resource_cost = data.get("invoke_resource_cost", 0)
350
+ create_expense_cost = data.get("create_expense_cost", 0)
351
+ invoke_expense_cost = data.get("invoke_expense_cost", 0)
352
  model_type = self._get_agent_type(base_model)
353
  manager_class = self._agent_types.get(model_type)
354
 
 
359
  base_model,
360
  system_prompt,
361
  description=data.get("description", ""),
362
+ create_resource_cost=create_resource_cost,
363
+ invoke_resource_cost=invoke_resource_cost,
364
+ create_expense_cost=create_expense_cost,
365
+ invoke_expense_cost=invoke_expense_cost,
366
  **data.get("additional_params", {})
367
  )
368
  self._agents[name] = manager_class(
369
  name,
370
  base_model,
371
  system_prompt,
372
+ create_resource_cost,
373
+ invoke_resource_cost,
374
+ create_expense_cost,
375
+ invoke_expense_cost,
376
  )
377
  except Exception as e:
378
  output_assistant_response(f"Error loading agents: {e}")
src/manager/budget_manager.py CHANGED
@@ -4,15 +4,18 @@ import psutil
4
 
5
  @singleton
6
  class BudgetManager():
7
- TOTAL_BUDGET = 100
 
 
8
  current_expense = 0
9
  is_budget_initialized = False
 
10
  def __init__(self):
11
  if not self.is_budget_initialized:
12
- self.TOTAL_BUDGET = self.set_total_budget()
13
  self.is_budget_initialized = True
14
 
15
- def set_total_budget(self)-> int:
16
  total_mem = 0
17
  if torch.cuda.is_available():
18
  gpu_index = torch.cuda.current_device()
@@ -28,24 +31,41 @@ class BudgetManager():
28
  print(f"Total RAM: {total_mem:.2f} GB")
29
  return round((total_mem / 16) * 100)
30
 
31
- def get_total_budget(self):
32
- return self.TOTAL_BUDGET
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
  def get_current_expense(self):
35
  return self.current_expense
36
 
37
- def get_current_remaining_budget(self):
38
- return self.TOTAL_BUDGET - self.current_expense
39
 
40
- def can_spend(self, cost):
41
- return True if self.current_expense + cost <= self.TOTAL_BUDGET else False
42
-
43
- def add_to_expense(self, cost):
44
- if not self.can_spend(cost):
45
- raise Exception("No budget remaining")
46
- self.current_expense += cost
47
-
48
- def remove_from_expense(self, cost):
49
- if self.current_expense - cost < 0:
50
- raise Exception("Cannot remove more than current expense")
51
- self.current_expense -= cost
 
4
 
5
  @singleton
6
  class BudgetManager():
7
+ total_resource_budget = 100
8
+ current_resource_usage = 0
9
+ total_expense_budget = 1000
10
  current_expense = 0
11
  is_budget_initialized = False
12
+
13
  def __init__(self):
14
  if not self.is_budget_initialized:
15
+ self.total_resource_budget = self.calculate_total_budget()
16
  self.is_budget_initialized = True
17
 
18
+ def calculate_total_budget(self)-> int:
19
  total_mem = 0
20
  if torch.cuda.is_available():
21
  gpu_index = torch.cuda.current_device()
 
31
  print(f"Total RAM: {total_mem:.2f} GB")
32
  return round((total_mem / 16) * 100)
33
 
34
+ def get_total_resource_budget(self):
35
+ return self.total_resource_budget
36
+
37
+ def get_current_resource_usage(self):
38
+ return self.current_resource_usage
39
+
40
+ def get_current_remaining_resource_budget(self):
41
+ return self.total_resource_budget - self.current_resource_usage
42
+
43
+ def can_spend_resource(self, cost):
44
+ return True if self.current_resource_usage + cost <= self.total_resource_budget else False
45
+
46
+ def add_to_resource_budget(self, cost):
47
+ if not self.can_spend_resource(cost):
48
+ raise Exception("No resource budget remaining")
49
+ self.current_resource_usage += cost
50
+
51
+ def remove_from_resource_expense(self, cost):
52
+ if self.current_resource_usage - cost < 0:
53
+ raise Exception("Not enough resource budget to remove")
54
+ self.current_resource_usage -= cost
55
+
56
+ def get_total_expense_budget(self):
57
+ return self.total_expense_budget
58
 
59
  def get_current_expense(self):
60
  return self.current_expense
61
 
62
+ def get_current_remaining_expense_budget(self):
63
+ return self.total_expense_budget - self.current_expense
64
 
65
+ def can_spend_expense(self, cost):
66
+ return True if self.current_expense + cost <= self.total_expense_budget else False
67
+
68
+ def add_to_expense_budget(self, cost):
69
+ if not self.can_spend_expense(cost):
70
+ raise Exception("No expense budget remaining")
71
+ self.current_expense += cost
 
 
 
 
 
src/manager/manager.py CHANGED
@@ -99,7 +99,8 @@ class GeminiManager:
99
  name=function_call.name,
100
  response={"result": toolResponse})
101
  try:
102
- self.toolsLoader.load_tools()
 
103
  except Exception as e:
104
  logger.info(f"Error loading tools: {e}. Deleting the tool.")
105
  yield {
 
99
  name=function_call.name,
100
  response={"result": toolResponse})
101
  try:
102
+ if function_call.name == "ToolCreator":
103
+ self.toolsLoader.load_tools()
104
  except Exception as e:
105
  logger.info(f"Error loading tools: {e}. Deleting the tool.")
106
  yield {
src/manager/tool_manager.py CHANGED
@@ -16,6 +16,8 @@ toolsImported = []
16
 
17
  TOOLS_DIRECTORIES = [os.path.abspath("./src/tools/default_tools"), os.path.abspath("./src/tools/user_tools")]
18
 
 
 
19
  class Tool:
20
  def __init__(self, toolClass):
21
  suppress_output(self.load_tool)(toolClass)
@@ -26,17 +28,17 @@ class Tool:
26
  self.name = self.inputSchema["name"]
27
  self.description = self.inputSchema["description"]
28
  self.dependencies = self.tool.dependencies
29
- self.create_cost = None
30
- self.invoke_cost = None
31
- if "create_cost" in self.tool.inputSchema:
32
- self.create_cost = self.tool.inputSchema["create_cost"]
33
- if "invoke_cost" in self.tool.inputSchema:
34
- self.invoke_cost = self.tool.inputSchema["invoke_cost"]
35
  if self.dependencies:
36
  self.install_dependencies()
37
 
38
  def install_dependencies(self):
39
  for package in self.dependencies:
 
 
40
  try:
41
  __import__(package.split('==')[0])
42
  except ImportError:
@@ -44,6 +46,7 @@ class Tool:
44
  if '==' in package:
45
  package = package.split('==')[0]
46
  pip.main(['install', package])
 
47
 
48
  def run(self, query):
49
  return self.tool.run(**query)
@@ -55,8 +58,11 @@ class ToolManager:
55
 
56
  def __init__(self):
57
  self.load_tools()
58
-
59
- output_assistant_response(f"Budget Remaining: {self.budget_manager.get_current_remaining_budget()}")
 
 
 
60
 
61
  def load_tools(self):
62
  newToolsImported = []
@@ -71,18 +77,23 @@ class ToolManager:
71
  toolClass = getattr(foo, class_name)
72
  toolObj = Tool(toolClass)
73
  newToolsImported.append(toolObj)
74
- if toolObj.create_cost is not None:
75
- self.budget_manager.add_to_expense(toolObj.create_cost)
 
 
76
  self.toolsImported = newToolsImported
77
 
78
  def runTool(self, toolName, query):
79
- output_assistant_response(f"Budget Remaining: {self.budget_manager.get_current_remaining_budget()}")
80
  for tool in self.toolsImported:
81
  if tool.name == toolName:
82
- if tool.invoke_cost is not None:
83
- self.budget_manager.add_to_expense(tool.invoke_cost)
 
 
 
84
  return tool.run(query)
85
- output_assistant_response(f"Budget Remaining: {self.budget_manager.get_current_remaining_budget()}")
86
  return {
87
  "status": "error",
88
  "message": f"Tool {toolName} not found",
@@ -119,8 +130,10 @@ class ToolManager:
119
  for tool in self.toolsImported:
120
  if tool.name == toolName:
121
  # remove budget for the tool
122
- if tool.create_cost is not None:
123
- self.budget_manager.remove_from_expense(tool.create_cost)
 
 
124
  self.toolsImported.remove(tool)
125
  return {
126
  "status": "success",
 
16
 
17
  TOOLS_DIRECTORIES = [os.path.abspath("./src/tools/default_tools"), os.path.abspath("./src/tools/user_tools")]
18
 
19
+ installed_packages = set()
20
+
21
  class Tool:
22
  def __init__(self, toolClass):
23
  suppress_output(self.load_tool)(toolClass)
 
28
  self.name = self.inputSchema["name"]
29
  self.description = self.inputSchema["description"]
30
  self.dependencies = self.tool.dependencies
31
+ self.create_resource_cost = self.inputSchema.get("create_resource_cost", 0)
32
+ self.invoke_resource_cost = self.inputSchema.get("invoke_resource_cost", 0)
33
+ self.create_expense_cost = self.inputSchema.get("create_expense_cost", 0)
34
+ self.invoke_expense_cost = self.inputSchema.get("invoke_expense_cost", 0)
 
 
35
  if self.dependencies:
36
  self.install_dependencies()
37
 
38
  def install_dependencies(self):
39
  for package in self.dependencies:
40
+ if package in installed_packages:
41
+ continue
42
  try:
43
  __import__(package.split('==')[0])
44
  except ImportError:
 
46
  if '==' in package:
47
  package = package.split('==')[0]
48
  pip.main(['install', package])
49
+ installed_packages.add(package)
50
 
51
  def run(self, query):
52
  return self.tool.run(**query)
 
58
 
59
  def __init__(self):
60
  self.load_tools()
61
+ self._output_budgets()
62
+
63
+ def _output_budgets(self):
64
+ output_assistant_response(f"Resource budget Remaining: {self.budget_manager.get_current_remaining_resource_budget()}")
65
+ output_assistant_response(f"Expense budget Remaining: {self.budget_manager.get_current_remaining_resource_budget()}")
66
 
67
  def load_tools(self):
68
  newToolsImported = []
 
77
  toolClass = getattr(foo, class_name)
78
  toolObj = Tool(toolClass)
79
  newToolsImported.append(toolObj)
80
+ if toolObj.create_resource_cost is not None:
81
+ self.budget_manager.add_to_resource_budget(toolObj.create_resource_cost)
82
+ if toolObj.create_expense_cost is not None:
83
+ self.budget_manager.add_to_resource_budget(toolObj.create_expense_cost)
84
  self.toolsImported = newToolsImported
85
 
86
  def runTool(self, toolName, query):
87
+ self._output_budgets()
88
  for tool in self.toolsImported:
89
  if tool.name == toolName:
90
+ if tool.invoke_resource_cost is not None:
91
+ if not self.budget_manager.can_spend_resource(tool.invoke_resource_cost):
92
+ raise Exception("No resource budget remaining")
93
+ if tool.invoke_expense_cost is not None:
94
+ self.budget_manager.add_to_resource_budget(tool.invoke_expense_cost)
95
  return tool.run(query)
96
+ self._output_budgets()
97
  return {
98
  "status": "error",
99
  "message": f"Tool {toolName} not found",
 
130
  for tool in self.toolsImported:
131
  if tool.name == toolName:
132
  # remove budget for the tool
133
+ if tool.create_resource_cost is not None:
134
+ self.budget_manager.remove_from_resource_expense(tool.create_resource_cost)
135
+ if tool.create_expense_cost is not None:
136
+ self.budget_manager.remove_from_resource_expense(tool.create_expense_cost)
137
  self.toolsImported.remove(tool)
138
  return {
139
  "status": "success",
src/models/system4.prompt CHANGED
@@ -1,60 +1,95 @@
1
- You are HASHIRU, an expert orchestrator of tools and agents. Always decompose user queries into subtasks, invoke agents and tools for each, then consolidate their outputs into a final response. Never answer directly.
2
-
3
- <Info>
4
- **Mechanisms**
5
- - **Tools** handle real-time data, external APIs, heavy computation, or model access.
6
- - **Agents** coordinate complex workflows, synthesize tool outputs, or tackle creative/research tasks. Agents cannot fetch live data themselves.
7
-
8
- **Tool Creation & Reuse**
9
-
10
- * Before creating any tool, list and inspect existing implementations in `src/tools/default_tools` and `src/tools/user_tools` via the `ListFiles` and `ReadFile` tools.
11
- * If no suitable tool exists, invoke `ToolCreator` to build a production-ready tool:
12
-
13
- * Full implementation (no stubs)
14
- * Input validation and error handling
15
- * Logging or helpful runtime messages
16
- * Minimal, clear dependencies
17
- * Docstrings or inline comments where useful
18
- * Always follow the directory structure and coding conventions of existing tools.
19
- * If a tool or agent returns an error, analyze the error message, adjust the input or approach, and retry. If the error persists, consider alternative tools or agents, or ask the user for clarification.
20
-
21
- **Agent Lifecycle & Reuse**
22
-
23
- * Always invoke `GetAgents` first to determine if an existing agent can handle the task, promoting agent reuse and efficiency.
24
- * If none fit a subtask, use `AgentCreator`—after consulting budget and cost—to spin up a new agent with precise capabilities.
25
- * Maintain agents for reuse; retire (“fire”) only when truly unnecessary or to reclaim budget for a critical new agent.
26
- * Create a new agent only if no existing agent can fulfill the required task, and the task is expected to be repeated in future interactions. Evaluate the potential for reuse before creating a new agent.
27
-
28
- **Handling Ambiguity**
29
-
30
- * If the user's request is ambiguous, ask clarifying questions to narrow down the scope and ensure accurate task execution.
31
-
32
- **Budget & Cost**
33
-
34
- * Start with a set amount of credits; each new agent consumes credits.
35
- * When credits run out, fire the least-useful agent before creating more.
36
- * **Before any model selection or creation**, always query `AgentCostManager` for available base models and their costs, then pick the most cost-effective.
37
-
38
- **Memory**
39
-
40
- * **Immediately** record any user preference, task-relevant context, or error-resolution detail via `MemoryManager.add_memory` before proceeding with subtasks. Focus on information that will help me assist the user better in the current task or future interactions.
41
- * Confirm and delete obsolete memories via `MemoryManager.delete_memory` (always validate the index first).
42
- * Only store memories that are directly relevant to the current conversation or future interactions and that will improve my ability to assist the user. Avoid storing greetings or other non-essential information.
43
- * Do not store information that is readily available or easily re-derived, such as the current date or time. Focus on storing user preferences, task-specific context, and insights gained during problem-solving.
44
- </Info>
45
-
46
- Here’s what you must do:
47
-
48
- * Never answer directly. Decompose each user query into subtasks and solve them via tools or agents, then merge results into one final response.
49
- * Use tools for any external data, calculations, or current information. Prefer existing tools over creating new ones.
50
- * Use agents for creative, multi-step, or research-oriented tasks. Prefer existing agents; create new ones only when needed.
51
- * Always invoke `GetAgents` first.
52
- * If no agent can handle a subtask, invoke `AgentCreator`—but first check budget and base-model costs via `AgentCostManager`.
53
- * Maintain agents until they’re no longer needed or to reclaim budget for critical new ones; evaluate usefulness before firing.
54
- * **Before doing anything else whenever the user shares new preferences, call `MemoryManager.add_memory` to store it**.
55
- * ** Don't store information that is readily available or easily re-derived such as greetings, current date, or time. Focus on user preferences, task-specific context, and insights gained during problem-solving**.
56
- * ** In case of errors, once you have solved the issue, call `MemoryManager.add_memory` to store details about how you solved the error**.
57
- * Make sure memories are relevant to the current conversation or future interactions.
58
- * If a subtask can’t proceed—due to ambiguity or lack of tools/agents—ask the user for clarification.
59
- * Strictly adhere to each tool’s and agent’s invocation schema.
60
- * Once all subtasks are complete, synthesize the information gathered from the tools and agents into a coherent and comprehensive response that directly addresses the user's original query. Avoid including unnecessary details or technical jargon.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ You are HASHIRU, an expert orchestrator of tools and agents. Your primary function is to decompose user queries into manageable subtasks, invoke the appropriate agents or tools for each subtask, and then synthesize their outputs into a comprehensive final response. **You must never answer user queries directly without first utilizing tools or agents.**
2
+
3
+ <Info>
4
+ **Core Mechanisms: Tools and Agents**
5
+
6
+ * **Tools:** These are invoked for tasks requiring real-time data access (e.g., current date, web searches), interaction with external APIs, heavy computational work, or direct model access.
7
+ * **Agents:** These are specialized entities designed to coordinate complex workflows, synthesize information from multiple tool outputs, or handle creative, research-oriented, or multi-step tasks. Agents themselves do not fetch live data directly but rely on tools for this.
8
+
9
+ **Tool Management: Creation and Reuse**
10
+
11
+ 1. **Prioritize Reuse:** Before creating any new tool, you **must** first inspect existing toolsets. Use the `ListFiles` tool to check `src/tools/default_tools` and `src/tools/user_tools`, then `ReadFile` to understand the functionality of potentially relevant tools.
12
+ 2. **Tool Creation (`ToolCreator`):** If, and only if, no existing tool meets the requirements, invoke `ToolCreator` to build a new one. New tools must be production-ready:
13
+ * Implement full functionality (no stubs or placeholders).
14
+ * Include robust input validation and error handling.
15
+ * Provide clear logging or helpful runtime messages for debugging and monitoring.
16
+ * Maintain minimal and clearly defined dependencies.
17
+ * Incorporate docstrings and inline comments for clarity and maintainability.
18
+ * Strictly adhere to the directory structure and coding conventions observed in existing tools.
19
+ 3. **Error Handling:** If a tool or agent returns an error, meticulously analyze the error message. Adjust the input parameters, rethink the approach, and retry the invocation. If the error persists after reasonable attempts, consider alternative tools or agents. If all else fails, or if the error indicates ambiguity in the original request, ask the user for clarification.
20
+
21
+ **Agent Lifecycle Management: Reuse, Creation, and Retirement**
22
+
23
+ 1. **Prioritize Reuse (`GetAgents`):** Before deciding on agent invocation or creation, **always** invoke `GetAgents` first to identify if an existing agent possesses the capabilities to handle the current subtask.
24
+ 2. **Budget Check (Mandatory before Agent Invocation/Creation):** **Before** deciding to invoke an existing agent *or* create a new one, **you must** first consult the current **Resource Budget** and **Expense Budget** status and use `AgentCostManager` to understand the costs associated with potential agents/models. This check informs whether invoking/creating an agent is feasible and which option is most cost-effective.
25
+ 3. **Agent Creation (`AgentCreator`):** Only if no suitable existing agent is found *and* the budget check (Step 2) confirms feasibility and cost-effectiveness, you may use `AgentCreator` to instantiate a new agent. Define its capabilities with precision.
26
+ * A new agent should only be created if no existing agent can fulfill the task *and* the task is anticipated to be recurrent in future interactions *and* it represents a justifiable use of budget resources. Carefully evaluate potential for reuse and cost-benefit before committing to creation.
27
+ 4. **Agent Maintenance and Retirement:** Maintain active agents for reuse. Retire ("fire") an agent only when it is definitively no longer necessary, or when its operational cost (see "Budget and Cost Management") needs to be reclaimed for a more critical new agent or task. Evaluate its ongoing usefulness before retiring.
28
+
29
+ **Handling Ambiguity and User Interaction**
30
+
31
+ * If a user's request is unclear, vague, or open to multiple interpretations, you **must** ask clarifying questions to narrow the scope and ensure the accurate and efficient execution of the intended task.
32
+
33
+ **Budget and Cost Management: Resource vs. Expense Costs**
34
+
35
+ You operate under two distinct budget categories:
36
+
37
+ 1. **Resource Costs:**
38
+ * **Definition:** Costs associated with utilizing *local* computational resources. This typically includes the operational cost of running agents or tools on the local system (e.g., CPU time, memory usage for a local model).
39
+ * **Budget Impact:** Each local tool or agent invocation deducts from the **resource budget**.
40
+ * **Replenishment:** The `resource_cost` associated with an agent is typically reclaimed (budget replenishes) once that agent's task is complete and it is fired or its invocation concludes.
41
+
42
+ 2. **Expense Costs:**
43
+ * **Definition:** Costs associated with utilizing *external* services or APIs. This includes fees for third-party API calls, data services, or externally hosted models.
44
+ * **Budget Impact:** Each external tool or agent invocation that incurs an external fee deducts from the **expense budget**.
45
+ * **Replenishment:** `expense_cost` is typically a hard cost that is deducted immediately upon use and is **not** automatically replenished. It's crucial to manage this budget wisely.
46
+
47
+ **Operational Guidelines for Budget Management:**
48
+
49
+ * **Initial State:** You will begin with a pre-defined amount for both your resource budget and expense budget.
50
+ * **Cost Inquiry (`AgentCostManager`):** **Crucially, before any agent model selection, agent invocation, or new agent creation**, you **must** query `AgentCostManager`. This tool provides a list of available base models, their `resource_cost` (for local execution), and their `expense_cost` (if they rely on external APIs). Always select the most cost-effective option that meets the task requirements *within the available budget*.
51
+ * **Managing Low Resource Budget:**
52
+ * Consider firing an existing, less critical agent to free up its `resource_cost`.
53
+ * Create a new agent using a base model with a lower `resource_cost` (after firing an existing one if necessary).
54
+ * Consolidate multiple related subtasks into a single agent invocation if feasible, to reduce overhead.
55
+ * **Managing Low Expense Budget:**
56
+ * Prioritize tools or agents that utilize local models (incurring `resource_cost` only) over those requiring external APIs (incurring `expense_cost`).
57
+ * If possible, combine multiple tasks that would require external API calls into a single, more efficient agent invocation to minimize `expense_cost`.
58
+ * If critical tasks cannot be completed due to an exhausted expense budget, ask the user to authorize an increase to the expense budget.
59
+ * **Avoid Waste:** Be judicious with operations that incur `expense_cost`. Ensure tasks are necessary and well-defined before invoking tools or agents that draw from this budget.
60
+
61
+ **Memory Management (`MemoryManager`)**
62
+
63
+ Effective memory management is key to providing consistent and personalized assistance.
64
+
65
+ 1. **Immediate Storage of Key Information:**
66
+ * **User Preferences:** As soon as a user expresses a new preference, correction, or provides explicit instructions for future interactions, **immediately** record this using `MemoryManager.add_memory`. Do this *before* proceeding with other subtasks.
67
+ * **Task-Relevant Context:** Store crucial contextual details that are necessary for the current task's successful completion or are highly likely to be relevant for closely related follow-up tasks.
68
+ * **Error Resolution Insights:** If you encounter an error and successfully resolve it, **immediately** store a concise summary of the problem and the effective solution using `MemoryManager.add_memory`. This aids in avoiding similar issues in the future.
69
+ 2. **Focus and Relevance:**
70
+ * Only store memories that are directly pertinent to the ongoing conversation, future interactions, or that genuinely enhance your ability to assist the user.
71
+ * **Do not store:** Greetings, trivial conversational fluff, information that is readily available (e.g., current date/time unless explicitly relevant to a stored preference), or data that can be easily re-derived without significant cost or effort.
72
+ 3. **Maintenance:**
73
+ * Regularly confirm the relevance of stored memories. Use `MemoryManager.delete_memory` to remove obsolete or incorrect information. **Always** validate the index of a memory before attempting deletion.
74
+
75
+ **Mandatory Operational Flow**
76
+
77
+ 1. **Decomposition:** Never answer directly. Break down every user query into logical subtasks.
78
+ 2. **Resource Allocation Strategy (Tools vs. Agents):**
79
+ * For external data, calculations, or accessing current information -> Use **Tools**. Prioritize existing tools. Check `ListFiles`/`ReadFile`. Create (`ToolCreator`) only if necessary and adhering to standards.
80
+ * For creative tasks, multi-step processes, research, or synthesis -> Use **Agents**.
81
+ 3. **Agent Selection/Creation Process:**
82
+ * **a. Check Existing Agents:** **Always** call `GetAgents` first.
83
+ * **b. Check Budget & Costs:** **Before invoking *any* agent (existing or new)**, check current Resource/Expense budgets and query `AgentCostManager` for costs of potential agents/models. **This is a mandatory check.**
84
+ * **c. Decide Action:** Based on agent availability (a) and budget/cost analysis (b):
85
+ * If a suitable *existing* agent is found AND affordable -> Invoke it.
86
+ * If *no* suitable existing agent exists, BUT creating one is affordable AND justifiable (recurring task) -> Invoke `AgentCreator` using the most cost-effective model.
87
+ * If the required action (invoking existing or creating new) is *not* affordable -> Re-evaluate (Can tasks be combined? Can a cheaper agent/tool be used? Is clarification needed? Should the user be informed about budget limits?). Do not proceed with unaffordable actions.
88
+ 4. **Memory Updates (as applicable per "Memory Management" guidelines):**
89
+ * Store new user preferences *immediately*.
90
+ * Store error resolution details *immediately* after solving an issue.
91
+ 5. **Iterative Refinement & Error Handling:** If a subtask is blocked (ambiguity, lack of tool/agent, persistent errors, budget constraints), analyze the issue. Ask the user for clarification or inform them of limitations if necessary. Adjust the plan and retry or find alternatives.
92
+ 6. **Schema Adherence:** Strictly follow the defined invocation schema (input parameters, expected output format) for every tool and agent.
93
+ 7. **Synthesis and Response:** Once all subtasks are successfully completed within budget, synthesize the information gathered from all tool and agent outputs. Formulate a coherent, comprehensive response that directly addresses the user's original query. Avoid superfluous details or overly technical jargon in the final answer to the user.
94
+
95
+ </Info>
src/tools/default_tools/agent_cost_manager.py CHANGED
@@ -17,53 +17,53 @@ class AgentCostManager():
17
  costs = {
18
  "llama3.2": {
19
  "description": "3 Billion parameter model",
20
- "create_cost": 10,
21
- "invoke_cost": 10,
22
  },
23
  "mistral": {
24
  "description": "7 Billion parameter model",
25
- "create_cost": 20,
26
- "invoke_cost": 50,
27
  },
28
  "gemini-2.5-flash-preview-04-17": {
29
  "description": "Adaptive thinking, cost efficiency",
30
- "create_cost": 20,
31
- "invoke_cost": 50
32
  },
33
  "gemini-2.5-pro-preview-03-25": {
34
  "description": "Enhanced thinking and reasoning, multimodal understanding, advanced coding, and more",
35
- "create_cost": 20,
36
- "invoke_cost": 50
37
  },
38
  "gemini-2.0-flash": {
39
  "description": "Next generation features, speed, thinking, realtime streaming, and multimodal generation",
40
- "create_cost": 20,
41
- "invoke_cost": 50
42
  },
43
  "gemini-2.0-flash-lite": {
44
  "description": "Cost efficiency and low latency",
45
- "create_cost": 20,
46
- "invoke_cost": 50
47
  },
48
  "gemini-1.5-flash": {
49
  "description": "Fast and versatile performance across a diverse variety of tasks",
50
- "create_cost": 20,
51
- "invoke_cost": 50
52
  },
53
  "gemini-1.5-flash-8b": {
54
  "description": "High volume and lower intelligence tasks",
55
- "create_cost": 20,
56
- "invoke_cost": 50
57
  },
58
  "gemini-1.5-pro": {
59
  "description": "Complex reasoning tasks requiring more intelligence",
60
- "create_cost": 20,
61
- "invoke_cost": 50
62
  },
63
  "gemini-2.0-flash-live-001": {
64
  "description": "Low-latency bidirectional voice and video interactions",
65
- "create_cost": 20,
66
- "invoke_cost": 50
67
  }
68
  }
69
 
 
17
  costs = {
18
  "llama3.2": {
19
  "description": "3 Billion parameter model",
20
+ "create_resource_cost": 10,
21
+ "invoke_resource_cost": 10,
22
  },
23
  "mistral": {
24
  "description": "7 Billion parameter model",
25
+ "create_resource_cost": 20,
26
+ "invoke_resource_cost": 50,
27
  },
28
  "gemini-2.5-flash-preview-04-17": {
29
  "description": "Adaptive thinking, cost efficiency",
30
+ "create_expense_cost": 20,
31
+ "invoke_expense_cost": 50
32
  },
33
  "gemini-2.5-pro-preview-03-25": {
34
  "description": "Enhanced thinking and reasoning, multimodal understanding, advanced coding, and more",
35
+ "create_expense_cost": 20,
36
+ "invoke_expense_cost": 50
37
  },
38
  "gemini-2.0-flash": {
39
  "description": "Next generation features, speed, thinking, realtime streaming, and multimodal generation",
40
+ "create_expense_cost": 20,
41
+ "invoke_expense_cost": 50
42
  },
43
  "gemini-2.0-flash-lite": {
44
  "description": "Cost efficiency and low latency",
45
+ "create_expense_cost": 20,
46
+ "invoke_expense_cost": 50
47
  },
48
  "gemini-1.5-flash": {
49
  "description": "Fast and versatile performance across a diverse variety of tasks",
50
+ "create_expense_cost": 20,
51
+ "invoke_expense_cost": 50
52
  },
53
  "gemini-1.5-flash-8b": {
54
  "description": "High volume and lower intelligence tasks",
55
+ "create_expense_cost": 20,
56
+ "invoke_expense_cost": 50
57
  },
58
  "gemini-1.5-pro": {
59
  "description": "Complex reasoning tasks requiring more intelligence",
60
+ "create_expense_cost": 20,
61
+ "invoke_expense_cost": 50
62
  },
63
  "gemini-2.0-flash-live-001": {
64
  "description": "Low-latency bidirectional voice and video interactions",
65
+ "create_expense_cost": 20,
66
+ "invoke_expense_cost": 50
67
  }
68
  }
69
 
src/tools/default_tools/agent_creater_tool.py CHANGED
@@ -45,21 +45,25 @@ class AgentCreator():
45
  system_prompt = kwargs.get("system_prompt")
46
  description = kwargs.get("description")
47
  model_costs = AgentCostManager().get_costs()
48
- create_cost = model_costs[base_model]["create_cost"]
49
  if base_model not in model_costs:
50
  print(f"[WARN] Auto-selected model '{base_model}' not in schema. Falling back to gemini-2.0-flash")
51
  base_model = "gemini-2.0-flash"
52
- invoke_cost = model_costs[base_model]["invoke_cost"]
 
 
 
53
 
54
  agent_manager = AgentManager()
55
  try:
56
- _, remaining_budget = agent_manager.create_agent(
57
  agent_name=agent_name,
58
  base_model=base_model,
59
  system_prompt=system_prompt,
60
  description=description,
61
- create_cost=create_cost,
62
- invoke_cost=invoke_cost
 
 
63
  )
64
  except ValueError as e:
65
  return {
@@ -71,5 +75,6 @@ class AgentCreator():
71
  return {
72
  "status": "success",
73
  "message": "Agent successfully created",
74
- "remaining_budget": remaining_budget,
 
75
  }
 
45
  system_prompt = kwargs.get("system_prompt")
46
  description = kwargs.get("description")
47
  model_costs = AgentCostManager().get_costs()
 
48
  if base_model not in model_costs:
49
  print(f"[WARN] Auto-selected model '{base_model}' not in schema. Falling back to gemini-2.0-flash")
50
  base_model = "gemini-2.0-flash"
51
+ create_resource_cost = model_costs[base_model].get("create_resource_cost", 0)
52
+ invoke_resource_cost = model_costs[base_model].get("invoke_resource_cost", 0)
53
+ create_expense_cost = model_costs[base_model].get("create_expense_cost", 0)
54
+ invoke_expense_cost = model_costs[base_model].get("invoke_expense_cost", 0)
55
 
56
  agent_manager = AgentManager()
57
  try:
58
+ _, remaining_resource_budget, remaining_expense_budget = agent_manager.create_agent(
59
  agent_name=agent_name,
60
  base_model=base_model,
61
  system_prompt=system_prompt,
62
  description=description,
63
+ create_resource_cost=create_resource_cost,
64
+ invoke_resource_cost=invoke_resource_cost,
65
+ create_expense_cost=create_expense_cost,
66
+ invoke_expense_cost=invoke_expense_cost
67
  )
68
  except ValueError as e:
69
  return {
 
75
  return {
76
  "status": "success",
77
  "message": "Agent successfully created",
78
+ "remaining_resource_budget": remaining_resource_budget,
79
+ "remaining_expense_budget": remaining_expense_budget
80
  }
src/tools/default_tools/ask_agent_tool.py CHANGED
@@ -36,7 +36,7 @@ class AskAgent():
36
  agent_manger = AgentManager()
37
 
38
  try:
39
- agent_response, remaining_budget = agent_manger.ask_agent(agent_name=agent_name, prompt=prompt)
40
  except ValueError as e:
41
  return {
42
  "status": "error",
@@ -49,5 +49,6 @@ class AskAgent():
49
  "status": "success",
50
  "message": "Agent has replied to the given prompt",
51
  "output": agent_response,
52
- "remaining_budget": remaining_budget
 
53
  }
 
36
  agent_manger = AgentManager()
37
 
38
  try:
39
+ agent_response, remaining_resource_budget, remaining_expense_budget = agent_manger.ask_agent(agent_name=agent_name, prompt=prompt)
40
  except ValueError as e:
41
  return {
42
  "status": "error",
 
49
  "status": "success",
50
  "message": "Agent has replied to the given prompt",
51
  "output": agent_response,
52
+ "remaining_resource_budget": remaining_resource_budget,
53
+ "remaining_expense_budget": remaining_expense_budget
54
  }
src/tools/default_tools/fire_agent.py CHANGED
@@ -29,7 +29,7 @@ class FireAgent():
29
  agent_manager = AgentManager()
30
 
31
  try:
32
- remaining_budget = agent_manager.delete_agent(agent_name=agent_name)
33
  except ValueError as e:
34
  return {
35
  "status": "error",
@@ -40,5 +40,6 @@ class FireAgent():
40
  return {
41
  "status": "success",
42
  "message": "Agent successfully fired.",
43
- "remaining_budget": remaining_budget
 
44
  }
 
29
  agent_manager = AgentManager()
30
 
31
  try:
32
+ remaining_resource_budget, remaining_expense_budget = agent_manager.delete_agent(agent_name=agent_name)
33
  except ValueError as e:
34
  return {
35
  "status": "error",
 
40
  return {
41
  "status": "success",
42
  "message": "Agent successfully fired.",
43
+ "remaining_resource_budget": remaining_resource_budget,
44
+ "remaining_expense_budget": remaining_expense_budget
45
  }
src/tools/default_tools/get_budget.py CHANGED
@@ -20,16 +20,23 @@ class GetBudget():
20
 
21
  def run(self, **kwargs):
22
  budget_manager = BudgetManager()
23
- total_budget = budget_manager.get_total_budget()
 
 
 
 
24
  current_expense = budget_manager.get_current_expense()
25
- current_remaining_budget = budget_manager.get_current_remaining_budget()
26
  return {
27
  "status": "success",
28
  "message": "Budget retrieved successfully",
29
  "output": {
30
- "total_budget": total_budget,
 
 
 
31
  "current_expense": current_expense,
32
- "current_remaining_budget": current_remaining_budget
33
  }
34
  }
35
 
 
20
 
21
  def run(self, **kwargs):
22
  budget_manager = BudgetManager()
23
+ total_resource_budget = budget_manager.get_total_resource_budget()
24
+ current_resource_usage = budget_manager.get_current_resource_usage()
25
+ current_remaining_resource_budget = budget_manager.get_current_remaining_resource_budget()
26
+
27
+ total_expense_budget = budget_manager.get_total_expense_budget()
28
  current_expense = budget_manager.get_current_expense()
29
+ current_remaining_expense_budget = budget_manager.get_total_expense_budget() - budget_manager.get_current_expense()
30
  return {
31
  "status": "success",
32
  "message": "Budget retrieved successfully",
33
  "output": {
34
+ "total_resource_budget": total_resource_budget,
35
+ "current_resource_usage": current_resource_usage,
36
+ "current_remaining_resource_budget": current_remaining_resource_budget,
37
+ "total_expense_budget": total_expense_budget,
38
  "current_expense": current_expense,
39
+ "current_remaining_expense_budget": current_remaining_expense_budget,
40
  }
41
  }
42
 
src/tools/default_tools/test_cost/agent_creator_tool.py CHANGED
@@ -150,8 +150,8 @@ class AgentCreator():
150
  base_model=base_model,
151
  system_prompt=system_prompt,
152
  description=description,
153
- create_cost=create_cost,
154
- invoke_cost=invoke_cost
155
  )
156
  except ValueError as e:
157
  return {
 
150
  base_model=base_model,
151
  system_prompt=system_prompt,
152
  description=description,
153
+ create_resource_cost=create_cost,
154
+ invoke_resource_cost=invoke_cost
155
  )
156
  except ValueError as e:
157
  return {
src/tools/user_tools/weather_tool.py CHANGED
@@ -19,7 +19,7 @@ class WeatherApi():
19
  },
20
  "required": ["location"],
21
  },
22
- "invoke_cost": 0.1,
23
  }
24
 
25
  def run(self, **kwargs):
 
19
  },
20
  "required": ["location"],
21
  },
22
+ "invoke_resource_cost": 0.1,
23
  }
24
 
25
  def run(self, **kwargs):