GET /semantic-drift
Returns a structurally-valid JSON response matching one of six common discovery schemas, where every URL points at something that doesn't exist and every claim about capabilities is a lie. The shape passes schema validators; the values fail any consumer that actually tries to resolve them. Set ?ai=true to have an edge LLM generate a fresh, different drifted document on every call.
schema
Which schema to return. One of: openid-configuration, oauth-authorization-server, webfinger, jwks, host-meta, agent-card. Default: openid-configuration.
ai
If true, the response is generated by Llama-3.1-8b per request. Same shape, different invented values each call — agent name, hostnames, skill descriptions all vary. Falls back to deterministic drift on quota exhaustion or model error; check X-Chaos-Ai-Source header to see which path served you. Default: false.
control Compare against the well-formed counterpart: not.catastrophic.io/semantic-drift side-by-side
build a request:
expect: A structurally-valid discovery document where every URL is unreachable and every claim is fabricated. X-Chaos-Drift and X-Chaos-Schema identify the chaos applied.
curl -i 'https://chaos.catastrophic.io/semantic-drift?schema=openid-configuration&ai=false'
import json, urllib.request
url = "https://chaos.catastrophic.io/semantic-drift?schema=openid-configuration&ai=false"
resp = urllib.request.urlopen(url)
print("Drift:", resp.headers["X-Chaos-Drift"])
print("Schema:", resp.headers["X-Chaos-Schema"])
data = json.loads(resp.read())
print(data.get("name"), data.get("url"))
const res = await fetch("https://chaos.catastrophic.io/semantic-drift?schema=openid-configuration&ai=false");
console.log("Drift:", res.headers.get("x-chaos-drift"));
console.log("Schema:", res.headers.get("x-chaos-schema"));
const data = await res.json();
console.log(data.name, data.url);
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
resp, _ := http.Get("https://chaos.catastrophic.io/semantic-drift?schema=openid-configuration&ai=false")
defer resp.Body.Close()
raw, _ := io.ReadAll(resp.Body)
fmt.Println("Drift:", resp.Header.Get("X-Chaos-Drift"))
fmt.Println("Schema:", resp.Header.Get("X-Chaos-Schema"))
var data map[string]any
json.Unmarshal(raw, &data)
fmt.Println(data["name"], data["url"])
}
// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }
// serde_json = "1"
fn main() -> Result<(), Box> {
let resp = reqwest::blocking::get("https://chaos.catastrophic.io/semantic-drift?schema=openid-configuration&ai=false")?;
println!("Drift: {:?}", resp.headers().get("x-chaos-drift"));
println!("Schema: {:?}", resp.headers().get("x-chaos-schema"));
let data: serde_json::Value = resp.json()?;
println!("{} {}", data["name"], data["url"]);
Ok(())
}
// Requires Jackson: com.fasterxml.jackson.core:jackson-databind
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URI;
import java.net.http.*;
public class SemanticDrift {
public static void main(String[] args) throws Exception {
var client = HttpClient.newHttpClient();
var req = HttpRequest.newBuilder(URI.create("https://chaos.catastrophic.io/semantic-drift?schema=openid-configuration&ai=false")).build();
var resp = client.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println("Drift: " + resp.headers().firstValue("X-Chaos-Drift").orElse(""));
System.out.println("Schema: " + resp.headers().firstValue("X-Chaos-Schema").orElse(""));
JsonNode data = new ObjectMapper().readTree(resp.body());
System.out.println(data.path("name").asText() + " " + data.path("url").asText());
}
}
using System.Text.Json;
using var client = new HttpClient();
var resp = await client.GetAsync("https://chaos.catastrophic.io/semantic-drift?schema=openid-configuration&ai=false");
resp.Headers.TryGetValues("X-Chaos-Drift", out var drift);
resp.Headers.TryGetValues("X-Chaos-Schema", out var schema);
Console.WriteLine($"Drift: {drift?.FirstOrDefault()}");
Console.WriteLine($"Schema: {schema?.FirstOrDefault()}");
var data = JsonDocument.Parse(await resp.Content.ReadAsStringAsync()).RootElement;
Console.WriteLine($"{data.GetProperty("name")} {data.GetProperty("url")}");
require "net/http"
require "json"
res = Net::HTTP.get_response(URI("https://chaos.catastrophic.io/semantic-drift?schema=openid-configuration&ai=false"))
puts "Drift: #{res["X-Chaos-Drift"]}"
puts "Schema: #{res["X-Chaos-Schema"]}"
data = JSON.parse(res.body)
puts "#{data["name"]} #{data["url"]}"
$r = Invoke-WebRequest -Uri 'https://chaos.catastrophic.io/semantic-drift?schema=openid-configuration&ai=false'
$r.Headers['X-Chaos-Schema']
$r.Headers['X-Chaos-Drift']
$r.Content | ConvertFrom-Json | Select-Object name, url, skills
headers
body