# Agent authentication vs user authentication

> What changes when software, not a person, signs in or sends, and what should an app check before it lets an agent in?

## The short answer

The goals stay the same when software signs in instead of a person: know who is acting, give them no more than they need, and be able to take it back. What changes is the evidence. A person proves who they are once, with a password, a passkey or a code sent to their inbox, and a cookie carries the rest; an agent holds a key, should sign each request, is one of many per person, and acts for somebody else who has to be named. Pidgeon gives an agent that signed identity today, and Sign in with Pidgeon, which turns it into an account on your site, is coming soon.

## A person and an agent, side by side

|                      | A person                               | An agent                                          |
| -------------------- | -------------------------------------- | ------------------------------------------------- |
| Proves itself with   | A password, a passkey, a code by email | A key it holds, signing each request              |
| How many per account | One                                    | Several per person, many per company              |
| Who answers for it   | Themselves                             | The company that runs it, and whoever it acts for |
| A CAPTCHA is         | A nuisance                             | A wall that was built to stop it                  |
| Lives on             | A long session cookie                  | Short-lived signatures and tokens                 |
| When it goes wrong   | Lock the account                       | Revoke that one agent and keep the person         |

The goals in the table do not move: somebody answers for every account, access is the least that does the job, and it can be taken back and audited afterwards. OAuth and OpenID Connect still carry the tokens, and your identity provider still owns your people. What moves is the evidence in each row.

The last row is the one that hurts today. Most agents run on their owner's OAuth token or API key, so your logs say the person did it, and the only way to stop one agent is to cut off the person and every other agent they run.

## How an agent proves who it is

With Pidgeon, an agent has a card: a JWS signed under a key its domain publishes, naming its address, a stable `sub`, its `kind`, the `operator` domain the company proved, who it acts for and a coarse standing. Its requests are signed with HTTP Message Signatures in Web Bot Auth's profile, covering the method, host, path, the agent's address as `From` and the body's digest, and each signature is good for five minutes.

The operator's side is one command per step, with no account:

```sh
npm install -g @pidgeon-ai/cli
pidgeon id init acme.com
pidgeon id issue support-agent
```

`init` makes an Ed25519 key on the operator's machine and asks for two DNS records: a TXT at `_post.acme.com` that proves the domain, and a CNAME for `post.acme.com`, which is where anyone else finds the domain's keys. `issue` gives `support-agent@acme.com` a card. Pidgeon only ever holds the public half of the key.

## A checklist for an app that accepts agents

1. **Check the signature on every request.** Send the request as you received it to `POST /v1/verify`, with no key, or check the RFC 9421 signature yourself against the keys at `https://post.<domain>/.well-known/http-message-signatures-directory`.

   ```sh
   curl -X POST https://pidgeon.ai/api/v1/verify \
     -H 'content-type: application/json' \
     -d '{"request": {"method": "POST", "url": "https://api.you.com/v1/signup", "headers": {"…": "…"}, "body": "…"}}'
   ```

2. **Key the account on the card's `sub`, not on the address.** An address can be deleted and created again; `sub` is never given to another agent.

3. **Store the operator, and whether it is verified.** On the shared domain, `pidgeon.email`, the answer says `shared: true` and `verified: false`: anyone can get an address there, so treat it as you would an anonymous sign-up.

4. **Record who it acts for.** Show `on_behalf_of` to the people in the account, next to everything the agent did.

5. **Give each agent its own session.** Never share one with a person or with another agent, so revoking one leaves the rest alone.

6. **Weigh the standing.** A card says `new` for its first 30 days, `established` after, and `restricted` while its operator has it suspended. Lower limits for `new` cost you little.

7. **Fetch the card again before anything that matters.** A copy is good for a day, and a revoked agent's card stops answering.

8. **Ask a person before what cannot be undone.** A payment, a deletion, an account closed. The card says who is accountable; it does not make the action right.

If your sign-up sends a code by email, an agent with an inbox of its own can receive it: [verification codes for AI agents](https://pidgeon.ai/blog/verification-codes-for-ai-agents) shows the one call.

## What Pidgeon does not do here

Pidgeon does not authenticate your people, store their passwords or run your single sign-on, and it does not decide what an agent may do. Your identity provider and your authorisation system keep those jobs. Pidgeon defines what an agent's ID says and lets anyone check it.

## Sign in with Pidgeon, coming soon

Sign in with Pidgeon will let an agent with a Pidgeon ID create an account on your site and sign in on its own, with no password and no CAPTCHA. It speaks OpenID Connect and OAuth token exchange, so it sits beside the sign-in you already run. The [Sign in with Pidgeon page](https://pidgeon.ai/sign-in-with-pidgeon) has the waitlist. What works today is the check above: a signed request, verified, with the agent's card.

## Start

[Quickstart](https://pidgeon.ai/docs/quickstart.md) proves a domain and issues an agent. [Checking a message](https://pidgeon.ai/docs/verifying.md) explains each verdict, and [Agents](https://pidgeon.ai/docs/agents.md) covers issuing, suspending and revoking. [The protocol](https://pidgeon.ai/protocol) is Post, the draft that defines the card and the signatures.

## Questions

### How is agent authentication different from a person signing in?

A person proves who they are once and a cookie carries the rest. An agent holds a key, signs each request, is one of many per person and acts for someone who has to be named.

### What should an app key an agent’s account on?

The card’s sub, not its address. An address can be deleted and created again; the sub is never given to another agent.

### Can I trust an agent on the shared pidgeon.email domain?

Treat it as an anonymous sign-up. Anyone can get an address there, so the verifier reports shared: true and verified: false.

### Can agents sign up to my product with Sign in with Pidgeon?

It is coming soon, with a waitlist on the Sign in with Pidgeon page. Today you can check an agent’s signed request and card with POST /v1/verify.
