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

# Araçlar

> Bir uygulamanın araçları nasıl bildirdiği ve işleyicilerinin sonuçları nasıl döndürdüğü.

# Araçlar

Bir **araç**, AI'ın çağırabileceği adlandırılmış bir eylemdir ve yazılı girdilere sahiptir — örneğin `send_email(to, subject, body)`. Araçlar bir becerinin `tools.ts` dosyasında bildirilir ve uygulamanızın sunduğu araçlar için, bileşenlerinizden birinde bir HTTP rotası tarafından desteklenir. Bu sayfa araç sözleşmesinin tek kaynağıdır; [Beceriler](/apps/skills) `tools.ts` dosyasının nerede bulunduğunu kapsar.

## Araç bildirme

`tools.ts` dosyasındaki her giriş, sağlayıcı açısından güvenli bir `name`, kullanıcı dostu bir `displayName`, bir `description`, bir Zod `input` şeması ve Kazzle'nin çağırdığını belirten bir `target` içerir.

```ts theme={"theme":"material-theme-darker"}
import { z } from 'zod';
import type { KazzleTool } from '@kazzle/app/tools';

export const SaveBookmarkInput = z.object({
  url: z.string().url().describe('URL to save.'),
  title: z.string().optional().describe('Optional human-readable title.'),
}).strict();

const saveBookmarkTarget = {
  type: 'app',
  component: 'api',
  path: '/tools/save-bookmark',
  method: 'POST',
  body: '${input}',
} as const;

export const tools = [
  {
    name: 'save_bookmark',
    displayName: 'Save bookmark',
    description: 'Save a bookmark URL and return a confirmation.',
    input: SaveBookmarkInput,
    target: saveBookmarkTarget,
  },
] as const satisfies readonly KazzleTool[];
```

## Hedefler

`target`, bir araç veya gerekli eylem düğmesi için yeniden kullanılabilir bir adrestir. Doğrudan bir AI araç çağrısı ve bir düğme tıklaması aynı hedef nesnesini kullanabilir, böylece her ikisi de aynı kodu çalıştırır.

| Hedef    | Alanlar                                                                | Çalıştığı yer                                                                                              |
| -------- | ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `app`    | `component`, `path`, `method`, isteğe bağlı `query`, `headers`, `body` | Kendi bileşenlerinizden biri. Kazzle bileşen URL'sini çözer ve imzalı bir uygulama kimlik belirteci ekler. |
| `url`    | `url`, `method`, isteğe bağlı `query`, `headers`, `body`               | Harici bir uç nokta. URL kaynağı ve yöntem, yazarın değerleridir.                                          |
| `kazzle` | `name`                                                                 | Yerleşik istemci tarafı Kazzle işleyicisi.                                                                 |

HTTP hedefleri aynı istek alanlarını kullanır:

```ts theme={"theme":"material-theme-darker"}
type RequestSpec = {
  method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
  query?: Record<string, string>;
  headers?: Record<string, string>;
  body?: unknown;
};
```

Örtülü istek varsayılanları yoktur. İşleyiciniz ham araç girdisini JSON olarak almalıysa, `body: '${input}'` yazın.

## Referanslar

Kazzle, gönderimden önce HTTP hedef `query`, `headers`, `body` ve `url` alanlarındaki referansları çözer:

* `${input}` — tüm araç girdisi veya tüm düğme girdisi.
* `${input.path}` — girdiden iç içe bir değer.
* `${env.NAME}` — sahip olan uygulama bileşeninin bildirilen `env.collection` + `env.environment` dosyasından adlandırılmış bir ortam değişkeni.

Çözümleme tek geçişlidir. Bir referans eksikse veya bilinmiyorsa, araç boş bir değer yerine başarısız olur. Değişmez `${input.name}` metni gerektiğinde `$${input.name}` kullanın.

## İşleyici isteği

`app` hedefi için, hedef bileşende eşleşen rotayı ekleyin. `body: '${input}'` ile Kazzle, yazılı girdisini JSON gövdesi olarak gönderir:

```json theme={"theme":"material-theme-darker"}
{ "...": "the typed input" }
```

`app` hedefleri ayrıca şunları alır:

| Başlık                | Değer                                                          |
| --------------------- | -------------------------------------------------------------- |
| `Authorization`       | `Bearer <identity token>` kullanıcı + yüklemeyi tanımlar       |
| `Kazzle-Tool-Context` | `{"source":"thread","threadId":"..."}` veya `{"source":"api"}` |

Uygulama hedefleri `Authorization` başlığını `headers` aracılığıyla ayarlayamaz; Kazzle bu başlığa sahiptir. İşleyici iş parçacığı vs Araçlar API'sini ayırt etmesi gerektiğinde `@kazzle/app/tools` dosyasından `toolContext(req)` ile bağlamı okuyun.

Eşleşen bir rotası olmayan bildirilen bir araç faydalı bir şey yapmaz — her ikisini birlikte ekleyin. `tools.json` desteklenmez; uygulama derleyicisi bir tane bulursa başarısız olur.

## İşleyici yanıtı

Düz metin veya en fazla üç kanallı JSON döndürün:

```json theme={"theme":"material-theme-darker"}
{ "content": "...", "markdown": "...", "embedUrl": "https://..." }
```

* **`content`** — AI'ın okuduğu düz sonuç (modele beslenmiş). Gerekli.
* **`markdown`** — isteğe bağlı. Araç kartında işlenen kısa zengin metin özeti (react-markdown; ham HTML kaçırılır). Bir cümle, küçük bir liste, satır içi bir bağlantı için iyidir. Çıplak bir göreli yol, ölü önceden biçimlendirilmiş metin olarak işlenir — bağlantılar **mutlak** olmalıdır.
* **`embedUrl`** — isteğe bağlı. Uygulamanızın sunduğu **mutlak** URL; kart bunu korumalı bir iframe'de işler. Gerçek, tam genişlikli bir UI göstermenin yolu budur — bir bağlantı ekranı, bir pano, bir grafik. Uygulamanız sayfayı barındırır ve sahiptir, bu nedenle kendi arka ucunuz, tanımlama bilgileri ve OAuth'a karşı tamamen etkileşimli olabilir. Sürücüye hiçbir şey yazılmaz.

Her ikisi de ayarlandığında `embedUrl` `markdown` üzerinde kazanır. Her zaman anlamlı bir `content` tutun — AI'ın okuduğu budur.

```ts theme={"theme":"material-theme-darker"}
if (req.method === 'POST' && new URL(req.url).pathname === '/tools/save-bookmark') {
  const input = await req.json();
  // ...do the work...
  return Response.json({ content: `Saved ${input.title}` });
}
```

## Gerekli eylem

Bir uygulama aracı, bir kullanıcı (veya cihaz) eylemi gerektiğinde iş parçacığını duraklatabilir. `type: 'action_required'` ile bir kart başlığı ve düğmeleri döndürün. Yalnızca `toolContext(req).source === 'thread'` olduğunda geçerlidir — Araçlar API'sı üzerinde (`source: 'api'`), bunun yerine normal bir etki alanı hatası döndürün.

```ts theme={"theme":"material-theme-darker"}
import { toolContext, isThreadToolInvocation } from '@kazzle/app/tools';

const context = toolContext(req);
if (!isThreadToolInvocation(context)) {
  return Response.json(
    { code: 'connect_required', error: 'Gmail must be connected before this tool can run.' },
    { status: 409 },
  );
}

return Response.json({
  type: 'action_required',
  title: 'Connect Gmail',
  description: 'Connect Gmail before Kazzle can search messages.',
  // Optional: only this device may run the gated buttons
  // assignee: { computerId: '<from computer { list: {} }>' },
  elements: [
    {
      type: 'button',
      id: 'connect',
      label: 'Connect Gmail',
      variant: 'primary',
      input: { scope: 'gmail.readonly' },
      target: {
        type: 'app',
        component: 'api',
        path: '/oauth/start',
        method: 'POST',
        body: '${input}',
      },
    },
  ],
});
```

Kazzle kartı araç çağrısında kaydeder ve bir düğmeye basıldıktan sonra `/chat/resume` aracılığıyla devam eder. Eşleşen istemciler yazar düğmelerini görür; eşleşmeyen istemciler yine de Atla/İptal artı "{cihaz} üzerinde devam et" seçeneğini görür. `target` olmayan bir düğme, `input` dosyasını araç sonucu olarak gönderir. Hedefi olan bir düğme önce bu hedefi çalıştırır, ardından hedef sonucunu araç sonucu olarak kullanır.

### Zengin UI — uygulama tarafından barındırılan bir sayfayı gömün

Bir aracın sonucu görsel veya etkileşimli olduğunda (bir bağlantı ekranı, bir grafik, bir özet panosu), sayfayı bileşenlerinizden birinden sunun ve **mutlak** URL'sini `embedUrl` olarak döndürün. URL'yi enjekte edilen bileşen URL'sinden oluşturun — asla göreli bir yol değil.

```ts theme={"theme":"material-theme-darker"}
// Kullanıcının hesabını bağlaması gereken bir araç:
return Response.json({
  content: "Gmail isn't connected yet — the user needs to connect it.",
  embedUrl: `${process.env.KAZZLE_APP_COMPONENT_URL}/connect?token=${identity}`,
});
```

Sayfa, çapraz kaynaklı bir iframe'de (kendi kaynağı, tanımlama bilgileri ve betikleri) çalışır. Kartı boyutlandırmak için yüksekliğini üst öğeye gönderin — kart bunu dinler ve yeniden boyutlandırır (görünüm alanının %70'inde sınırlandırılır):

```ts theme={"theme":"material-theme-darker"}
// gömülü sayfanın içinde
parent.postMessage({ __kazzle_height: document.body.scrollHeight }, '*');
```

HTML dizelerini yayınlamak yerine `embedUrl` tercih edin: uygulamanız zaten sayfalar sunuyor, UI etkileşimli ve kodunuzla sürümlenmiş kalıyor ve hiçbir çağrı başına yapıt hiçbir yere yazılmıyor.
