# Tools Guide

Extend agents with native catalog entries, custom uploads, and GL Connectors. Use this guide when you need to attach bespoke logic, integrate vendor connectors, or govern tool reuploads across environments via REST, the Python SDK, or the CLI.

{% hint style="info" %}
Check tooling coverage in the [AIP capability matrix](https://gdplabs.gitbook.io/gl-aip/overview#platform-capabilities-at-a-glance). Today the CLI lacks inline edits for metadata, tool configs, and runtime overrides—use export/import or the SDK/REST when you need those controls. Remote-managed GL Connectors remain partially gated behind operations enablement.
{% endhint %}

### When to Use Which Tool Pattern?

| Scenario                          | Recommended Pattern                                    | Remote deploy?                                      |
| --------------------------------- | ------------------------------------------------------ | --------------------------------------------------- |
| Rapid prototyping / Local testing | `Agent(..., tools=[ToolClass])`                        | No (Native tools require platform)                  |
| Platform development              | `Agent(..., tools=[ToolClass, Tool.from_native(...)])` | Yes (Custom tools bundled + uploaded automatically) |
| Manual registry management        | CLI/REST (SDK Client for automation)                   | Yes (Direct code upload to registry)                |

{% hint style="info" %}
**Local Native Tool Parity**

When running agents locally, `Tool.from_native("tool_name")` automatically attempts to discover and use the corresponding local implementation from the `aip-agents` SDK. This allows you to test agents using platform tools without a remote connection, provided the `aip-agents` package is installed in your environment.
{% endhint %}

### Create and Attach Tools

Prefer the **Agent-First** pattern for development. It prioritizes **local execution** via `agent.run()` for rapid iteration, while `agent.deploy()` handles bundling and upload to the platform when you are ready.

#### Single-File Tool Integration

Assume your tool lives at `tool/calculator.py` within your project:

```python
# tool/calculator.py
from typing import Any
from langchain_core.tools import BaseTool
from pydantic import BaseModel, Field

class CalculatorArgs(BaseModel):
    expression: str = Field(..., description="Arithmetic expression to evaluate")

class CalculatorTool(BaseTool):
    name = "calculator"
    description = "Evaluates simple arithmetic expressions."
    args_schema = CalculatorArgs

    def _run(self, expression: str, **_: Any) -> str:
        # Replace with business-safe evaluation logic
        return str(eval(expression, {"__builtins__": {}}, {}))
```

You can then orchestrate it directly in your application. The SDK defaults to **local execution**, meaning `agent.run()` will execute the agent logic in your current environment using the `aip-agents` engine.

```python
# app.py
from glaip_sdk import Agent, Tool
from tool.calculator import CalculatorTool

agent = Agent(
    name="math-agent",
    instruction="You are a helpful math assistant",
    tools=[
        CalculatorTool,                # Custom tool (bundled automatically)
        Tool.from_native("time_tool"), # Native platform tool
    ],
)

agent.run("What is 2+2?")
```

#### Complex Tool Logic

When a tool requires complex logic, you can organize it across multiple files for better maintainability. During agent deployment (using the **`Agent(tools=[...])`** pattern), the SDK's automatic bundler detects and includes local imports—such as helper functions, services, or schemas—from your project into the uploaded tool source.

**Example structure:**

```
my_project/
  main.py
  tools/
    weather/
      __init__.py
      tool.py     # Exports WeatherTool
      service.py  # Contains helper logic
```

**Example `tools/weather/service.py`:**

```python
def get_mock_weather(city: str) -> str:
    return f"The weather in {city} is sunny."
```

**Example `tools/weather/tool.py`:**

```python
# Absolute import (recommended for portability)
from tools.weather.service import get_mock_weather
# OR Relative import (also supported)
# from .service import get_mock_weather

from langchain_core.tools import BaseTool

class WeatherTool(BaseTool):
    name = "weather_tool"
    description = "Gets weather info"

    def _run(self, city: str) -> str:
        # Bundler will include service.py automatically
        return get_mock_weather(city)
```

**Example `main.py`:**

```python
from glaip_sdk import Agent
from tools.weather.tool import WeatherTool

agent = Agent(
    name="weather-agent",
    instruction="Check the weather",
    tools=[WeatherTool],
)

agent.run("What's the weather in Tokyo?")
```

#### Modular Tools (Multiple Files)

For complex projects, you can organize multiple modular tools across your project. The SDK correctly resolves absolute imports and bundles the entire dependency tree.

```python
from glaip_sdk import Agent
from tools.flight_status import FlightStatusTool
from tools.stock_checker import StockCheckerTool
from tools.weather import WeatherTool

agent = Agent(
    name="travel-assistant",
    instruction="Help users with travel planning",
    tools=[WeatherTool, FlightStatusTool, StockCheckerTool],
)

agent.run("Check flight GA123 and weather in Bali.")
```

Refer to the [Modular Tool Integration](https://github.com/GDP-ADMIN/gl-sdk-cookbook/tree/main/glaip/examples/modular-tool-integration) example in the Cookbook for a full working implementation.

{% hint style="info" %}
**Absolute vs Relative Imports**

The SDK bundler supports both styles. For portable examples in the [GL SDK Cookbook](https://github.com/GDP-ADMIN/gl-sdk-cookbook), absolute imports (e.g., `from tools.weather.service import ...`) are used to ensure the tools work regardless of the user's local directory structure.
{% endhint %}

### Tool Implementation Expectations

When building custom tools for the AIP platform, ensure they meet the following technical requirements:

1. **BaseTool Inheritance**: All tools must inherit from LangChain's `BaseTool`.
2. **Metadata**: Tools must define `name` and `description` attributes.
3. **Schemas**: Tools must provide an `args_schema` (Pydantic model) for input validation.
4. **Standard I/O**: Runtime `stdout` and `stderr` are automatically captured and forwarded in the agent's event stream.

### Manage Tools

#### Registry Management

Use CLI or REST for one-off registry changes. Use the SDK Client only for automation or governance; the **Agent-First** pattern is preferred for application code.

**Use this pattern for:**

1. Managing the tool registry
2. Listing and searching tools
3. Batch tool operations
4. Tool governance across environments

> **Note**: Tags are optional and stored as a list on the tool record. The SDK accepts list\[str] or comma-separated strings and serializes them for the API. For listing/searching tools, prefer `aip tools list` or `GET /tools` unless you need SDK automation.

**Update or Re-upload**

CLI re-uploads replace the code package; adjust metadata by editing an export and re-importing or by using the SDK/REST helpers.

{% tabs %}
{% tab title="CLI" %}

```bash
aip tools update <TOOL_REF> --file calculator_v2.py
```

{% endtab %}

{% tab title="REST" %}

```bash
curl -X POST "$AIP_API_URL/tools/<TOOL_ID>/upload" \
  -H "X-API-Key: $AIP_API_KEY" \
  -F "file=@calculator_v2.py"
```

{% endtab %}
{% endtabs %}

**Delete**

{% tabs %}
{% tab title="Python SDK" %}

```python
client.tools.delete_tool("tool-id")
```

{% endtab %}

{% tab title="CLI" %}

```bash
aip tools delete <TOOL_REF>
```

{% endtab %}

{% tab title="REST" %}

```bash
# Soft delete
curl -X DELETE "$AIP_API_URL/tools/<TOOL_ID>" -H "X-API-Key: $AIP_API_KEY"
```

{% endtab %}
{% endtabs %}

**Common errors and fixes**

| Symptom                                            | Likely cause                                             | Fix                                                                                                                 |
| -------------------------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `422 Unprocessable Entity` on upload               | Invalid metadata fields or missing BaseTool inheritance. | Validate the class inherits from LangChain BaseTool and includes required fields (name, description, args\_schema). |
| CLI upload hangs after progress bar                | Large dependency bundle or slow network upload.          | Zip the tool directory, remove unused assets, or upload via the REST API with a resumable client.                   |
| Agent cannot run the tool at runtime               | Tool not attached, or config missing required keys.      | Re-run `aip agents update --tools` and verify `tool_configs` in the agent payload.                                  |
| `401 Unauthorized` when calling `/tools` endpoints | API key scoped to viewer-only role.                      | Request a creator or runner key, or perform the action via an operator account.                                     |

#### GL Connectors and Managed Connectors

Remote-managed connectors (GL Connectors library) appear in the tool catalog with predefined IDs. Request enablement from the AIP operations team, then attach them like any other tool. Updates are handled centrally; monitor the [changelog](https://gdplabs.gitbook.io/gl-aip/resources/changelog) for new versions.

#### MCP Tool Discovery

```bash
# List tools exposed by an MCP configuration
curl -sL "$AIP_API_URL/mcps/<MCP_ID>/tools" \
  -H "X-API-Key: $AIP_API_KEY" | jq
```

Use the response to seed agent definitions or generate tool uploads where appropriate. The [MCP guide](https://gdplabs.gitbook.io/gl-aip/how-to-guides/mcps-guide) covers credential rotation and live connection testing in detail.

#### Observability and Auditing

1. `GET /tools/<id>` returns metadata, version, and upload timestamps.
2. `GET /agents?tools=<id>` surfaces reuse across agents.
3. Leverage the [Configuration management guide](https://gdplabs.gitbook.io/gl-aip/how-to-guides/configuration-management-guide) to export/import tools alongside agents for promotion pipelines.

#### Best Practices

1. **Version your uploads** — keep source code in git and re-upload on change.
2. **Scope permissions** — custom tools run with the same rights as the agent execution environment; follow least-privilege principles.
3. **Validate inputs** — handle argument validation inside the tool to avoid unexpected failures mid-run.
4. **Document configs** — record supported configuration keys in your README so teammates know how to set `tool_configs`.

### Production Readiness Checklist

Before deploying tools to production:

* [ ] All tools have required attributes: `name`, `description`, and `args_schema`
* [ ] Error handling is comprehensive in `_run()` methods
* [ ] Dependencies are minimal and well-documented
* [ ] Tool configs are documented in README
* [ ] Tools are tested with various input scenarios
* [ ] Source code is versioned in git
* [ ] Tool follows BaseTool inheritance pattern (no decorator needed)

#### Related Documentation

1. [Agents guide](https://gdplabs.gitbook.io/gl-aip/how-to-guides/agents-guide) — attach tools, manage `tool_configs`, and run overrides.
2. [File processing](https://gdplabs.gitbook.io/gl-aip/how-to-guides/file-processing-guide) — upload artifacts during agent runs and reuse chunk IDs.
3. [Automation & scripting](https://gdplabs.gitbook.io/gl-aip/how-to-guides/automation-and-scripting) — script tool creation and promotion in CI.
