Dokümantasyon

Yapay zekâ ajanları

Her yapay zekâ ajanına API anahtarınız yerine kendi kimliğini verin. Ajan bir isim değil, bir anahtardır: yalnızca açık anahtarını kaydedersiniz, ajan private_key_jwt iddiasıyla giriş yapar ve o anahtara DPoP ile bağlı 10 dakikalık bir jeton alır; bir logdan ya da istemden kopyalanan jeton tek başına işe yaramaz. Her ajanın sorumlu bir sahibi, kullanıcılarınızdan onay isteyebileceği işlem türleri ve bir gözden geçirme tarihi vardır.

Bir ajana asla API anahtarınızı vermeyin. Bir tq_ anahtarı yetkilerinin izin verdiği her şeyi yapabilir; bir ajan jetonu yalnızca ajanın işini. Bir betiğe anahtar vermeniz gerekiyorsa dar yetkili bir anahtar oluşturun (örneğin login:*): geri kalan her şey 403 insufficient_scope döner.
Ajan nasıl giriş yapar
ParçaKural
client_assertionAjanın anahtarlarından biriyle imzalı JWT (RFC 7523; ES256 ya da EdDSA, başlıkta kid): iss = sub = ajan kimliği, aud = …/agents/token, en çok 5 dakika, bir kez kullanılan jti.
DPoPJeton isteğinde ve her çağrıda bir kanıt JWT (RFC 9449): htm, htu, taze bir iat, benzersiz bir jti; çağrılarda ath (jetonun özeti). Jeton yalnızca bağlandığı anahtarla çalışır.
access_tokenOpak, 10 dakika, yetkiler agent:read approvals:request approvals:read. Yenileme jetonu yok: ajan yeniden ister (SDK'lar bunu yapar).
Ajanı anında ne durdurur
DurumAnlamı
blocked: suspendedSiz askıya aldınız (API ya da dashboard); devam ettirince tekrar çalışır.
statusReason: owner_leftSahibi organizasyondan ayrıldı: yeni bir sahip verin (PATCH ownerEmail) ya da iptal edin.
blocked: review_overdueGözden geçirme tarihi geçti: hâlâ gerekli olduğunu kontrol edip yenileyin (PATCH reviewInDays).
blocked: workspace_pausedKill switch açık: çalışma alanının tüm ajanları durdu.
blocked: revokedKalıcı olarak iptal edildi; kayıt denetim izi için kalır.

Her ajan çağrısı ajanını yeniden denetler; askıya alma, iptal, anahtar kaldırma ya da kill switch (PUT /agents/kill-switch) önceden verilmiş jetonları da bitirir. Dashboard'da (Developers → AI agents) durdurmak anında olur; ajanın yeniden çalışmasına yöneticinin telefonu onay verir. Her giriş ve değişiklik bir log satırıdır (AGENT_*), üzerine işlem yapabileceğiniz olanlar ayrıca webhook olarak gelir. Bir SIEM hepsini GET /agents/events?after=… ile okur (en eskiden başlar; next'i saklayın; her SDK'da tq.agents.listEvents); agent.approval tetikleyicisindeki bir Action telefona bir şey gitmeden reddedebilir, adım yükseltebilir ya da passkey isteyebilir.

Bir kişiden onay istemek

Ajan POST /agents/approvals ile serbest metin özet değil, tipli authorizationDetails gönderir. Touchque her alanı denetler ve telefondaki satırları kendi sözcükleriyle çizer: önce ajanın adı, sonra ayrıntılar, en sonda doğrulanmamış diye işaretli ajan gerekçesi. Görünmez, kontrol ya da yön değiştiren karakter içeren metin reddedilir. İstek bir girişle aynı denetimlerden geçer (dondurma, itme sınırı, risk motoru, Actions, Vishing Shield, vaka kodu); telefon Face ID ya da donanım anahtarı ister ve imzası tam olarak bu satırları kapsar. presence: interactive (varsayılan) ile kişi konuşmanızda görünen sayıyı yazar; background'da sayı yoktur ve kritik işlem türlerinde asla izin verilmez.

typeAlanlar
payment_initiationinstructedAmount { currency, amount }, creditorName, creditorAccount { iban | accountNumber }, remittanceInformationUnstructured IBAN'lar kontrol basamaklarını geçmelidir.
purchaseamount { currency, amount }, merchant, item
data_accessresource, actions [read, write, delete, export, share], records, destination
account_changesetting, from, to
message_sendchannel [email, sms, chat, social, other], recipients[], subject
genericfields [{ label, value }] (1-4) Kendi etiketleriniz; mümkünse tipli bir kayıt kullanın.
statusAnlamı
pendingTelefon bekleniyor; challengeCode'u konuşmada gösterin.
approvedYanıtta approvalToken var (5 dakika; kullanılabilir oldukça yenisini isteyin).
provisionalBir telefon görüşmesi sırasında onaylandı (Vishing Shield): telefon görüşmeden sonra doğrulayana kadar jeton yok.
rejected · blocked · revokedKişi reddetti, risk motoru reddetti ya da onay geri alındı.
awaiting_secondDört göz: kişi onayladı, ikinci onaylayan henüz onaylamadı (secondApprover, secondChallengeCode). İkisi de onaylamadan jeton yok.
expired · stale · redeemedZamanında yanıtlanmadı, 15 dakikadan önce onaylandı ya da zaten kullanıldı.
Onay jetonu tam olarak neyin onaylandığını söyler. ES256, typ: touchque-approval+jwt, anahtarlar GET /agents/jwks.json'da: sub (kişi), act.sub (ajan), authorization_details, cnf.jkt (ajanın anahtarı), details ve proof (telefonun bunlar üzerindeki donanım imzası), 5 dakika. Yürüten sunucunuz işlemden hemen önce onu bir kez kullanır (POST /agents/approvals/redeem) ve ayrıntıları yapacağı işle karşılaştırır; SDK'lar ikisini redeemApproval(token, expect) ile yapar ve uyuşmazlıkta hiçbir şey kullanılmadan reddeder.
Politikalar, dört göz ve sürekli izinler

Her ajanın bir politikası vardır (PUT /agents/{agentId}/policy ya da dashboard'daki sayfası); bir telefona bir şey ulaşmadan önce denetlenir, ardından kişinin kendi itme sınırı, dondurma ve risk motoru yine uygulanır. Dashboard'da daha sıkı bir politika hemen kaydedilir, daha gevşek olan yöneticinin telefonunu bekler.

AlanKural
requestsPer10Min · requestsPerUserPer10Min60 · 5. Ajanın tüm istekleri ve tek bir kişiye istekler (bildirim yorgunluğu).
amountPerRequest · amountPerDay{ "TRY": "1000.00" }: bir onayın ve 24 saatte bekleyen ile onaylananların taşıyabileceği en çok tutar.
backgroundnon_critical (varsayılan) ya da never. Kritik bir işlem türü asla arka planda sorulmaz.
newRecipients · recipientAllowlistBu kişinin bu ajan için hiç onaylamadığı hesap, satıcı ya da adresi ask (varsayılan) ile sor ya da deny ile reddet; IBAN ya da hesap listesi diğerlerini reddeder.
fourEyes{ approvers, above?, types? }: kişiden sonra ikinci bir kişi (asla aynı kişi, asla ajanın sahibi değil) kendi telefonunda onaylar; bu işlem türlerinde ya da above üstündeki tutarlarda.
requirePasskeyAbove{ "TRY": "10000.00" }: üstünde kişi sizin sayfanızda passkey ile onaylar (onay requiresPasskey der; sayfanız @touchque/web'in passkeys.approveLogin({ requestId: approvalId }) çağrısını yapar, çağrı relay'inizin /passkey/login rotalarından geçer), asla telefonda ya da sürekli izinle değil; arka plan isteği 409 interactive_required alır.
PUT /agents/workspace-policyAynı alanlar tüm çalışma alanı için: her ajanın tabanı. Ajanın kendi politikası her alanı yalnızca sıkılaştırabilir; çalışma alanının boş bıraktığı alan taban koymaz.

Bir sürekli izin, kişinin düşünmeden onaylayacağı itmeleri tek bir bilinçli karara çevirir: ajan bir kez sorar (POST /agents/mandates): tek bir işlem türü, en çok N istek, tek para biriminde toplam ve isteğe bağlı istek başı üst sınır, isteğe bağlı alıcılar, bir bitiş zamanı (5 dakikadan 7 güne). Telefon her sınırı gösterir ve kişi sayıyla onaylar. İçindeki istekler (POST /agents/approvals üzerinde mandateId) itme olmadan onaylanır ve izinden atomik olarak düşülür; döngüye giren ya da ele geçirilen bir ajan kişinin okuduğunun ötesine asla geçemez. Sürekli izinler yalnızca ödeme ve satın almaları kapsar ve dört gözün yerine asla geçmez. Kişi, ajan, siz ya da bir yönetici istediği an bitirebilir.

errorAnlamı
blocked_by_personKişi "bu ben değilim" dedi, telefondaki birinin yönlendirdiğini söyledi ya da 30 dakikada üç kez reddetti. Yalnızca bir yönetici kendi telefonuyla kaldırır.
amount_over_limit · daily_amount_over_limitamountPerRequest ya da amountPerDay aşıldı.
recipient_not_allowed · new_recipientListede yok ya da yeni ve newRecipients deny.
loop_detected (429)10 dakikada üç kez aynı istek; AGENT_LOOP_DETECTED olarak loglanır.
no_second_approver · four_eyes_requiredDört göz geçerli ve bu kişi ya da sahip dışında kimse yok; bir sürekli izin dört gözün yerine geçemez.
mandate_mismatch · mandate_exceeded · mandate_revoked …Sürekli iznin dışında (tür, para birimi, alıcı, istek başı), yer kalmadı ya da etkin değil.
suspicious_content (400)Ajanın metninde modele bir talimat ya da veri taşımak için kurulmuş bir bağlantı var (markers: instruction, data_url). Motora da telefona da bir şey gitmez.
interactive_required (409)Denetimler sayı eşleştirme istedi ve ajan arka planda sordu; sayıyı okuyacak kimse yok. presence interactive ile yeniden sorun.
Ajan çatınızda

Tek bir onay politikası bir araç çağrısını kimin, hangi işlem türü olarak onaylayacağını ve telefonun ne göstereceğini (aracın argümanlarından çıkarılan tipli ayrıntılar) söyler. Bir aracı withTouchqueApproval ile sarın (Python: @with_touchque_approval): yalnızca kişi telefonda onayladıktan sonra çalışır; sarılmış araç imzasını korur, böylece LangChain, LlamaIndex, OpenAI Agents SDK ve Vercel AI SDK aynı argümanları okur; currentApproval() yürütücünüz için tek kullanımlık jetonu tutar. Kendi onay adımı olan çatıların her biri için bir yardımcı var: approveInterruptionsWithTouchque (OpenAI Agents SDK kesintileri), touchqueCanUseTool ve touchquePreToolUseHook (Claude Agent SDK), guardMcpClient (bir MCP istemcisi; jeton sunucuya _meta içinde gider). Go ve PHP'de RequireApproval / requireApproval var: sor, sayıyı göster, bekle. Bir ajan kendi Touchque kimliğini yukarıdaki gibi SDK'lardan alır: TQ_AGENT_ID ve TQ_AGENT_KEY ile TouchqueAgent ve çatısındaki bu yardımcılar. Bunu kodunuza bir yapay zekâ kod asistanına kurdurmak için Touchque MCP'yi kullanın; o bir ajan olarak değil, sizin adınıza giriş yapar.

Touchque neyi fark eder

Yukarıdaki her ret bir caseCode döner: dashboard'da (Logs → Look up a case) açın; ne girdiğini, hangi kuralın reddettiğini ve neyin geçeceğini görürsünüz. Risk motoru her isteği ajanın kendi geçmişiyle de karşılaştırır; her sinyal bir adım yükseltmedir (kişi sayıyı yazar), tek başına asla engel değildir; adım yükselttiği arka plan isteği interactive_required ile reddedilir. Sayısı bir insanın okuyup yazabileceğinden önce dönen onay (telefonu bir şey sürüyor) asla kullanılamaz: durum blocked, neden inhuman_approval. Adı, çalışma alanındaki başka bir ajanınkine benzeyen (benzer harfler, 0/O, 1/l, büyük-küçük harf, boşluk) yeni ya da yeniden adlandırılan ajan name_too_similar ile reddedilir; telefon önce ajanın adını gösterir. Webhook'lar: diğerlerinin yanında AGENT_INJECTION_SUSPECTED, AGENT_INHUMAN_APPROVAL, AGENT_LOOKALIKE_NAME; dashboard'da yapılan değişiklikler de gönderir.

SinyalNe zaman
agent_volume_spikeBu saatte, geçen haftanın en yoğun saatinin iki katından fazla istek (en az 10).
agent_amount_outlierBu para biriminde olağan tutarının beş katından ve şimdiye kadarkinin hepsinden fazla.
agent_new_networkAjanın daha önceki bir günde hiç kullanmadığı bir ağ (ASN).
agent_off_hoursİsteklerinin %1'inden azını tutan bir saat.
agent_new_destinationBu kişinin bu ajan için hiç onaylamadığı bir alıcı.
Kendi organizasyonunuzdaki ajanlar (Touchque SSO)

Şirketinizin kendi ajanları ve otomasyonları için onları dashboard'da ekleyin (Organization → AI agents): her biri için sorumlu bir üye (ayrılınca ajan durur), belirteç alabileceği OpenID Connect uygulamaları, kapsamlar, bir gözden geçirme tarihi ve kimliğini nasıl kanıtlayacağı: kendi açık anahtarı ya da platformunun zaten verdiği belirteç (GitHub Actions, GitLab, Google Cloud, Azure, Kubernetes; güven politikası yayıncıyı, konuyu ve kitleyi belirtir). Paylaşılan gizli anahtar yok. /sso/token'dan tek bir uygulama için 5 dakikalık, DPoP anahtarına bağlı (cnf.jkt) at+jwt belirteçleri alır; uygulama bunları SSO'nun JWKS'i ve her çağrıdaki kanıtla doğrular ya da /sso/introspect'e sorar: ajan askıya alınınca, kill switch açılınca ya da sorumlusu ayrılınca hemen etkin değil der. Bir ajana daha fazla yetki vermek yöneticinin telefonuyla onaylanır. Üyeler adına çalışmasına izin verilmiş bir ajan, bir üyenin kendi belirtecini ikisini birden adlandıran bir belirteçle değiştirebilir (jeton değişimi, RFC 8693: sub üye, act.sub ajan; üyenin açabileceğinden fazlası asla) ya da üyeye telefonda sorabilir (CIBA, /sso/bc-authorize, yoklama): telefon ajanı, uygulamayı ve tipli authorization_details'i gösterir, Face ID ve ajanın gösterdiği sayıyı ister; belirteç tam olarak onaylananı taşır.

Üyenin başka yerdeki kendi hesapları (jeton kasası)

Organization → AI agents → Accounts agents may use altında bir hesap bağlantısı ekleyin (Google, Microsoft 365, GitHub, Slack, Salesforce ya da herhangi bir OAuth 2.0 hizmeti; telefonunuz onaylar) ve onu kullanabilecek ajanları seçin. Her üye kendi hesabını portalda (/connections) bir kez bağlar; Touchque jetonları şifreli saklar ve yeniler. Ajan sonra /sso/token'a jeton değişimiyle, üyenin belirteci, requested_token_type=urn:touchque:params:oauth:token-type:connection-access-token ve connection ile sorar; o hizmet için bir Bearer jetonu alır, yenileme jetonunu asla almaz; scope yalnızca üyenin verdiğini daraltabilir. Üye bağlantıyı keserse, ayrılırsa ya da askıya alınırsa (jetonları silinir), ajan durursa ya da bağlantı kapatılır veya ajanı artık listelemezse hiçbir şey dönmez.

Envanter, gölge yapay zekâ, gözden geçirmeler ve kanıt

Organization → AI agents her ajanı neler yapabildiği, son 30 günde ne yaptığı ve risk düzeyiyle (üyeler adına çalışma ile birlikte üyelerin hesapları ya da ortak hesaplar, çok sayıda ret, kullanılmama, gecikmiş gözden geçirme) ve üyelerin MCP sunucularınıza bağladığı ya da bağlamaya çalıştığı her yapay zekâ aracını geldiği alan adıyla gösterir. Bir aracı telefonunuzla onaylayın ya da engelleyin: tüm bağlantıları anında biter ve kimse yeniden bağlayamaz. "Only approved AI tools" açıkken üyeler onaylamadığınız araçları bağlayamaz. Erişim gözden geçirmeleri yapay zekâ ajanlarını da kapsayabilir: seçtiğiniz sahip ve yöneticiler her birini gözden geçirir (hiçbir zaman sorumlusu değil); tutmak 90 gün onaylar, iptal ajanı iptal eder, kanıt imzalıdır. Yapay zekâ ajanı kanıt paketi (imzalı JSON + CSV, herkese açık doğrulama sayfasında denetlenir) bir dönemdeki ajanları, araçları ve her jetonu, üye onayını, hesabı, ortak hesabı ve araç çağrısını listeler. Log akışları ajan ve araç olaylarını agent kategorisiyle gönderir.

Oturum açmanıza karşı kullanılan ajanlar

Saldırganlar da tarayıcıyı yazılımla sürer: Playwright ya da Selenium, başsız bir Chrome, oturum açma sayfasını dolduran bir yapay zekâ tarayıcı ajanı ya da gizli bir istemle e-posta kodunu okuyup sızdıran kullanıcının kendi ajanı. Her Touchque oturum açma sayfası (SSO, Touchque Login, onaylar, dashboard) kendi sayfa denetimini gönderir; kendi sayfalarınızda @touchque/web startClientSignals() aynısını yapar, siz clientSignals olarak iletirsiniz. Yalnızca evet/hayır, sayı ve süre bildirir: navigator.webdriver, otomasyon izleri, başsız tarayıcı, betiğin ürettiği giriş, yazmadan doldurulan alanlar, makine düzeninde yazma, tarayıcıya uymayan istek başlıkları. Formun nasıl doldurulduğuna dair işaretler birlikte bir kez sayılır; formu dolduran ve gönderen bir parola yöneticisi tek başına yetmez. Risk motoru ağı (barındırma adresi, tarayıcının kendisine dair bir işaretle) ekler ve automated_client der: sessiz giriş yok, tek başına e-posta kodu ya da bağlantısı yok; passkey ya da sayı eşleştirmeli telefon onayı. Her çalışma alanı, organizasyon ve Touchque Login kiracısı monitor, step_up (varsayılan) ya da block seçer: block açık bir işarette (webdriver, otomasyon izleri, başsız tarayıcı, tarayıcı yerine bir araç) reddeder, daha zayıf işaretlerde step_up gibi sorar. Ajan tuzağına notunun istediği kelimeyi yazan yazılım monitor dışında reddedilir. Her retin bir vaka kodu vardır.

Kim olduğunu söyleyen ajanlar insan sayfalarında değil, ajan yolunda karşılanır: Web Bot Auth ile imzalanmış bir istek (HTTP Message Signatures, RFC 9421; anahtarları ajanın /.well-known/http-message-signatures-directory dizininde, yalnızca HTTPS ile getirilip ana makine başına sabitlenir) o ajan olarak tanınır ve agent_identity_required ile ajan kimliklerine yönlendirilerek reddedilir; doğrulanmayan imza (değiştirilmiş, yeniden kullanılmış, bilinmeyen anahtar) da aynı şekilde reddedilir. Telefonda emülatör ya da simülatör, hata ayıklayıcı, geliştirici seçenekleri ya da dokunabilen bir erişilebilirlik hizmeti (ekran okuyucular ve parola yöneticileri dışında) kritik bir işlemi asla onaylayamaz; bir çalışma alanı donanımı kanıtlanmış telefon isteyebilir (requireAttestedPhone).

MCP sunucularınız (yetkilendirme sunucusu Touchque SSO)

Organizasyonunuzun her MCP sunucusunu dashboard'da kaydedin (Organization → MCP servers): adresi, araçlarının gerektirdiği kapsamlar ve her birinin riski, kimlerin bağlanabileceği. Üyeler Claude, Cursor, VS Code ya da herhangi bir MCP istemcisini standart yolla bağlar: sunucunun korunan kaynak meta verisi (RFC 9728) https://sso.touchque.com/mcp'yi gösterir, istemci kendini bir istemci kimlik meta veri belgesiyle tanıtır (https adresi, kayıt yok) ve üyeyi PKCE (S256) ve zorunlu resource (RFC 8707) ile oturum açtırır. Üye istemcinin adresini ve kapsamları gösteren bir onay ekranı görür; hassas bir kapsam telefonunu ister (Face ID ve bir sayı). Belirteçler yalnızca o sunucu için (aud = adresi) 10 dakikalık at+jwt'dir, isteğe bağlı DPoP'ye bağlıdır; yenileme belirteçleri döner, eskisinin yeniden kullanılması bağlantıyı bitirir. Yönetici her bağlantıyı görür ve bitirebilir; bir sunucuyu daraltmak ya da kapatmak anında olur, genişletmek telefonla onaylanır. Sunucuda her SDK'daki McpAuth meta veriyi sunar, her belirteci denetler (Touchque'nun JWKS'i, yayıncı, kitle, süre, DPoP kanıtı) ve MCP istemcilerinin izlediği WWW-Authenticate başlığıyla 401 ya da 403 insufficient_scope döner.

Bir sunucu için Touchque ağ geçidini açın (dashboard'daki sayfası): yapay zekâ araçlarıyla sunucunun arasına bir politika noktası girer. Araçlar artık yalnızca https://sso.touchque.com/sso/mcp/gw/<id> adresine bağlanır; sunucunun kendisi için jeton istenirse reddedilir, sunucu her çağrıda Touchque'nun bastığı 2 dakikalık bir jeton alır (act.sub touchque-mcp-gateway), aracın kendi jetonunu asla. Araçlar tanımlarının özetiyle sabitlenir: yeni bir araç siz onaylayana dek gizlidir, tanımı değişen araç yeniden gizlenir (rug pull); modeli yönlendiren, anahtar dosyalarını anan, başka bir aracı anan ya da başka bir aracın adına benzeyen açıklamalar işaretlenir. Her araç izinli, üyenin telefonuna soran ya da yasak olabilir; talimat ya da gizli anahtar taşıyan argümanlar telefona sorar, kişisel veri ya da izin listeniz dışındaki bir adres dışarı yazan bir araçla çıkamaz; güvenilmeyen girdi ve özel veri okumuş bir oturum böyle bir araçtan önce telefona sorar (ikinin kuralı). Dakika bütçesi, döngü kesici ve kill switch kontrolden çıkan ajanları durdurur; her çağrının vaka kodu vardır ve SIEM'inize gider.

Uygulamalar arası erişim ve A2A ajan kartları

Organizasyonunuzun OpenID Connect uygulamalarından birini (istemci sırrı olan) dashboard'da bir hizmete bağlayın (Organization → AI agents → Cross App Access): MCP sunucularınıza ya da yetkilendirme sunucusu Touchque'dan ID-JAG kabul eden başka bir hizmete (yayıncısı, uygulamanın oradaki client ID'si, kaynaklar, kapsamlar). Telefonunuz onaylar. Uygulama sonra bir üyenin ID token'ını /sso/token'da bir Identity Assertion JWT Authorization Grant ile (ID-JAG, açık bir IETF taslağı; MCP Enterprise-Managed Authorization uzantısı bunun üstüne kurulu), ID-JAG'i de o hizmette bir erişim belirteciyle değiştirir; üye başına rıza ekranı yoktur. Her ID-JAG 5 dakika yaşar (typ oauth-id-jag+jwt), üyeyi, hizmeti ve uygulamanın oradaki client ID'sini adlandırır ve her seferinde yeniden denetlenir: üye hâlâ organizasyonda ve uygulamaya izinli mi, bağlantı açık mı, yapay zekâ aracı kuralı. Kendi MCP sunucularınız onu /sso/mcp/token'da alır (jwt-bearer, bir kez, yenileme belirteci yok). Bir yetkilendirme sunucusu işletiyorsanız her SDK ID-JAG'i sizin için denetler (yayıncı, tek kitle, istemciniz, süre, bir kez kullanım). Ajanınız başka bir ajanın A2A kartına güvenmeden önce SDK'lar imzalarını denetler (RFC 8785 kanonik kart üzerinde JWS); jku'nun gösterdiği anahtarlar yalnızca kartın kendi alan adından ya da güvendiğiniz alan adlarından alınır.

Kaydet, giriş yap, durdur
import { Touchque, TouchqueAgent, generateAgentKey } from '@touchque/node';

const tq = new Touchque(); // TQ_API_KEY / TQ_API_SECRET ortamdan

// Bir kez, sunucunuzdan (agents:write yetkili bir API anahtarıyla)
const { privateJwk, publicJwk } = generateAgentKey();   // ES256; 'EdDSA' too
const agent = await tq.agents.create({
  name: 'Invoice bot',
  allowedTypes: ['PAY_INVOICE'],          // isteyebileceği tek onaylar
  publicKey: publicJwk,                   // özel anahtar asla gönderilmez
  ownerEmail: 'ada@acme.com',             // sorumlu kişi; ayrılınca ajan durur
  platform: 'openai-agents',
});
// agent.id ve privateJwk ajanın gizli deposuna: TQ_AGENT_ID, TQ_AGENT_KEY

// Ajanın içinde: kendi anahtarıyla giriş, DPoP
const me = await new TouchqueAgent().me();

// Bir şey ters giderse
await tq.agents.suspend(agent.id, 'looping');
await tq.agents.setKillSwitch(true, 'incident');   // tüm ajanlar, hemen
İste, bekle, bir kez kullan
// Ajanda: serbest metin değil, tipli ayrıntılar
const ask = await agent.requestApproval({
  user: 'jane@example.com', type: 'PAY_INVOICE', reason: 'October rent',
  authorizationDetails: [{ type: 'payment_initiation',
    instructedAmount: { currency: 'TRY', amount: '500.00' },
    creditorName: 'Jane Doe', creditorAccount: { iban: 'TR33 0006 1005 1978 6457 8413 26' } }],
});
reply(`Type ${ask.challengeCode} in the Touchque app to approve.`);
const { approvalToken } = await agent.waitForApproval(ask.approvalId);

// Yürüten sunucuda, ödemeden hemen önce: bir kez, yalnızca bu iş için
const approval = await tq.agents.redeemApproval(approvalToken, {
  user: 'jane@example.com', type: 'PAY_INVOICE',
  authorizationDetails: { type: 'payment_initiation', instructedAmount: { currency: 'TRY', amount: '500.00' } },
});
Ajan çatınızda
import { withTouchqueApproval, currentApproval, touchqueCanUseTool, guardMcpClient } from '@touchque/node';

const policy = { agent, user: 'jane@example.com', type: 'PAY_INVOICE',
  details: ({ iban, amount }) => [{ type: 'payment_initiation',
    instructedAmount: { currency: 'TRY', amount }, creditorAccount: { iban } }],
  onChallenge: (s) => reply(`Type ${s.challengeCode} in the Touchque app.`) };

// LangChain tool(), OpenAI Agents tool(), Vercel AI SDK tool(): aynı imza
const pay = withTouchqueApproval(async ({ iban, amount }) =>
  bank.pay(iban, amount, currentApproval().approvalToken), policy);

// Claude Agent SDK
query({ prompt, options: { canUseTool: touchqueCanUseTool({ pay: policy }, { tokenField: 'approvalToken' }) } });
// MCP istemcisi: jeton _meta["touchque/approvalToken"] içinde gider
const guarded = guardMcpClient(client, { pay: policy });
Organizasyonunuzun ajanları (SSO)
import { TouchqueOrgAgent, githubActionsToken } from '@touchque/node';

// Kendi anahtarıyla (TQ_ORG_AGENT_ID, TQ_ORG_AGENT_KEY)
const agent = new TouchqueOrgAgent();
const res = await agent.fetch('https://payments.acme.com/invoices', { resource: 'tqapp_…', scope: 'invoices:read' });

// GitHub Actions içinde, saklanacak anahtar yok (permissions: id-token: write)
const ci = new TouchqueOrgAgent({ agentId: 'oagt_…', assertion: githubActionsToken('touchque') });

// Bir üye adına: kendi belirteciyle (RFC 8693) ya da telefonundan onay isteyerek (CIBA)
const forAda = await agent.exchangeToken({ subjectToken: adasAccessToken, resource: 'tqapp_…' });
const ask = await agent.askMember({ loginHint: 'ada@acme.com', bindingMessage: 'Pay invoice 42', authorizationDetails: [payment] });
reply(`Type ${ask.bindingCode} in the Touchque app.`);
const approved = await agent.waitForMember(ask);   // approved.authorizationDetails

// Jeton kasası: üyenin bağladığı kendi Google hesabı, yenileme anahtarı olmadan
const google = await agent.getConnectionToken({ subjectToken: adasAccessToken, connection: 'google' });
Oturum açmanıza karşı ajanlar
// Tarayıcıda (oturum açma sayfanız)
import { startClientSignals, addAgentTrap } from '@touchque/web';
const probe = startClientSignals();   // sayfa açılınca
addAgentTrap(form);   // ekran dışında bir alan: insan görmez; notunun istediği kelimeyi yazan yazılımın girişi reddedilir
form.onsubmit = () => { form.clientSignals.value = probe.encode(); };

// Sunucunuzda
const risk = await tq.risk.check({ externalUsername, clientIp, browserProof, clientSignals: req.body.clientSignals });
await tq.login.request({ externalUsername, type: 'LOGIN', clientIp, clientSignals: req.body.clientSignals });
// yazılımla sürülen tarayıcı: sessiz giriş yok, sayı eşleştirme; ya da 403 automated_client
MCP sunucularınız
import { McpAuth } from '@touchque/node';

const auth = new McpAuth({
    issuer: 'https://sso.touchque.com/mcp',   // Organization → MCP servers
    resource: 'https://mcp.acme.com/mcp',     // kayıtlı olduğu gibi
    tools: { search_tickets: 'tickets:read', delete_ticket: 'tickets:delete' },
});
app.use(auth.express());   // meta veriyi sunar; belirteç yoksa 401 + WWW-Authenticate

// bir aracı çalıştırmadan önce
auth.requireTool(req.touchqueMcp, 'delete_ticket');   // 403 insufficient_scope: istemci üyeden fazlasını ister
Uygulamalar arası erişim ve A2A kartları
import { requestIdJag, redeemIdJag, IdJagVerifier, verifyAgentCard } from '@touchque/node';

// Uygulamanız (gizli anahtarlı OIDC uygulaması): üyenin ID token'ı → ID-JAG → erişim belirteci
const { assertion } = await requestIdJag({ issuer: 'https://sso.touchque.com', clientId, clientSecret, idToken, audience: 'https://auth.files.example' });
const tokens = await redeemIdJag({ tokenEndpoint: 'https://auth.files.example/token', clientId: 'acme', clientSecret: filesSecret, assertion });

// Kendi yetkilendirme sunucunuz (jwt-bearer): bir kez kullanılır
const claims = await new IdJagVerifier({ issuer: 'https://sso.touchque.com', audience: 'https://auth.files.example' })
  .verify(form.assertion, { clientId: authenticatedClientId });

// Başka bir ajanın A2A kartı
await verifyAgentCard(card, { cardUrl: 'https://agent.example/.well-known/agent-card.json' });
Sürekli izinler ve dört göz
// Bir kez sor: en çok 5 fatura, toplam 10.000 TRY, bu IBAN, 24 saat
const m = await agent.requestMandate({
  user: 'jane@example.com', type: 'PAY_INVOICE', maxCount: 5,
  maxTotal: { currency: 'TRY', amount: '10000.00' }, perRequest: '2500.00',
  recipients: ['TR33 0006 1005 1978 6457 8413 26'], validFor: 86400,
});
reply(`Type ${m.challengeCode} in the Touchque app.`);

// Etkinleşince: her ödeme itme olmadan onaylanır, atomik olarak sayılır
const ask = await agent.requestApproval({ user: 'jane@example.com', type: 'PAY_INVOICE',
  authorizationDetails: [payment], mandateId: m.mandateId });
// ask.status === "approved", token yanıtta; redeemApproval aynı

await tq.agents.setPolicy(agentId, { fourEyes: { approvers: ['cfo@acme.com'], above: { TRY: '5000' } } });
POST /agents/token 200
{
  "access_token": "tqat_…",
  "token_type": "DPoP",
  "expires_in": 600,
  "scope": "agent:read approvals:request approvals:read"
}