Sign
Every agent gets a key, bound to the person or team that runs it. Every request it sends is signed with HTTP Message Signatures (RFC 9421), so the chain from person to agent to request can be checked.
Prompt injections, cloned voices and lookalike agents all fake the same thing: authority. Spoofed makes every high-risk action carry a signature from the person who asked for it, so a fooled agent still can't move money, send mail or delete data.
curl https://spoofed.ai/llms.txtFaces, voices, writing style, agent names, tool descriptions: models produce all of them on demand, and detectors lose ground with every new generator. A signature is different. No model, however good, can produce one without the key.
Every agent gets a key, bound to the person or team that runs it. Every request it sends is signed with HTTP Message Signatures (RFC 9421), so the chain from person to agent to request can be checked.
High-risk tools run only with a mandate: a short-lived signature over the exact call. For the riskiest, a real person approves with a passkey, and what they see is what they sign.
Any service can check a mandate with public keys, offline. Keys stay on your devices and servers, so not even Spoofed can sign for you.
Some channels can't carry a signature yet: phone calls, video meetings, a scanned ID. There, Spoofed scores media for signs of generation and reports it as a signal, never as the guarantee.
import { Spoofed } from "@spoofed/sdk";
const spoofed = new Spoofed({ apiKey: process.env.SPOOFED_API_KEY });
// The tool now runs only with a mandate for this exact call.
export const transfer = spoofed.gate("payments.transfer", {
approval: "passkey", // a real person signs the amount and payee
run: ({ amount, to }) => bank.transfer({ amount, to }),
});
// On the receiving side: check it offline, with public keys.
const mandate = await spoofed.verify(request);
if (!mandate.valid) return deny(mandate.reason);Without a mandate, the call is refused with a reason an agent can act on:
{
"decision": "deny",
"reason": "no_mandate",
"action": "payments.transfer",
"params": {
"amount": 48000,
"to": "acct_••4471"
},
"agent": {
"id": "billing-agent@acme",
"signature": "valid"
},
"mandate": null,
"next": "request_approval",
"request_id": "req_01JA7XK2Q9"
}Proof over prediction.
Guarantees come from signatures. Detection scores are labeled as signals, and never decide on their own.
Keys stay with you.
Private keys live on your devices and servers. Verification needs only public keys, so it works without us.
What you see is what you sign.
An approval shows the exact action and is bound to its parameters. Change the amount or the payee, and the signature fails.
Honest about limits.
A compromised device can still sign, and ungated tools stay reachable. We show which actions are protected and which aren't.
We're working with teams whose agents touch money, mail, records or production. Tell us what yours can do, and we'll help you gate it.