Stebėti DI agentus
DI naršyklės — nuo GPTBot iki ClaudeBot ir PerplexityBot — skaito jūsų svetainę kasdien, ir dauguma svetainių savininkų to niekada nemato. Stebėjimo režimas yra SilentShield DI agentų kontrolės 1 lygis: jis registruoja, kurios DI paslaugos lankosi kuriuose puslapiuose — nieko neblokuodamas ir nekeisdamas jūsų svetainės veikimo.
Matomumas eina pirmiau nei kontrolė: tik žinodami, kas skaito jūsų turinį, galite pagrįstai nuspręsti, ką leisti, riboti ar blokuoti. Todėl kiekvienas apsilankymas priskiriamas vienai iš trijų kategorijų:
- Mokymas
- Naršyklė renka jūsų turinį būsimiems DI modeliams mokyti (pvz., GPTBot, ClaudeBot, CCBot).
- DI paieška
- Paslauga skaito puslapius, kad atsakytų į naudotojų klausimus, ir gali cituoti jūsų svetainę kaip šaltinį (pvz., OAI-SearchBot, PerplexityBot).
- Agentai
- Botas realiuoju laiku veikia konkretaus naudotojo pavedimu, pavyzdžiui, tiria produktą ar užpildo formą jūsų svetainėje (pvz., ChatGPT-User, Claude-User).
Sąranka pagal platformą
WordPress
Integruotas observer atkeliaus su būsimu SilentShield papildinio atnaujinimu. Iki tol stebėjimą aktyvuokite mažu must-use papildiniu — vienas failas, jokios konfigūracijos:
Sukurkite failą wp-content/mu-plugins/silentshield-observer.php su šiuo turiniu (mu-papildiniai įkeliami automatiškai; norėdami išjungti, failą ištrinkite):
<?php
/**
* Plugin Name: SilentShield — AI Agent Observer
* Description: Reports AI crawler visits to SilentShield (fire-and-forget;
* IP/UA are hashed server-side, GDPR). Delete this file to disable.
*
* Install: save this file as wp-content/mu-plugins/silentshield-observer.php
* (mu-plugins load automatically — no activation needed). To force it off
* without deleting: define('SILENTSHIELD_OBSERVER', false) in wp-config.php.
* An upcoming SilentShield plugin update will build this in.
*/
if (!defined('ABSPATH')) exit;
if (defined('SILENTSHIELD_OBSERVER') && !SILENTSHIELD_OBSERVER) return;
const SS_OBSERVE_URL = "https://api.silentshield.io/api/v1/agent/telemetry";
const SS_API_KEY = "YOUR_API_KEY"; // publishable site key
// For the always-fresh list, cache https://api.silentshield.io/api/v1/agent/bot-directory daily.
$ss_bots = ["GPTBot","OAI-SearchBot","ChatGPT-User","ClaudeBot","Claude-User",
"PerplexityBot","Perplexity-User","Bingbot","Applebot","Amazonbot","CCBot",
"Bytespider","meta-externalagent","Google-Agent"];
register_shutdown_function(function () use ($ss_bots) {
$ua = $_SERVER["HTTP_USER_AGENT"] ?? "";
$signed = !empty($_SERVER["HTTP_SIGNATURE"]);
$isBot = $signed;
foreach ($ss_bots as $b) { if (stripos($ua, $b) !== false) { $isBot = true; break; } }
if (!$isBot) return;
if (function_exists("fastcgi_finish_request")) { fastcgi_finish_request(); }
wp_remote_post(SS_OBSERVE_URL, [
"timeout" => 3,
"blocking" => false,
"headers" => ["Content-Type" => "application/json", "x-api-key" => SS_API_KEY],
"body" => wp_json_encode(["sightings" => [[
"ua" => $ua,
"ip" => $_SERVER["REMOTE_ADDR"] ?? "",
"path" => strtok($_SERVER["REQUEST_URI"] ?? "/", "?"),
"method" => $_SERVER["REQUEST_METHOD"] ?? "GET",
]]]),
]);
});Next.js
Savarankiškas middleware — be SDK. Stebėjimas vyksta per event.waitUntil(), už atsakymo kelio ribų, todėl jūsų puslapių niekada nelėtina:
// middleware.ts — self-contained observer, no SDK required.
// Sightings are reported via event.waitUntil(), off the response path,
// so your pages never wait. Best-effort and fail-open by design.
import { NextResponse, type NextRequest } from "next/server";
const OBSERVE_URL = "https://api.silentshield.io/api/v1/agent/telemetry";
const API_KEY = "YOUR_API_KEY"; // publishable site key
// Known AI-agent UA tokens. For the always-fresh list, fetch
// https://api.silentshield.io/api/v1/agent/bot-directory once a day and cache it.
const BOTS = ["GPTBot", "OAI-SearchBot", "ChatGPT-User", "ClaudeBot", "Claude-User",
"PerplexityBot", "Perplexity-User", "Bingbot", "Applebot", "Amazonbot", "CCBot",
"Bytespider", "meta-externalagent", "Google-Agent"];
export function middleware(req: NextRequest, event: { waitUntil(p: Promise<unknown>): void }) {
const ua = req.headers.get("user-agent") ?? "";
const signed = !!req.headers.get("signature");
if (signed || BOTS.some((b) => ua.toLowerCase().includes(b.toLowerCase()))) {
const sighting = {
ua,
path: req.nextUrl.pathname,
method: req.method,
ip: req.headers.get("x-forwarded-for")?.split(",")[0]?.trim(),
...(signed && {
signature: req.headers.get("signature"),
signature_input: req.headers.get("signature-input"),
signature_agent: req.headers.get("signature-agent"),
authority: req.nextUrl.host,
scheme: req.nextUrl.protocol.replace(":", ""),
}),
};
event.waitUntil(
fetch(OBSERVE_URL, {
method: "POST",
headers: { "Content-Type": "application/json", "x-api-key": API_KEY },
body: JSON.stringify({ sightings: [sighting] }),
}).catch(() => {}) // best-effort, fail-open
);
}
return NextResponse.next();
}Node.js (Express)
Express (ar bet kuriam kitam Node serveriui) pridėkite „fire-and-forget“ middleware. Jis praneša tik apie užklausas, kurių User-Agent atitinka žinomą DI agentą arba kurios turi Web Bot Auth parašą — ir niekada neblokuoja atsakymo:
import express from "express";
const app = express();
const OBSERVE_URL = "https://api.silentshield.io/api/v1/agent/telemetry";
const API_KEY = "YOUR_API_KEY";
// Known AI-agent UA tokens. For the always-fresh list, fetch
// https://api.silentshield.io/api/v1/agent/bot-directory once a day and cache it.
const BOTS = ["GPTBot", "OAI-SearchBot", "ChatGPT-User", "ClaudeBot", "Claude-User",
"PerplexityBot", "Perplexity-User", "Bingbot", "Applebot", "Amazonbot", "CCBot",
"Bytespider", "meta-externalagent", "Google-Agent"];
// Fire-and-forget observer — never blocks the response.
app.use((req, res, next) => {
const ua = req.headers["user-agent"] || "";
const signed = !!req.headers["signature"];
if (signed || BOTS.some((b) => ua.toLowerCase().includes(b.toLowerCase()))) {
const sighting = {
ua, ip: req.ip, path: req.path, method: req.method,
...(signed && {
signature: req.headers["signature"],
signature_input: req.headers["signature-input"],
signature_agent: req.headers["signature-agent"],
authority: req.headers["host"], scheme: req.protocol,
}),
};
fetch(OBSERVE_URL, {
method: "POST",
headers: { "Content-Type": "application/json", "x-api-key": API_KEY },
body: JSON.stringify({ sightings: [sighting] }),
}).catch(() => {}); // best-effort, fail-open
}
next();
});PHP
Gryname PHP šį stebėtoją įtraukite pačiame front controller viršuje. Jis apsilankymą išsiunčia tik po to, kai atsakymas jau pristatytas (fastcgi_finish_request), todėl puslapis niekada nesulėtėja:
<?php
// Drop-in observer: include at the very top of your front controller.
// It runs after the response is sent (fastcgi_finish_request) so it never
// slows down the page. Reuses the same publishable key.
const SS_OBSERVE_URL = "https://api.silentshield.io/api/v1/agent/telemetry";
const SS_API_KEY = "YOUR_API_KEY";
// For the always-fresh list, cache https://api.silentshield.io/api/v1/agent/bot-directory daily.
$ss_bots = ["GPTBot","OAI-SearchBot","ChatGPT-User","ClaudeBot","Claude-User",
"PerplexityBot","Perplexity-User","Bingbot","Applebot","Amazonbot","CCBot",
"Bytespider","meta-externalagent","Google-Agent"];
register_shutdown_function(function () use ($ss_bots) {
$ua = $_SERVER["HTTP_USER_AGENT"] ?? "";
$signed = !empty($_SERVER["HTTP_SIGNATURE"]);
$isBot = $signed;
foreach ($ss_bots as $b) { if (stripos($ua, $b) !== false) { $isBot = true; break; } }
if (!$isBot) return;
if (function_exists("fastcgi_finish_request")) { fastcgi_finish_request(); }
$sighting = [
"ua" => $ua,
"ip" => $_SERVER["REMOTE_ADDR"] ?? "",
"path" => strtok($_SERVER["REQUEST_URI"] ?? "/", "?"),
"method" => $_SERVER["REQUEST_METHOD"] ?? "GET",
];
$ch = curl_init(SS_OBSERVE_URL);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 3,
CURLOPT_HTTPHEADER => ["Content-Type: application/json", "x-api-key: " . SS_API_KEY],
CURLOPT_POSTFIELDS => json_encode(["sightings" => [$sighting]]),
]);
curl_exec($ch); // best-effort, fail-open
curl_close($ch);
});Go
Savarankiškas observer keliomis eilutėmis — tik standartinė biblioteka, be SDK. Aptikimai siunčiami fire-and-forget būdu, todėl nė viena užklausa nesulėtėja:
// Self-contained observer — stdlib only, no SDK required.
// Reports AI-agent sightings fire-and-forget: never blocks a request,
// fail-open on any error. For the always-fresh bot list, cache
// https://api.silentshield.io/api/v1/agent/bot-directory daily.
const observeURL = "https://api.silentshield.io/api/v1/agent/telemetry"
const siteKey = "YOUR_API_KEY" // publishable — or os.Getenv("SILENTSHIELD_SITE_KEY")
var bots = []string{"GPTBot", "OAI-SearchBot", "ChatGPT-User", "ClaudeBot",
"Claude-User", "PerplexityBot", "Perplexity-User", "Bingbot", "Applebot",
"Amazonbot", "CCBot", "Bytespider", "meta-externalagent", "Google-Agent"}
func observe(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ua, signed := r.UserAgent(), r.Header.Get("Signature") != ""
hit := signed
for _, b := range bots {
if strings.Contains(strings.ToLower(ua), strings.ToLower(b)) {
hit = true
break
}
}
if hit {
ip, _, _ := net.SplitHostPort(r.RemoteAddr)
s := map[string]any{"ua": ua, "ip": ip, "path": r.URL.Path, "method": r.Method}
if signed { // Web Bot Auth (RFC 9421) — forward for verification
s["signature"] = r.Header.Get("Signature")
s["signature_input"] = r.Header.Get("Signature-Input")
s["signature_agent"] = r.Header.Get("Signature-Agent")
s["authority"] = r.Host
}
body, _ := json.Marshal(map[string]any{"sightings": []any{s}})
go func() { // best-effort, fail-open
req, _ := http.NewRequest("POST", observeURL, bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("x-api-key", siteKey)
if resp, err := (&http.Client{Timeout: 3 * time.Second}).Do(req); err == nil {
resp.Body.Close()
}
}()
}
next.ServeHTTP(w, r)
})
}
// net/http: http.ListenAndServe(":8080", observe(mux))
// Gin: srv := &http.Server{Addr: ":8080", Handler: observe(r)}
// srv.ListenAndServe()Patikrinkite ryšį
Nebūtina laukti pirmosios tikros DI naršyklės, kad įsitikintumėte, jog integracija veikia. Išsiųskite tuščią paketą — jis užregistruoja jūsų rakto „heartbeat“ signalą, neįrašydamas jokių netikrų apsilankymų:
curl -X POST https://api.silentshield.io/api/v1/agent/telemetry \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
--data '{"sightings":[]}'Tuomet jūsų API rakto agentų centras (API raktai → pasirinkite raktą → Agentas) iš „neprijungta“ persijungia į „prijungta — klausomasi“. Jūsų ataskaita lieka tuščia, kol apsilankys tikras agentas: SilentShield niekada neišgalvoja duomenų.
BDAR
Stebėjimas grindžiamas teisėtu interesu (BDAR 6 str. 1 d. f p.). IP adresai serverio pusėje užšifruojami maišos funkcija su kasdien keičiama „salt“ reikšme — neapdoroti IP niekada nesaugomi. Apsilankymai saugomi 14 dienų, o saugomos apskritai tik žinomų DI agentų užklausos: įprastas lankytojų srautas niekada neregistruojamas.
DUK
Ar tai sulėtins mano svetainę?
Ne. Kiekviena integracija veikia „fire-and-forget“ principu: Next.js naudoja event.waitUntil(), PHP praneša tik po atsakymo pristatymo, Node ir Go siunčia fone. O jei SilentShield API kada nors būtų nepasiekiama, jūsų svetainė nenukentės — viskas veikia „fail-open“ principu.
Kas laikoma DI agentu?
Tik užklausos, atitinkančios SilentShield žinomų DI naršyklių ir agentų botų katalogą (GPTBot, ClaudeBot, PerplexityBot, …) arba turinčios Web Bot Auth parašą. Visada aktualų sąrašą rasite adresu https://api.silentshield.io/api/v1/agent/bot-directory.
Kodėl dar nematau duomenų?
DI naršyklės ateina pagal savo grafiką. Daugumoje svetainių pirmieji apsilankymai pasirodo per 24–72 valandas; mažesnėse svetainėse tai gali užtrukti ilgiau. Tuo metu „heartbeat“ signalas jūsų agentų centre patvirtina, kad pati integracija veikia.