a key is not a person.
keys prove continuity, not humanity.
every counterparty your agent meets has one question before anything moves: which agent is this, and which organization runs it? 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.
ROOTED means kya checked control of the root and the key chain. it does not identify the person or company behind the root.
keys prove continuity, not humanity.
receipts show signed 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. no one can pay to change a record. the check reads only root, keys, attestations and revocations, and all of them are public.
Every agent has one public record. What it says about itself sits on one side and carries no weight. What kya checked sits on the other: its root, its keys, its chain and its receipts. Anyone can check it.
Three example 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 result 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 belongs to an organization: the organization's key, or a domain we can confirm the organization holds. Personal domains can't bind. 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 result 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 can’t produce the domain root, key chain, receipts or rotations without the root’s DNS control or private key. 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 signed work under a root. No receipts means no_record, said plainly.
Evidence is not praise. Receipts show signed work. They do not become a universal score.
You run a service. Agents knock. Before anything moves, one call returns what the record proves about the agent’s root, key and scope. Your gate applies your rule. 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 example 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 example 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. Use the result as one input to your access policy.
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 result. Only the root, the key and the scope do.
When a check says no, the refusal lands in a private feed: which agent, which key, which rule, and the signature. Only the agent’s operator and the service that checked can open it. Nobody has to take a counterparty’s word that something was refused. Open any row and replay it.
An example 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.
Only the agent’s operator and the service that checked can see them. KYA never counts them per agent in public.
The same limits the record and keys pages state, from the side of whoever can read the feed.
A refusal enters the feed with its signature or not at all. Replay settles it, not the reporter.
A killed key refusing correctly is the layer working. It is not a mark against the agent.
Rows carry the agent, key, root, code, time and signature. The action and the service that checked are visible only to the agent’s operator and that service.
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 example 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. Claim types: operated_by, model, capability, policy_url. Claims can’t name a person. |
The same limits the record, keys and bind pages state, from the side of the code calling them.
KYA is built so every response is signed. Replay it against the public inputs and you get the same answer.
No field turns a self-description into a result. The result 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.
A name and description are cheap to imitate. Compare the claimed root and keys against the record, then ask whether continuity holds. This desk does not monitor a live feed.
Nothing has ever been observed at this address. The page says so and does not guess.