Let’s imagine we have the following Python tool. This tool is required to make an API call to sample-api.com, which requires an API key for authentication. Please note that sample-api.com is a fictitious endpoint used solely for demonstration purposes.

[Python]
import requests
from ibm_watsonx_orchestrate.agent_builder.tools import tool, ToolPermission

@tool(
    permission=ToolPermission.READ_ONLY
)
def my_sample_tool() -> str:
    """
    A tool which takes 2 params and passes them to an api
    """

    url = "https://sample-api.com/"
    headers = {
        "Authorization": <my_api_key>
    }
    response = requests.get(url, headers=headers)
    return response

The ADK utilizes ibm_watsonx_orchestrate.run.connections, which provides access to the connections created. This enables the tool to obtain an API key without including it directly in the code. Using this approach, we can rewrite our tool as the following:

[Python]
import requests
from ibm_watsonx_orchestrate.agent_builder.tools import tool, ToolPermission
from ibm_watsonx_orchestrate.run import connections
from ibm_watsonx_orchestrate.agent_builder.connections import ConnectionType, ExpectedCredentials

@tool(
    permission=ToolPermission.READ_ONLY,
    expected_credentials=[ExpectedCredentials(
        app_id = <my_connection_app_id>,
        type = ConnectionType.API_KEY_AUTH
    )]
)
def my_sample_tool() -> str:
    """
    A tool which takes 2 params and passes them to an api
    """

    url = "https://sample-api.com/"
    conn = connections.api_key_auth(<my_connection_app_id>)
    headers = {
        "Authorization": conn.api_key
    }
    response = requests.get(url, headers=headers)
    return response

The key change is the inclusion of connections.api_key_auth(<my_connection_app_id>). This line retrieves the connection of type api_key using the provided app_id.

Additionally, note the inclusion of the expected_credentials option in the @tool decorator. This option accepts a list of dictionaries or ExpectedCredentials objects and enforces that the connection is established at tool import time.

There are various types of connections, all of which can be accessed using the following method:

  • basic - conn = connections.basic_auth(<app_id>)
    • conn.username
    • conn.password
    • conn.url
  • bearer - conn = connections.bearer_token(<app_id>)
    • conn.token
    • conn.url
  • api_key - conn = connections.api_key_auth(<app_id>)
    • conn.api_key
    • conn.url
  • oauth_auth_on_behalf_of_flow - conn = connections.oauth2_on_behalf_of(<app_id>)
    • conn.access_token
    • conn.url
  • key_value - conn = connections.key_value(<app_id>)