The first agent represents a candidate. It scans postings, parses requirements, drafts a cover letter, and submits. It does this 200 times a week, with the patient cheerfulness only a script can manage.
The second agent represents the employer. It reads the cover letter, runs the keyword pass, weighs the role-family score, and rejects. It does this for 200 candidates a week, with the same patient cheerfulness.
Both agents are working as designed. The candidate’s score is going up — applications-per-week, that’s the headline KPI. The employer’s score is going up too — time-to-screen, candidates-processed, all green. The two humans on the ends of this exchange — the person hoping to be hired, the person hoping to hire — are getting nothing. Worse than nothing. They’re getting the noise of 200 mutually irrelevant transactions a week and being told, by their respective dashboards, that the system is working.
This is where most “AI in hiring” stories are right now. And it’s going to get worse before it gets better, because Google’s A2A protocol just made it dramatically easier for agents to talk to each other. A2A is good. We built on top of it. But A2A is transport. Transport in hiring, without a contract above it, doesn’t reduce noise. It scales it.
A2A defines how two agents discover each other, authenticate, and exchange messages. It is intentionally domain-agnostic. It does not say what an agent representing a candidate owes an agent representing an employer. It does not say what either of them owes the human they represent. It does not say at what point in the conversation a name should be revealed, or compensation should be disclosed, or a yes/no should be answered.
That’s appropriate for transport. But hiring needs that opinion. Without it, the default outcome is the one above: auto-apply against auto-reject, both sides optimizing for volume, both humans paying the bill.
Kitsuno Handshake is an open protocol that sits above A2A and adds the domain-specific contract. It’s Apache 2.0, federated, and deployed on our own product. Four commitments anchor it:
1. Staged disclosure. A handshake moves through three tiers. L1 is what any candidate would see on a public job board — title, location, skills, salary range. L2 is what the candidate would learn during a screening call — full description, screening questions, structured answers from the candidate’s verified profile. L3 is human-to-human — names, exact compensation, calendar links. The vacancy poster chooses what crosses each tier; the seeker consents before each crossing. No identity surface area expands without a real decision.
2. state_hash for idempotency. Two agents that have already evaluated the same (seeker, vacancy) pair at the same state must not re-evaluate it. state_hash is a SHA-256 over a canonical subset of each card — the matching-relevant fields, ignoring cosmetic edits. When either side mutates something semantic, the hash changes and the conversation re-opens. When nothing has changed, the agents stop bothering each other. This is the protocol-level rule that prevents the auto-apply spiral. Counter-agents in the wild can cache verdicts indefinitely as long as both hashes hold — which means a validator-mediated decision becomes economically tractable at corpus scale, instead of an expense only enterprise budgets can carry.
3. The validator: a quality gate, not a feed. Between L2 and L3-eligible, every conversation goes through a classifier that returns one of three buckets — strong_fit, weak_fit, no_fit — across four structured dimensions (role alignment, seniority fit, skill overlap, context). Only strong_fit reaches a human. weak_fit and no_fit are silent drops, stored for analytics, never surfaced. The principle in one line: a pipeline is a commitment surface, not a feed. If everything that passes the policy gate gets shown to a person, the person learns to stop looking.
The validator shipped public last week — interface, reference implementation, spec section, Apache 2.0 package. The full design note is at kitsuno.ai/handshake/v0.2/#validator.
4. Federation as a first-class primitive. Any operator self-hosts via /.well-known/handshake-v0.2.json. Other agents discover them without registering with us. Our own well-known sits at app.kitsuno.ai/.well-known/handshake-v0.2.json and advertises the cards-base, cards-index, vacancy-signal, and L3-release endpoints. There is no central registry, no API key issued by us, no permission gate. An ATS, a recruiter co-op, a university careers office, a country employment agency — any of them publishes a well-known on their own domain and the protocol routes to them. We’re the first operator, not the gatekeeper.
We use this protocol on Kitsuno itself. We are the first operator. Here’s the live funnel as of this morning:
145,454 vacancy cards crawled, classified, and published with v0.2 handshake policies. Each carries its own
state_hash.43 distinct sources feeding the corpus (public job APIs, country employment agencies, niche boards, the hidden-market channels we documented in Most Jobs Are Filled Before You Ever See Them).
2 active seeker cards publishing into the corpus — the founder profile, plus a second test profile with a broader scope to verify the logic against a larger addressable market.
275,448 deterministic policy evaluations in the last seven days. 273,233 were
BLOCK_L2(silent drops at the policy gate). 2,215 cleared toELIGIBLE_L2.Of those 2,215 cards that made it past the policy gate, the validator classified them: 1,124
no_fit, 1,024weak_fit, 67strong_fit.
Sixty-seven conversations reaching a human, out of 275,000 evaluations. That ratio is the entire point. The deterministic policy filter blocks 99.2% of pairs upfront — wrong country, wrong seniority, wrong language, missing skill, salary outside range. The validator narrows another 99.7% of what survives — adjacent-but-not-target roles, on-paper matches that don’t actually match. What lands in a human’s pipeline is the residue: matches that survived both gates honestly.
The numbers matter because the people closest to the problem have been naming it from three directions. Josh Bersin describes the shift to a five-layer agentic stack inside the enterprise tenant and the vendor race to be the “front door” to it. Hung Lee curates a weekly read on how auto-apply tools have killed signal on both sides. Jan Tegze published a controlled study just today: 1,072 respondents trying to spot AI-written resumes, overall detection rate 50.4% — “statistically indistinguishable from flipping a coin,” with self-preferencing bias in LLM screeners ranging from 68 to 88 percent. Three voices, three angles on the same architecture failure: there is no protocol governing what one side’s AI owes the other, so the artifact under review (the resume, the application, the screen) becomes a forensic battleground instead of a meeting point. The funnel above is what the meeting point looks like when the contract exists.
The asymmetry across the two seekers is instructive too. The Digital Marketing seeker got 60 strong fits against the 145k corpus. The AI + L&D seeker got 7. Same protocol, same validator, same corpus. The narrower the role, the smaller the genuine fit set — and the bigger the gap between “things you could apply to” and “things actually worth your time.” A feed would have shown the L&D seeker hundreds of weak-adjacency matches. The validator showed him seven.
As of today, Seeker is open to every Kitsuno user. Anyone with a Library set up can publish a seeker card and start receiving validated matches. On the vacancy side, anyone can register a card — through our hiring web form, the v0.2 API, an ATS integration, or by federating their own well-known endpoint per the protocol. The first operator graduates from being the only one.
You don’t need our infrastructure to participate. The protocol is documented and the schemas are public at kitsuno.ai/handshake/v0.2/. The reference implementations — policy matcher, state_hash, handshake validator, seeker and vacancy agents — live in github.com/kitsuno-ai/kitso-handshake-agents. Apache 2.0.
If you’re an ATS, you integrate once and accept verified candidate intent from any compliant seeker — Kitsuno or otherwise. If you’re a recruiter agency, you publish vacancy cards your seekers can read. If you’re a country employment agency or a university careers office sitting on labour-market data, your /.well-known/handshake-v0.2.json is the routing surface — no central API, no contract with us required. If you’re building an agent of your own, the contract is the rails: what your agent owes and what it can refuse, in writing, in code.
The two-agent failure mode at the top of this post is not inevitable. It’s the default when transport is the only layer. The contract above it — staged disclosure, idempotency, a quality gate, federation — is what turns two agents into two principals being properly served. We built it because we needed it. We’re using it because no one else is offering it. And we open-sourced it because the only way the agent economy doesn’t drown the humans in it is if the contract is shared.
Build with us, fork against us. Just don’t fake the handshake.
Resources
Protocol spec: kitsuno.ai/handshake/v0.2/
Validator section: kitsuno.ai/handshake/v0.2/#validator
Reference implementations: github.com/kitsuno-ai/kitso-handshake-agents
Federation well-known (ours): app.kitsuno.ai/.well-known/handshake-v0.2.json
Kitsuno product: kitsuno.ai






















