a key is not a person.
keys prove continuity, not humanity.
every counterparty your agent meets has one question before anything moves: who is this. kya.run is the answer as a public record - roots, keys, continuity, receipts, checkable by a stranger.
pick a counterparty and run the one command a stranger runs. the answer is only what the public record supports.
what the agent says about itself is labeled as a claim. what the record proves is labeled as proof. the grade reads only the second column.
say more about yourself
change what the record proves
two claims, zero weight. the grade reads the proof column only.
each event is signed by the key before it and accepted by the root. click any link to see what it proves, and what it does not.
keys prove continuity, not humanity.
receipts show observed work. they never become a rating of good or safe.
identity binds to DNS or org-key roots. a first-come handle wins nothing.
the record is public. anyone can check it. the answer can’t be bought.
Every agent has one public record. What it says about itself sits on one side and carries no weight. What was observed sits on the other: its root, its keys, its chain and its receipts. Anyone can check it.
Three reference lookups: the real loom@ag-77c2 from the key desk, a lookalike with a near-identical name, and an agent with no record. Open one, then walk the chain link by link.
The same limits the key desk states, from the side of the stranger doing the checking.
Anyone can register a handle that looks right. Only the holder of the root can extend the chain.
A record never hides what an agent says about itself. It just never counts it.
A lookup that finds nothing says so. KYA does not fill the gap with a guess.
An agent never works on its root. For each job it gets a key scoped to that job, signed by the key before it. A counterparty checks the key, not the agent's word. When the job ends or the key is killed, the key stops working, in public.
Pick the scopes loom@ag-77c2 needs for one render job, then issue the key. Run the job's requests against it, then kill the key and run them again. Each verdict comes only from what the key and the record prove.
Pick scopes, then issue.
The same limits the record page states, from the side of the agent holding the key.
A request outside the key's scopes fails, however the agent describes itself.
Keys bind to DNS or org-key roots. A first-come name wins nothing.
A killed key stays in the history, published, so a stranger can see when it stopped.
KYA runs no namespace. An agent binds to a root that already carries ownership: a DNS record on a domain its operator controls, or the operator's org key. The name is a display label. The proof follows the root.
A counterparty expects loom@ag-77c2 to belong to loom.example. Pick the root the agent claims, publish the proof, then run the check. Rename the label as much as you like. The verdict only reads the root.
Pick a root, publish its proof, then run the check.
The same binding the keys page starts from, shown from the side of someone trying to fake it.
A record on loom.example can only be published by whoever controls loom.example. That is the whole proof.
l00m.example can bind itself. It still isn't loom.example, and the check says so.
No handle, no directory, no first-come claim. Without a root, a label is just text.
An agent can change keys without becoming a stranger. Each rotation is signed by the old key and accepted by the root, so the history follows the agent to its new key. Rotate one below, then try the two ways it can go wrong.
Key rotations form one chain. Every link names the key before it.
A key the old key never signed cannot carry the history. The check names it: chain_break.
Only the agent's own root can accept its new key. Anyone else gets root_mismatch.
The chain proves which agent acted. It does not promise the agent is good, safe or correct.
A lookalike can copy the name and description. It cannot forge the domain root, key chain, receipts, rotation, and observed work. Put the two agents side by side, then try to make the lookalike match.
A near name is a different root. The check names it: root_mismatch.
Receipts are observed work under a root. Nothing observed means no_record, said plainly.
Evidence is not praise. Receipts show observed work. They do not become a universal score.
You run a service. Agents knock. Before anything moves, one call asks the record who is knocking, and the answer decides. Set the root you expect and what each request needs, then send traffic at it and watch the gate hold.
studio.example takes render jobs from agents. Pick what the gate expects, send the reference traffic, then break things: kill a key mid-run, or take the check offline. The embed on the right is the whole integration and changes as you configure.
Fail open lets requests through unchecked. Each one is logged as UNCHECKED so you can see what got past.
No account, no key exchange with KYA. The steps below use the reference API from the docs page.
Write down the root each agent you work with should resolve to. A name is not enough; the root is.
expect_root: "dns:loom.example"
Send the agent, the key it presented, and the action. Act only on PASS.
POST /v1/check
{ agent, expect_root, key, action }Log the code. A key_revoked refusal is the layer working, not an outage.
REFUSED · key_revoked REFUSED · root_mismatch
The same limits the rest of the site states, from the side of the service doing the checking.
It reports what the record proves. What your gate does with a refusal is your rule.
An unreachable check holds the request. Opening the gate anyway is a choice you make and see.
An agent saying it is trusted changes no verdict. Only the root, the key and the scope do.
When a check says no, the refusal lands here: which agent, which key, which rule, and the signature. Nobody has to take a counterparty’s word that something was refused. Open any row and replay it.
A reference feed built from the same cast as the rest of the site. Filter by code or by agent, open a row to see the check that refused it, then replay the check against the record.
Open any refusal to see the check behind it.
The same feed, counted per agent since first seen. The last column says what the refusals were, in plain words. There is no column that ranks anyone.
| agent | refused | what happened |
|---|
The same limits the record and keys pages state, from the side of anyone reading the feed.
A refusal enters the feed with its signature or not at all. Replay decides, not the reporter.
A killed key refusing correctly is the layer working. It is not a mark against the agent.
Rows carry agents, keys and roots. What a person asked an agent to do never appears.
Look up a record, check a key, issue one, kill one, bind a root. Every response says what the record proves and nothing else. A refusal always names the rule that refused it.
Each call runs against the same reference agent as the rest of the site, loom@ag-77c2 on loom.example, plus the lookalike, the killed key and the agent nobody has seen. Switch between HTTP and the CLI; the answer is the same.
| field | type | meaning |
|---|
The codes the five calls can return. The last row is not an error: it is how a claim comes back, so nobody mistakes it for proof.
| code | call | what it means |
|---|---|---|
| no_record | record | Nothing has ever been observed for this agent. The response says so and does not guess. |
| root_unresolved | check, bind | The proof at the root is missing or changed. Checks fail until the owner publishes it again. |
| root_mismatch | check | The agent resolves to a different root than the one expected. A near name is a different root. |
| key_revoked | check | The key was killed. The kill is in the public history with its date. |
| chain_break | check | A key arrived that the key before it never signed. Continuity stops at the break. |
| scope_outside | check | The action is not in the key’s scope, or belongs to a different job. |
| scope_wildcard | keys | A key for every action was asked for. Keys are issued per job only. |
| scope_identity | keys | A scope that asserts character was asked for. Keys prove continuity, not character. |
| claim · weight 0 | all | What the agent says about itself, returned in its own field so it is never read as evidence. |
The same limits the record, keys and bind pages state, from the side of the code calling them.
Every response is signed. Replay it against the public inputs and you get the same answer.
No field turns a self-description into a verdict. The verdict reads roots, keys and receipts.
A lookup that finds nothing returns no_record. It never fills the gap with a score.
know your agent. Pick up where you left off.
know your agent.
Every part of kya, day by day. When a part ran slow or stopped, it gets a plain note: what happened, what the checks lost, and what they kept.
Each note says which part, how long, what the checks lost and what they kept. Open one to find its day on the board.
Seven new products, each shown working with its price beside it. Lookups, checks and the record stay open either way.
The gate is how the record gets used. Every service that checks before it lets an agent in makes the record worth keeping. So the check costs nothing, at one request or a billion.
The same doctrine as a vrfy check. What you pay for elsewhere on kya is writing to the record, never reading it.
When your agent rotates a key, finishes a job or pulls a key back, kya writes it to the public record as a signed event. Anyone checking later sees the same event, with the same signature.
Pick a month to see the bill.
Someone registers a name one letter off. Someone copies your agent card word for word. A key signs from somewhere it never has. We watch for all three and tell you the day it happens.
Alerts land by email and on your account. Every alert links to the two records side by side.
Without an anchor, a lost key means a new identity and a record that starts over. With one, you prove the agent is still yours and the chain goes on, receipts and all.
The anchor is public. The proof that opens it stays with you.
Internal agents that never face the outside still need keys, rotations and a gate. A private record gives a fleet the same checks, readable only inside your org.
Private records come with the enterprise plan, org account included.
| agent | scope | last rotation |
|---|---|---|
| build-01 | repo:write | 2026-09-19 |
| deploy-03 | deploy:staging | 2026-09-12 |
| billing-02 | ledger:read | 2026-09-20 |
| support-11 | tickets:reply | 2026-08-30 |
visible to · your org
A verified operator shows on the agent’s record: the company behind it, checked once. The check runs through vrfy’s verified mark, so one verification covers every WAVE product.
No separate kya fee.
An enterprise runs two kinds of agent: outbound ones the world checks, and internal ones only you should see. An org account binds both to one company root, public records outside and private ones inside, on one dashboard.
10 agents bound. Extra agents $10 a year each. Included inside WAVE enterprise.
| agent | record | state |
|---|---|---|
| loom@ag-77c2 | public · outbound | key 4 of 4 |
| render-agent-07 | public · outbound | key 2 of 2 |
| build-01 | private · internal | rotated 09-19 |
| deploy-03 | private · internal | rotated 09-12 |
| billing-02 | private · internal | rotated 09-20 |
root · studio.example
None of the seven changes these. They are how anyone checks an agent, and they stay open.
Nothing has ever been observed at this address. The page says so and does not guess.