Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 

Repository files navigation

BindAgt

Verify that an AI agent actually belongs to the domain it claims — and that the caller holds its key.

agt://apple.com/siri either proves it is Apple's agent, or it does not. There is no third answer, and you never have to trust us to find out.

npm install bindagt
import { verifyOnChain } from "bindagt";

// No API key. No account. No BindAgt server involved.
const result = await verifyOnChain("agt://bindagt.com/hello");

console.log(result.valid);        // true
console.log(result.domain);       // "bindagt.com"
console.log(result.domainStatus); // "active"

That call reads the public registry directly. Verification is free, open, and permissionless — it works whether or not BindAgt exists tomorrow.

mainnet npm standard


Come break it

Our agent's identity document is public. verify_url serves it to anyone, with no authentication, by design — that is what keeps verification free.

Download it right now:

curl https://api.bindagt.com/v1/verify/0xb2069e0c4a378a182a682d33ab7f59fcb38c7f15e299f4d3b196a5898e2fe07a

That is the genuine article — the same bytes our own agent presents. Now try to be us with it.

git clone https://github.com/bindagt/bindagt && cd bindagt/examples/agent-to-agent
node demo.mjs
TEST MODE. Signing with a generated key, and the key lookup for it is stubbed.
Identity and domain status still come from mainnet.

1. The owner calls — presentAs("agt://bindagt.com/hello")
   → ACCEPTED  agt://bindagt.com/hello · possession proven

2. An attacker replays the REAL document, downloaded from the public verify_url
   → REJECTED  missing_possession_signature

3. An attacker captures a signed request and replays it against /admin
   → REJECTED  possession_not_proven

4. Someone calls with no identity
   → REJECTED  missing_header

Without the domain's key you get the banner above: the demo generates a key so you can still run it, and identity and domain standing are read from mainnet either way. The owner runs the same file unchanged with BINDAGT_KEY_PASSWORD set. Case 2 is the one to watch, and it does not depend on which key is used — the attacker has no key at all.

Holding the document proves nothing. Under AGT-9303 §7.3 the caller signs each individual request with the domain's key (RFC 9421), and that signature is valid for 60 seconds against that one request. A copied document, a captured header, a replayed call against a different path — all refused.

Until 29 July 2026, case 2 passed. We found it in our own review, stopped the launch, and built §7.3. If you find the next one, open an issue — we would rather hear it from you than from Hacker News.

The problem

Any agent can claim to be Apple's. Any tool can claim to be your bank's. Today there is no universal, vendor-neutral way to check whether an AI agent genuinely belongs to the organisation it says it does.

BindAgt fixes the origin question — and only the origin question. It does not score agents, rank them, or judge their behaviour. It answers two things, cryptographically: does this agent belong to this domain, and does the caller hold its key?

How it works

  1. A domain owner proves control of their domain with a DNS TXT challenge (the same model Let's Encrypt uses).
  2. Once verified, the agent's identity is anchored to a public, immutable registry on Ethereum L1.
  3. Anyone, anywhere, can verify that anchor directly — no account, no API key, no permission.
  4. When an agent calls out, it signs the request with the domain's key. The receiver checks that signature against the key in the registry.

The trust root is DNS, which the entire internet already relies on. BindAgt inherits that trust rather than inventing a new one.

Two ways to verify

Method What it does Needs
verifyOnChain() Reads the public registry directly. Trustless. Nothing — talks to a public RPC
verify() Same answer via the BindAgt API (cached, faster at scale). Nothing to start; a free key raises rate limits

Both return the same shape:

{
  valid: true,
  agentId: "agt://bindagt.com/hello",
  domain: "bindagt.com",
  domainStatus: "active",
  agentType: "public",
  anchoredAt: "2026-07-22T11:44:47.000Z",
  source: "l1"
}

Proving possession

import { loadSigningKey } from "bindagt";
import { presentAs } from "@bindagt/openai";

// Your key, decrypted locally from ~/.bindagt/key.enc using
// BINDAGT_KEY_PASSWORD. Synchronous, and it never leaves the process.
const { key, keyType } = loadSigningKey();

// Signs this request with it (RFC 9421, AGT-9303 §7.3).
const headers = await presentAs("agt://acme.com/support-bot", {
  signer: key,
  keyType,
});
import { verifyIdentityGuardrail } from "@bindagt/openai";

// Requires the signature by default. A document on its own is refused.
const out = await verifyIdentityGuardrail(req);

You hold the signing key. BindAgt never sees it.

Register your own agent

npx bindagt register example.com

The CLI walks you through the DNS challenge and anchors your first agent. The first 100 domains are free.

Why not an existing standard?

Each of these is a reasonable choice, and we adopt two of them.

  • did:web — publish your key at a URL on your own site. Free, no new authority, works today, and the honest baseline. What it cannot do is tell you what the key was yesterday: there is no history, no revocation trail, and if an attacker owns the web server they own the key file too. BindAgt records which key, and since when, somewhere the compromised server does not control.
  • Sigstore / Rekor — the real architectural neighbour: a mature, tamper-evident transparency log. It is built for signing software artefacts, not for agent identity rooted in DNS with a lifecycle (suspension, expiry, transfer behind a time-lock). We claim no novelty over Rekor.
  • A2A (Agent2Agent) — the channel agents talk over. Not a competitor; we speak it. verifyAgentCard() bridges the two. A2A moves the message, BindAgt says whose key signed it.
  • SPIFFE — secures workloads inside one organisation. BindAgt verifies identity across organisations with no prior relationship.
  • ERC-8004 — mixes identity with reputation scoring. BindAgt refuses reputation by design: origin is a fact, reputation is an opinion.

In one line: others prove the message was not altered; BindAgt proves whose key signed it, and whether that key has ever changed.

What BindAgt does not do

  • It does not tell you an agent is trustworthy, competent, or safe. Only that it is who it says it is.
  • It does not do reputation, ranking or scoring, and it never will.
  • Ephemeral delegated agents are specified in AGT-9303 §6 but not implemented — the SDK rejects them, which is the behaviour the spec requires of a receiver that does not support them.

Status

Good first issue

Want to help? Add AGT-9303 verification to a framework you use (LangChain, the OpenAI Agents SDK, CrewAI, …). Open an issue and we will help you scope it.

Learn more


BindAgt — open protocol for AI agent identity.

Releases

Packages

Contributors