Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add autogen tools new version #1190

Merged
merged 4 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions python/composio/client/enums/action.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -1594,6 +1594,7 @@ class Action(Enum[ActionData], metaclass=EnumGenerator):
CAL_GET_EVENT_TYPE_BY_TEAM_ID: "Action"
CAL_GET_GOOGLE_CALENDAR_OAUTH_AUTHENTICATION_URL: "Action"
CAL_GET_OAUTH_CLIENTS_USER: "Action"
CAL_GET_ORGANIZATION_ID: "Action"
CAL_GET_ORGANIZATION_SCHEDULES: "Action"
CAL_GET_ORGANIZATION_TEAMS_EVENT_TYPES: "Action"
CAL_GET_ORGANIZATION_USER_SCHEDULES: "Action"
Expand Down Expand Up @@ -1921,6 +1922,7 @@ class Action(Enum[ActionData], metaclass=EnumGenerator):
CODE_ANALYSIS_TOOL_GET_METHOD_SIGNATURE: "Action"
CODE_ANALYSIS_TOOL_GET_RELEVANT_CODE: "Action"
CODE_FORMAT_TOOL_FORMAT_AND_LINT_CODEBASE: "Action"
COMPOSIO_ADVANCED_USE_CASE_SEARCH: "Action"
COMPOSIO_CHECK_ACTIVE_CONNECTION: "Action"
COMPOSIO_ENABLE_TRIGGER: "Action"
COMPOSIO_EXECUTE_ACTION: "Action"
Expand Down Expand Up @@ -8039,6 +8041,11 @@ class Action(Enum[ActionData], metaclass=EnumGenerator):
TWITTER_USER_LOOKUP_BY_USERNAME: "Action"
TWITTER_USER_LOOKUP_BY_USERNAMES: "Action"
TWITTER_USER_LOOKUP_ME: "Action"
TYPEFULLY_CREATE_DRAFT: "Action"
TYPEFULLY_GET_NOTIFICATIONS: "Action"
TYPEFULLY_GET_RECENTLY_PUBLISHED: "Action"
TYPEFULLY_GET_RECENTLY_SCHEDULED: "Action"
TYPEFULLY_MARK_NOTIFICATIONS_READ: "Action"
WEATHERMAP_WEATHER: "Action"
WEBTOOL_SCRAPE_WEBSITE_CONTENT: "Action"
WEBTOOL_SCRAPE_WEBSITE_ELEMENT: "Action"
Expand Down
1 change: 1 addition & 0 deletions python/composio/client/enums/app.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ class App(Enum[AppData], metaclass=EnumGenerator):
TWITCH: "App"
TWITTER: "App"
TWITTER_MEDIA: "App"
TYPEFULLY: "App"
VENLY: "App"
VERO: "App"
VISME: "App"
Expand Down
2 changes: 2 additions & 0 deletions python/composio/client/enums/tag.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,8 @@ class Tag(Enum[TagData], metaclass=EnumGenerator):
TWITTER_TWEETS: "Tag"
TWITTER_USAGE: "Tag"
TWITTER_USERS: "Tag"
TYPEFULLY_DRAFTS: "Tag"
TYPEFULLY_NOTIFICATIONS: "Tag"
WRIKE_ACCOUNTS: "Tag"
WRIKE_CONTACTS: "Tag"
WRIKE_CUSTOM_FIELDS: "Tag"
Expand Down
45 changes: 45 additions & 0 deletions python/plugins/autogen/autogen_demo_2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""
Autogen demo using get_tools() approach.
"""

import asyncio
import os

import dotenv
from autogen_agentchat.agents import AssistantAgent
from autogen_core import CancellationToken
from autogen_ext.models.openai import OpenAIChatCompletionClient

from composio_autogen import App, ComposioToolSet


async def main():
# Initialize toolset and get tools
composio_toolset = ComposioToolSet()
tools = composio_toolset.get_tools(apps=[App.GITHUB])

model_client = OpenAIChatCompletionClient(
model="gpt-4",
api_key=os.environ["OPENAI_API_KEY"],
)
# Create assistant agent with tools
assistant = AssistantAgent(
name="github_assistant",
system_message=(
"You are an AI assistant that helps with GitHub tasks. "
"Use the provided tools to interact with GitHub."
),
model_client=model_client,
tools=list(tools),
)

# Define task and initiate chat
task = "Star the repository composiohq/composio on GitHub"
result = await assistant.run(task=task, cancellation_token=CancellationToken())
print(result)


if __name__ == "__main__":
# Load environment variables from .env
dotenv.load_dotenv()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding error handling for environment variable loading. If .env file is missing or required variables are not set, the code will fail silently.

asyncio.run(main())
113 changes: 109 additions & 4 deletions python/plugins/autogen/composio_autogen/toolset.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
import autogen
import typing_extensions as te
from autogen.agentchat.conversable_agent import ConversableAgent
from autogen_core.tools import FunctionTool

from composio import Action, ActionType, AppType, TagType
from composio.tools import ComposioToolSet as BaseComposioToolSet
from composio.tools.toolset import ProcessorsType
from composio.utils.shared import get_signature_format_from_schema_params


Expand Down Expand Up @@ -137,10 +139,14 @@ def execute_action(**kwargs: t.Any) -> t.Dict:
),
closure=execute_action.__closure__,
)
function.__signature__ = Signature( # type: ignore
parameters=get_signature_format_from_schema_params(
schema_params=schema["parameters"],
),
params = get_signature_format_from_schema_params(
schema_params=schema["parameters"],
)
setattr(function, "__signature__", Signature(parameters=params))
setattr(
function,
"__annotations__",
{p.name: p.annotation for p in params} | {"return": t.Dict[str, t.Any]},
)
function.__doc__ = (
description if description else f"Action {name} from {appName}"
Expand All @@ -154,3 +160,102 @@ def execute_action(**kwargs: t.Any) -> t.Dict:
),
description=description if description else f"Action {name} from {appName}",
)

def _wrap_tool(
self,
schema: t.Dict[str, t.Any],
entity_id: t.Optional[str] = None,
) -> FunctionTool:
"""
Wraps a composio action as an Autogen FunctionTool.

Args:
schema: The action schema to wrap
entity_id: Optional entity ID for executing function calls

Returns:
FunctionTool: Wrapped function as an Autogen FunctionTool
"""
name = schema["name"]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding validation for the schema parameters in _wrap_tool method. Currently, there's no validation to ensure required schema fields are present before accessing them.

description = schema["description"] or f"Action {name} from {schema['appName']}"

def execute_action(**kwargs: t.Any) -> t.Dict:
"""Placeholder function for executing action."""
return self.execute_action(
action=Action(value=name),
params=kwargs,
entity_id=entity_id or self.entity_id,
_check_requested_actions=True,
)

# Create function with proper signature
function = types.FunctionType(
code=execute_action.__code__,
globals=globals(),
name=self._process_function_name_for_registration(input_string=name),
closure=execute_action.__closure__,
)

# Set signature and annotations
params = get_signature_format_from_schema_params(
schema_params=schema["parameters"]
)
setattr(function, "__signature__", Signature(parameters=params))
setattr(
function,
"__annotations__",
{p.name: p.annotation for p in params} | {"return": t.Dict[str, t.Any]},
)
function.__doc__ = description

return FunctionTool(
func=function,
description=description,
name=self._process_function_name_for_registration(input_string=name),
)

def get_tools(
self,
actions: t.Optional[t.Sequence[ActionType]] = None,
apps: t.Optional[t.Sequence[AppType]] = None,
tags: t.Optional[t.List[TagType]] = None,
entity_id: t.Optional[str] = None,
*,
processors: t.Optional[ProcessorsType] = None,
check_connected_accounts: bool = True,
) -> t.Sequence[FunctionTool]:
"""
Get composio tools as Autogen FunctionTool objects.

Args:
actions: List of actions to wrap
apps: List of apps to wrap
tags: Filter apps by given tags
entity_id: Entity ID for function wrapper
processors: Optional dict of processors to merge
check_connected_accounts: Whether to check for connected accounts

Returns:
List of Autogen FunctionTool objects
"""
self.validate_tools(apps=apps, actions=actions, tags=tags)
if processors is not None:
self._merge_processors(processors)

tools = [
self._wrap_tool(
schema=tool.model_dump(
exclude_none=True,
),
entity_id=entity_id or self.entity_id,
)
for tool in self.get_action_schemas(
actions=actions,
apps=apps,
tags=tags,
check_connected_accounts=check_connected_accounts,
_populate_requested=True,
)
]

return tools
2 changes: 2 additions & 0 deletions python/plugins/autogen/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
"composio_core>=0.6.11,<0.7.0",
"pyautogen>=0.2.19",
"flaml==2.2.0",
"autogen_core>=0.4.0",
"autogen_agentchat>=0.4.0",
],
include_package_data=True,
)
Loading