chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
# composio-google-adk
|
||||
|
||||
Adapts Composio tools to [Google ADK](https://google.github.io/adk-docs/) `FunctionTool` objects, so your ADK agents can take action across 1000+ apps.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install composio composio-google-adk google-adk
|
||||
```
|
||||
|
||||
Set `COMPOSIO_API_KEY` (from the [dashboard](https://dashboard.composio.dev/settings)) and `GOOGLE_API_KEY` in your environment.
|
||||
|
||||
## Quickstart
|
||||
|
||||
```python
|
||||
from composio import Composio
|
||||
from composio_google_adk import GoogleAdkProvider
|
||||
from google.adk.agents import Agent
|
||||
from google.adk.runners import Runner
|
||||
from google.adk.sessions import InMemorySessionService
|
||||
from google.genai import types
|
||||
|
||||
composio = Composio(provider=GoogleAdkProvider())
|
||||
|
||||
# Each Composio session is scoped to one of your users
|
||||
composio_session = composio.create(user_id="user_123")
|
||||
tools = composio_session.tools()
|
||||
|
||||
agent = Agent(
|
||||
name="personal_assistant",
|
||||
model="gemini-2.0-flash",
|
||||
instruction="You are a helpful assistant. Use Composio tools to take action.",
|
||||
tools=tools,
|
||||
)
|
||||
|
||||
session_service = InMemorySessionService()
|
||||
session_service.create_session_sync(
|
||||
app_name="personal_assistant",
|
||||
user_id="user_123",
|
||||
session_id="1234",
|
||||
)
|
||||
runner = Runner(
|
||||
agent=agent,
|
||||
app_name="personal_assistant",
|
||||
session_service=session_service,
|
||||
)
|
||||
|
||||
events = runner.run(
|
||||
user_id="user_123",
|
||||
session_id="1234",
|
||||
new_message=types.Content(
|
||||
role="user",
|
||||
parts=[types.Part(text="Star the repository composiohq/composio on GitHub")],
|
||||
),
|
||||
)
|
||||
for event in events:
|
||||
if event.is_final_response() and event.content and event.content.parts:
|
||||
print(event.content.parts[0].text)
|
||||
```
|
||||
|
||||
For multi-turn use, store `composio_session.session_id` and reuse it with `composio.use(session_id)` instead of calling `create()` again.
|
||||
|
||||
## How tools are wrapped
|
||||
|
||||
`GoogleAdkProvider` turns each Composio tool into a `google.adk.tools.FunctionTool` with a Python signature and docstring generated from the tool's schema, so ADK can pass them to Gemini as regular function declarations.
|
||||
|
||||
## Links
|
||||
|
||||
- [Quickstart](https://docs.composio.dev/docs/quickstart)
|
||||
- [Composio documentation](https://docs.composio.dev)
|
||||
@@ -0,0 +1,3 @@
|
||||
from .provider import GoogleAdkProvider
|
||||
|
||||
__all__ = ("GoogleAdkProvider",)
|
||||
@@ -0,0 +1,85 @@
|
||||
import types
|
||||
import typing as t
|
||||
from inspect import Signature
|
||||
|
||||
from google.adk.tools import FunctionTool
|
||||
|
||||
from composio.client.types import Tool
|
||||
from composio.core.provider import AgenticProvider
|
||||
from composio.core.provider.agentic import AgenticProviderExecuteFn
|
||||
from composio.utils.openapi import function_signature_from_jsonschema
|
||||
from composio.utils.shared import alias_tool_input_schema, normalize_tool_arguments
|
||||
|
||||
|
||||
class GoogleAdkProvider(
|
||||
AgenticProvider[FunctionTool, list[FunctionTool]], name="google_adk"
|
||||
):
|
||||
"""
|
||||
Composio toolset for Google ADK framework.
|
||||
"""
|
||||
|
||||
__schema_skip_defaults__ = True
|
||||
|
||||
def wrap_tool(
|
||||
self,
|
||||
tool: Tool,
|
||||
execute_tool: AgenticProviderExecuteFn,
|
||||
) -> FunctionTool:
|
||||
"""Wraps composio tool as Google Genai SDK compatible function calling object."""
|
||||
|
||||
input_parameters = t.cast(
|
||||
t.Dict[str, t.Any],
|
||||
tool.input_parameters
|
||||
or {
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
"required": [],
|
||||
},
|
||||
)
|
||||
aliases = alias_tool_input_schema(schema=input_parameters)
|
||||
properties = t.cast(
|
||||
t.Dict[str, t.Dict[str, t.Any]],
|
||||
aliases.schema.get("properties", {}),
|
||||
)
|
||||
docstring = tool.description or f"Execute {tool.slug}"
|
||||
docstring += "\nArgs:"
|
||||
for _param, _schema in properties.items():
|
||||
docstring += "\n "
|
||||
docstring += _param + ": " + _schema.get("description", _param.title())
|
||||
|
||||
docstring += "\nReturns:"
|
||||
docstring += "\n A dictionary containing response from the action"
|
||||
|
||||
def _execute(**kwargs: t.Any) -> t.Dict:
|
||||
kwargs = aliases.restore_arguments(kwargs)
|
||||
# Normalize defensively so a stringified payload is coerced to a dict (issue #2406).
|
||||
return execute_tool(
|
||||
slug=tool.slug, arguments=normalize_tool_arguments(kwargs)
|
||||
)
|
||||
|
||||
function = types.FunctionType(
|
||||
code=_execute.__code__,
|
||||
name=tool.slug,
|
||||
globals=globals(),
|
||||
closure=_execute.__closure__,
|
||||
)
|
||||
parameters = function_signature_from_jsonschema(
|
||||
schema=aliases.schema,
|
||||
skip_default=self.skip_default,
|
||||
)
|
||||
setattr(function, "__signature__", Signature(parameters=parameters))
|
||||
setattr(
|
||||
function,
|
||||
"__annotations__",
|
||||
{p.name: p.annotation for p in parameters} | {"return": dict},
|
||||
)
|
||||
function.__doc__ = docstring
|
||||
return FunctionTool(function)
|
||||
|
||||
def wrap_tools(
|
||||
self,
|
||||
tools: t.Sequence[Tool],
|
||||
execute_tool: AgenticProviderExecuteFn,
|
||||
) -> list[FunctionTool]:
|
||||
"""Get composio tools wrapped as Google Genai SDK compatible function calling object."""
|
||||
return [self.wrap_tool(tool, execute_tool) for tool in tools]
|
||||
@@ -0,0 +1,62 @@
|
||||
from composio_google_adk import GoogleAdkProvider
|
||||
from google.adk.agents import Agent
|
||||
from google.adk.runners import Runner
|
||||
from google.adk.sessions import InMemorySessionService
|
||||
from google.genai import types
|
||||
|
||||
from composio import Composio
|
||||
|
||||
# ADK config
|
||||
model = "gemini-2.0-flash"
|
||||
app_name = "weather_sentiment_agent"
|
||||
session_id = "1234"
|
||||
user_id = "user1234"
|
||||
|
||||
# Initialize composio tools
|
||||
composio = Composio(provider=GoogleAdkProvider())
|
||||
tools = composio.tools.get(user_id=user_id, toolkits=["GITHUB"])
|
||||
|
||||
# Agent
|
||||
weather_sentiment_agent = Agent(
|
||||
name=app_name,
|
||||
model=model,
|
||||
instruction="You are a github utility agent with ability to interact with github APIs",
|
||||
tools=tools,
|
||||
)
|
||||
|
||||
# Session and Runner
|
||||
session_service = InMemorySessionService()
|
||||
session = session_service.create_session_sync(
|
||||
app_name=app_name,
|
||||
user_id=user_id,
|
||||
session_id=session_id,
|
||||
)
|
||||
runner = Runner(
|
||||
agent=weather_sentiment_agent,
|
||||
app_name=app_name,
|
||||
session_service=session_service,
|
||||
)
|
||||
|
||||
|
||||
# Agent Interaction
|
||||
content = types.Content(
|
||||
role="user",
|
||||
parts=[
|
||||
types.Part(
|
||||
text="Star github repository composiohq/composio",
|
||||
)
|
||||
],
|
||||
)
|
||||
events = runner.run(
|
||||
user_id=user_id,
|
||||
session_id=session_id,
|
||||
new_message=content,
|
||||
)
|
||||
for event in events:
|
||||
if (
|
||||
event.is_final_response()
|
||||
and event.content is not None
|
||||
and event.content.parts
|
||||
and len(event.content.parts) > 0
|
||||
):
|
||||
print("Agent Response: ", event.content.parts[0].text)
|
||||
@@ -0,0 +1,21 @@
|
||||
[project]
|
||||
name = "composio-google-adk"
|
||||
version = "0.17.1"
|
||||
description = "Use Composio to get an array of tools with your Google AI Python Gemini model."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10,<4"
|
||||
authors = [
|
||||
{ name = "Composio", email = "tech@composio.dev" }
|
||||
]
|
||||
classifiers = [
|
||||
"Programming Language :: Python :: 3",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
"Operating System :: OS Independent",
|
||||
]
|
||||
dependencies = [
|
||||
"google-adk>=2.2.0",
|
||||
"composio",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/ComposioHQ/composio"
|
||||
@@ -0,0 +1,29 @@
|
||||
"""
|
||||
Setup configuration for Composio Google AI Python Gemini plugin
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
setup(
|
||||
name="composio_google_adk",
|
||||
version="0.17.1",
|
||||
author="Composio",
|
||||
author_email="tech@composio.dev",
|
||||
description="Use Composio to get an array of tools with your Google AI Python Gemini model.",
|
||||
long_description=(Path(__file__).parent / "README.md").read_text(encoding="utf-8"),
|
||||
long_description_content_type="text/markdown",
|
||||
url="https://github.com/ComposioHQ/composio",
|
||||
classifiers=[
|
||||
"Programming Language :: Python :: 3",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
"Operating System :: OS Independent",
|
||||
],
|
||||
python_requires=">=3.10,<4",
|
||||
install_requires=[
|
||||
"google-adk>=2.2.0",
|
||||
"composio",
|
||||
],
|
||||
include_package_data=True,
|
||||
)
|
||||
Reference in New Issue
Block a user