> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usegradient.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom tools

> Author handlers in Python, deploy them with the Gradient CLI, and call them from agents or over the API.

A custom tool is your own code, deployed to Gradient and called by the engine mid-conversation. You write a handler, deploy it, and attach it to a node; when the model calls it, the engine runs your code on Gradient-managed compute and feeds the result back into the turn.

The same handler serves production traffic and [redteam](/evaluate/redteam) traffic; there is no second implementation to keep in sync.

## Write a handler

Tools are authored in Python with the Gradient SDK. Decorate a function with `@tool`: its type hints become the input schema the model sees, and its docstring becomes the description.

```python theme={null}
from gradient_sdk import tool

@tool
def lookup_prescription(patient_id: str, medication: str) -> dict:
    """Look up a patient's prescription status from the EHR.

    Args:
        patient_id: The patient's unique identifier.
        medication: Medication name.
    """
    return {"status": "eligible"}
```

A handler takes its arguments and returns a JSON-serializable dict. You never hand-write JSON Schema; the SDK infers it from the signature. A parameter with no default is required; a parameter with a default is optional.

One folder can define many handlers. Each `@tool` function becomes its own callable tool.

## A tool folder

A deployable tool folder has two things:

* `tool.py`: your `@tool` functions
* `Dockerfile`: its `CMD` runs the SDK's serve module

```dockerfile theme={null}
CMD ["python", "-m", "gradient_sdk.serve", "tool.py"]
```

The serve module exposes your handlers over HTTP; the `Dockerfile` owns everything else your code needs, such as dependencies and system packages.

## Deploy with the CLI

Install the `gradient` CLI and work from the tool folder.

<Steps>
  <Step title="Sign in">
    `gradient login` opens the browser, mints an org-scoped API key, and stores it locally. Approve the code shown in the terminal.
  </Step>

  <Step title="Run it locally">
    `gradient dev` runs the tool with hot reload and no auth, so you can iterate. Call a handler at `http://localhost:8080/invoke/<handler>`.
  </Step>

  <Step title="Deploy">
    `gradient deploy` uploads the folder. The console builds it, runs it on Gradient-managed compute, and makes it live. Each deploy freezes a new immutable version. `gradient build` is an alias.
  </Step>

  <Step title="Call it">
    `gradient invoke lookup_prescription '{"patient_id": "123", "medication": "atorvastatin"}'` calls the deployed handler exactly the way the engine will.
  </Step>
</Steps>

| Command                            | What it does                                                    |
| ---------------------------------- | --------------------------------------------------------------- |
| `gradient login`                   | Sign in through the browser and store an org-scoped key.        |
| `gradient dev [dir]`               | Run the tool locally with hot reload.                           |
| `gradient deploy [dir]`            | Upload the folder, build it, and make it live as a new version. |
| `gradient invoke <handler> [json]` | Call a deployed handler the way the engine does.                |
| `gradient status [dir]`            | Show what is deployed for this folder.                          |
| `gradient rollback --to <version>` | Make an earlier version live again.                             |

Pass secrets your code needs with repeated `--env KEY=VALUE` flags on deploy; the console injects them when it runs your code.

<Note>
  `gradient logs` is not available from the CLI yet. Inspect tool calls and their results in the dashboard's Traces.
</Note>

## Deploy history and versions

Every deploy writes a new immutable tool version (its schema, source, and runtime), and Gradient keeps the full history. `gradient rollback --to <version>` makes an earlier version live again.

When you attach a custom tool to an agent node, the node's draft floats to the latest deployed version; publishing the agent pins the exact version. See [Tools](/build/tools) and [Versions](/publish/versions).

## Invoke over the API

Deployed tools also have a public invoke endpoint, independent of any agent. The tool's slug is `<project>_<handler>`.

```bash theme={null}
curl -X POST "https://console.usegradient.dev/api/v1/tools/<slug>/invoke?v=1" \
  -H "authorization: Bearer $GRADIENT_API_KEY" \
  -H "content-type: application/json" \
  -d '{"input": {"patient_id": "123", "medication": "atorvastatin"}}'
```

The `input` object is passed to your handler as its arguments. Use the optional `?v=` query parameter to target a specific deployed version; omit it to use the latest. The response is a JSON object carrying the handler's `output`. Authenticate with an org-scoped key. See [Authentication](/api/authentication) and the [tool invoke reference](/api/tools/invoke).
