---
title: 'Custom tools'
description: 'Define, deploy, discover, and attach server-side tools.'
---

# Custom tools

> **Release requirement:** This guide uses Studio extension APIs that are not present in npm `@flexkit/studio@0.0.31`. See [package availability](/docs/reference/compatibility#package-availability) before using the example.

A custom tool lets AI call your application code. Keep tool definitions in server-only modules and start with a harmless operation that makes no external writes.





## Define a tool

Install `zod` in the host application. Create:

```ts filename="flexkit.tools.ts"
import { defineTool } from '@flexkit/studio/tools';
import { z } from 'zod';

export const summarizeCatalogCheck = defineTool({
  name: 'summarizeCatalogCheck',
  description: 'Format a catalog check result without reading or changing data.',
  input: z.object({
    checked: z.number().int().min(0),
    missingCategory: z.number().int().min(0),
  }),
  execute: ({ checked, missingCategory }, actor) => ({
    checked,
    missingCategory,
    invokedBy: actor.kind,
    message: `${missingCategory} of ${checked} checked products need review.`,
  }),
});
```

The handler validates input before calling `execute`. The actor describes either a Chat user or an automation. This example returns only supplied counts; it does not claim to have independently inspected records.

## Register in Next.js

```ts filename="app/api/flexkit/[...path]/route.ts"
import { createFlexkitApiHandler } from '@flexkit/studio/nextjs';
import { NextResponse } from 'next/server';
import { cookies, headers } from 'next/headers';
import { summarizeCatalogCheck } from '../../../../flexkit.tools';

export const runtime = 'nodejs';
export const { GET, POST, PUT, PATCH, DELETE } = createFlexkitApiHandler(
  { NextResponse, cookies, headers },
  { tools: [summarizeCatalogCheck], projectId: 'your-project-id' }
);
```

This path assumes an application without a `src` directory. Replace the project ID. For Astro or TanStack Start, pass the same tools option through the corresponding [framework adapter](/docs/reference/framework-adapters).

## Deploy and discover

1. Set `FLEXKIT_TOOLS_SECRET` in the server environment using the project's signing secret from Dashboard. Never put it in a public environment variable or client configuration.
2. Deploy the handler at a publicly reachable HTTPS application URL.
3. Open **Dashboard → project API → Custom tools**.
4. Set the production tools URL to your application's `/api/flexkit/tools` endpoint and use **Sync tools**.
5. Confirm `summarizeCatalogCheck` appears in the production catalog.
6. Attach it to an automation and ask the automation to format a small result with it.
7. Inspect the run's tool output and confirm the supplied counts match.

A browser opening the signed endpoint without a signature is not a valid discovery test. A catalog entry also does not attach the tool to an automation.

## Local development

The Dashboard distinguishes **Production tools** from **Your local runtime**. The handler's project ID supports local runtime connection. Use that status to diagnose local development, but deploy and sync production tools for scheduled and shared operation.

Before adding external side effects, read [security and deployment](/docs/automations/custom-tools/security-and-deployment) and [tools reference](/docs/reference/tools).


---

[View full sitemap](/docs/sitemap.md)
