Add a Function Tool to an Agent using the ADK
This tutorial covers the steps to add a function tool to an existing agent in Generative AI Agents.
Function tools allow the agent to use custom-written, locally-defined functions as tools. They're very flexible and particularly useful for enterprise cases due to its local processing, easy authentication, and seamless integration with existing functionality.
In this example, we have a weather agent equipped with a custom function tool. This is also known as a function calling agent.
Function tools are executed locally on your side.
What is sent to a remote agent on OCI servers is the function definition (function name, function parameters, and their descriptions). OCI servers do not access the function implementation.
Overview
When a weather query is made, the remote agent effectively does the intent classification to use the get_weather
tool. For example, based on the natural language query Is it cold in Seattle?
, the remote agent fills the argument slot and makes the request.
The agent sends a request that contains the required actions for the client app. In this case, the required action for the client is to invoke the get_weather
function tool with an argument location
=Seattle
.
The Agent Development Kit (ADK) does the following:
- parses the required action
- finds the local function registered
- runs this function with the specific arguments
- captures the function call output
- submits the output back to the remote agent, so that the agent can use that output to generate an answer to the user prompt
Prerequisites
- On the machine running your code, set up an OCI API config file. Ensure the configuration refers to a region in which Generative AI Agents is hosted.
-
Create a virtual environment:
python3 -m venv <myenv>
Activate the virtual environment.
source <myenv>/bin/activate
-
Install the ADK. Python ADK requires Python 3.10 or later.
pip install "oci[adk]
Set up a Compartment for Development
-
Ask an administrator to add the following IAM policy for you:
allow <a-group-your-user-name-belongs-to> to manage all-resources in compartment <your-compartment-name>
Important
Providing complete access to a compartment is convenient for a tutorial. However, in production, use more restrictive policies to limit access to the agent. See Getting Access to Generative AI Agents. - Sign in to the Oracle Cloud Infrastructure Console.
- Open the navigation menu and select Identity & Security. Under Identity, select Compartments.
- Select Create Compartment.
-
Fill in the following information:
- Name:
<your-compartment-name>
- Description:
Compartment for <your-description>.
- Parent Compartment:
<your-tenancy>(root)
- Name:
- Select Create compartment.
Reference: Create a compartment
Create an Agent
- In the navigation bar of the Console, select the same region that you selected for the config file in the previous section.
- On the Agents list page, select Create agent. If you need help finding the list page, see Listing Agents.
-
Enter the following information:
- Name:
<your-agent-name>
- Compartment: Select a compartment that you have permission to work in.
- Description: Agent with no initial tools. Adding tools with ADK.
- Welcome message: Leave blank.
- Routing instructions: Leave blank.
- Name:
- Select Next to navigate to the Add Tool step. Skip this page and don't add any tools.
- Select Next.
- (Optional) Select Automatically create an endpoint for this agent to create an endpoint when the agent is created and keep all the other default options.
-
Select Next and then select Create Agent.
Note
Accept license terms if requested. - Wait for the agent to become active.
Gather Required Info
-
In your environment, copy the region that you set up for the config file in a notepad. For example,
us-chicago-1
. - In the Console, on the Agents list page, select the agent that you created in this tutorial. If you need help finding the list page, see Listing Agents.
-
Copy the OCID for the agent and paste it in a notepad for the next section.
Example agent OCID:
ocid1.genaiagent.oc1.us-chicago-1.<unique-id>
- Select the Endpoint for this agent.
-
Copy the OCID for the endpoint and paste it in a notepad for the next section.
Example endpoint OCID:
ocid1.genaiagentendpoint.oc1.us-chicago-1.<unique-id>
-
Navigate to Identity and Security and select Compartments. Select the compartment with the agent. Copy the OCID for the compartment and paste it in a notepad.
Example compartment OCID:
ocid1.compartment.oc1..<unique-id>
Create a Local File
- From the terminal, go to your home directory.
- Create a directory called ADK.
- Change to the ADK directory.
-
Create a file called,
weather_agent.py
. -
Paste the following code into
weather-agent.py
.Replace <region-where-agent-is-created> and <your-agent-endpoint> with the values that you gathered.from typing import Dict from adk import Agent, AgentClient, tool @tool def get_weather(location: str) -> Dict[str, str]: """Get the weather for a given location""" return {"location": location, "temperature": 72, "unit": "F"} def main(): # Create a client with your authentication details client = AgentClient( auth_type="api_key", profile="DEFAULT", region="<region-where-agent-is-created>" ) # Instantiate the agent with your agent endpoint ID and the tool agent = Agent( client=client, agent_endpoint_id="<your-agent-endpoint>", instructions="Perform weather queries using the given tools.", tools=[get_weather] ) # Set up the agent (configures instructions and tools in the remote agent resource) agent.setup() # Run the agent with an input input = "Is it cold in Seattle?" response = agent.run(input) # Print the response response.pretty_print() if __name__ == "__main__": main()
Add the Tool
If you chose an existing agent instead of creating a new one for this tutorial, before you run this file ensure the remote agent has no tools. This program deletes all the tools on the remote agent, unless it's the tool is named
get_weather
tool. If it finds a remote get_weather
tool it updates the remote tool to be synchronized with the local one.-
In the Console, navigate to the agent's detail page and note the values for.
- Routing instructions: Should be blank.
- Select Tools. The tool list should be empty.
-
Run the Python file,
get_weather
python3 weather-agent.py
-
In the output, review the local and remote function names and ensure that the
get_weather
tool is being added to the remote agent. Example output:Waiting for agent to be active... ╭─ Local and remote function tools found ─╮ │ Local function tools (1): │ │ ['get_weather'] │ │ │ │ Remote function tools (0): │ │ [] │ ╰─────────────────────────────────────────╯ Found local tool not in remote tools: get_weather. Adding it to the remote agent... Waiting for tool to be active... Checking synchronization of local and remote RAG tools... No active remote RAG tools found. No local RAG tool to add.
-
In the Console, navigate to the agent's detail page and watch the updates.
- In the agent detail page, the Routing instructions changes from blank to
Perform weather queries using the given tools.
- Select Tools. The tool,
get_weather
appears in the list of tools. - Select get_weather and under work requests, see that the CREATE_TOOL operation succeeded.
- In the agent detail page, the Routing instructions changes from blank to
Read the Outputs
-
In the output, read the user message. Example output:
╭──────────────────────────────────── Chat request to remote agent ─────────────────────────────────────╮ │ (Local --> Remote) │ │ │ │ user message: │ │ Is it cold in Seattle? │ │ │ │ performed actions by client: │ │ [] │ │ │ │ session id: │ │ ocid1.genaiagentsession.<unique-id> │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯
-
Read the chat response. Example output:
╭────────────────── Chat response from remote agent ──────────────────╮ │ (Local <-- Remote) │ │ │ │ agent message: │ │ null │ │ │ │ required actions for client to take: │ │ [ │ │ { │ │ "action_id": "<unique-id>", │ │ "required_action_type": "FUNCTION_CALLING_REQUIRED_ACTION", │ │ "function_call": { │ │ "name": "get_weather", │ │ "arguments": "{\"location\": \"Seattle\"}" │ │ } │ │ } │ │ ] │ ╰─────────────────────────────────────────────────────────────────────╯
-
Read the function call requested by the agent. Example output:
╭─ Function call requested by agent and mapped local handler function ─╮ │ Agent function tool name: │ │ get_weather │ │ │ │ Agent function tool call arguments: │ │ {'location': 'Seattle'} │ │ │ │ Mapped local handler function name: │ │ get_weather │ ╰──────────────────────────────────────────────────────────────────────╯
-
Read the function execution result. Example output:
╭─────── Obtained local function execution result ────────╮ │ {'location': 'Seattle', 'temperature': 72, 'unit': 'F'} │ ╰─────────────────────────────────────────────────────────╯
-
Read the chat request to the remote agent example output:
╭──────────────────────────────────── Chat request to remote agent ─────────────────────────────────────╮ │ (Local --> Remote) │ │ │ │ user message: │ │ null │ │ │ │ performed actions by client: │ │ [ │ │ { │ │ "action_id": "<unique-id>", │ │ "performed_action_type": "FUNCTION_CALLING_PERFORMED_ACTION", │ │ "function_call_output": "{\"location\": \"Seattle\", \"temperature\": 72, \"unit\": \"F\"}" │ │ } │ │ ] │ │ │ │ session id: │ │ ocid1.genaiagentsession.oc1.us-chicago-1.xxx │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯
-
Read the chat response from the remote agent example output:
╭─────────────────────────────── Chat response from remote agent ────────────────────────────────╮ │ (Local <-- Remote) │ │ │ │ agent message: │ │ { │ │ "role": "AGENT", │ │ "content": { │ │ "text": "It's not cold in Seattle. The current temperature is 72 degrees Fahrenheit.", │ │ "citations": null, │ │ "paragraph_citations": null │ │ }, │ │ "time_created": "2025-04-10T18:47:33.617000+00:00" │ │ } │ │ │ │ required actions for client to take: │ │ null │ ╰────────────────────────────────────────────────────────────────────────────────────────────────╯
-
Read the agent run response that's in natural language. Example output:
╭──────────────────────────────────────────────── Agent run response ────────────────────────────────────────────────╮ │ agent text message: │ │ It's not cold in Seattle. The current temperature is 72 degrees Fahrenheit. │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Remove the Tool
-
In your local environment, create a file called
list_agent_tools.py
with the following content. Also update the all the ID variables with your OCID information.import json from adk import AgentClient def main(): agent_id = "ocid1.genaiagent.<unique-id>" agent_compartment_id = "<your-compartment-ocid>" region_id = "<your-region-id>" # Enter an OCI region such as "us-chicago-1" or airport code such as "ORD" # Create a client with your authentication details client = AgentClient( auth_type="api_key", profile="DEFAULT", region=region_id ) # Find the tools of the following agent in the following compartment tool_list = client.find_tools(agent_compartment_id, agent_id) json_str = json.dumps(tool_list, indent=4) print(json_str) for item in tool_list: print(f"Tool Name: {item.get('display_name')} \nTool OCID: {item.get('id')}") if __name__ == "__main__": main()
This script calls the client's
find_tool
operation and returns all the tools for a specified agent in a specified compartment. -
Review the output:
[ { "id": "ocid1.genaiagenttool.<unique-id>", "lifecycle_state": "ACTIVE", "time_created": "2025-04-10T21:49:19.350000+00:00", "time_updated": "2025-04-10T21:49:42.132000+00:00", "display_name": "get_weather", "description": "Get the weather for a given location created by ADK", "compartment_id": "<your-compartment-ocid>", "agent_id": "ocid1.genaiagent.<unique-id>", "tool_config": { "tool_config_type": "FUNCTION_CALLING_TOOL_CONFIG", "function": { "name": "get_weather", "description": "Get the weather for a given location", "parameters": { "type": "object", "properties": "{\"location\": {\"type\": \"string\"}}", "required": "['location']" } } }, "metadata": null, "freeform_tags": { "ModifiedBy": "ADK", "CreatedBy": "ADK" }, "defined_tags": { "Oracle-Tags": { "CreatedBy": "john.doe@example.com", "CreatedOn": "2025-04-10T21:49:19.277Z" } }, "system_tags": {} } ] Tool Name: get_weather Tool OCID: ocid1.genaiagenttool.oc1.us-chicago-1.amaa<your-ocid>
-
Create a file called
delete_tools.py
and copy the following information to use thedelete_tool
operation to delete theweather_tool
. Also update the all the ID variables with your OCID information.import json from adk import AgentClient def main(): agent_id = "ocid1.genaiagent.<unique-id>" agent_compartment_id = "<your-compartment-ocid>" endpoint_id = "ocid1.genaiagentendpoint.<unique-id>" region_id = "<your-region-id>" # Create a client with your authentication details client = AgentClient( auth_type="api_key", profile="DEFAULT", region=region_id ) # Find the tools of the following agent in the following compartment tool_list = client.find_tools(agent_compartment_id, agent_id) json_str = json.dumps(tool_list, indent=4) print(json_str) for item in tool_list: print(f"Tool Name: {item.get('display_name')} \nTool OCID: {item.get('id')}") for item in tool_list: print(f"Deleting tool {item.get('display_name')} with tool OCID: {item.get('id')}") client.delete_tool(item.get('id')) print ("Tool deleted!") if __name__ == "__main__": main()
- In the Console, go to the agent's detail page and see that the tool is deleted.
-
Deactivate the virtual environment.
decativate