joaomorossini commited on
Commit
ecde140
Β·
1 Parent(s): 5cdadc0

Refactor imports in test files to use new agent structure and add utility function for JSON serialization

Browse files
Files changed (25) hide show
  1. .gitignore +3 -1
  2. {agents β†’ agency_ai_demo/agents}/ClickUpAgent/ClickUpAgent.py +0 -0
  3. {agents β†’ agency_ai_demo/agents}/ClickUpAgent/__init__.py +0 -0
  4. {agents β†’ agency_ai_demo/agents}/ClickUpAgent/instructions.md +0 -0
  5. agency_ai_demo/{tools/clickup_tools.py β†’ agents/ClickUpAgent/tools/ClickUpTools.py} +11 -203
  6. agency_ai_demo/agents/ClickUpAgent/tools/ExampleTool.py +30 -0
  7. agency_ai_demo/agents/ClickUpAgent/tools/GetTaskTool.py +78 -0
  8. agency_ai_demo/agents/ClickUpAgent/tools/__init__.py +0 -0
  9. {agents β†’ agency_ai_demo/agents}/ResearchAndReportAgent/ResearchAndReportAgent.py +0 -0
  10. {agents β†’ agency_ai_demo/agents}/ResearchAndReportAgent/__init__.py +0 -0
  11. {agents β†’ agency_ai_demo/agents}/ResearchAndReportAgent/instructions.md +0 -0
  12. agency_ai_demo/agents/ResearchAndReportAgent/tools/ExampleTool.py +30 -0
  13. {agents β†’ agency_ai_demo/agents}/TechnicalProjectManager/TechnicalProjectManager.py +0 -0
  14. {agents β†’ agency_ai_demo/agents}/TechnicalProjectManager/__init__.py +0 -0
  15. {agents β†’ agency_ai_demo/agents}/TechnicalProjectManager/instructions.md +0 -0
  16. agency_ai_demo/agents/TechnicalProjectManager/tools/ExampleTool.py +30 -0
  17. agency_ai_demo/agents/__init__.py +0 -0
  18. agency_ai_demo/demo.ipynb +533 -0
  19. agency_ai_demo/shared_files/agency_manifesto.md +0 -0
  20. agency_ai_demo/tests/test_clickup_agent.py +1 -1
  21. agency_ai_demo/tests/test_clickup_tool_conversion.py +1 -1
  22. agency_ai_demo/tests/test_clickup_tools.py +1 -1
  23. agency_ai_demo/tests/test_list_tasks.py +2 -2
  24. agency_ai_demo/tests/test_tool_directly.py +5 -1
  25. agency_ai_demo/utils/ensure_serializable.py +30 -0
.gitignore CHANGED
@@ -4,4 +4,6 @@ agency-swarm-main/
4
  .cursor
5
  temp/
6
  __pycache__/
7
- settings.json
 
 
 
4
  .cursor
5
  temp/
6
  __pycache__/
7
+ settings.json
8
+ .DS_Store
9
+ .idea/
{agents β†’ agency_ai_demo/agents}/ClickUpAgent/ClickUpAgent.py RENAMED
File without changes
{agents β†’ agency_ai_demo/agents}/ClickUpAgent/__init__.py RENAMED
File without changes
{agents β†’ agency_ai_demo/agents}/ClickUpAgent/instructions.md RENAMED
File without changes
agency_ai_demo/{tools/clickup_tools.py β†’ agents/ClickUpAgent/tools/ClickUpTools.py} RENAMED
@@ -1,4 +1,5 @@
1
  import os
 
2
  import requests
3
  from dotenv import load_dotenv
4
  from langchain.tools import StructuredTool, BaseTool, tool
@@ -9,37 +10,6 @@ from typing import Any, Type, List, Dict
9
  import datetime
10
  import json
11
  import re
12
-
13
-
14
- # Add a utility function to ensure all values are JSON serializable
15
- def _ensure_serializable(obj):
16
- """
17
- Recursively ensure that an object and all its contents are JSON serializable.
18
- Handles Pydantic Field objects by extracting their values.
19
- """
20
- # Handle None
21
- if obj is None:
22
- return None
23
-
24
- # Check if it's a Field object (has certain common Field attributes)
25
- if hasattr(obj, "default") and hasattr(obj, "description"):
26
- # Return the default value or None
27
- if obj.default is not None:
28
- return obj.default
29
- return None
30
-
31
- # Handle dictionaries
32
- if isinstance(obj, dict):
33
- return {k: _ensure_serializable(v) for k, v in obj.items()}
34
-
35
- # Handle lists
36
- if isinstance(obj, list):
37
- return [_ensure_serializable(item) for item in obj]
38
-
39
- # Return other objects as is
40
- return obj
41
-
42
-
43
  from composio.tools.local.clickup.actions.base import OpenAPIAction
44
  from composio.tools.local.clickup.actions.create_task import (
45
  CreateTask,
@@ -76,7 +46,11 @@ from composio.tools.local.clickup.actions.get_task import (
76
  GetTaskResponse,
77
  )
78
 
 
 
 
79
  from utils.tool_wrapper import convert_langchain_tools
 
80
 
81
  load_dotenv()
82
  CLICKUP_TOKEN = os.getenv("CLICKUP_TOKEN")
@@ -306,7 +280,7 @@ class CreateTaskTool(BaseTool):
306
  # Add any other parameters from kwargs
307
  for key, value in kwargs.items():
308
  if value is not None and key != "kwargs" and key != "list_id":
309
- params[key] = _ensure_serializable(value)
310
 
311
  # For testing, ensure we have the minimum required parameters
312
  if "name" not in params:
@@ -461,7 +435,7 @@ class DeleteTaskTool(BaseTool):
461
 
462
  # Make sure all parameters are JSON serializable
463
  params = {
464
- key: _ensure_serializable(value)
465
  for key, value in kwargs.items()
466
  if value is not None and key != "kwargs" and key != "task_id"
467
  }
@@ -772,13 +746,11 @@ class UpdateTaskTool(BaseTool):
772
  # Add update parameters from kwargs
773
  for key, value in kwargs.items():
774
  if value is not None and key != "kwargs" and key != "task_id":
775
- update_params[key] = _ensure_serializable(value)
776
 
777
  # Make sure all parameters are JSON serializable
778
  params = {
779
- k: _ensure_serializable(v)
780
- for k, v in update_params.items()
781
- if v is not None
782
  }
783
 
784
  print(f"Update parameters: {params}")
@@ -967,7 +939,7 @@ class AddDependencyTool(BaseTool):
967
 
968
  # Make sure all parameters are JSON serializable
969
  params = {
970
- key: _ensure_serializable(value)
971
  for key, value in kwargs.items()
972
  if value is not None and key != "kwargs" and key != "task_id"
973
  }
@@ -1139,7 +1111,7 @@ class GetTasksTool(BaseTool):
1139
 
1140
  # Make sure all parameters are JSON serializable
1141
  query_params = {
1142
- k: _ensure_serializable(v)
1143
  for k, v in kwargs.items()
1144
  if v is not None and k != "kwargs"
1145
  }
@@ -1186,170 +1158,6 @@ class GetTasksTool(BaseTool):
1186
  return filtered_response
1187
 
1188
 
1189
- class GetTaskTool(BaseTool):
1190
- name: str = "get_task_tool"
1191
- description: str = """
1192
- Tool to retrieve details of a specific task from ClickUp based on its ID.
1193
- - Get Task:
1194
- Invoke: "GetTaskTool" with the appropriate parameters.
1195
-
1196
- Parameters:
1197
- - task_id (required): The ID of the task to retrieve
1198
- - custom_task_ids (optional): Whether to use custom task IDs
1199
- - team_id (optional): Team ID for the task
1200
- - include_subtasks (optional): Whether to include subtasks
1201
- """
1202
- args_schema: Type[BaseModel] = GetTaskRequest
1203
- headers: dict = {"Authorization": f"{CLICKUP_TOKEN}"}
1204
-
1205
- def __init__(self, **data):
1206
- super().__init__(**data)
1207
-
1208
- def _run(self, **kwargs) -> Any:
1209
- """Executes task retrieval from ClickUp"""
1210
-
1211
- # Log the received parameters to help debug
1212
- print("\n==== GetTaskTool._run received parameters: ====")
1213
- print(f"kwargs: {kwargs}")
1214
-
1215
- # Extract task_id from different possible locations
1216
- task_id = None
1217
- task_name = None
1218
-
1219
- # 1. Direct task_id parameter
1220
- if "task_id" in kwargs:
1221
- task_id = kwargs.get("task_id")
1222
- print(f"Found task_id in direct parameter: {task_id}")
1223
-
1224
- # 2. Check if task_id is inside nested kwargs
1225
- if "kwargs" in kwargs and isinstance(kwargs["kwargs"], dict):
1226
- task_id = task_id or kwargs["kwargs"].get("task_id")
1227
- print(f"Found task_id in nested kwargs: {task_id}")
1228
-
1229
- # 3. Check if task_id is in FieldInfo format
1230
- if "kwargs" in kwargs and hasattr(kwargs["kwargs"], "task_id"):
1231
- if hasattr(kwargs["kwargs"].task_id, "default"):
1232
- task_id = kwargs["kwargs"].task_id.default
1233
- print(f"Found task_id in FieldInfo default: {task_id}")
1234
-
1235
- # 4. Check for task_id in description or raw query
1236
- if "kwargs" in kwargs and hasattr(kwargs["kwargs"], "description"):
1237
- desc = kwargs["kwargs"].description
1238
- # Look for task ID pattern in the description
1239
- task_id_match = re.search(r'task_id[=:]\s*["\']?([0-9a-z]{8,})["\']?', desc)
1240
- if task_id_match:
1241
- task_id = task_id_match.group(1)
1242
- print(f"Found task_id in description: {task_id}")
1243
-
1244
- # Look for task name in the description
1245
- task_name_match = re.search(r'task\s+["\']([^"\']+)["\']', desc)
1246
- if task_name_match:
1247
- task_name = task_name_match.group(1).strip()
1248
- print(f"Found task_name in description: {task_name}")
1249
-
1250
- # 5. Check any string parameters for task_id
1251
- for k, v in kwargs.items():
1252
- if isinstance(v, str):
1253
- # Check if the parameter contains a task ID pattern
1254
- task_id_match = re.search(
1255
- r'task_id[=:]\s*["\']?([0-9a-z]{8,})["\']?', v
1256
- )
1257
- if task_id_match:
1258
- task_id = task_id_match.group(1)
1259
- print(f"Found task_id in string parameter: {task_id}")
1260
- break
1261
-
1262
- # Check for task name pattern in the string
1263
- task_name_match = re.search(r'task\s+["\']([^"\']+)["\']', v)
1264
- if task_name_match:
1265
- task_name = task_name_match.group(1).strip()
1266
- print(f"Found task_name in string parameter: {task_name}")
1267
- break
1268
-
1269
- # 6. If task name found but no ID, try to lookup ID by name
1270
- if not task_id and task_name:
1271
- try:
1272
- # Get all tasks in the list to find the task ID by name
1273
- get_tasks_tool = GetTasksTool()
1274
- tasks = get_tasks_tool._run(list_id=901307715461)
1275
-
1276
- # Find the task by name
1277
- for task in tasks:
1278
- if task.get("name") == task_name:
1279
- task_id = task.get("id")
1280
- print(f"Found task_id {task_id} for task name '{task_name}'")
1281
- break
1282
- except Exception as e:
1283
- print(f"Error getting task ID from name: {e}")
1284
-
1285
- # 7. Hardcoded fallback for testing
1286
- if not task_id and task_name:
1287
- if task_name == "TEST TASK 2":
1288
- task_id = "86a702gha" # Known ID of TEST TASK 2
1289
- print(f"Using hardcoded task_id for 'TEST TASK 2': {task_id}")
1290
- elif task_name == "TEST TASK":
1291
- task_id = "86a700c6e" # Known ID of TEST TASK
1292
- print(f"Using hardcoded task_id for 'TEST TASK': {task_id}")
1293
-
1294
- if not task_id:
1295
- raise ToolException("task_id is required for getting a task")
1296
-
1297
- print(f"task_id being used: {task_id}")
1298
- print("==== End parameters ====\n")
1299
-
1300
- action = GetTask()
1301
-
1302
- url = f"{action.url}{action.path}".format(task_id=task_id)
1303
- print(f"URL being used: {url}")
1304
-
1305
- # Make sure all parameters are JSON serializable
1306
- params = {
1307
- key: _ensure_serializable(value)
1308
- for key, value in kwargs.items()
1309
- if value is not None and key != "kwargs" and key != "task_id"
1310
- }
1311
-
1312
- response = requests.get(url, headers=self.headers, params=params)
1313
- print(f"Response status code: {response.status_code}")
1314
-
1315
- if response.status_code == 200:
1316
- response_json = response.json()
1317
- else:
1318
- try:
1319
- response_json = response.json()
1320
- print(f"Error response: {response_json}")
1321
- except requests.JSONDecodeError:
1322
- response_json = {"error": "Invalid JSON response"}
1323
- print("Could not decode JSON response")
1324
-
1325
- task_details = GetTaskResponse(data=response_json)
1326
-
1327
- # Format the response for better readability
1328
- if task_details.data and isinstance(task_details.data, dict):
1329
- task = task_details.data
1330
- formatted_response = {
1331
- "name": task.get("name", "N/A"),
1332
- "id": task.get("id", "N/A"),
1333
- "status": task.get("status", {}).get("status", "N/A"),
1334
- "assignees": [
1335
- a.get("username", "N/A") for a in task.get("assignees", [])
1336
- ],
1337
- "description": task.get("description", "N/A"),
1338
- "due_date": task.get("due_date", "N/A"),
1339
- "time_estimate": task.get("time_estimate", "N/A"),
1340
- }
1341
-
1342
- print(f"Found task: {formatted_response}")
1343
- return formatted_response
1344
- else:
1345
- error_message = "Task not found or API error occurred"
1346
- if "err" in task_details.data:
1347
- error_message = f"Error: {task_details.data['err']}"
1348
-
1349
- print(f"Result: {error_message}")
1350
- return error_message
1351
-
1352
-
1353
  # Util for converting dates
1354
  @tool
1355
  def date_to_timestamp(date_str: str) -> int:
 
1
  import os
2
+ import sys
3
  import requests
4
  from dotenv import load_dotenv
5
  from langchain.tools import StructuredTool, BaseTool, tool
 
10
  import datetime
11
  import json
12
  import re
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  from composio.tools.local.clickup.actions.base import OpenAPIAction
14
  from composio.tools.local.clickup.actions.create_task import (
15
  CreateTask,
 
46
  GetTaskResponse,
47
  )
48
 
49
+ # Add the parent directory to sys.path to enable imports
50
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
51
+
52
  from utils.tool_wrapper import convert_langchain_tools
53
+ from utils.ensure_serializable import ensure_serializable
54
 
55
  load_dotenv()
56
  CLICKUP_TOKEN = os.getenv("CLICKUP_TOKEN")
 
280
  # Add any other parameters from kwargs
281
  for key, value in kwargs.items():
282
  if value is not None and key != "kwargs" and key != "list_id":
283
+ params[key] = ensure_serializable(value)
284
 
285
  # For testing, ensure we have the minimum required parameters
286
  if "name" not in params:
 
435
 
436
  # Make sure all parameters are JSON serializable
437
  params = {
438
+ key: ensure_serializable(value)
439
  for key, value in kwargs.items()
440
  if value is not None and key != "kwargs" and key != "task_id"
441
  }
 
746
  # Add update parameters from kwargs
747
  for key, value in kwargs.items():
748
  if value is not None and key != "kwargs" and key != "task_id":
749
+ update_params[key] = ensure_serializable(value)
750
 
751
  # Make sure all parameters are JSON serializable
752
  params = {
753
+ k: ensure_serializable(v) for k, v in update_params.items() if v is not None
 
 
754
  }
755
 
756
  print(f"Update parameters: {params}")
 
939
 
940
  # Make sure all parameters are JSON serializable
941
  params = {
942
+ key: ensure_serializable(value)
943
  for key, value in kwargs.items()
944
  if value is not None and key != "kwargs" and key != "task_id"
945
  }
 
1111
 
1112
  # Make sure all parameters are JSON serializable
1113
  query_params = {
1114
+ k: ensure_serializable(v)
1115
  for k, v in kwargs.items()
1116
  if v is not None and k != "kwargs"
1117
  }
 
1158
  return filtered_response
1159
 
1160
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1161
  # Util for converting dates
1162
  @tool
1163
  def date_to_timestamp(date_str: str) -> int:
agency_ai_demo/agents/ClickUpAgent/tools/ExampleTool.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from agency_swarm.tools import BaseTool
2
+ from pydantic import Field
3
+ import os
4
+
5
+ account_id = "MY_ACCOUNT_ID"
6
+ api_key = os.getenv("MY_API_KEY") # or access_token = os.getenv("MY_ACCESS_TOKEN")
7
+
8
+ class ExampleTool(BaseTool):
9
+ """
10
+ A brief description of what the custom tool does.
11
+ The docstring should clearly explain the tool's purpose and functionality.
12
+ It will be used by the agent to determine when to use this tool.
13
+ """
14
+
15
+ # Define the fields with descriptions using Pydantic Field
16
+ example_field: str = Field(
17
+ ..., description="Description of the example field, explaining its purpose and usage for the Agent."
18
+ )
19
+
20
+ def run(self):
21
+ """
22
+ The implementation of the run method, where the tool's main functionality is executed.
23
+ This method should utilize the fields defined above to perform the task.
24
+ Docstring is not required for this method and will not be used by the agent.
25
+ """
26
+ # Your custom tool logic goes here
27
+ # do_something(self.example_field, api_key, account_id)
28
+
29
+ # Return the result of the tool's operation as a string
30
+ return "Result of ExampleTool operation"
agency_ai_demo/agents/ClickUpAgent/tools/GetTaskTool.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import requests
4
+ from dotenv import load_dotenv
5
+ from langchain.tools import BaseTool
6
+ from langchain_core.pydantic_v1 import BaseModel
7
+ from langchain_core.tools import ToolException
8
+ from typing import Any, Type
9
+ import re
10
+ from composio.tools.local.clickup.actions.get_task import (
11
+ GetTask,
12
+ GetTaskRequest,
13
+ GetTaskResponse,
14
+ )
15
+
16
+ # Add the parent directory to sys.path to enable imports
17
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
18
+
19
+ # Add project utils
20
+ from utils.tool_wrapper import convert_langchain_tools
21
+ from utils.ensure_serializable import ensure_serializable
22
+
23
+ load_dotenv()
24
+
25
+
26
+ CLICKUP_TOKEN = os.getenv("CLICKUP_TOKEN")
27
+
28
+
29
+ # TODO: FIX THIS TOOL
30
+ class GetTaskTool(BaseTool):
31
+ name: str = "get_task_tool"
32
+ description: str = """
33
+ Ferramenta para visualizar detalhes de uma tarefa no ClickUp.
34
+ - Obter detalhes da tarefa:
35
+ Invocar: "GetTaskTool" com o ID da tarefa e parΓ’metros opcionais.
36
+ """
37
+ args_schema: Type[BaseModel] = GetTaskRequest
38
+ headers: dict = {"Authorization": f"{CLICKUP_TOKEN}"}
39
+
40
+ def _init_(self, **data):
41
+ super()._init_(**data)
42
+
43
+ def _run(self, **kwargs) -> Any:
44
+ """Executa a requisiΓ§Γ£o para obter detalhes de uma tarefa no ClickUp"""
45
+
46
+ action = GetTask()
47
+
48
+ url = f"{action.url}{action.path}".format(task_id=kwargs.get("task_id"))
49
+
50
+ query_params = {k: v for k, v in kwargs.items() if v is not None}
51
+
52
+ response = requests.get(url, headers=self.headers, params=query_params)
53
+
54
+ if response.status_code == 200:
55
+ response_json = response.json()
56
+ else:
57
+ try:
58
+ response_json = response.json()
59
+ except requests.JSONDecodeError:
60
+ response_json = {"error": "Invalid JSON response"}
61
+
62
+ response = GetTaskResponse(data=response_json)
63
+
64
+ filtered_response = {
65
+ "id": response.data.get("id"),
66
+ "name": response.data.get("name"),
67
+ "status": response.data.get("status", {}).get("status"),
68
+ "due_date": response.data.get("due_date"),
69
+ "date_created": response.data.get("date_created"),
70
+ "url": response.data.get("url"),
71
+ "assignees": [
72
+ {"id": assignee.get("id"), "username": assignee.get("username")}
73
+ for assignee in response.data.get("assignees", [])
74
+ ],
75
+ "error": response.data.get("error"),
76
+ }
77
+
78
+ return filtered_response
agency_ai_demo/agents/ClickUpAgent/tools/__init__.py ADDED
File without changes
{agents β†’ agency_ai_demo/agents}/ResearchAndReportAgent/ResearchAndReportAgent.py RENAMED
File without changes
{agents β†’ agency_ai_demo/agents}/ResearchAndReportAgent/__init__.py RENAMED
File without changes
{agents β†’ agency_ai_demo/agents}/ResearchAndReportAgent/instructions.md RENAMED
File without changes
agency_ai_demo/agents/ResearchAndReportAgent/tools/ExampleTool.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from agency_swarm.tools import BaseTool
2
+ from pydantic import Field
3
+ import os
4
+
5
+ account_id = "MY_ACCOUNT_ID"
6
+ api_key = os.getenv("MY_API_KEY") # or access_token = os.getenv("MY_ACCESS_TOKEN")
7
+
8
+ class ExampleTool(BaseTool):
9
+ """
10
+ A brief description of what the custom tool does.
11
+ The docstring should clearly explain the tool's purpose and functionality.
12
+ It will be used by the agent to determine when to use this tool.
13
+ """
14
+
15
+ # Define the fields with descriptions using Pydantic Field
16
+ example_field: str = Field(
17
+ ..., description="Description of the example field, explaining its purpose and usage for the Agent."
18
+ )
19
+
20
+ def run(self):
21
+ """
22
+ The implementation of the run method, where the tool's main functionality is executed.
23
+ This method should utilize the fields defined above to perform the task.
24
+ Docstring is not required for this method and will not be used by the agent.
25
+ """
26
+ # Your custom tool logic goes here
27
+ # do_something(self.example_field, api_key, account_id)
28
+
29
+ # Return the result of the tool's operation as a string
30
+ return "Result of ExampleTool operation"
{agents β†’ agency_ai_demo/agents}/TechnicalProjectManager/TechnicalProjectManager.py RENAMED
File without changes
{agents β†’ agency_ai_demo/agents}/TechnicalProjectManager/__init__.py RENAMED
File without changes
{agents β†’ agency_ai_demo/agents}/TechnicalProjectManager/instructions.md RENAMED
File without changes
agency_ai_demo/agents/TechnicalProjectManager/tools/ExampleTool.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from agency_swarm.tools import BaseTool
2
+ from pydantic import Field
3
+ import os
4
+
5
+ account_id = "MY_ACCOUNT_ID"
6
+ api_key = os.getenv("MY_API_KEY") # or access_token = os.getenv("MY_ACCESS_TOKEN")
7
+
8
+ class ExampleTool(BaseTool):
9
+ """
10
+ A brief description of what the custom tool does.
11
+ The docstring should clearly explain the tool's purpose and functionality.
12
+ It will be used by the agent to determine when to use this tool.
13
+ """
14
+
15
+ # Define the fields with descriptions using Pydantic Field
16
+ example_field: str = Field(
17
+ ..., description="Description of the example field, explaining its purpose and usage for the Agent."
18
+ )
19
+
20
+ def run(self):
21
+ """
22
+ The implementation of the run method, where the tool's main functionality is executed.
23
+ This method should utilize the fields defined above to perform the task.
24
+ Docstring is not required for this method and will not be used by the agent.
25
+ """
26
+ # Your custom tool logic goes here
27
+ # do_something(self.example_field, api_key, account_id)
28
+
29
+ # Return the result of the tool's operation as a string
30
+ return "Result of ExampleTool operation"
agency_ai_demo/agents/__init__.py ADDED
File without changes
agency_ai_demo/demo.ipynb ADDED
@@ -0,0 +1,533 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 1,
6
+ "metadata": {},
7
+ "outputs": [
8
+ {
9
+ "data": {
10
+ "text/plain": [
11
+ "True"
12
+ ]
13
+ },
14
+ "execution_count": 1,
15
+ "metadata": {},
16
+ "output_type": "execute_result"
17
+ }
18
+ ],
19
+ "source": [
20
+ "import os\n",
21
+ "import requests\n",
22
+ "from dotenv import load_dotenv\n",
23
+ "# from langchain.tools import StructuredTool, BaseTool, tool\n",
24
+ "from langchain_core.pydantic_v1 import BaseModel, Field\n",
25
+ "from langchain_core.tools import ToolException\n",
26
+ "from pydantic import ValidationError\n",
27
+ "from typing import Any, Type, List, Dict\n",
28
+ "import datetime\n",
29
+ "\n",
30
+ "from openai import AzureOpenAI\n",
31
+ "from agency_swarm import set_openai_client\n",
32
+ "from agency_swarm import Agent, Agency\n",
33
+ "\n",
34
+ "\n",
35
+ "from composio.tools.local.clickup.actions.base import OpenAPIAction\n",
36
+ "from composio.tools.local.clickup.actions.create_task import CreateTask, CreateTaskResponse\n",
37
+ "\n",
38
+ "from agents.ClickUpAgent.tools.ClickUpTools import initialize_clickup_tools\n",
39
+ "\n",
40
+ "\n",
41
+ "load_dotenv()"
42
+ ]
43
+ },
44
+ {
45
+ "cell_type": "code",
46
+ "execution_count": 2,
47
+ "metadata": {},
48
+ "outputs": [],
49
+ "source": [
50
+ "client = AzureOpenAI(\n",
51
+ " api_key=os.getenv(\"AZURE_OPENAI_API_KEY\"),\n",
52
+ " api_version=os.getenv(\"OPENAI_API_VERSION\"),\n",
53
+ " azure_endpoint=os.getenv(\"AZURE_OPENAI_ENDPOINT\"),\n",
54
+ " timeout=5,\n",
55
+ " max_retries=5,\n",
56
+ ")\n",
57
+ "\n",
58
+ "set_openai_client(client)"
59
+ ]
60
+ },
61
+ {
62
+ "cell_type": "code",
63
+ "execution_count": 3,
64
+ "metadata": {},
65
+ "outputs": [],
66
+ "source": [
67
+ "project_manager = Agent(\n",
68
+ " name=\"project_manager\",\n",
69
+ " description=\"I am the Project Manager\",\n",
70
+ " model=\"gpt-4o\",\n",
71
+ " )"
72
+ ]
73
+ },
74
+ {
75
+ "cell_type": "code",
76
+ "execution_count": 4,
77
+ "metadata": {},
78
+ "outputs": [],
79
+ "source": [
80
+ "clickup_agent_instructions = f\"\"\"# PROJECT_MANAGEMENT\n",
81
+ "Your team uses ClickUp to manage projects and tasks.\n",
82
+ "Users often refer to lists and tasks by name, and sometimes there may not be an exact match, so you should look for the closest ones.\n",
83
+ "If in doubt, provide the user with valid options to choose from or ask for more information if necessary.\n",
84
+ "\n",
85
+ "## CLICKUP_STRUCTURE\n",
86
+ "-> Workspace: The highest level of organization in ClickUp. Contains all your Spaces.\n",
87
+ "--> Space: A collection of Folders and Lists. It is a way to group related work.\n",
88
+ "---> Folder: Used to group Lists.\n",
89
+ "----> List: Used to group tasks. Lists can be in a Folder or directly in a Space.\n",
90
+ "-----> Task: The basic unit of work in ClickUp, assignable with due dates.\n",
91
+ "------> Subtask: A child task of a parent Task, assignable to different people.\n",
92
+ "\n",
93
+ "## DEFAULT_CLICKUP_IDS\n",
94
+ "Use these IDs unless specified otherwise\n",
95
+ "- Team ID: {os.getenv(\"CLICKUP_TEAM_ID\")}\n",
96
+ "- List ID 'test_clickup_tool': {os.getenv(\"CLICKUP_LIST_ID\")}\n",
97
+ "\n",
98
+ "## CLICKUP_USERS\n",
99
+ "- Your id: {os.getenv(\"CLICKUP_AGENT_USER_ID\")}\n",
100
+ "- Main user id: {os.getenv(\"CLICKUP_USER_ID\")}\n",
101
+ "\"\"\""
102
+ ]
103
+ },
104
+ {
105
+ "cell_type": "code",
106
+ "execution_count": 5,
107
+ "metadata": {},
108
+ "outputs": [
109
+ {
110
+ "name": "stdout",
111
+ "output_type": "stream",
112
+ "text": [
113
+ "[<class 'utils.tool_wrapper._convert_function_tool.<locals>.ConvertedFunctionTool'>, <class 'utils.tool_wrapper._convert_function_tool.<locals>.ConvertedFunctionTool'>, <class 'utils.tool_wrapper._convert_function_tool.<locals>.ConvertedFunctionTool'>, <class 'utils.tool_wrapper._convert_function_tool.<locals>.ConvertedFunctionTool'>, <class 'utils.tool_wrapper._convert_function_tool.<locals>.ConvertedFunctionTool'>, <class 'utils.tool_wrapper._convert_function_tool.<locals>.ConvertedFunctionTool'>, <class 'utils.tool_wrapper._convert_function_tool.<locals>.ConvertedFunctionTool'>, <class 'utils.tool_wrapper._convert_function_tool.<locals>.ConvertedFunctionTool'>]\n"
114
+ ]
115
+ }
116
+ ],
117
+ "source": [
118
+ "# clickup_tools = initialize_clickup_tools()\n",
119
+ "# print(clickup_tools)"
120
+ ]
121
+ },
122
+ {
123
+ "cell_type": "code",
124
+ "execution_count": null,
125
+ "metadata": {},
126
+ "outputs": [],
127
+ "source": [
128
+ "from agents.ClickUpAgent.tools.GetTaskTool import GetTaskTool\n",
129
+ "from utils.tool_wrapper import convert_langchain_tools\n",
130
+ "get_task_tool = GetTaskTool()\n",
131
+ "clickup_tools = convert_langchain_tools([get_task_tool])"
132
+ ]
133
+ },
134
+ {
135
+ "cell_type": "code",
136
+ "execution_count": 6,
137
+ "metadata": {},
138
+ "outputs": [
139
+ {
140
+ "data": {
141
+ "text/plain": [
142
+ "'Create_task_toolTool'"
143
+ ]
144
+ },
145
+ "execution_count": 6,
146
+ "metadata": {},
147
+ "output_type": "execute_result"
148
+ }
149
+ ],
150
+ "source": [
151
+ "clickup_tools[0].__name__"
152
+ ]
153
+ },
154
+ {
155
+ "cell_type": "code",
156
+ "execution_count": 7,
157
+ "metadata": {},
158
+ "outputs": [],
159
+ "source": [
160
+ "\n",
161
+ "clickup_agent = Agent(\n",
162
+ " name=\"clickup_agent\",\n",
163
+ " description=\"I am a simple agent\",\n",
164
+ " instructions=clickup_agent_instructions,\n",
165
+ " model=\"gpt-4o\",\n",
166
+ " tools=clickup_tools,\n",
167
+ " )"
168
+ ]
169
+ },
170
+ {
171
+ "cell_type": "code",
172
+ "execution_count": 8,
173
+ "metadata": {},
174
+ "outputs": [
175
+ {
176
+ "name": "stdout",
177
+ "output_type": "stream",
178
+ "text": [
179
+ "Updating agent... clickup_agent\n"
180
+ ]
181
+ }
182
+ ],
183
+ "source": [
184
+ "agency = Agency(\n",
185
+ " agency_chart=[\n",
186
+ " project_manager,\n",
187
+ " [project_manager, clickup_agent],\n",
188
+ "],\n",
189
+ " # shared_instructions=\"agency_manifesto.md\"\n",
190
+ ")"
191
+ ]
192
+ },
193
+ {
194
+ "cell_type": "code",
195
+ "execution_count": 9,
196
+ "metadata": {},
197
+ "outputs": [
198
+ {
199
+ "name": "stderr",
200
+ "output_type": "stream",
201
+ "text": [
202
+ "/Users/morossini/Projects/professional_demos/agency_swarm_demo/.venv/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
203
+ " from .autonotebook import tqdm as notebook_tqdm\n",
204
+ "/Users/morossini/Projects/professional_demos/agency_swarm_demo/.venv/lib/python3.11/site-packages/gradio/components/chatbot.py:285: UserWarning: You have not specified a value for the `type` parameter. Defaulting to the 'tuples' format for chatbot messages, but this is deprecated and will be removed in a future version of Gradio. Please set type='messages' instead, which uses openai-style dictionaries with 'role' and 'content' keys.\n",
205
+ " warnings.warn(\n"
206
+ ]
207
+ },
208
+ {
209
+ "name": "stdout",
210
+ "output_type": "stream",
211
+ "text": [
212
+ "* Running on local URL: http://127.0.0.1:7860\n",
213
+ "\n",
214
+ "To create a public link, set `share=True` in `launch()`.\n"
215
+ ]
216
+ },
217
+ {
218
+ "data": {
219
+ "text/html": [
220
+ "<div><iframe src=\"http://127.0.0.1:7860/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
221
+ ],
222
+ "text/plain": [
223
+ "<IPython.core.display.HTML object>"
224
+ ]
225
+ },
226
+ "metadata": {},
227
+ "output_type": "display_data"
228
+ },
229
+ {
230
+ "data": {
231
+ "text/plain": [
232
+ "Gradio Blocks instance: 6 backend functions\n",
233
+ "-------------------------------------------\n",
234
+ "fn_index=0\n",
235
+ " inputs:\n",
236
+ " |-<gradio.components.textbox.Textbox object at 0x11f7e8c50>\n",
237
+ " |-<gradio.components.chatbot.Chatbot object at 0x11f2cd950>\n",
238
+ " outputs:\n",
239
+ " |-<gradio.components.textbox.Textbox object at 0x11f7e8c50>\n",
240
+ " |-<gradio.components.chatbot.Chatbot object at 0x11f2cd950>\n",
241
+ "fn_index=1\n",
242
+ " inputs:\n",
243
+ " |-<gradio.components.textbox.Textbox object at 0x11f7e8c50>\n",
244
+ " |-<gradio.components.chatbot.Chatbot object at 0x11f2cd950>\n",
245
+ " |-<gradio.components.dropdown.Dropdown object at 0x123608550>\n",
246
+ " outputs:\n",
247
+ " |-<gradio.components.textbox.Textbox object at 0x11f7e8c50>\n",
248
+ " |-<gradio.components.chatbot.Chatbot object at 0x11f2cd950>\n",
249
+ " |-<gradio.components.dropdown.Dropdown object at 0x123608550>\n",
250
+ "fn_index=2\n",
251
+ " inputs:\n",
252
+ " |-<gradio.components.dropdown.Dropdown object at 0x123608550>\n",
253
+ " outputs:\n",
254
+ "fn_index=3\n",
255
+ " inputs:\n",
256
+ " |-<gradio.templates.Files object at 0x122a95b50>\n",
257
+ " outputs:\n",
258
+ "fn_index=4\n",
259
+ " inputs:\n",
260
+ " |-<gradio.components.textbox.Textbox object at 0x11f7e8c50>\n",
261
+ " |-<gradio.components.chatbot.Chatbot object at 0x11f2cd950>\n",
262
+ " outputs:\n",
263
+ " |-<gradio.components.textbox.Textbox object at 0x11f7e8c50>\n",
264
+ " |-<gradio.components.chatbot.Chatbot object at 0x11f2cd950>\n",
265
+ "fn_index=5\n",
266
+ " inputs:\n",
267
+ " |-<gradio.components.textbox.Textbox object at 0x11f7e8c50>\n",
268
+ " |-<gradio.components.chatbot.Chatbot object at 0x11f2cd950>\n",
269
+ " |-<gradio.components.dropdown.Dropdown object at 0x123608550>\n",
270
+ " outputs:\n",
271
+ " |-<gradio.components.textbox.Textbox object at 0x11f7e8c50>\n",
272
+ " |-<gradio.components.chatbot.Chatbot object at 0x11f2cd950>\n",
273
+ " |-<gradio.components.dropdown.Dropdown object at 0x123608550>"
274
+ ]
275
+ },
276
+ "execution_count": 9,
277
+ "metadata": {},
278
+ "output_type": "execute_result"
279
+ },
280
+ {
281
+ "name": "stdout",
282
+ "output_type": "stream",
283
+ "text": [
284
+ "Message files: []\n",
285
+ "Images: []\n",
286
+ "THREAD:[ user -> project_manager ]: URL https://platform.openai.com/playground/assistants?assistant=asst_q3bAPsDDQmwfijHqK7v8Z655&mode=assistant&thread=thread_awYwQAYJsii7m4eCHOOtpQtX\n",
287
+ "THREAD:[ project_manager -> clickup_agent ]: URL https://platform.openai.com/playground/assistants?assistant=asst_NQWCwFwP37B8T5rATBm6Fi6E&mode=assistant&thread=thread_tT4NsmS9eZuM0FmYLzwfwHMl\n"
288
+ ]
289
+ },
290
+ {
291
+ "name": "stderr",
292
+ "output_type": "stream",
293
+ "text": [
294
+ "[2025-02-27 18:56:41,742][ERROR] Tool execution failed: list_id is required for getting list information\n",
295
+ "Traceback (most recent call last):\n",
296
+ " File \"/Users/morossini/Projects/professional_demos/agency_swarm_demo/agency_ai_demo/utils/tool_wrapper.py\", line 409, in run\n",
297
+ " result = tool_func._run(**kwargs)\n",
298
+ " ^^^^^^^^^^^^^^^^^^^^^^^^\n",
299
+ " File \"/Users/morossini/Projects/professional_demos/agency_swarm_demo/agency_ai_demo/agents/ClickUpAgent/tools/ClickUpTools.py\", line 1055, in _run\n",
300
+ " raise ToolException(\"list_id is required for getting list information\")\n",
301
+ "langchain_core.tools.base.ToolException: list_id is required for getting list information\n"
302
+ ]
303
+ },
304
+ {
305
+ "name": "stdout",
306
+ "output_type": "stream",
307
+ "text": [
308
+ "\n",
309
+ "==== GetListTool._run received parameters: ====\n",
310
+ "kwargs: {'kwargs': FieldInfo(annotation=NoneType, required=False, default=None, description='Parameter: kwargs')}\n",
311
+ "\n",
312
+ "==== GetTasksTool._run received parameters: ====\n",
313
+ "kwargs: {'kwargs': FieldInfo(annotation=NoneType, required=False, default=None, description='Parameter: kwargs')}\n",
314
+ "No list_id found in parameters, using hardcoded value 901307715461\n",
315
+ "list_id being used: 901307715461\n",
316
+ "==== End parameters ====\n",
317
+ "\n",
318
+ "URL being used: https://api.clickup.com/api/v2/list/901307715461/task\n",
319
+ "Response status code: 200\n",
320
+ "Returning filtered response with 1 items\n"
321
+ ]
322
+ },
323
+ {
324
+ "name": "stderr",
325
+ "output_type": "stream",
326
+ "text": [
327
+ "[2025-02-27 18:56:46,276][ERROR] Tool execution failed: task_id is required for getting a task\n",
328
+ "Traceback (most recent call last):\n",
329
+ " File \"/Users/morossini/Projects/professional_demos/agency_swarm_demo/agency_ai_demo/utils/tool_wrapper.py\", line 409, in run\n",
330
+ " result = tool_func._run(**kwargs)\n",
331
+ " ^^^^^^^^^^^^^^^^^^^^^^^^\n",
332
+ " File \"/Users/morossini/Projects/professional_demos/agency_swarm_demo/agency_ai_demo/agents/ClickUpAgent/tools/ClickUpTools.py\", line 1299, in _run\n",
333
+ " raise ToolException(\"task_id is required for getting a task\")\n",
334
+ "langchain_core.tools.base.ToolException: task_id is required for getting a task\n"
335
+ ]
336
+ },
337
+ {
338
+ "name": "stdout",
339
+ "output_type": "stream",
340
+ "text": [
341
+ "\n",
342
+ "==== GetTaskTool._run received parameters: ====\n",
343
+ "kwargs: {'kwargs': FieldInfo(annotation=NoneType, required=False, default=None, description='Parameter: kwargs')}\n"
344
+ ]
345
+ },
346
+ {
347
+ "name": "stderr",
348
+ "output_type": "stream",
349
+ "text": [
350
+ "[2025-02-27 18:56:47,808][ERROR] Tool execution failed: task_id is required for getting a task\n",
351
+ "Traceback (most recent call last):\n",
352
+ " File \"/Users/morossini/Projects/professional_demos/agency_swarm_demo/agency_ai_demo/utils/tool_wrapper.py\", line 409, in run\n",
353
+ " result = tool_func._run(**kwargs)\n",
354
+ " ^^^^^^^^^^^^^^^^^^^^^^^^\n",
355
+ " File \"/Users/morossini/Projects/professional_demos/agency_swarm_demo/agency_ai_demo/agents/ClickUpAgent/tools/ClickUpTools.py\", line 1299, in _run\n",
356
+ " raise ToolException(\"task_id is required for getting a task\")\n",
357
+ "langchain_core.tools.base.ToolException: task_id is required for getting a task\n"
358
+ ]
359
+ },
360
+ {
361
+ "name": "stdout",
362
+ "output_type": "stream",
363
+ "text": [
364
+ "\n",
365
+ "==== GetTaskTool._run received parameters: ====\n",
366
+ "kwargs: {'kwargs': FieldInfo(annotation=NoneType, required=False, default=None, description='Parameter: kwargs')}\n",
367
+ "Message files: []\n",
368
+ "Images: []\n",
369
+ "THREAD:[ user -> project_manager ]: URL https://platform.openai.com/playground/assistants?assistant=asst_q3bAPsDDQmwfijHqK7v8Z655&mode=assistant&thread=thread_awYwQAYJsii7m4eCHOOtpQtX\n",
370
+ "THREAD:[ project_manager -> clickup_agent ]: URL https://platform.openai.com/playground/assistants?assistant=asst_NQWCwFwP37B8T5rATBm6Fi6E&mode=assistant&thread=thread_tT4NsmS9eZuM0FmYLzwfwHMl\n"
371
+ ]
372
+ },
373
+ {
374
+ "name": "stderr",
375
+ "output_type": "stream",
376
+ "text": [
377
+ "[2025-02-27 18:58:01,081][ERROR] Tool execution failed: task_id is required for getting a task\n",
378
+ "Traceback (most recent call last):\n",
379
+ " File \"/Users/morossini/Projects/professional_demos/agency_swarm_demo/agency_ai_demo/utils/tool_wrapper.py\", line 409, in run\n",
380
+ " result = tool_func._run(**kwargs)\n",
381
+ " ^^^^^^^^^^^^^^^^^^^^^^^^\n",
382
+ " File \"/Users/morossini/Projects/professional_demos/agency_swarm_demo/agency_ai_demo/agents/ClickUpAgent/tools/ClickUpTools.py\", line 1299, in _run\n",
383
+ " raise ToolException(\"task_id is required for getting a task\")\n",
384
+ "langchain_core.tools.base.ToolException: task_id is required for getting a task\n"
385
+ ]
386
+ },
387
+ {
388
+ "name": "stdout",
389
+ "output_type": "stream",
390
+ "text": [
391
+ "\n",
392
+ "==== GetTaskTool._run received parameters: ====\n",
393
+ "kwargs: {'kwargs': FieldInfo(annotation=NoneType, required=False, default=None, description='Parameter: kwargs')}\n"
394
+ ]
395
+ },
396
+ {
397
+ "name": "stderr",
398
+ "output_type": "stream",
399
+ "text": [
400
+ "[2025-02-27 18:58:04,314][ERROR] Tool execution failed: task_id is required for getting a task\n",
401
+ "Traceback (most recent call last):\n",
402
+ " File \"/Users/morossini/Projects/professional_demos/agency_swarm_demo/agency_ai_demo/utils/tool_wrapper.py\", line 409, in run\n",
403
+ " result = tool_func._run(**kwargs)\n",
404
+ " ^^^^^^^^^^^^^^^^^^^^^^^^\n",
405
+ " File \"/Users/morossini/Projects/professional_demos/agency_swarm_demo/agency_ai_demo/agents/ClickUpAgent/tools/ClickUpTools.py\", line 1299, in _run\n",
406
+ " raise ToolException(\"task_id is required for getting a task\")\n",
407
+ "langchain_core.tools.base.ToolException: task_id is required for getting a task\n"
408
+ ]
409
+ },
410
+ {
411
+ "name": "stdout",
412
+ "output_type": "stream",
413
+ "text": [
414
+ "\n",
415
+ "==== GetTaskTool._run received parameters: ====\n",
416
+ "kwargs: {'kwargs': FieldInfo(annotation=NoneType, required=False, default=None, description='Parameter: kwargs')}\n"
417
+ ]
418
+ },
419
+ {
420
+ "name": "stderr",
421
+ "output_type": "stream",
422
+ "text": [
423
+ "[2025-02-27 18:58:08,100][ERROR] Tool execution failed: task_id is required for getting a task\n",
424
+ "Traceback (most recent call last):\n",
425
+ " File \"/Users/morossini/Projects/professional_demos/agency_swarm_demo/agency_ai_demo/utils/tool_wrapper.py\", line 409, in run\n",
426
+ " result = tool_func._run(**kwargs)\n",
427
+ " ^^^^^^^^^^^^^^^^^^^^^^^^\n",
428
+ " File \"/Users/morossini/Projects/professional_demos/agency_swarm_demo/agency_ai_demo/agents/ClickUpAgent/tools/ClickUpTools.py\", line 1299, in _run\n",
429
+ " raise ToolException(\"task_id is required for getting a task\")\n",
430
+ "langchain_core.tools.base.ToolException: task_id is required for getting a task\n"
431
+ ]
432
+ },
433
+ {
434
+ "name": "stdout",
435
+ "output_type": "stream",
436
+ "text": [
437
+ "\n",
438
+ "==== GetTaskTool._run received parameters: ====\n",
439
+ "kwargs: {'kwargs': FieldInfo(annotation=NoneType, required=False, default=None, description='Parameter: kwargs')}\n",
440
+ "Message files: []\n",
441
+ "Images: []\n",
442
+ "THREAD:[ user -> project_manager ]: URL https://platform.openai.com/playground/assistants?assistant=asst_q3bAPsDDQmwfijHqK7v8Z655&mode=assistant&thread=thread_awYwQAYJsii7m4eCHOOtpQtX\n",
443
+ "THREAD:[ project_manager -> clickup_agent ]: URL https://platform.openai.com/playground/assistants?assistant=asst_NQWCwFwP37B8T5rATBm6Fi6E&mode=assistant&thread=thread_tT4NsmS9eZuM0FmYLzwfwHMl\n",
444
+ "\n",
445
+ "==== CreateTaskTool._run received parameters: ====\n",
446
+ "kwargs: {'kwargs': FieldInfo(annotation=NoneType, required=False, default=None, description='Parameter: kwargs')}\n",
447
+ "No list_id found in parameters, using hardcoded value 901307715461\n",
448
+ "list_id being used: 901307715461\n",
449
+ "==== End parameters ====\n",
450
+ "\n",
451
+ "URL being used: https://api.clickup.com/api/v2/list/901307715461/task\n",
452
+ "Request parameters: {'name': 'API TEST TASK', 'assignees': [81918955]}\n",
453
+ "Response status code: 200\n",
454
+ "Error response: {'id': '86a706rnx', 'custom_id': None, 'custom_item_id': 0, 'name': 'API TEST TASK', 'text_content': '', 'description': '', 'status': {'id': 'c90131663060_Uk5SstGY', 'status': 'backlog', 'color': '#9c09bc', 'orderindex': 0, 'type': 'open'}, 'orderindex': '120305513.00000000000000000000000000000000', 'date_created': '1740693545341', 'date_updated': '1740693545341', 'date_closed': None, 'date_done': None, 'archived': False, 'creator': {'id': 84141406, 'username': 'Ana Beatriz', 'color': '#455963', 'email': '[email protected]', 'profilePicture': 'https://attachments.clickup.com/profilePictures/84141406_ZkZ.jpg'}, 'assignees': [{'id': 81918955, 'username': 'JoΓ£o Guilherme Silva Morossini', 'color': '#81b1ff', 'initials': 'JM', 'email': '[email protected]', 'profilePicture': 'https://attachments.clickup.com/profilePictures/81918955_kcK.jpg'}], 'group_assignees': [], 'watchers': [{'id': 81918955, 'username': 'JoΓ£o Guilherme Silva Morossini', 'color': '#81b1ff', 'initials': 'JM', 'email': '[email protected]', 'profilePicture': 'https://attachments.clickup.com/profilePictures/81918955_kcK.jpg'}, {'id': 84141406, 'username': 'Ana Beatriz', 'color': '#455963', 'initials': 'AB', 'email': '[email protected]', 'profilePicture': 'https://attachments.clickup.com/profilePictures/84141406_ZkZ.jpg'}], 'checklists': [], 'tags': [], 'parent': None, 'top_level_parent': None, 'priority': None, 'due_date': None, 'start_date': None, 'points': None, 'time_estimate': None, 'time_spent': 0, 'custom_fields': [], 'dependencies': [], 'linked_tasks': [], 'locations': [], 'team_id': '12927880', 'url': 'https://app.clickup.com/t/86a706rnx', 'sharing': {'public': False, 'public_share_expires_on': None, 'public_fields': ['assignees', 'priority', 'due_date', 'content', 'comments', 'attachments', 'customFields', 'subtasks', 'tags', 'checklists', 'coverimage'], 'token': None, 'seo_optimized': False}, 'permission_level': 'create', 'list': {'id': '901307715461', 'name': 'test_clickup_tool', 'access': True}, 'project': {'id': '90131663060', 'name': 'Agentes', 'hidden': False, 'access': True}, 'folder': {'id': '90131663060', 'name': 'Agentes', 'hidden': False, 'access': True}, 'space': {'id': '54804921'}}\n",
455
+ "Returning filtered response: {\n",
456
+ " \"id\": \"86a706rnx\",\n",
457
+ " \"name\": \"API TEST TASK\",\n",
458
+ " \"status\": \"backlog\",\n",
459
+ " \"assignees\": [\n",
460
+ " {\n",
461
+ " \"id\": 81918955,\n",
462
+ " \"username\": \"Jo\\u00e3o Guilherme Silva Morossini\",\n",
463
+ " \"color\": \"#81b1ff\",\n",
464
+ " \"initials\": \"JM\",\n",
465
+ " \"email\": \"[email protected]\",\n",
466
+ " \"profilePicture\": \"https://attachments.clickup.com/profilePictures/81918955_kcK.jpg\"\n",
467
+ " }\n",
468
+ " ],\n",
469
+ " \"due_date\": null,\n",
470
+ " \"error\": null\n",
471
+ "}\n",
472
+ "Message files: []\n",
473
+ "Images: []\n",
474
+ "THREAD:[ user -> project_manager ]: URL https://platform.openai.com/playground/assistants?assistant=asst_q3bAPsDDQmwfijHqK7v8Z655&mode=assistant&thread=thread_awYwQAYJsii7m4eCHOOtpQtX\n",
475
+ "THREAD:[ project_manager -> clickup_agent ]: URL https://platform.openai.com/playground/assistants?assistant=asst_NQWCwFwP37B8T5rATBm6Fi6E&mode=assistant&thread=thread_tT4NsmS9eZuM0FmYLzwfwHMl\n",
476
+ "\n",
477
+ "==== CreateTaskTool._run received parameters: ====\n",
478
+ "kwargs: {'kwargs': FieldInfo(annotation=NoneType, required=False, default=None, description='Parameter: kwargs')}\n",
479
+ "No list_id found in parameters, using hardcoded value 901307715461\n",
480
+ "list_id being used: 901307715461\n",
481
+ "==== End parameters ====\n",
482
+ "\n",
483
+ "URL being used: https://api.clickup.com/api/v2/list/901307715461/task\n",
484
+ "Request parameters: {'name': 'API TEST TASK', 'assignees': [81918955]}\n",
485
+ "Response status code: 200\n",
486
+ "Error response: {'id': '86a706rxv', 'custom_id': None, 'custom_item_id': 0, 'name': 'API TEST TASK', 'text_content': '', 'description': '', 'status': {'id': 'c90131663060_Uk5SstGY', 'status': 'backlog', 'color': '#9c09bc', 'orderindex': 0, 'type': 'open'}, 'orderindex': '120305514.00000000000000000000000000000000', 'date_created': '1740693581177', 'date_updated': '1740693581177', 'date_closed': None, 'date_done': None, 'archived': False, 'creator': {'id': 84141406, 'username': 'Ana Beatriz', 'color': '#455963', 'email': '[email protected]', 'profilePicture': 'https://attachments.clickup.com/profilePictures/84141406_ZkZ.jpg'}, 'assignees': [{'id': 81918955, 'username': 'JoΓ£o Guilherme Silva Morossini', 'color': '#81b1ff', 'initials': 'JM', 'email': '[email protected]', 'profilePicture': 'https://attachments.clickup.com/profilePictures/81918955_kcK.jpg'}], 'group_assignees': [], 'watchers': [{'id': 81918955, 'username': 'JoΓ£o Guilherme Silva Morossini', 'color': '#81b1ff', 'initials': 'JM', 'email': '[email protected]', 'profilePicture': 'https://attachments.clickup.com/profilePictures/81918955_kcK.jpg'}, {'id': 84141406, 'username': 'Ana Beatriz', 'color': '#455963', 'initials': 'AB', 'email': '[email protected]', 'profilePicture': 'https://attachments.clickup.com/profilePictures/84141406_ZkZ.jpg'}], 'checklists': [], 'tags': [], 'parent': None, 'top_level_parent': None, 'priority': None, 'due_date': None, 'start_date': None, 'points': None, 'time_estimate': None, 'time_spent': 0, 'custom_fields': [], 'dependencies': [], 'linked_tasks': [], 'locations': [], 'team_id': '12927880', 'url': 'https://app.clickup.com/t/86a706rxv', 'sharing': {'public': False, 'public_share_expires_on': None, 'public_fields': ['assignees', 'priority', 'due_date', 'content', 'comments', 'attachments', 'customFields', 'subtasks', 'tags', 'checklists', 'coverimage'], 'token': None, 'seo_optimized': False}, 'permission_level': 'create', 'list': {'id': '901307715461', 'name': 'test_clickup_tool', 'access': True}, 'project': {'id': '90131663060', 'name': 'Agentes', 'hidden': False, 'access': True}, 'folder': {'id': '90131663060', 'name': 'Agentes', 'hidden': False, 'access': True}, 'space': {'id': '54804921'}}\n",
487
+ "Returning filtered response: {\n",
488
+ " \"id\": \"86a706rxv\",\n",
489
+ " \"name\": \"API TEST TASK\",\n",
490
+ " \"status\": \"backlog\",\n",
491
+ " \"assignees\": [\n",
492
+ " {\n",
493
+ " \"id\": 81918955,\n",
494
+ " \"username\": \"Jo\\u00e3o Guilherme Silva Morossini\",\n",
495
+ " \"color\": \"#81b1ff\",\n",
496
+ " \"initials\": \"JM\",\n",
497
+ " \"email\": \"[email protected]\",\n",
498
+ " \"profilePicture\": \"https://attachments.clickup.com/profilePictures/81918955_kcK.jpg\"\n",
499
+ " }\n",
500
+ " ],\n",
501
+ " \"due_date\": null,\n",
502
+ " \"error\": null\n",
503
+ "}\n"
504
+ ]
505
+ }
506
+ ],
507
+ "source": [
508
+ "agency.demo_gradio()"
509
+ ]
510
+ }
511
+ ],
512
+ "metadata": {
513
+ "kernelspec": {
514
+ "display_name": ".venv",
515
+ "language": "python",
516
+ "name": "python3"
517
+ },
518
+ "language_info": {
519
+ "codemirror_mode": {
520
+ "name": "ipython",
521
+ "version": 3
522
+ },
523
+ "file_extension": ".py",
524
+ "mimetype": "text/x-python",
525
+ "name": "python",
526
+ "nbconvert_exporter": "python",
527
+ "pygments_lexer": "ipython3",
528
+ "version": "3.11.3"
529
+ }
530
+ },
531
+ "nbformat": 4,
532
+ "nbformat_minor": 2
533
+ }
agency_ai_demo/shared_files/agency_manifesto.md ADDED
File without changes
agency_ai_demo/tests/test_clickup_agent.py CHANGED
@@ -5,7 +5,7 @@ from dotenv import load_dotenv
5
  from openai import AzureOpenAI
6
  from agency_swarm import set_openai_client, Agent, Agency
7
 
8
- from tools.clickup_tools import initialize_clickup_tools
9
 
10
  load_dotenv()
11
 
 
5
  from openai import AzureOpenAI
6
  from agency_swarm import set_openai_client, Agent, Agency
7
 
8
+ from agents.ClickUpAgent.tools.ClickUpTools import initialize_clickup_tools
9
 
10
  load_dotenv()
11
 
agency_ai_demo/tests/test_clickup_tool_conversion.py CHANGED
@@ -15,7 +15,7 @@ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
15
  from utils.tool_wrapper import convert_langchain_tool, LangChainBaseTool
16
 
17
  # Import all tools from the clickup_tools module
18
- from tools.clickup_tools import (
19
  CreateTaskTool,
20
  DeleteTaskTool,
21
  UpdateTaskTool,
 
15
  from utils.tool_wrapper import convert_langchain_tool, LangChainBaseTool
16
 
17
  # Import all tools from the clickup_tools module
18
+ from agents.ClickUpAgent.tools.ClickUpTools import (
19
  CreateTaskTool,
20
  DeleteTaskTool,
21
  UpdateTaskTool,
agency_ai_demo/tests/test_clickup_tools.py CHANGED
@@ -6,7 +6,7 @@ import json
6
  # Add the parent directory to sys.path to import modules
7
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
8
 
9
- from agency_ai_demo.tools.clickup_tools import (
10
  CreateTaskTool,
11
  DeleteTaskTool,
12
  UpdateTaskTool,
 
6
  # Add the parent directory to sys.path to import modules
7
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
8
 
9
+ from agents.ClickUpAgent.tools.ClickUpTools import (
10
  CreateTaskTool,
11
  DeleteTaskTool,
12
  UpdateTaskTool,
agency_ai_demo/tests/test_list_tasks.py CHANGED
@@ -4,7 +4,7 @@ from openai import AzureOpenAI
4
  from agency_swarm import set_openai_client
5
  from agency_swarm import Agent
6
 
7
- from tools.clickup_tools import initialize_clickup_tools
8
 
9
  load_dotenv()
10
 
@@ -34,7 +34,7 @@ def main():
34
 
35
  print("\nTesting get_tasks_tool...")
36
  # Test GetTasksTool directly without using the agent
37
- from tools.clickup_tools import GetTasksTool
38
 
39
  tool = GetTasksTool()
40
  result = tool._run(list_id=901307715461)
 
4
  from agency_swarm import set_openai_client
5
  from agency_swarm import Agent
6
 
7
+ from agents.ClickUpAgent.tools.ClickUpTools import initialize_clickup_tools
8
 
9
  load_dotenv()
10
 
 
34
 
35
  print("\nTesting get_tasks_tool...")
36
  # Test GetTasksTool directly without using the agent
37
+ from agents.ClickUpAgent.tools.ClickUpTools import GetTasksTool
38
 
39
  tool = GetTasksTool()
40
  result = tool._run(list_id=901307715461)
agency_ai_demo/tests/test_tool_directly.py CHANGED
@@ -6,7 +6,11 @@ from dotenv import load_dotenv
6
  from openai import AzureOpenAI
7
  from agency_swarm import set_openai_client, Agent, Agency
8
 
9
- from tools.clickup_tools import initialize_clickup_tools, GetTasksTool, GetTaskTool
 
 
 
 
10
 
11
  load_dotenv()
12
 
 
6
  from openai import AzureOpenAI
7
  from agency_swarm import set_openai_client, Agent, Agency
8
 
9
+ from agents.ClickUpAgent.tools.ClickUpTools import (
10
+ initialize_clickup_tools,
11
+ GetTasksTool,
12
+ GetTaskTool,
13
+ )
14
 
15
  load_dotenv()
16
 
agency_ai_demo/utils/ensure_serializable.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+
3
+
4
+ # Add a utility function to ensure all values are JSON serializable
5
+ def ensure_serializable(obj):
6
+ """
7
+ Recursively ensure that an object and all its contents are JSON serializable.
8
+ Handles Pydantic Field objects by extracting their values.
9
+ """
10
+ # Handle None
11
+ if obj is None:
12
+ return None
13
+
14
+ # Check if it's a Field object (has certain common Field attributes)
15
+ if hasattr(obj, "default") and hasattr(obj, "description"):
16
+ # Return the default value or None
17
+ if obj.default is not None:
18
+ return obj.default
19
+ return None
20
+
21
+ # Handle dictionaries
22
+ if isinstance(obj, dict):
23
+ return {k: ensure_serializable(v) for k, v in obj.items()}
24
+
25
+ # Handle lists
26
+ if isinstance(obj, list):
27
+ return [ensure_serializable(item) for item in obj]
28
+
29
+ # Return other objects as is
30
+ return obj