
Ajan Modu, Memo'ya araç kullanma yeteneği kazandırır — dosyaları okuyup düzenleyebilir, terminal komutları çalıştırabilir, web'de arama yapabilir, takviminize bakabilir, WhatsApp'tan mesaj gönderebilir ve daha fazlasını yapabilir. Ajan, tehlike seviyesine dayalı sıkı bir izin sistemiyle, kum havuzlu (sandboxed) bir ortamda çalışır.
Ajan Modu'nun işe yaraması için gerçekten tool/function-calling destekleyen bir model gerekir. Aktif bir harici sağlayıcı (OpenAI, Claude, Gemini, vb.) en güvenilir yol. Çalışan bir yerel llama.cpp modeli de aynı tool-calling isteğine sarılıyor — yani sadece harici sağlayıcıya bağlı değil — ama yerel modellerde gerçek tool-calling kalitesi yüklediğiniz GGUF'a göre büyük fark gösteriyor; birçok küçük/kuantize model bunu ya kötü ya da hiç desteklemiyor.
v3.3.3'ten itibaren, ajan modu toggle'ı doğrudan sohbetin üst çubuğunda, web arama toggle'ının yanında duruyor — araçları açmak için artık ayrı bir Ajan sekmesine gitmeye gerek yok. Skill araçları da artık gerçekten çalışıyor: bir skill'in SKILL.md'i bir command: alanı tanımlayabiliyor, bu da run_command/dosya-düzenleme araçlarıyla aynı ajan pipeline'ından ve izin UI'ından geçiyor — yani bir skill'in araçları da hiçbir ek kurulum gerektirmeden aynı "çalıştırmadan önce sor" güvenlik ağına sahip oluyor.
Ajan, her biri bir JSON Şema ile tanımlanmış ve bir tehlike seviyesiyle kayıtlı 22 araçla geliyor (ilk sürümdeki 8'den):
| Araç | Tehlike | İşlev |
|---|---|---|
read_file |
Safe | Dosya içeriğini okur (max 1MB) |
write_file |
Medium | Dosya oluşturur/üzerine yazar, .bak yedek tutar |
edit_file |
Medium | Var olan dosyada find-replace veya satır aralığı değişimi, önizlemeli |
insert_line |
Medium | Belirli bir satır numarasına içerik ekler |
delete_lines |
Medium | Bir satır aralığını siler |
delete_file |
Dangerous | Dosya/dizin siler (.git/ korumalı) |
list_directory |
Safe | Dizin içeriğini listeler (max 1000 girdi) |
get_file_info |
Safe | Dosya meta bilgisi — boyut, mod, değişiklik zamanı |
search_files |
Safe | Glob pattern ile dosya arar |
run_command |
Dangerous | Kabuk komutu çalıştırır (60s timeout, 23 desenlik kara liste) |
read_env |
Medium | Ortam değişkenlerini listeler (hassas olanlar maskelenir) |
web_search |
Safe | DuckDuckGo araması — aşağıya bakın, bu araç yakın zamanda değişti |
self_clone |
Dangerous | Tüm projeyi başka bir yerel dizine kopyalar |
configure_provider |
Dangerous | Sohbet içinden sağlayıcı ekler/günceller, onay gerektirir |
get_calendar_events |
Safe | Gerçek takvim verinizden bir tarih aralığındaki etkinlikleri okur |
create_routine |
Medium | Düz dilden bir zamanlanmış rutin oluşturur (v3.9.0) |
list_routines |
Safe | Var olan rutinleri listeler (v3.9.0) |
cancel_routine |
Medium | Bir rutini iptal eder (v3.9.0) |
whatsapp_send |
Medium | WhatsApp mesajı gönderir |
whatsapp_search |
Safe | WhatsApp mesaj geçmişinizde arama yapar |
whatsapp_latest |
Safe | En son mesajlaştığınız sohbetleri listeler |
whatsapp_messages |
Safe | Belirli bir sohbetin mesaj geçmişini getirir |
web_search ve yakın zamandaki değişikliğiAjanın web_search aracı DuckDuckGo'da arama yapar — model, tool'un kendi açıklamasında, sadece training cutoff'undan sonra değişmiş olabilecek güncel olay/fiyat/gerçekler için bunu çağırması, selamlaşma veya zaten bildiği bir şey için çağırmaması yönünde yönlendirilir.
Yakın zamana kadar, sohbet üst çubuğundaki "web arama" toggle'ı (ajan toggle'ının yanındaki küre ikonu) bu araçtan tamamen farklı çalışıyordu: açık olduğunda her tek mesaj — selamlaşma olsun olmasın — kör bir web araması tetikliyor, sonuçlar mesajın gerçekten ihtiyacı olsun olmasın prompt'a tıkıştırılıyordu. Bu artık yok. Toggle artık tam olarak aynı aracı, ajan pipeline'ının tek-araçlı, kapsamlandırılmış bir versiyonu üzerinden çalıştırıyor: model, her mesajda, gerçekten arama yapması gerekip gerekmediğine kendisi karar veriyor — karar vermediğinde sıfır ekstra maliyetle — ve tam agent modu hiç istemeyen düz bir sohbete ajanın geri kalan araç setini (dosya yazma, run_command yok) hiç açmadan. Artık düz bir "naber" sıfır arama tetikliyor; "bugün dolar kuru ne kadar" ise tam olarak bir arama tetikliyor, ham mesajınızın tamamı yerine gerçek ve konuya uygun bir sorguyla.
{
"name": "run_command",
"description": "Kum havuzlu bir ortamda terminal komutu çalıştırır",
"parameters": {
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "Çalıştırılacak kabuk komutu"
},
"cwd": {
"type": "string",
"description": "Çalışma dizini (varsayılan: proje kökü)"
}
},
"required": ["command"]
}
}
Her aracın bir tehlike seviyesi vardır — safe, medium, veya dangerous — ve bu, kullanıcıya hiç sorulup sorulmayacağını belirler. safe araçlar her zaman otomatik çalışır, hiç soru sorulmaz, istisna yok. medium/dangerous araçlar önce var olan bir oturum/kalıcı kararı kontrol eder, ikisi de yoksa ancak o zaman gerçek bir onay isteğine düşer. Bir onay isteği çıktığında kullanıcı altı politikadan birini seçer:
| Politika | Davranış | Kalıcılık |
|---|---|---|
AllowOnce |
Bu bir çağrıya izin ver | Çalıştıktan hemen sonra temizlenir |
AllowSession |
Bu oturumun geri kalanında izin ver | RAM'de, yeniden başlatmada kaybolur |
AllowForever |
Kalıcı izin ver | data/permissions.json'a kaydedilir |
DenyOnce |
Bu bir çağrıyı reddet | Çalıştıktan hemen sonra temizlenir |
DenyForever |
Kalıcı reddet | data/permissions.json'a kaydedilir |
| (yanıt yok) | 60 saniye sonra otomatik reddedilir | — |
Herhangi bir izin politikasından bağımsız olarak run_command'da 23 desen kara listeye alınmıştır — run_command için genel bir AllowForever bile bunları tekrar açmaz:
| Kategori | Örnekler |
|---|---|
| Yıkıcı | rm -rf /, rm -rf ~, rm -rf . |
| Disk işlemleri | dd, mkfs, format, fdisk, parted |
| Yetki değişiklikleri | chmod 777, sistem yollarında chown |
| Yetki yükseltme | sudo, su, pkexec |
| Fork bomb'lar | :(){ :|:& };: ve varyantları |
| Reverse shell | nc -e, bash -i, mkfifo |
| Sistem kontrolü | shutdown, reboot, halt, poweroff |
Dosyaya dokunan araçlar her yolu doğrular: symlink'ler çözülür (bir symlink bir düzenlemeyi kum havuzunun dışına yönlendiremez), çözülen yol proje kökü içinde kalmalıdır, .. ile gezinme reddedilir, ve sabit bir sistem dizini listesi (/etc/, /usr/, /boot/, vb.) tamamen yasaktır.
Araç çağrıları tüm araçlar genelinde dakikada 30 ile sınırlıdır, ve aynı çağrı (aynı araç, aynı argümanlar) 5 saniyede bir defadan fazla tekrarlanamaz — bu bir bekleme süresi, sert bir engelleme değil, yani gerçekten tekrarlanan bir eylem pencere geçtikten sonra yine de geçer.
Ajan yinelemeli bir döngüde çalışır: mesaj listesini oluştur, kayıtlı her aracın şemasını ekle, modeli çağır (streaming değil, temperature 0.2), sonra ya gelen araç çağrılarını çalıştırıp sonuçlarla döngüye devam et, ya da — model düz içerik döndürdüyse — bu nihai cevaptır, bitti.
Kullanıcı Mesajı
│
▼
[Yineleme 1] Model araçları görür, (varsa) neyi çağıracağına karar verir
│
├─▶ Araç çalışır (izin kontrollü, kum havuzlu, süreli) ──▶ Sonuç
│
▼
[Yineleme 2] Model araç sonucunu/sonuçlarını alır, sonraki adıma karar verir
│
├─▶ Başka bir araç çağrısı, ya da...
│
▼
...
│
▼
[Nihai] Model düz içerik döndürür — araç çağrısı yok — bitti
| Parametre | Değer |
|---|---|
| Maksimum yineleme | 40 |
| Araç başına timeout | 120s |
run_command timeout |
60s |
| Hız sınırı | 30 çağrı/dk, aynı çağrı için 5s bekleme |
| Context bütçesi | Sohbetten hesaplanır + araç yinelemeleri için 32K pay, hiçbir zaman 64K'nın altına düşmez |
Pipeline şu durumlarda durur: model araç çağrısı olmadan nihai bir yanıt döndürür, yineleme limitine ulaşılır, bir izin bekleyişi zaman aşımına uğrar (60s, otomatik reddedilir), veya istek iptal edilir.
Her araç çağrısı loglanır — zaman, araç adı, argümanlar (hassas olanlar maskelenir), sonuç özeti, izin kararı. Son 1000 kayıt RAM'de tutulur; her kayıt ayrıca diskte agent-audit.jsonl'a tek satır JSON olarak da yazılır, yani kayıt geçmişi sadece RAM tamponu değil, yeniden başlatmalardan da sağ çıkar.
┌─ Ajan Çalıştırması ──────────────────────────────────┐
│ Model: claude-3-5-sonnet │
│ Yinelemeler: 3 │
│ │
│ [1] web_search("sqlite-vec go örneği") │
│ → 4 sonuç (0.9s) │
│ [2] read_file("internal/memory/store.go") │
│ → 312 satır (0.02s) │
│ [3] run_command("go test ./internal/memory/...") │
│ → BAŞARILI (2.1s) │
│ │
│ Nihai yanıt üretildi │
└──────────────────────────────────────────────────────────┘
Ajan modu, aktif backend'in function-calling (tool-use) desteğine dayanır:
| Sağlayıcı | Function-calling desteği |
|---|---|
| OpenAI | Yerel |
| Anthropic Claude | Yerel (tool_use blokları) |
| Google Gemini | Yerel (function declarations) |
| Groq | Uyumlu hosted modellerle |
| OpenRouter | Yönlendirilen modele bağlı |
| xAI Grok | Sınırlı |
| OpenCode Zen / OpenCode Go | Yerel |
| Ollama (harici sağlayıcı olarak yapılandırılmış) | Yüklenen modelin chat template'ine bağlı |
| Memo'nun kendi gömülü yerel llama.cpp modeli | Yukarıdakilerle aynı isteğe sarılıyor — tamamen yüklenen GGUF'un kendi tool-calling desteğine bağlı, bu da modelden modele büyük fark gösteriyor |
v3.3.3'teki bir düzeltme, sağlayıcının API'sine gönderilen araç tanımlarına yanlışlıkla sızan dahili bir muhasebe alanını kaldırdı — bu, aynı sağlayıcıda düz sohbet sorunsuz çalışırken bile ajan modunun bazı harici sağlayıcılara karşı gizemli bir400 invalid_request_errorile tamamen başarısız olmasına neden oluyordu. Sohbette gösterilen hata mesajları artık sağlayıcının ham JSON hata yanıtı yerine sadece okunabilir mesajı gösteriyor.
v3.3.4'teki bir düzeltme, araç tanımlarını modelin context penceresine karşı bütçeliyor — önceden hiç sayılmıyorlardı, yani küçük context'li bir yerel modelde tek kelimelik bir mesaj bile kafa karıştırıcı bir "request exceeds context size" hatasıyla başarısız olabiliyordu. Chat template'i tool-calling desteklemeyen bir yerel model başlatmak artık sohbetin ortasında açıklanamayan bir başarısızlık yerine baştan net bir uyarı gösteriyor.