Dokümanlar menüsü
Studio — inspector & yönetim düzlemi
Journal'ı gözlemleyen web UI + JSON API: run timeline/state/diff/trace/cost, canlı Playground, onaylar, metrikler, threads, organizasyonlar ve bütçe yönetimi.
Ne işe yarar / ne zaman kullanılır#
Studio, @gnldev/durable journal'ının üstüne oturan bir teftiş + yönetim düzlemi: run'ların timeline'ını, adım adım materyalize durumunu (state/diff), OTel-benzeri trace'i ve maliyeti gösterir; tarayıcıdan agent çalıştırıp (Playground) askıdaki tool onaylarını inceler/onaylar; thread'leri (memory), workflow'ları, organizasyonları ve bütçeleri yönetir. "Bu run neden askıya alındı", "hangi model adımı ne kadar tuttu", "prod'a almadan önce agent'ı tarayıcıdan deneyeyim" gibi ihtiyaçlarda — kendi backend'inizde bu görünürlüğü sıfırdan yazmak yerine — kullanılır. Çoğu görünüm (Playground, Memory, Workflows, Scorers, Kullanıcılar, Organizasyonlar) opsiyoneldir: yalnız ilgili opsiyon verilirse açılır, yoksa sessizce gizlenir (GET /capabilities UI'ın hangi görünümleri göstereceğini buradan keşfeder).
Kurulum / import#
Çekirdek export'lar @gnldev/studio kökünden gelir; Playground'un araç şemasını JSON Schema'ya çevirmek için ayrı bir alt-export gerekir (ai paketine bağımlılığı studio çekirdeğinden izole tutar):
import { createStudioApp, createStudioRunner } from '@gnldev/studio';
import { aiToolSchema } from '@gnldev/studio/ai';Adım adım kullanım#
En basit kurulum: kendi Hono/Node app'inize bir yola createStudioApp mount edin. Bu, hem JSON API'yi (/api/*) hem de derlenmiş React arayüzünü (@gnldev/studio-ui) tek app'te birleştirir — apiBase, arayüzün fetch edeceği API önekini söyler (mount ettiğiniz yolla aynı olmalı):
const gnl = createGnl(config);
app.route('/studio', createStudioApp({
reader: toJournal(storage.runs),
apiBase: '/studio',
gnl: createStudioRunner(gnl, config, { toJsonSchema: aiToolSchema }),
auth,
org: {},
budgets: { default: { tokenLimit: 100 } },
users: userStore,
}));reader zorunludur ve journal'ı gösterir (toJournal(storage.runs) ile mevcut storage'ınızdan türetilir). gnl verilmezse Playground/Tools/Workflows görünümleri gizlenir — verildiğinde createStudioRunner createGnl instance'ınızı ve config'inizi alıp tarayıcıdan çalıştırılabilir bir koşucuya sarar (agent listesi, tool şemaları, model adı gibi hassas olmayan metadata dışarı sızar; model objesinin kendisi asla sızmaz). auth verilmezse tüm uçlar serbesttir; verilirse (ücretsiz roleAuth veya paralı @gnldev/auth-ee) okuma/yazma uçları kapı(gate)lenir. org: {} çok-organizasyonlu okuma teftişini açar (varsayılan çözücü x-gnl-org header'ıdır); budgets Organizasyonlar panelinde düzenlenebilen varsayılan/organizasyon-bazlı limitleri; users ise Studio'nun "Kullanıcılar" görünümünü açar.
Yalnız JSON API'ye (UI olmadan, kendi arayüzünüzü kuracaksanız) ya da yalnız statik/ayrı servis edilen HTML UI'a ihtiyacınız varsa aynı seçenekleri iki ayrı fonksiyona bölebilirsiniz:
app.route('/studio/api', createStudioApi({ reader, gnl, auth })); // JSON only
app.route('/studio', createStudioAdmin({ apiBase: '/studio' })); // HTML UI only (it points at a remote API)Mount ettikten sonra REST uçları doğrudan da kullanılabilir — ör. bir run'ın maliyeti veya trace'i:
GET /studio/api/runs/:id/state?step=3 → the materialized state at step 3 (reconstructState)
GET /studio/api/runs/:id/cost → getRunCost(reader, id)
GET /studio/api/runs/:id/trace → waterfall span'leri (maliyet dahil)
GET /studio/api/approvals → pending tool approvals across ALL suspended runs (inbox)Dead-letter — parkta ne var, ve geri koymak#
events verdiğinizde Dead-letter görünümü açılır; yanında GET /dead-events/topics, GET /dead-events ve POST /dead-events/release gelir. queue ile aynı kendi-store'unu-sar deseni: StudioEvents host'un sağladığı bir köprüdür, yani Studio @gnldev/events'e bağımlı değildir ve kendi store'unuz üzerinde de aynı şekilde çalışır.
Her şey üçlü ile adreslenir: (topic, consumer, id). Bir konu dallanır, yani tek bir olayın tüketici başına bir karantina kaydı olur — tek başına id bunların birkaçını birden gösterir. Yarım bir üçlü bu yüzden sessizce ıskalayan bir arama değil, 400'dür.
import { listDeadEvents, retryDeadEvent } from '@gnldev/events';
createStudioApp({
reader: toJournal(storage.runs),
events: {
orgScoped: true, // the host declaring it honours the ctx.orgId it is handed
topics: () => listTopics(storage.work),
listDead: (topic, consumer, ctx) => listDeadEvents(storage.work, topic, consumer),
release: (topic, consumer, id) => retryDeadEvent(storage.work, topic, consumer, id),
},
});Üç şey yüzeyin sonradan eklenmiş parçası değil, kendisidir. Olay gövdesi, çağıran hem istemedikçe hem de payloads:read taşımadıkça verilmez; işleyicinin hata metni aynı izinle tutulur ve istemeye gerek yoktur, çünkü varsayılan cevapta gelir. Tarama pahalıdır — bütün bir konu kaydını okur — bu yüzden dağıtım genelinde aynı anda bir tane koşar, kalanlar sıraya girer ve Retry-After sabit bir sayı değil, bu dağıtımın kendi tamamlanmış taramalarından ölçülür.
Serbest bırakma etkisiz-tekrarlanabilirdir: zaten bırakılmış bir olayı geri vermek 409 değil, belgelenmiş bir işlemdir. Yalnızca teslim edilmiş olay nihaidir. Her bırakma denetim kaydına event.release olarak yazılır.
API referansı#
createStudioAppAdmin HTML UI + JSON API (/api/*) tek app'te — en kolay geriye uyumlu kurulum.
createStudioApiYalnız JSON API (UI yok); kendi mount/auth/programatik akışınıza gömmek için.
createStudioAdminYalnız HTML UI; apiBase ile yerel veya uzakta çalışan bir Studio API'ye bakar.
createStudioRunnercreateGnl instance'ından Playground/Tools/Workflows koşucusu türetir (StudioAgentRunner).
aiToolSchema@gnldev/studio/ai alt-export'u — zod şemasını JSON Schema'ya çevirir (Tools görünümü formu için).
deadEventScanDead-letter taramasını ayarlar: timeoutMs (host'un taraması ne kadar sürebilir), queueWaitMs ve queueDepth (kaç çağıran bekleyebilir), maxAbandonedScans (cevap vermeyen bir store'a yeni okuma açmayı durdurur).
StudioApiOptionscreateStudioApi/Runner girdisi: reader (zorunlu) + resume/chat/gnl/memory/workflows/scorers/datasets/mcp/queue/events/deadEventScan/cache/vectors/users/auth/org/budgets/retention/evalGate/alerts (hepsi opsiyonel).
StudioAppOptionsStudioApiOptions + apiBase (admin HTML'in fetch edeceği API öneki).
GET /capabilities yalnız verilen opsiyonlara göre true döner (ör. gnl yoksa playground: false). UI, giriş ekranından önce bu uçla kendini uyarlar; siz de kendi entegrasyonunuzda hangi yüzeylerin açık olduğunu buradan doğrulayabilirsiniz.users (Kullanıcılar görünümü + /users uçları) paralı bir sözleşmedir — implementasyonu (createJournalUserStore) @gnldev/auth-ee'de yaşar; ücretsiz katmanda bu opsiyonu vermezseniz görünüm sessizce gizlenir. Aynı şekilde Organizasyonlar/Bütçe yönetimi yalnız çok-organizasyonluluk açıkken (org verildiğinde veya auth sağlayıcısı multiOrganization bildirdiğinde) görünür.