Çalışma Zamanı
Tool Sistemi
Luma'da tool, contract ile implementasyonun ayrıldığı bir yapıdır: .luma dosyası tool'un imzasını, güvenlik sınıfını ve dayanıklılık politikasını tanımlar; gerçek kod host tarafındaki JS/TS module'ünde yaşar. Runtime aradaki her şeyi — doğrulama, izin, timeout, retry, cache, telemetry — üstlenir.
Tool contract'ı
schema CalcResult {
result: float
}
tool calculate(
a: float @range(0, 1000000),
b: float @range(0, 1000000),
operation: enum["add", "multiply"] @desc("Yapılacak işlem")
) -> CalcResult {
side_effects: "none"
cache: true
}| Parça | Kural |
|---|---|
| Parametreler | Tipli olmak zorunda. Field annotation'ları kullanılabilir (@desc, @range, @default…). Bunlardan otomatik bir input schema üretilir. |
| Dönüş tipi | Tanımlı bir schema referansı olmalıdır — tagged by union dahil, aşağıya bak. Primitive veya inline tip kabul edilmez. |
| Gövde | Yalnızca yapılandırma anahtarları. Kod içermez — boş bırakılabilir. |
| Opsiyonel parametre | limit?: int @default(10) — eksikse doldurulur ve JSON Schema'da required olmaz. |
Parametrelerden __tool_<name>_input adında bir iç schema oluşturulur. Bu schema hem yerel input doğrulaması hem de modele gönderilen tool declaration'ının parameters alanı için kullanılır — yani parametre annotation'ların modele de görünür.
Tool seçenekleri
| Anahtar | Değerler | Varsayılan | Açıklama |
|---|---|---|---|
side_effects | none · read · write | none | Tool'un yan etki sınıfı. tool_policy bunu temel alır. |
cache | true · false | false | Aynı input için sonucu process içinde saklar. |
scope | string | — | İzin etiketi. Agent'ın tool_scopes listesinde olmalıdır. |
credential | ENV adı | — | Bu environment değişkeni yoksa tool hiç çalıştırılmaz. |
error | schema adı | — | Handler'ın fırlattığı hatanın doğrulanacağı typed error schema'sı. |
retries | int | 0 | Ek deneme sayısı (yalnızca retryable hatalarda). |
retry_backoff | none · fixed · exponential | none | Denemeler arası bekleme stratejisi. |
retry_delay | ms | 100 | Temel bekleme süresi. |
timeout | ms | — | Tool'a özel timeout; agent'ın tool_timeout'unu ezer. |
idempotent | true · false | false | Aynı anahtarla yalnızca bir kez çalıştırma. |
idempotency_key | input alan yolu | — | idempotent: true ile zorunlu. Örn. request_id. |
idempotency_ttl_ms | ms | 300000 | Kaydın geçerlilik süresi. |
needs <name>: <Type> | bildirim | — | Host tarafından sağlanacak bağımlılık (DB bağlantısı, credential seti…). Tekrarlanabilir. |
Tutarlılık kuralları
| Kural | İhlal edilirse |
|---|---|
| Write tool cache edilemez | Write tool 'x' cannot use cache. |
| Write tool retry için idempotent olmalı | A write tool 'x' must be idempotent and specify an idempotency_key to be retried. |
idempotent anahtar ister | Idempotent tool 'x' must specify an idempotency_key. |
timeout: 0 geçersiz | Tool 'x' timeout must be greater than zero. |
needs kullanan tool cache edilemez | Cache cannot be used on a tool that uses needs: x (çalışma zamanında) |
Direct tool çağrısı
Direct çağrı garantilidir: modelin kararına bağlı değildir, kaynak koda yazdığın yerde ve sırayla çalışır.
agent Flow {
tools: [text_stats, calculate]
fn run(text: string) -> Answer {
stats = tool text_stats({ text: text })
if stats.words > 3 {
bonus = tool calculate({ a: stats.words, b: 2, operation: "multiply" })
}
ask "İstatistikler: {stats}, bonus: {bonus}" -> Answer
}
}| Biçim | Anlamı |
|---|---|
x = tool name({ a: 1, b: 2 }) | Object literal ile çağrı. |
x = tool name(variable) | Hazır bir nesne değişkeniyle çağrı. |
x: Result = tool name({ … }) | Sonucu ayrıca tipe göre doğrula. |
- Tool, agent'ın
toolslistesinde olmalıdır; değilseAgent 'A' does not allow tool 'x' to be called directly. - Üst düzeyde de çağrılabilir:
result = tool calculate({ a: 2, b: 3, operation: "add" }) - Input ve output ayrı ayrı doğrulanır; hata
TOOL_INPUT_INVALID/TOOL_OUTPUT_INVALIDkodu taşır. - İki taraf
@severityaçısından simetrik değildir: output üzerindeki soft kural değeri şerhleyip koşuyu sürdürür, aynı kural input üzerinde yok sayılır ve sert kalır. Tool yan etkili koddur; sözleşmesini ihlal ettiği bilinen veriyle çağrılması, kuralın engellemek için var olduğu şeydir.
Native tool calling
Agent'ın tools listesi, tool'ları aynı zamanda modele görünür kılar. Model bir tool çağırmaya karar verirse runtime bunu çalıştırır ve sonucu geri gönderir.
agent MultiToolWorker {
model: GPT54Mini
tools: [text_stats, calculate]
tool_rate_limit: 2
tool_concurrency: 2
fn run() -> FinalResult {
ask "Her iki tool'u da tam olarak bir kez çağır. text_stats'i text='Luma DSL' ile, calculate'ı a=20, b=22, operation='add' ile çağır. Tool sonuçlarını aldıktan sonra yalnızca geçerli JSON döndür." -> FinalResult
}
}Çok turlu akış
1. istek → messages + tools + tool_choice: "auto" (veya zorunlu tool)
response_format gönderilmez
↓
2. yanıt → assistant mesajı + tool_calls[]
↓
3. runtime → her tool call: policy → input doğrulama → çalıştırma → output doğrulama
(tool_concurrency kadarı eşzamanlı)
↓
4. mesajlar ← assistant(tool_calls) + her tool sonucu için bir tool mesajı
↓
5. istek → messages + tools + response_format: json_schema (strict)
↓
6. yanıt → nihai JSON → yerel schema doğrulamasıModel tool çağırabilsin diye ilk istekte response_format gönderilmez; yalnızca en az bir tool çağrısı gerçekleştikten sonra strict JSON Schema eklenir.
Pratik sonucu: tools tanımlı bir agent'ta model hiç tool çağırmadan doğrudan cevap verirse, o yanıt gateway tarafından format açısından zorlanmamış olur — yalnızca Luma'nın yerel doğrulaması devreye girer. Bu durumda retry vermek özellikle değerlidir.
Varsayılanda istek tool_choice: "auto" ile gider ve seçimi model yapar. Bir ask'in sonuna using tool <name> eklersen o tool zorunlu olur — argümanları yine model üretir, ama gateway'e çağrının mecburi olduğu bildirilir:
fn settle(text: string) -> Answer {
ask "Hesabı kapat: {text}" -> Answer using tool calculate
}Tool, agent'ın tools listesinde olmalıdır; değilse parser Agent 'A' does not allow the tool 'calculate' required by using tool. ile düşer. Her adapter'a kendi diliyle bildirilir — bkz. Provider eşlemesi. Bir adımın, argümanlarını model seçmeden kesin çalışmasını istiyorsan direct tool çağrısı hâlâ daha basit cevaptır.
Provider eşlemesi
| Provider ailesi | Model → tool çağrısı | Runtime → sonuç |
|---|---|---|
| OpenAI-compatible · Azure | tool_calls[] | role: "tool" mesajı |
| Anthropic | tool_use bloğu | tool_result içeren user mesajı |
| Gemini | functionCall part'ı | functionResponse part'ı |
Bu dönüşüm adapter katmanında otomatik yapılır; .luma tarafında hiçbir şey değişmez.
Limitler
| Ayar | Kapsam |
|---|---|
tool_rate_limit 5 | Bir ask akışındaki toplam native tool çağrısı. Her yeni ask'te (ve her retry denemesinde) sıfırlanır. |
tool_concurrency | Tek provider turunda eşzamanlı çalışacak tool sayısı. |
tool_failure_limit | Bu kadar hatadan sonra circuit breaker açılır. |
Implementasyon: tool registry
Bir tool'un .luma tarafında contract'ı, host tarafında handler'ı olmalıdır. Handler yoksa program başlamaz:
Error: 'calculate' is not registered in the tool registry.
Handler imzası
export type ToolHandler = ( input: any, // validated input signal?: AbortSignal, // timeout / iptal sinyali needs?: Record<string, any>, // contract'ta bildirilen bağımlılıklar ) => any | Promise<any>;
// tools.ts
export const calculate = async (input, signal, needs) => {
if (input.operation === "add") return { result: input.a + input.b };
if (input.operation === "multiply") return { result: input.a * input.b };
throw new Error("Unsupported operation");
};Typed hata fırlatma
schema ToolError {
code: string
message: string
retryable: bool
details?: any
}
tool db_write(table: string, value: string) -> DbWriteResult {
side_effects: "write"
error: ToolError
retries: 3
retry_backoff: "exponential"
idempotent: true
idempotency_key: request_id
}import { LumaToolError } from "./src/tool-registry";
throw new LumaToolError({
code: "DB_TIMEOUT",
message: "Database timeout oldu",
retryable: true, // → retry döngüsü devam eder
details: { table: input.table },
});retryable: true→retrieskadar yeniden denenir.retryable: false→ hem tool retry'ı hem LLM retry döngüsü anında durur.error:schema'sı verilmişse fırlatılan hata o schema'ya göre doğrulanır; uymazsaTOOL_ERROR_INVALID.- Hata nesnesi
try/catchdeğişkenine olduğu gibi aktarılır.
Tool module yükleme
Varsayılan handler'lar src/tool-registry.ts içindedir. Kendi module'ünü iki yolla ekleyebilirsin:
luma program.luma --tool-module ./tools.ts
{
"tool_modules": [
{
"path": "./tools.ts",
"version": "1.0.0",
"integrity": "sha256-<base64-sha256>",
"dependencies": ["node-fetch"],
"dependency_root": "./vendor"
}
]
}| Manifest alanı | Anlamı |
|---|---|
path | Module dosyası (program dizinine göre). |
version | Semver metadata'sı. Aynı dosya farklı metadata ile ikinci kez yüklenirse hata. |
integrity | sha256-<base64>. Dosya içeriği eşleşmezse yükleme reddedilir. |
dependencies | Module'ün import/require edebileceği paket allowlist'i. Liste verilirse dinamik import() yasaklanır. |
dependency_root | Bağımlılıkların okunabileceği filesystem kökü (proje dışına çıkamaz). |
Kısa biçim de geçerlidir: "tool_modules": ["./tools.ts"]
| Dosya türü | Yükleme |
|---|---|
.ts · .mts | typescript ile transpile edilip yüklenir (runtime dependency gerekir). |
.js · .cjs | CommonJS olarak yüklenir. |
.mjs, ya da package.json'da "type": "module" olan .js | ESM olarak yüklenir. |
Export biçimi
Module şu anahtarlardan birini (sırayla aranır) veya doğrudan kendisini object olarak export etmelidir: lumaTools → tools → default → module'ün kendisi. Her değer bir fonksiyon olmalıdır.
export const lumaTools = {
calculate: (input) => ({ result: input.a + input.b }),
text_stats: (input) => ({
characters: input.text.length,
words: input.text.trim().split(/\s+/).length,
}),
};Registry'de aynı isim iki kez tanımlanamaz: Tool registry conflict: calculate.
datasource / query / command (v0.4.0)
Luma tipli veritabanı contract'ını sahiplenir, sürücüyü değil. Üç bildirim — datasource, query, command — sınırı tarif eder; veritabanıyla asıl konuşan ~20 satırlık köprü ise bir tool modülü meselesidir, bilinen bir ad altında dışa açılır:
export const datasources = {
Warehouse: async (sql, params, signal) => (await pool.query(sql, params)).rows,
};Bir DB sürücüsü npm paketidir; onu buranın dışında tutmak transpiler'ın sıfır bağımlılık sözünü koruyan şeydir. Köprü yoksa program hiçbir şey çalıştırmadan durur: datasource 'Warehouse' has no registered bridge.
Bildirimlerin kendisi, alan varsayılanları, satır doğrulama garantisi ve eksik transaction yüzeyinin gerekçesi Veri & Entegrasyon sayfasında.
Sandbox politikası
{
"tool_module_policy": {
"sandbox": "strict",
"allow_builtins": ["crypto"],
"allow_env": false,
"allow_network": false,
"max_memory_mb": 256,
"max_concurrency": 2
}
}| Ayar | Değerler | Varsayılan | Etkisi |
|---|---|---|---|
sandbox | none · strict | none | strict: aşağıdaki yükleme-anı kontrollerini ve bir kaynak lint'ini açar. CommonJS/TS modülleri ayrıca açık global listesi olan bir VM context'inde koşar; ESM modülleri süreç içinde yüklenir. |
allow_builtins | string listesi | [] | İzin verilen Node builtin'leri. Listede olmayan require("fs") reddedilir. |
allow_env | bool | false | false ise metninde process ya da globalThis geçen modül reddedilir. Engel değil, lint — aşağıdaki uyarıya bak. |
allow_network | bool | false | false ise metninde fetch, http, net, tls ya da WebSocket geçen modül reddedilir. Engel değil, lint. |
max_memory_mb | int ≥ 16 | — | Kabul edilip kaydediliyor ama v0.6.0'dan beri uygulanmıyor — artık var olmayan child process'i sınırlıyordu. |
max_concurrency | int ≥ 1 | 1 | Bir modüle eşzamanlı çağrı sayısı. Worker'a bağlıydı; bugünkü ele alınışı için transpiler notlarına bak. |
Başkasının modülüne strict ile güvenmeden önce bunu oku. v0.6.0'a kadar bir ESM modülü OS permission modeli altında ayrı bir süreçte koşuyordu; o runtime gitti ve izolasyon yeniden üretilemedi, bu yüzden taklit edilmek yerine kaldırıldı. strict'in bugünkü anlamı ikiye ayrılıyor:
Modül yüklenirken zorlanan, fail-closed: builtin allowlist — hesaplanmış specifier dahil, çünkü o da listede olmayan bir isme çözülüp reddediliyor; çözümlemenin proje dizinine hapsi; manifest bütünlüğü; ve CommonJS için globalleri gerçekleri değil açık bir liste olan VM context'i.
Modül metni üzerinde lint, o kadar: allow_env, allow_network ve dinamik-kod kontrolleri. Yazımları eşliyorlar. Hiçbirini adlandırmayan bir modül sürecin kendi ayrıcalıklarıyla çalışmaya devam eder — şu modül her kontrolden geçiyor ve süreç başlatıyor:
export const scan = () => ({ count: Bun.spawnSync(["id", "-u"]).stdout.toString().trim().length });Bu ölçüldü ve lint'in ileride izolasyon sanılmaması için geçen bir testle kilitlendi. Bugünkü dürüst sözleşme: hangi tool modülünü yükleyeceğine sen karar verirsin, dil onu sınırlamaz. Yalnızca kendin çalıştıracağın kodu yükle. ROADMAP.md § U10'da izleniyor.
Yukarıdaki tablodaki varsayılanlar bir tool_module_policy bloğunun içinde geçerlidir. Blok hiç yoksa hiçbiri geçerli değildir: modül sandbox: "none" ile çalışır, process, global ve ağ erişilebilir durumdadır. Policy'siz bir tool modülü çalıştırılarak doğrulandı — fetch tanımlı.
Yani allow_network: false, hiçbir şey yapmayınca ulaştığın durum değildir; policy bildirip anahtarı yazmayınca ulaştığın durumdur. Yazmadığın bir tool modülüne her zaman policy ver.
Strict modda her zaman yasak olanlar
eval(...)veFunction(...)— dinamik kodchild_process— process spawn- Proje dizini dışındaki module'lerin yüklenmesi
v0.6.0'a kadar strict modda bir ESM module'ü işletim sisteminin permission modeli altında ayrı süreçte koşuyordu. O dal, dayandığı runtime ile birlikte kalktı; ESM module'ü artık diğer her import gibi süreç içinde yükleniyor.
Yüklenmeden önce ESM için de koşmaya devam edenler: kaynak lint'i, manifest bütünlüğü, bağımlılık allowlist'i ve builtin allowlist'i. Koşmayan: açık global listesine sahip VM context — o yalnızca CommonJS ve TypeScript module'leri için var. Yani strict altındaki bir ESM module'ü gerçek global'leri görür.
VM context'i istiyorsan module'ü CommonJS ya da TypeScript olarak yaz. İstemiyorsan, strict'in hiçbir yanı bir ESM module'ünü körlemesine yüklemeyi güvenli kılmaz — yukarıdaki sözleşmeye bak.
Güvenlik politikaları
tool_policy
| Değer | Davranış |
|---|---|
allow varsayılan | Kısıt yok. |
deny_write | side_effects: "write" olan tool'lar reddedilir → TOOL_PERMISSION_DENIED. |
approval | Write tool'ları yalnızca LUMA_APPROVED_TOOLS içindeyse çalışır. Terminal interaktifse onay sorulur; değilse reddedilir. |
export LUMA_APPROVED_TOOLS="db_write,send_email"
scope ve credential
tool db_write(table: string, value: string) -> DbResult {
side_effects: "write"
scope: "db:write"
credential: "DB_PASSWORD"
}
agent Writer {
tools: [db_write]
tool_scopes: ["db:write"]
tool_policy: "approval"
}credentialile bildirilen env değişkeni yoksa tool hiç çalıştırılmaz:Tool 'db_write' is missing credential: DB_PASSWORD.scopetanımlıysa ve agent'ıntool_scopeslistesinde yoksa:Tool 'db_write' scope access was denied: db:write.tool_scopeshiç verilmezse scope kontrolü yapılmaz.
needs ve tool_contexts
needs, tool'un host tarafından sağlanacak bağımlılıklarını bildirir. Bunlar prompt'a veya modele asla girmez; doğrudan handler'ın üçüncü parametresine geçer.
schema Database {
user: string
port: int
}
tool db_write(table: string) -> DbResult {
needs db: Database
side_effects: "write"
}{
"tool_contexts": {
"db": {
"user": { "env": "DB_USER" },
"password": { "env": "DB_PASSWORD" },
"port": { "env": "DB_PORT", "parse": "integer" }
}
}
}parse değeri | Sonuç |
|---|---|
string varsayılan | Ham metin. |
json | JSON.parse — geçersizse hata. |
number | Sonlu sayı olmalı. |
integer | Tam sayı olmalı. |
boolean | Yalnızca "true" / "false". |
Agent tarafında tool_contexts: ["db"] ile hangi context'lerin kullanılabileceği daraltılır. Liste verilmezse tümü serbesttir; boş liste hiçbirine izin vermez. İzin dışı erişim TOOL_CONTEXT_INVALID üretir.
Not: file tabanlı context provider'ı henüz desteklenmiyor; secret'lar için env kullanılmalıdır.
Retry, idempotency, cache
Retry ve backoff
tool http_get(url: string) -> HttpResult {
error: ToolError
retries: 3
retry_backoff: "exponential"
retry_delay: 100
timeout: 3000
}retry_backoff | Bekleme süreleri (retry_delay: 100) |
|---|---|
none varsayılan | 0 ms — hemen tekrar dener. |
fixed | 100, 100, 100 … |
exponential | 100, 200, 400 … |
Yalnızca retryable: true hatalar yeniden denenir. İptal sinyali geldiyse retry durur.
Idempotency
tool db_write(request_id: string, value: string) -> DbResult {
side_effects: "write"
idempotent: true
idempotency_key: request_id
idempotency_ttl_ms: 300000
retries: 3
retry_backoff: "exponential"
}idempotency_keyyalnızca bir input alan yolu olabilir (request_idveyainput.request_id); ifade yazılamaz.- Aynı anahtar + aynı input → handler bir kez çalışır, ikinci çağrı saklanan sonucu döndürür.
- Aynı anahtar + farklı input →
TOOL_IDEMPOTENCY_CONFLICT. - TTL dolduğunda kayıt düşer ve tool yeniden çalışır.
Kalıcı store
{
"idempotency_store": {
"backend": "file",
"path": ".luma-idempotency.json",
"encryption": "aes-256-gcm"
}
}export LUMA_IDEMPOTENCY_KEY="uzun-ve-guvenli-bir-key"
Varsayılan store process-local'dır ("memory"). File store; exclusive lock, ölü process lock kurtarma, versiyonlu zarf ve atomik rename kullanır. Bozuk dosyalar karantinaya alınıp yenisi oluşturulur. Süresi dolan kayıtlar başlangıçta temizlenir.
Store aynı makinedeki process'ler için güvenlidir; dağıtık bir kurulumda (çok makineli worker havuzu) paylaşılan transactional bir backend sağlamaz. Production'da bu sınırı göz önünde bulundur.
Cache ve single-flight
tool calculate(a: float, b: float, operation: enum["add", "multiply"]) -> CalcResult {
side_effects: "none"
cache: true
}- Cache anahtarı tool adı + input JSON'udur; process ömrü boyunca yaşar.
- Aynı anahtar için eşzamanlı çağrılar tek bir çalıştırmayı paylaşır (single-flight); telemetry'de
single_flight: truegörünür. - Write tool'ları ve
needskullanan tool'lar cache edilemez.
Circuit breaker
agent Resilient {
tools: [http_get]
tool_failure_limit: 3
}Bir agent method çağrısı içinde tool hataları sayılır. Sayaç tool_failure_limit'e ulaştığında hata TOOL_CIRCUIT_OPEN koduna dönüştürülür ve retryable: false olur — böylece bozuk bir bağımlılığa karşı denemeler durur.
Tool çalıştırma sırası
Her tool çağrısı — direct veya native fark etmez — tam olarak şu boru hattından geçer:
1 registry araması TOOL_NOT_FOUND
2 credential kontrolü TOOL_PERMISSION_DENIED
3 scope allowlist'i TOOL_PERMISSION_DENIED
4 tool_policy: deny_write TOOL_PERMISSION_DENIED
5 tool_policy: approval TOOL_PERMISSION_DENIED
6 input doğrulaması TOOL_INPUT_INVALID
7 needs çözümleme + tip kontrolü TOOL_CONTEXT_INVALID
8 cache / single-flight araması
9 idempotency araması TOOL_IDEMPOTENCY_CONFLICT
10 handler çalıştırma (timeout + AbortSignal)
└─ hata → retryable ise retry/backoff ile 10'a dön TOOL_TIMEOUT
11 output doğrulaması TOOL_OUTPUT_INVALID
12 cache/idempotency yazımı + telemetry
└─ hata olduysa: failure sayacı++ → TOOL_CIRCUIT_OPENEtkin timeout min(tool.timeout ?? agent.tool_timeout, agent.tool_timeout_max) olarak hesaplanır. Timeout dolduğunda handler'a verilen AbortSignal tetiklenir — uzun süren işleri handler tarafında bu sinyale bağlamak önemlidir.
TypeScript tip üretimi
Tool tipi olarak tagged union
Bir tagged by union tanımlı bir schema'dır, dolayısıyla tool'un parametre tipi ya da dönüş tipi olabilir. Girdi olarak etiketlenmiş hâlde gelir — discriminator'ı handler görmeden önce runtime yazar, yani input.doc.kind üzerinde dallanabilirsin. Çıktı olarak yön tersine döner: tag'i senin yerine kimse yazmaz ve çıplak member alanları döndüren handler reddedilir.
schema Invoice {
invoice_number: string
}
schema Receipt {
reference: string
}
schema Document = Invoice | Receipt tagged by kind
tool classify(text: string) -> Document {
side_effects: "none"
}Error: [TOOL_OUTPUT_INVALID] classify.output.kind must identify a tagged union member.
Üretilen tipler bu zorunluluğu çalışma anında keşfedilmeye bırakmak yerine taşır — union, TypeScript'te discriminated union olur, yani kind'ı unutan handler derlenmez:
export type Document =
(Invoice & { kind: "Invoice" }) | (Receipt & { kind: "Receipt" });luma luma/018_direct_tool.luma \ --generate-tool-types tools.generated.d.ts
Bu bayrak verildiğinde program çalıştırılmaz; yalnızca tip dosyası üretilir.
// Generated by Luma. Do not edit manually.
export type ToolHandler<I, O, N = Record<string, never>> =
(input: I, signal?: AbortSignal, needs?: N) => O | Promise<O>;
export interface CalcResult {
result: number;
}
export interface CalculateInput {
a: number;
b: number;
operation: "add" | "multiply";
}
export interface CalculateNeeds {}
export type CalculateHandler = ToolHandler<CalculateInput, CalcResult, CalculateNeeds>;
export interface GeneratedToolModule {
calculate: CalculateHandler;
}import type { GeneratedToolModule } from "./tools.generated";
export const tools: GeneratedToolModule = {
calculate: async (input, signal, needs) => ({
result: input.operation === "add" ? input.a + input.b : input.a * input.b,
}),
};Üretilen dosya programdaki tüm schema'ları, her tool için <Name>Input / <Name>Needs / <Name>Handler tiplerini ve toplu GeneratedToolModule arayüzünü içerir. @desc açıklamaları JSDoc yorumu olarak taşınır.
export const tools: GeneratedToolModule = {
calculate: (input) => ({
result: input.a + input.b,
}),
};export const tools = {
calculate: (input: any) => ({
// schema değişince derleme kırılmaz
results: input.a + input.b,
}),
};