(score.kyde · free)
Know when your agents go rogue.
Your agents run where you can't watch them, in your clients' networks. Point their OpenTelemetry at KYDE. When one behaves strangely, you get a webhook.
- OpenTelemetry in
- Webhook out
- No SDK
- Metadata only
- No LLM in the loop
OpenTelemetry in. A webhook out. Nothing in between.
- You send
- OpenTelemetry over OTLP/HTTP (JSON) to https://score.kyde.com. From any OTel SDK, an OTel Collector or Claude Code. Scoring reads log events today; traces and metrics are accepted.
- Auth
- One header: x-kyde-key. Nothing else to configure.
- Registering agents
- Nothing to register. Each agent is identified by its OpenTelemetry service.name and appears with its first data. One key covers all your agents.
- You get
- A webhook POST with a JSON body when an agent's band changes, HMAC-SHA256 signed with your key.
- You can pull
- The current score of every agent, as JSON: GET /score/v0/scores. Every score carries its method_version.
- Your agent waits on KYDE
- Never. Export is asynchronous. If KYDE is down, your agents run exactly as before.
- How it scores
- Deterministic statistics, no LLM. Same records, same score. Recompute any verdict yourself.
- Code changes
- None. No SDK, no wrapper, no proxy in the call path.
- Leaving
- DELETE /score/v0/keys with your key. The key and every record under it are gone. There is no account to close, because there was no account.
- Price
- Free hosted. The detectors are open source if you would rather run them yourself.
Three environment variables. That's the integration.
-
(Step 1) Get a key
POST the URL that should receive alerts. You get the key back in the response, together with the method version your scores will carry.
curl -X POST https://score.kyde.com/score/v0/keys \ -H "Content-Type: application/json" \ -d '{"webhook_url":"https://your.app/hooks/kyde"}' # → {"key":"kyde_…","method_version":"…"} -
(Step 2) Point your exporter at KYDE
Whatever already speaks OTLP. Run the Collector in your client's network to strip content before it leaves.
export OTEL_EXPORTER_OTLP_ENDPOINT=https://score.kyde.com export OTEL_EXPORTER_OTLP_PROTOCOL=http/json export OTEL_EXPORTER_OTLP_HEADERS="x-kyde-key=<YOUR_KEY>"export CLAUDE_CODE_ENABLE_TELEMETRY=1 export OTEL_LOGS_EXPORTER=otlp export OTEL_EXPORTER_OTLP_PROTOCOL=http/json export OTEL_EXPORTER_OTLP_ENDPOINT=https://score.kyde.com export OTEL_EXPORTER_OTLP_HEADERS="x-kyde-key=<YOUR_KEY>"processors: attributes/kyde: # content never leaves actions: - { key: gen_ai.prompt, action: delete } - { key: gen_ai.completion, action: delete } - { key: gen_ai.tool.call.arguments, action: hash } exporters: otlphttp/kyde: endpoint: https://score.kyde.com encoding: json headers: { x-kyde-key: "<YOUR_KEY>" } -
(Step 3) Read the scores
KYDE learns each agent's baseline over its first 30 runs, then freezes and fingerprints it. From then on, a band change sends one POST — or poll whenever you like.
curl -s https://score.kyde.com/score/v0/scores \ -H "x-kyde-key: <YOUR_KEY>" # → {"agents":[{"service_name":"invoice-agent","status":"scored", # "score":92,"band":"normal","runs_seen":41,…}]}
An LLM watching your LLM drifts too.
A model that judges your agent changes with every update, just like the agent. Then you are watching one drifting system with another, and nobody can say which of the two moved.
KYDE scores with plain statistics against a frozen, fingerprinted baseline: CUSUM for sudden shifts, Jensen-Shannon divergence for slow drift. No model calls, no GPU, no token cost per score.
Every score names the baseline and the method version it was computed with. Run the open-source detectors on the same records and you get the same number. A disputed score is settled by recomputing it, not by trusting us.
Read the paper → Detection approaches surveyed, and the case for deterministic detection.
Three ways a good agent goes bad.
(Hijack)
It starts doing new things.
An agent suddenly calls tools it rarely or never called before. The pattern a prompt injection in an email or a web page tends to leave.
CUSUM on the surprisal of each call against the baseline.
reason abrupt_shift
(Loop)
It does the same thing again and again.
The same tool with the same parameters, over and over. Runaway retries, double submissions, a token bill at 3 a.m.
Duplicate calls counted within a run.
reason duplicate_submission
(Drift)
It slowly stops being itself.
The mix of actions moves away from the baseline, often after a model update nobody told you about.
Windowed Jensen-Shannon divergence on the action distribution.
reason gradual_drift
Read the detectors → Python standard library only.
*An unusual pattern is not proof of an attack. Detection depends on the drift type and the records available.
Call metadata. Never the conversation.
No prompts, no model outputs, no raw parameters. A deny-by-default allowlist scrubs attributes before anything is stored — and you can delete or hash them in the Collector before export, and KYDE still scores. The hosted service runs in the EU.
- Timestampwhen the call happened
- Run ID and step numberwhich task, which position in it
- Tool namewhat the agent did
- Hash of the parametersrepeats are visible, the content is not
- Statusok, error or abort
- Model and model versiondrift after an update
Agents change. The logs rarely say so.
Public agent records, reproducible methods, every number linked to its results file. These show observable shifts and gaps in error reporting, not attack-detection rates in production.
| Public records | Observation |
|---|---|
| OpenHands submissions: Kimi K2 vs. GPT-5, July and August 2025 | Tool-use distributions differed by a Jensen-Shannon divergence of 0.105. Results |
| SWE-agent submissions: GPT-4 vs. Claude 3.5 Sonnet, April and June 2024 | Tool-use distributions differed by 0.116. Results |
| SWE-agent submissions: Claude 3.5 Sonnet vs. GPT-4o, June and July 2024 | Tool-use distributions differed by 0.091. Results |
| GAIA agent, o3-mini (TRAIL): 117 runs, 3,579 calls | Calls with an error status rose from 2.1% in steps 0 to 9 to 25.5% in steps 30 to 39. Results |
| GAIA and SWE-bench traces (TRAIL): 148 runs with human error annotations | Only 5.8% and 5.5% of the errors humans annotated also carried an error status in the trace. Results |
*The SWE-agent and OpenHands rows compare submissions with different models, not one deployment over time. Code, paper and results →
Is this an API or a webhook?
Both, in one direction each. Your agents push OpenTelemetry to KYDE, KYDE pushes an alert to your webhook. If you would rather poll, the current score of every agent is a JSON record you can GET.
How do I add an agent?
Start it with the environment variables above. KYDE knows it by its OpenTelemetry service.name, so give each agent its own (OTEL_SERVICE_NAME=invoice-agent). It shows up with its first data and starts learning its baseline. No form, no dashboard, no registration call.
What does the score mean?
A number from 0 to 100 for how close an agent's behavior is to its own baseline. 70 and above is normal, 40 to 69 is watch, below 40 is deviating. You get an alert when the band changes, not on every unusual call. It is a signal for triage, not a probability that an agent was compromised.
Does it detect prompt injection?
It detects what a hijacked agent does next: tools it does not normally use, in an order it does not normally use them. From metadata alone it cannot prove an attack, and it will not catch an injection that changes nothing the agent does. The published results show where the detectors work and where they do not.
I run agents for clients, inside their networks. Does that work?
That is the case it is built for. The agent exports from wherever it runs, and the alert goes to you, the team that deployed it. Only call metadata leaves the client's network, and you can strip it further in their Collector before it does.
Will I get false alarms?
Sometimes. Alerts fire on band changes after a baseline of 30 runs, which keeps the noise down. We publish detector results, false-alarm rates included where we have them, so you can judge the fit before you rely on it.
Why is it free?
Real operational records show us how agents behave outside benchmarks, and that makes the detectors better. What we sell is the same scoring inside your own infrastructure, plus blocking and quarantine.
Can I run it myself?
Yes. The reference detectors are open source and use only the Python standard library. Same records, same score. No LLM in the scoring path.
How do I leave?
DELETE /score/v0/keys with your key in the x-kyde-key header. That removes the key and every record stored under it, in one request. Stored data expires on a retention schedule either way.
Find out before your client does.
Three environment variables. One webhook.
Free · No SDK · Open-source detectors