> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://poly-ai.ferndocs.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://poly-ai.ferndocs.com/_mcp/server.

# Create tool

> Write Python functions with parameters and return values to integrate APIs and business logic.

**This page requires Python familiarity.** Functions are written in Python and run inside your agent.

Create a function in **Tools**.

![Tools main screen](/_fern-files/_img/b1470ed75d4a5fa5302b9e1b48d4657530bff9fa1ccfcf730c2ff758d2818f33.webp)

## Step-by-step guide

Set up a new function to integrate APIs, validate input, or add custom business logic to your agent.

### 1. **Find "Tools" in the sidebar**

* Go to the agent's main page and navigate to **Tools** in the sidebar.

### 2. **Click "Add Function"**

* Select **Add Function** to create a new function.

### 3. **Define the function name**

* At the top of the page, define the function name. Note that the function name can only contain alphanumeric characters and underscores.

> **Tip**
>
> Function names are processed by the LLM like any other text, so descriptive accuracy is key. Name functions to explicitly describe what they do and avoid "start" and "stop" language. For example, changing `start_package_upgrade` to `get_available_packages` prevents the LLM from assuming an unnecessary process is starting.

### 4. **Provide a description**

* Use the "Description" field to provide an accurate summary of what your function does. This helps the model understand when to call the function. Be descriptive and concise about its purpose.

### 5. **Define LLM parameters**

* In the "LLM Parameters" field, specify the parameters the LLM model will collect and use in the function.
  * **Name**: Assign a clear and descriptive name to improve the accuracy of the LLM result.
  * **Context Description**: Provide essential context to help the LLM accurately understand and extract the parameter from the caller.
  * **Type**: Specify the parameter type. Options include "string," "number," "integer," or "boolean." Note that "number" supports decimals, while "integer" does not.

### 6. **Define the function**

* Use the "Function Definition" field to write the function in Python. You can retrieve secrets in your Python definition – see [Secrets](/advanced/secrets/overview) for details.
* The function should return a string or dictionary. A string provides additional context for the LLM. A dictionary can control agent behavior (handoff, hangup, listen, etc.). See [Return values](/agent-studio/tools/return-values) for the full list of supported return types.

### 7. **Save the function**

* Click "Save" to finalize and create your function.

## Best practices

### Environment configuration

You can use the [`conv.env`](/agent-studio/tools/classes-and-objects/object#env) property to define environment-specific functions and activate test features in sandbox or pre-release environments.

```python
if conv.env == "sandbox":
    # enable early feedback flow
    pass
elif conv.env == "pre-release":
    # activate staging tools
    pass
elif conv.env == "live":
    # run production features
    pass
```

### Handling API response errors

When writing functions that call external APIs (e.g. to fetch user records or transactions), always handle non-`200` HTTP responses explicitly.

> **Note**
>
> If `response.status_code != 200`, make sure to distinguish:
>
> * A **true error** (e.g. invalid URL or broken integration)
> * From a **valid request with no user data** (e.g. user has no transaction history)
>
> Instead of returning a generic failure, you can hand off the call or give a clearer response depending on the cause.

Example:

```python
response = requests.get(url)

if response.status_code == 404:
    return {
        "handoff": {
            "reason": "no_transaction_data",
            "utterance": "It looks like there's no recent activity on your account. Let me transfer you to someone who can help."
        }
    }
elif response.status_code != 200:
    return {
        "utterance": "Sorry, we couldn't reach your account information right now. Please try again later."
    }
```

## Related pages

#### [Libraries](/agent-studio/tools/libraries)

Standard and non-standard libraries available in functions.

#### [Return values](/agent-studio/tools/return-values)

Control agent behavior with string and dictionary returns.

#### [conv object](/agent-studio/tools/classes-and-objects/object)

Full reference for conv.state, conv.log, and other properties.