KeyID's JavaScript SDK: Ed25519-Provisioned Email for Agents That Have No Human
Free email for AI agents. No signup, no human needed. Install → provision → send and receive. Ed25519 keypair auth.
At a glance
- What is it?
- @keyid/sdk gives an AI agent a mailbox from a keypair instead of a signup form. The README documents a broad mail API, but the licence line and the repository metadata disagree, and that is the first thing to settle before adopting it.
- Who is it for?
- Adopt @keyid/sdk if you are building an agent that needs an inbox without a human in the registration loop, and you are willing to route mail through KeyID's hosted service, since the SDK is a client and not a mail server. Do not adopt it if you need self-hosted mail, a signed SLA, or an unambiguous licence, because the README says MIT while the repository metadata shows no licence file, and those two cannot both be right.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 89 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The signup form is the thing KeyID removes
Mail providers assume a human at the keyboard. Someone opens a browser, accepts terms, solves a challenge, and clicks a link in a verification email. An autonomous agent cannot do any of that, and a developer who spins up fifty ephemeral agents does not want to do it fifty times either. @keyid/sdk addresses that gap by replacing the account with a keypair. The README's framing is direct: "No signup. No human needed." The agent generates an Ed25519 keypair, calls provision(), and receives an email address. The stated scope is broader than receiving mail. The README claims KeyID handles "domain management, rotation, reputation monitoring, deliverability," which is the part a solo developer would otherwise have to build. The audience is narrow and specific: teams running agents that must send or receive mail as part of a task, and who accept that the mail infrastructure lives on someone else's servers.
Challenge-response auth, and where the private key lives
The authentication model is the most concrete thing in the README, and it is worth reading closely because it determines your operational burden. On first use the SDK generates a keypair, or loads one you pass in via `keypair: { publicKey, privateKey }` or from the environment. provision() registers the public key and returns an email address. After that, the README states that "all subsequent calls auto-authenticate via signed nonce exchange," meaning each request is signed with the private key rather than carrying a bearer token. That design removes the shared secret you would otherwise have to store and rotate. It also means the private key is the account. Lose it and you lose the mailbox, which is presumably why getRecoveryToken() exists under Identity. The README lists getRecoveryToken() and describes it as the "recovery token for key rotation" but does not document the rotation procedure itself. That is a gap worth noting: the method is listed, the workflow is not. The SDK also accepts a `baseUrl` option, which implies the client can point at an instance other than the default, though the README does not state whether a self-hosted server exists or how it would be deployed.
What the documented API surface actually covers
The API reference is unusually wide for a v0.2.0 package. Beyond provision(), getInbox(), send() and reply(), the README documents threads (listThreads, getThread, deleteThread), drafts with a full create/update/delete/sendDraft cycle, contacts, settings for signature and forwarding and auto-reply, webhooks with delivery history, allow and blocklists, and a getMetrics() call. Message-level operations include updateMessage() for labels, read state and starred state, plus replyAll() and forward(). Sending supports HTML bodies, CC and BCC, attachments passed as `{ filename, content, contentType }`, and scheduled delivery via `scheduledAt`. Search is exposed as a parameter on getInbox(), for example `getInbox({ search: 'invoice' })`. Webhooks are the piece that makes the SDK usable for agents that cannot poll: createWebhook(url, events?, options?) registers an endpoint, and getWebhookDeliveries() returns the delivery record. The README does not enumerate the event names, which is a real omission if you plan to filter on them.
Install and first provision, as documented
The runtime requirement is stated plainly: Node.js 18 or later, and the README claims no external dependencies, which keeps the install surface small. Installation is `npm install @keyid/sdk` or `yarn add @keyid/sdk`. The quick start constructs a client with `new KeyID()`, calls `await agent.provision()` to get `{ email, agentId }`, then `await agent.getInbox()` for `{ messages }`, then `agent.send('user@example.com', 'Hello', 'Message body')`, then `agent.reply(messages[0].id, 'Thanks for your email!')`. Three constructor forms are documented: no arguments for an auto-generated keypair, an explicit keypair object, and a custom baseUrl. Everything runs through those. If you want a scheduled message, the README's example is `send('to@x.com', 'Sub', 'Body', { scheduledAt: '2025-01-01T10:00:00Z' })`. Note that the README shows no environment variable names for key material even though it says the keypair can be "loaded from env/options." You will have to read the source to learn which variable it reads.
The licence field is the first thing to resolve
The README ends with a License section reading "MIT." The repository metadata supplied for this review lists the licence as unknown, and the recent release list contains only v0.2.0 from March 2026 against a last push in June 2026. Those two signals do not agree. A missing LICENSE file at the repository root is not the same as a permissive grant, and it is not the same as a restrictive one either. For a package that would sit in the dependency tree of a production agent, that ambiguity matters more than any feature on the API list, because it determines whether you can redistribute the code. This is not a legal opinion and I am not giving one. The practical step is to check the repository for a LICENSE file and read the package metadata on the registry before you commit to the dependency. If neither resolves it, treat the licence as undetermined until the maintainers publish one.
Hosted service, no self-hosting story, and polling as a fallback
The clearest limitation is architectural. The SDK is a client. The README says KeyID handles domain management, rotation, reputation monitoring and deliverability, which means mail flows through KeyID's infrastructure and the addresses are on domains KeyID controls. There is no documented path to run the server yourself, and the baseUrl option does not come with deployment instructions. So the trade is: you skip signup and domain setup, and in exchange you accept a dependency on a hosted third party for a channel your agent may need to be reliable. The second limitation is delivery semantics. The README documents webhooks and getWebhookDeliveries() but says nothing about retry behaviour, ordering, or what happens when an endpoint is down. If your agent depends on inbound mail, you need either a webhook endpoint you trust or a polling loop on getInbox(), and the README gives you no guidance on which the service prefers. The third is version maturity: v0.2.0 is the only release listed, and the README does not include a deprecation policy or a changelog link, so method signatures may still move.
How this differs from an agent framework's built-in tooling
The obvious alternative is the email tool that ships with an agent framework, or a general transactional mail API such as Postmark or SendGrid. Those differ from KeyID in a way that is easy to miss. A transactional mail API is built around sending on behalf of a verified domain you own, and it usually requires a human to complete domain verification through DNS records. It gives you strong deliverability guarantees and a sending reputation tied to your own domain, and it typically does not give the agent its own inbox. KeyID inverts that: the agent gets an address and an inbox without owning a domain, and the sending reputation belongs to KeyID's pool rather than yours. The second alternative is running your own mail server, which returns control over the data and the licence but puts deliverability, blocklists and rotation back on your team, which is exactly the work the README says KeyID absorbs. If your agent only needs to send notifications from a domain you already control, a transactional API is the more predictable choice. If it needs to receive and reply as an independent correspondent, KeyID's provision() call is doing something the transactional APIs generally do not.
Maintenance cost and who should wait
The upgrade surface looks small. No external dependencies, Node 18 as the floor, and one release so far. The maintenance cost that matters is not in the code, it is in the key material: because authentication is a signed nonce exchange against a private key, your deployment has to persist that key across restarts, and the README does not describe a storage convention. If the process regenerates a keypair on every boot, you get a new identity each time, which would break any address your agent has already given out. That is the failure mode to test before trusting the SDK in anything long-running. The second cost is the hosted dependency: when KeyID rotates a domain, your agent's address may change, and getAddresses() exists precisely because the README says it lists "current + historical" addresses. Any system that has stored an agent's email address needs to tolerate that rotation. Teams that should wait: anyone who needs a signed data processing agreement, anyone whose compliance regime forbids routing mail through an unnamed third party, and anyone who needs the licence question answered before procurement will look at the package. Teams that should try it now: builders prototyping multi-agent systems where each agent needs a distinct correspondent address and no human is available to create one.
Editorial conclusion
Adopt @keyid/sdk if you are building an agent that needs an inbox without a human in the registration loop, and you are willing to route mail through KeyID's hosted service, since the SDK is a client and not a mail server. Do not adopt it if you need self-hosted mail, a signed SLA, or an unambiguous licence, because the README says MIT while the repository metadata shows no licence file, and those two cannot both be right. Before you ship, run `npm install @keyid/sdk`, call `provision()` against a throwaway keypair, and confirm three things yourself: the response shape of `getIdentity()`, whether `getRecoveryToken()` returns a token you can actually use to rotate a key, and what happens when the process restarts without a persisted private key.
Community notes