Yakın zamanda, Laravel ve Filament kullanarak geliştirdiğim ücretsiz, açık kaynak CRM olan Relaticle hakkında yazmıştım. O zamandan beri, karşımıza sıkça çıkan bir istek: AI.
Pek çok bu isteği, v3.3 sürümünde – “Relaticle’ı Sor” adında, CRM’i okuyor ve her yazma işlemi için insan onayı alıyor olan bir uygulama içi ajanı sunduk. Bu yazı, başlarken karşılaşabileceğiniz zorlukları gözler önüne seriyor: yeni laravel/ai paketini üretime almak için gerçekten neler gerektiği ve asıl zorlukların nerelerde yattığı (spoiler: zor olan, komutlar değil).
Neden MCP varken yerleşik bir ajana ihtiyaç var?
Neden MCP varken yerleşik bir ajana ihtiyaç var?
Relaticle, zaten bir MCP sunucusu (Sanctum üzerindeki 30 araç ile ekip bazında izolasyon) sağlıyor, böylece Claude veya ChatGPT uzaktan bunu yönetebiliyor. Bu, ajansız azınlık için yeterli. Yerleşik sohbet ise herkes içindir – Claude Desktop’ı asla açmayacak bir satış temsilcisi, Cmd+J tuşlarına basmayı ve “şirketi oluştur ve iletişimi ekle” yazmayı sevecektir.
Bunu mantıklı kılan mimari kural: REST API, MCP araçları ve uygulama içindeki ajan aynı eylem sınıflarını çağırır. İster Filament formundaki bir insan, ister bir HTTP istemcisi, ister bir model değişiklik önermek olsun, iş mantığı, etkinlik günlüğü, bildirimler ve kiracı kapsamı için tek bir kod yolu vardır.
Ajanın kendisi kolay kısım
Ajanın kendisi kolay kısım
Bütün ajan tanımı tek bir sınıf. laravel/ai ise nitelikler ve sözleşmeler aracılığıyla ağır yükü üstleniyor:
#[Provider(['anthropic', 'openai'])]
#[MaxSteps(15)]
#[Temperature(0.3)]
#[Timeout(120)]
final class CrmAssistant implements Agent, Conversational, HasMiddleware, HasProviderOptions, HasTools
{
use Promptable;
use RemembersConversations;
// ~28 araç kayıtlı: Şirketler, insanlar, fırsatlar, görevler, notlar + arama + özetler için CRUD
}
RemembersConversations, yerleşik olarak kalıcı bir geçmiş sunar. #[Provider] ise ajanın sağlayıcıdan bağımsız olmasını sağlar – kullanıcılar her konuşmada Claude veya GPT’yi seçebilir ve kendi anahtarlarını getirir. Bu, belki bir iş günü süren bir çalışma gerektirir. Altındaki her şey ise diğer altı haftayı aldı.
Gerçeklikte hayatta kalan akış
Gerçeklikte hayatta kalan akış
Sohbet, Reverb üzerinden akış yapan bir kuyruk taşıyıcı (Horizon) olarak çalışır. Demo videolarındaki dünya, hikayenin sonunu getiriyor. Üretimde ise:
- Kullanıcılar akış sırasında sayfayı yenileyebilir.
- Websockets kopup yeniden bağlanabilir.
- Livewire, rahatsız edici anlarda yeniden oluşturur.
Her akış bir kimlik gerektirir, böylece istemci yeniden bağlanma sonrası neyin zaten render edildiğini uzlaştırabilir ve devam eden durumların devam edilebilir olması gerekir – cevap ortada kaldığında yeniden yüklenme işleminde akışı devam ettirebilmelidir, yarım kalmış bir yanıt terk edilmiş olmamalıdır.
Gerçek üretimde başımıza gelen bir hata: yayın kanalının yetkilendirmesi, rotalar önbelleğe alındığında sessizce kaydı durdurdu. Eğer kanallarınız olağandışı bir yerde yaşıyorsa, bunların route:cache açıkken kaydolduğunu doğrulayın – yerel ortamda her şey çalışır, ancak üretimde Echo’nın asla abone olmadığı gibi davranabilir.
Güvenilir yazma işlemleri: onay süreci
Güvenilir yazma işlemleri: onay süreci
Ajan asla doğrudan yazmaz. Araçlar öneriler üretir; kullanıcı bir onay kartı görür ve karar verir. Basit görünse de, karmaşık olan kısımlar:
İdempotent onaylar. Onay, bir HTTP isteğidir ve HTTP istekleri tekrar edilir. Eğer “Acme Robotics’i oluştur” onayı iki kez çalıştırılırsa, iki şirket almamalısınız. (Kendi demo filmleri çekerken, otomasyon onay butonuna çift tıklamıştı – idempotans katmanı bunu absorbe etti. Tatmin edici bir andı.)
Onay anında kiracı kapsamı. Bir öneri, bir ekip bağlamında oluşturulmalıdır ve aynı bağlamda yürütülmelidir – onay yer aldığında çevresel duruma güvenmeyin. Çok kiracılı bir CRM’de bu, bir güvenlik özelliği ile bir veri ihlali arasındaki farktır.
Toplu öneriler. Model beş kayıt oluşturmak istediğinde, bu bir kart ve bir tıklama ile yapılmalıdır, beş kesintiye uğratma ile değil.
Geçersiz kılma, hayalet bırakma. Kullanıcı onay yerine yazmaya devam ederse, bekleyen öneriler geçersiz kılınır ve modele bildirilir. Bunu yapmazsanız, model sürekli olarak aynı kayıtları yeniden önerir – bu, gerçek kullanımda keşfedilebilecek bir davranıştır.
Sunucu tarafında geri alma sözleşmesi. Silmeler 5 saniyelik bir geri alma uyarısı gösterir, ancak sunucu geri alma penceresini 5 dakika boyunca dikkate alır. Uyarı kullanıcı deneyimidir; pencere asıl garantidir.
Öneri yaşam döngüsü, son derece küçük bir durum makinesi gibi sonuçlanır – bekleyen → onaylı / reddedilmiş / geçersiz kılınmış / süresi dolmuş – bunu modellediğinizde, kenar durumları (geçersiz kılma sonrasında onay verme, süresi dolmuş bir geri alma) açık hale gelir, rastgele değil.
Özel alanlar statik araç şemalarını bozar
Özel alanlar statik araç şemalarını bozar
Relaticle’ın kayıtları, kullanıcı tanımlı özel alanlara sahiptir – her ekibin şeması farklıdır. Bu nedenle aracın JSON şemasını çoğu ajanın demolarında olduğu gibi sabit kodlamak mümkün değildir.
Bizim yaklaşımımız: çalışma zamanında, her kiracı için tanım seçimini doğrudan göre sınıf içerisine eklemek – alan kodları, türleri ve seçenek etiketlerini içerir – ve doğrulama anında etiketleri geri çevirerek seçenek kimliklerine dönüştürmektir. Bu avantajı, bir alanı admin UI’da eklemenin hemen sohbetten (ve MCP istemcilerinden) kullanılabilir olmasını sağlamak için kod yazmanıza gerek kalmadan yapmanızdır.
Sağlayıcı notları deneyimlerden
Sağlayıcı notları deneyimlerden
Gemini, kasıtlı olarak dışlanmıştır. Sürücü şu anda sağlayıcı seçeneklerini generationConfig içine birleştiriyor, bu nedenle function_calling_config ayarlayamıyorsunuz – ve bunun olmaması durumunda, ardışık yazma korumamızı sağlayamayız. Farklı bir şekilde davranan bir ajan göndermek yerine, sürücü bunu destekleyene dek listeyi sınırladık.
Anthropic onay önbelleklemesi, bir yapılandırma bayrağıdır ve buna değerdir. Çok turlu ajanın konuşmaları büyük bir sistem prompt’u (özellikle her kiracı için şema enjeksiyonu içerdiğinde) tekrar aktarır. Ön belleği etkinleştirmek, çok turlu giriş token’larını önemli ölçüde kısalttı:
'anthropic_prompt_caching' => (bool) env('CHAT_ANTHROPIC_PROMPT_CACHING', true),
Dürüst hatalar sessizlerden daha iyidir
Dürüst hatalar sessizlerden daha iyidir
Oran limitleri oluşur. Sağlayıcılar sorunlar yaşayabilir. Bir ajanın yapabileceği en kötü şey, hatayı yutmak ve kullanıcıyı donmuş bir imleçle baş başa bırakmaktır.
Her hata durumu, UI’de açık bir durumda ortaya çıkar – “yeniden deneme,” “başarısız – devam edelim mi?” – ve devam etme işlemi, konuşmayı yeniden başlatmak yerine sürdürmeyi sağlar. Yarım kalan işler, sessizce kaybolduğunda, bir ajana güveni kaybeder. Bu, bir tasarım kararıydı ve olay modelini (akış başarısız / akış yeniden deniyor / sohbet askıya alındı) ilk sınıf olaylar haline getirdi.
Başlarken sana söyleyeceğim şeyler
Başlarken sana söyleyeceğim şeyler
- [Кibuz] Dağıtılmış sistem hijyenine bütçenizi en çok ayırın: akış kimliği, devam edilebilirlik, idempotans, kiracı kapsamı. LLM kısmı sadece bir demodur; bu ürün.
- Yazma işlemleri için insan onayına öncelik verin. Bir modelin güvenle yanlış kayıt güncellemesi önermesini izledikten sonra, başka kişilerin gelir verileri için varsayılan onay, tek dürüst varsayımdır.
- Başarısızlık durumlarını birinci sınıf yapın. Kullanıcılarınız birinci günde oran limitleriyle karşılaşacak.
- Eğer alanınız dinamik şemalara sahipse, komut enjeksiyonunu erken tasarlayın – bu, araç tanımları hakkında düşünme şeklinizi değiştirir.
Bu yazının içeriği, repoda okunabilir – sohbet packages/Chat dizininde yer almakta ve gerçekten bir öğleden sonranız bu konuda geçirebileceğiniz iyi bir zamandır: https://github.com/relaticle/relaticle
laravel/ai hakkında üretimdeki sorularınıza açığım – bu konuda çok fazla gerçek dünya materyali yok ve yukarıdaki başlıklardan biri üzerinde daha derinlemesine konuşmaya memnuniyetle açığım.
Kaynak: Orijinal Makale


