Skip to content

add Google ADK support #34

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

Merged
merged 7 commits into from
May 21, 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
45 changes: 45 additions & 0 deletions python/examples/adapter_google_adk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# thirdweb-ai with Google Agent Development Kit (ADK)

This example demonstrates how to integrate thirdweb-ai's blockchain tooling with [Google ADK](https://github.com/google/adk-python), an open-source toolkit from Google for building autonomous agents.

## Overview

thirdweb-ai provides powerful blockchain data access and interaction tools through its Insight and Nebula services. This example shows how to use these tools with Google ADK to create an AI assistant that can answer queries about blockchain data, check wallet balances, and more, all through natural language.

## Installation

First, ensure you have Python 3.10+ installed. Then install the required packages:

```bash
# Using pip
pip install "thirdweb-ai[google-adk]"

# Using uv
uv add "thirdweb-ai[google-adk]"
```

## Usage

1. Set your thirdweb API key as an environment variable:
```bash
export THIRDWEB_SECRET_KEY=your_api_key_here
```

2. Run the example:
```bash
python example.py
```

The script demonstrates using the agent to:
- Get details of a transaction

## Customization

You can customize the assistant by modifying the example code:
- Add different types of tools by extending the `tools` list
- Change the model by modifying the `model` configuration
- Add your own queries

## Requirements

See `pyproject.toml` for the full list of dependencies.
81 changes: 81 additions & 0 deletions python/examples/adapter_google_adk/example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import asyncio
import os

from google.adk.agents import LlmAgent
from google.adk.models.lite_llm import LiteLlm
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import types

from thirdweb_ai import Insight
from thirdweb_ai.adapters.google_adk.google_adk import get_google_adk_tools

# Example app configuration
APP_NAME = "thirdweb_insight_app"
USER_ID = "test_user"
SESSION_ID = "test_session"


async def setup_agent() -> Runner:
"""Set up an agent with Thirdweb Insight tools.

Returns:
Runner: Google ADK runner for the agent
"""
# Initialize Insight with secret key
secret_key = os.getenv("THIRDWEB_SECRET_KEY")
if not secret_key:
raise ValueError("THIRDWEB_SECRET_KEY environment variable is required")

# Get Insight tools
insight = Insight(secret_key=secret_key, chain_id=1)
insight_tools = insight.get_tools()

# Convert to Google ADK tools
adk_tools = get_google_adk_tools(insight_tools)

# Print all available tools for debugging
print(f"Available tools ({len(adk_tools)}):")
for tool_count, tool in enumerate(adk_tools, start=1):
print(f"- Tool #{tool_count} {tool.name}")

# Create the agent with the tools
agent = LlmAgent(
model=LiteLlm(model="gpt-4o-mini"),
name="thirdweb_insight_agent",
# Convert BaseTool to the expected type for LlmAgent
tools=adk_tools, # type: ignore
)

# Set up session
session_service = InMemorySessionService()
# We need to create the session but don't need to store it
await session_service.create_session(app_name=APP_NAME, user_id=USER_ID, session_id=SESSION_ID)

# Return runner
return Runner(agent=agent, app_name=APP_NAME, session_service=session_service)


async def call_agent(query: str) -> None:
"""Run a query through the agent.

Args:
query: The query to send to the agent
"""
runner = await setup_agent()
content = types.Content(role="user", parts=[types.Part(text=query)])
events = runner.run(user_id=USER_ID, session_id=SESSION_ID, new_message=content)

for event in events:
if (
hasattr(event, "is_final_response")
and event.is_final_response()
and (event.content and hasattr(event.content, "parts") and event.content.parts)
):
final_response = event.content.parts[0].text
print("Agent Response: ", final_response)


if __name__ == "__main__":
test_query = "Find information on transaction: 0x45027cce9d2b990349b4a1e015ec29ca7c7ef15d82487d898f24866a09e8b84c."
asyncio.run(call_agent(test_query))
16 changes: 16 additions & 0 deletions python/examples/adapter_google_adk/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[project]
name = "thirdweb-ai-examples-autogen"
version = "0.1.0"
description = "Example of using thirdweb_ai with Google ADK"
authors = [{ name = "thirdweb", email = "[email protected]" }]
requires-python = "~=3.10"
dependencies = [
"thirdweb-ai[google-adk]"
]

[tool.uv]
package = false

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
2,699 changes: 2,699 additions & 0 deletions python/examples/adapter_google_adk/uv.lock

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions python/thirdweb-ai/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ all = [
"mcp>=1.3.0",
"smolagents>=1.10.0",
"pydantic-ai>=0.0.39",
"google-adk>=1.0.0"
]
langchain = ["langchain-core>=0.3.0"]
goat = ["goat-sdk>=0.1.0"]
Expand All @@ -37,6 +38,7 @@ agentkit = ["coinbase-agentkit>=0.1.0,<0.2"]
mcp = ["mcp>=1.3.0"]
smolagents = ["smolagents>=1.10.0"]
pydantic-ai = ["pydantic-ai>=0.0.39"]
google-adk = ["google-adk>=1.0.0", "litellm>=v1.70.0"]

[dependency-groups]
dev = [
Expand Down Expand Up @@ -84,6 +86,7 @@ dependencies = [
[tool.uv-dynamic-versioning]
vcs = "git"
style = "semver"
format = "{base}"

[tool.pyright]
include = ["src"]
Expand Down
1 change: 0 additions & 1 deletion python/thirdweb-ai/src/thirdweb_ai/_version.py

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
from typing import Any

from google.adk.tools import BaseTool, ToolContext
from google.genai import types

from thirdweb_ai.tools.tool import Tool, ToolSchema

from pydantic import BaseModel

class GoogleAdkTool(BaseTool):
"""Adapter for Thirdweb Tool to Google ADK BaseTool.

This allows Thirdweb tools to be used with Google ADK agents.
"""

def __init__(self, tool: Tool):
"""Initialize the Google ADK Tool wrapper.

Args:
tool: The Thirdweb Tool to wrap
"""
self.tool = tool
super().__init__(
name=tool.name,
description=tool.description,
)

@property
def schema(self) -> ToolSchema:
"""Return the schema for the tool.

Returns:
The schema for the function declaration
"""
return self.tool.schema

def _get_declaration(self) -> types.FunctionDeclaration:
"""Generate the function declaration for Google ADK.

Returns:
A FunctionDeclaration for Google ADK
"""
parameters = self.tool.schema["parameters"]
del parameters["additionalProperties"]
return types.FunctionDeclaration(
name=self.name,
description=self.description,
parameters=parameters,
)

# Override the method with the expected signature based on the error message
# and adapting from the reference implementation
async def run_async(self, args: dict[str, Any], tool_context: ToolContext) -> Any:
"""Execute the tool asynchronously.

This method adapts the Thirdweb tool to work with Google ADK's async execution.

Returns:
The result of running the tool
"""
return self.tool.run_json(args)


def get_google_adk_tools(tools: list[Tool]) -> list[BaseTool]:
"""Convert Thirdweb tools to Google ADK tools.

Args:
tools: List of Thirdweb tools to convert

Returns:
List of Google ADK tools
"""
return [GoogleAdkTool(tool) for tool in tools]
Loading