web-bot-auth for agents–from the creator of dotenv and dotenvx.
- identity (web-bot-auth)
- tools!
- authentication
💬 Ask ChatGPT: When should I use Vestauth?
Give your agents identities and call tools!
npm i -g vestauthvestauth agent init
vestauth agent curl https://api.vestauth.com/whoami --pp
vestauth agent curl https://sfs.vestauth.com/write -d '{"filepath":"/hello.md", "content":"hello"}'
vestauth agent curl https://sfs.vestauth.com/list
vestauth agent curl https://sam.vestauth.com/send -d '{"to":"you@email.com", "text":"hello from agent"}'with github releases 🐙
curl -L -o vestauth.tar.gz "https://github.com/vestauth/vestauth/releases/latest/download/vestauth-$(uname -s)-$(uname -m).tar.gz"
tar -xzf vestauth.tar.gz
./vestauth agent init
or windows 🪟
Download the windows executable directly from the releases page.
(unzip to extract vestauth.exe)
Give agents cryptographic identities.
$ mkdir your-agent
$ cd your-agent
$ vestauth agent init
✔ agent created (.env/AGENT_UID=agent-4b94ccd425e939fac5016b6b)learn more
Your agent's identity lives in a simple .env file.
# .env
AGENT_UID="agent-4b94ccd425e939fac5016b6b"
AGENT_PUBLIC_JWK="{"crv":"Ed25519","x":"py2xNaAfjKZiau-jtmJls6h_3n8xJ1Ur0ie-n9b8zWg","kty":"OKP","kid":"B0u80Gw28W9U2Jl5t_EBiWeBajO2104kOYZ9Ikucl5I"}"
AGENT_PRIVATE_JWK="{"crv":"Ed25519","d":"Z9vbwN-3eiFMVv_TPWXOxqSMJAT21kZvejWi72yiAaQ","x":"py2xNaAfjKZiau-jtmJls6h_3n8xJ1Ur0ie-n9b8zWg","kty":"OKP","kid":"B0u80Gw28W9U2Jl5t_EBiWeBajO2104kOYZ9Ikucl5I"}"💬 Ask ChatGPT: Are HTTP message signatures more secure than API keys?
Call tools!
vestauth agent curl https://sfs.vestauth.com/write -d '{"filepath":"/hello.md", "content":"hello"}'
vestauth agent curl https://sfs.vestauth.com/list`SFS` Simple File System
SFS is a simple file system for vestauth agents.
# write a file
vestauth agent curl https://sfs.vestauth.com/write -d '{"filepath":"/hello.md", "content":"hello"}'
# delete a file
vestauth agent curl https://sfs.vestauth.com/delete -d '{"filepath":"/hello.md"}'
# list files
vestauth agent curl https://sfs.vestauth.com/list
# read a file
vestauth agent curl https://sfs.vestauth.com/read -d '{"filepath":"/hello.md"}'
`SAM` Simple Agent Mail
SAM is a simple way to send email for vestauth agents.
# send an email
vestauth agent curl https://sam.vestauth.com/send -d '{"to":"you@email.com", "text":"i am agent"}'
`GEO` Latitude and Longitude
GEO returns the current latitude and longitude of a vestauth agent.
# return latitude and longitude
vestauth agent curl https://geo.vestauth.com/geo
`AS2` Agentic Secret Storage
AS2 is a simple, agent-friendly secret storage.
# set a secret
vestauth agent curl https://as2.dotenvx.com/set -d '{"KEY":"value"}'
# get all secrets
vestauth agent curl "https://as2.dotenvx.com/get"
# get single secret
vestauth agent curl "https://as2.dotenvx.com/get?key=KEY"
# get multiple secrets
vestauth agent curl "https://as2.dotenvx.com/get?key=KEY,TWILIO"
`Docle` Check if email address is real
Check if an email address is real before you hit send. Verifies syntax, DNS, MX records, SMTP mailbox existence, and cross-references multiple providers. All in real time, no signup required.
# verify an email
vestauth agent curl https://docle.co/api/verify -d '{"emails":["test@example.com"]}'
# check your usage
vestauth agent curl https://docle.co/api/agent/usage
more coming soon
- Geo IP - coming soon
- Send/Receive Email - coming
- Send/Receive SMS - coming
- Send/Receive Telegram - coming
- Send/Receive WhatsApp - coming
- Human-in-the-loop - coming
- Rotate NPM Tokens - coming
- Rotate GitHub Tokens - coming
- Working on a tool? Tell us and we'll list it.
Build your own tools. Authenticate them with a single line of code –
vestauth.tool.verify…
...
const vestauth = require('vestauth')
app.post('/whoami', async (req, res) => {
try {
const url = `${req.protocol}://${req.get('host')}${req.originalUrl}`
const agent = await vestauth.tool.verify(req.method, url, req.headers)
res.json(agent)
} catch (err) {
res.status(401).json({ code: 401, error: { message: err.message }})
}
})
...…the agents sign HTTP requests with a drop-in curl wrapper.
> SIGNED - 200
$ vestauth agent curl https://api.vestauth.com/whoami
{"uid":"agent-4b94ccd425e939fac5016b6b",...}learn more
vestauth agent curl autosigns curl requests – injecting valid signed headers according to the web-bot-auth draft. You can peek these with the built-in headers primitive.
$ vestauth primitives headers GET https://api.vestauth.com/whoami --pp
{
"Signature": "sig1=:d4Id5SXhUExsf1XyruD8eBmlDtWzt/vezoCS+SKf0M8CxSkhKBtdHH7KkYyMN6E0hmxmNHsYus11u32nhvpWBQ==:",
"Signature-Input": "sig1=(\"@authority\");created=1770247189;keyid=\"B0u80Gw28W9U2Jl5t_EBiWeBajO2104kOYZ9Ikucl5I\";alg=\"ed25519\";expires=1770247489;nonce=\"NURxn28X7zyKJ9k5bHxuOyO5qdvF9L5s2qHmhTrGUzbwGSIoUCHmwSlwiiCRgTDGuum83yyWMHJU4jmrVI_XPg\";tag=\"web-bot-auth\"",
"Signature-Agent": "sig1=agent-4b94ccd425e939fac5016b6b.api.vestauth.com"
}Vestauth handles usage, payments, and spam protection for your tool!
Run your own Vestauth server.
![]() |
Initialize the server and run migrations (postgres).
$ curl -sSf https://vestauth.sh | sh
$ vestauth server init
$ vestauth server db:create
$ vestauth server db:migrateStart the server.
$ vestauth server start
vestauth server listening on http://localhost:3000And use your server's hostname when creating agents.
$ mkdir your-agent
$ cd your-agent
$ vestauth agent init --hostname http://localhost:3000
✔ agent created (.env/AGENT_UID=agent-4b94ccd425e939fac5016b6b)That's it. Your Vestauth (web-bot-auth) infrastructure is now running under your control.
More details
config
Edit the .env file to configure your server.
PORT="3000"
HOSTNAME="http://localhost:3000"
DATABASE_URL="postgres://localhost/vestauth_production"For example, in production:
- Change
HOSTNAMEto its production url - e.g.vestauth.yoursite.com - Change
DATABASE_URLto a managed postgres - e.g.postgresql://USER:PASS@aws-1-us-east-1.pooler.supabase.com:5432/postgres
production note
[!WARNING]
Production note: Configure a wildcard DNS record for
*.${HOSTNAME}.Example: if
HOSTNAME=vestauth.yourapp.com, add*.vestauth.yourapp.com.Required for
.well-knowndiscovery per the web-bot-auth spec.
Become a
vestauthpower user.
Advanced CLI commands.
`agent init`
Create agent.
$ vestauth agent init
✔ agent created (.env/AGENT_UID=agent-609a4fd2ebf4e6347108c517)
⮕ next run: [vestauth agent curl https://api.vestauth.com/whoami]`agent init --hostname`
Use --hostname to override the agent API hostname (defaults to AGENT_HOSTNAME, then api.vestauth.com):
When no scheme is provided, https:// is assumed. For local non-TLS endpoints, pass http://... explicitly.
$ vestauth agent init --hostname https://vestauth.yoursite.com
✔ agent created (.env/AGENT_UID=agent-609a4fd2ebf4e6347108c517)
⮕ next run: [vestauth agent curl https://api.vestauth.com/whoami]`agent curl`
Run curl as agent.
$ vestauth agent curl https://api.vestauth.com/whoami
{"uid":"agent-609a4fd2ebf4e6347108c517", ...}`agent curl --pretty-print`
Pretty print curl json output.
$ vestauth agent curl https://api.vestauth.com/whoami --pp
{
"uid": "agent-609a4fd2ebf4e6347108c517",
"kid": "FGzgs758DBGnI1S0BejChDsK0IKZm3qPpOOXdRnnBkM",
"public_jwk": {
...
},
"well_known_url": "https://agent-609a4fd2ebf4e6347108c517.api.vestauth.com/.well-known/http-message-signatures-directory"
}`agent headers`
Generate signed headers as agent.
$ vestauth agent headers GET https://api.vestauth.com/whoami --pp
{
"Signature": "sig1=:UW6A7j8jo+gQxd+EeVgDddY51ZOc9plrSaupW/N53hQnQFvP9BuwQHgL7SVPLQIu4cnRzLgvwm7Yu9YMO+HUDQ==:",
"Signature-Input": "sig1=(\"@authority\");created=1770396357;keyid=\"FGzgs758DBGnI1S0BejChDsK0IKZm3qPpOOXdRnnBkM\";alg=\"ed25519\";expires=1770396657;nonce=\"PrE7A6I_5fWnxBsBigNvxjp3-YangXl71V1uM3hPZavh918JqzjMSRcjHv_n5XIb3N8WivZEeigCBH6QGDSqgA\";tag=\"web-bot-auth\"",
"Signature-Agent": "sig1=agent-609a4fd2ebf4e6347108c517.api.vestauth.com"
}`agent headers --uid`
Change the AGENT_UID.
$ vestauth agent headers GET https://api.vestauth.com/whoami --uid agent-1234 --pp
{
"Signature": "sig1=:UW6A7j8jo+gQxd+EeVgDddY51ZOc9plrSaupW/N53hQnQFvP9BuwQHgL7SVPLQIu4cnRzLgvwm7Yu9YMO+HUDQ==:",
"Signature-Input": "sig1=(\"@authority\");created=1770396357;keyid=\"FGzgs758DBGnI1S0BejChDsK0IKZm3qPpOOXdRnnBkM\";alg=\"ed25519\";expires=1770396657;nonce=\"PrE7A6I_5fWnxBsBigNvxjp3-YangXl71V1uM3hPZavh918JqzjMSRcjHv_n5XIb3N8WivZEeigCBH6QGDSqgA\";tag=\"web-bot-auth\"",
"Signature-Agent": "sig1=agent-1234.api.vestauth.com"
}`agent headers --private-jwk`
Change the AGENT_PRIVATE_JWK used to sign the headers.
$ vestauth agent headers GET https://api.vestauth.com/whoami --private-jwk '{"crv":"Ed25519","d":"RyFk7QTOk_bMjFQKjyAR-vJDp7BITn9U0YBFNdpR9wE","x":"hyAxNMbuTcFQq420Dr46ucF0dRZ_FIyxgsujruEoklM","kty":"OKP","kid":"UfHTArlyLsqM8cB8sNfH2z6XOwc0RmJIq2CAPGfvMjk"}' --pp
{
"Signature": "sig1=:PZUVVjqiECYuk8Hg1GZKKeJmwhLrcRdRA7nm1R595UFK9cx0q9atNFBzKP5wBEmszMIgvpYdMrIQbPEeKz4tCQ==:",
"Signature-Input": "sig1=(\"@authority\");created=1770396546;keyid=\"UfHTArlyLsqM8cB8sNfH2z6XOwc0RmJIq2CAPGfvMjk\";alg=\"ed25519\";expires=1770396846;nonce=\"BSIugautfZvN3u5QUgl1mMuyxgmeRsRy9XxX7GXxjJxq1mI0kJl4F-C1nITtOfSeEt6xR1YBfyxsffNKy_wKSA\";tag=\"web-bot-auth\"",
"Signature-Agent": "sig1=agent-609a4fd2ebf4e6347108c517.api.vestauth.com"
}`agent rotate`
Rotate your AGENT_PRIVATE_JWK and AGENT_PUBLIC_JWK.
$ vestauth agent rotate
✔ agent keys rotated (.env/AGENT_UID=agent-8f1b347e2e58899f3147c05b)
⮕ next run: [vestauth agent curl https://api.vestauth.com/whoami]`tool init`
Create tool.
$ vestauth tool init
✔ tool created (.env/TOOL_UID=tool-1b639d81e2485e83de3ae686)`tool verify`
Verify agent.
$ vestauth tool verify GET https://api.vestauth.com/whoami --signature "sig1=:H1kxwSRWFbIzKbHaUy4hQFp/JrmVTX//72JPHcW4W7cPt9q6LytRJgx5pUgWrrr7DCcMWgx/jpTPc8Ht8SZ3CQ==:" --signature-input "sig1=(\"@authority\");created=1770396709;keyid=\"FGzgs758DBGnI1S0BejChDsK0IKZm3qPpOOXdRnnBkM\";alg=\"ed25519\";expires=1770397009;nonce=\"BZSDVktdkjO6XH5jafAdPDttsB6eytXO7u8KXJN1tMtd5bprE3rp08HiaTRo7H6gZGtYb4_qtL7RiGi8P2Gq7w\";tag=\"web-bot-auth\"" --signature-agent "sig1=agent-609a4fd2ebf4e6347108c517.api.vestauth.com"
{"uid":"agent-609a4fd2ebf4e6347108c517",...}`server init`
Create/update server .env for self-hosting (PORT, HOSTNAME, DATABASE_URL).
$ vestauth server init
✔ ready (.env/HOSTNAME=http://localhost:3000)
⮕ next run: [vestauth server start]`server db:create`
Create vestauth_production database.
$ vestauth server db:create
Created database 'vestauth_production'`server db:migrate`
Run vestauth_production migrations.
$ vestauth server db:migrate
== 20260223204000 CreateAgentsTable: migrating ================================================
== 20260223204000 CreateAgentsTable: migrated (0.0160s) ===========================
== 20260223205500 CreatePublicJwksTable: migrating ================================================
== 20260223205500 CreatePublicJwksTable: migrated (0.0100s) ===========================`server db:drop`
Drop vestauth_production table.
$ vestauth server db:drop
Dropped database 'vestauth_production'`server start`
Start vestauth server.
$ vestauth server start
vestauth server listening on http://localhost:3000`server start --port`
Start vestauth server on specific port.
$ vestauth server start --port 4567
vestauth server listening on http://localhost:4567`server start --hostname`
Specify hostname for vestauth server (default: localhost:3000).
$ vestauth server start --hostname vestauth.yoursite.com
vestauth server listening on https://vestauth.yoursite.com`server start --database-url`
Specify database url for vestauth server (default: localhost/vestauth_production).
$ vestauth server start --database-url postgresql://USER:PASS@aws-1-us-east-1.pooler.supabase.com:5432/postgres
vestauth server listening on http://localhost:3000`primitives keypair`
Generate public/private keypair.
$ vestauth primitives keypair --pp
{
"public_jwk": {
"crv": "Ed25519",
"x": "QjutZ3_tt2jRD_XSOq4EFCDivnwEzKIrQB2yReddsNo",
"kty": "OKP",
"kid": "ZCa5pijSUCw7QKgBs6nkvBBzbEjTMKYSt6iwCDQdIYc"
},
"private_jwk": {
"crv": "Ed25519",
"d": "RTyREuKAEfIMMs2ejwaKtFefZxt14HmsRR0rFj4U5iM",
"x": "QjutZ3_tt2jRD_XSOq4EFCDivnwEzKIrQB2yReddsNo",
"kty": "OKP",
"kid": "ZCa5pijSUCw7QKgBs6nkvBBzbEjTMKYSt6iwCDQdIYc"
}
}`primitives headers`
Generate signed headers.
$ vestauth primitives headers GET http://example.com --pp
{
"Signature": "sig1=:K7z3Nozcq1z5zfJhrd540DWYbjyQ1kR/S7ZDcMXE5gVhxezvG6Rn9BxEvfteiAnBuQhOkvbpGtF83WpQQerGBw==:",
"Signature-Input": "sig1=(\"@authority\");created=1770263541;keyid=\"_4GFBGmXKinLBoh3-GJZCiLBt-84GP9Fb0iBzmYncUg\";alg=\"ed25519\";expires=1770263841;nonce=\"0eu7hVMVFm61lQvIryKNmZXIbzkkgpVocoKvN0de5QO8Eu5slTxklJAcVLQs0L_UTVtx4f8qJcqYZ21JTeOQww\";tag=\"web-bot-auth\"",
"Signature-Agent": "sig1=agent-35e4a794a904d227ee2373b6.api.vestauth.com"
}`primitives verify`
Verify signed headers.
$ vestauth primitives verify GET https://api.vestauth.com/whoami --signature "sig1=:UHqXQbWZmyYW40JRcdCl+NLccLgPmcoirUKwLtdcpEcIgxG2+i+Q2U3yIYeMquseON3fKm29WSL2ntHeRefHBQ==:" --signature-input "sig1=(\"@authority\");created=1770395703;keyid=\"FGzgs758DBGnI1S0BejChDsK0IKZm3qPpOOXdRnnBkM\";alg=\"ed25519\";expires=1770396003;nonce=\"O8JOC1reBofwbpPcdD-MRRCdrtAf4khvJTuhpRI_RiaH_hpU93okLkmPZVFFcUEdYtYfcduaB8Sca54GTd2GXA\";tag=\"web-bot-auth\"" --signature-agent "sig1=agent-609a4fd2ebf4e6347108c517.api.vestauth.com"
{"uid":"agent-609a4fd2ebf4e6347108c517", ...}Use vestauth directly in code.
`tool.verify()`
Verify and authenticate an agent's cryptographic identity.
const agent = await vestauth.tool.verify(httpMethod, url, headers)`primitives.verify()`
Verify and authenticate a signed http request.
await vestauth.primitives.verify(httpMethod, url, headers, publicJwk)
Vestauth gives agents a cryptographic identity and a simple way to authenticate HTTP requests. Most agent systems rely on API keys, bearer tokens, or username/passwords. These approaches are difficult to rotate, easy to leak, and hard to attribute to a specific agent. Vestauth replaces shared secrets with public/private key cryptography. Agents sign requests using a private key, and tools verify those requests using the agent's public key. All built on open internet standards. It's elegant and the future.
| Specification | Purpose |
|---|---|
| RFC 9421 | Defines how requests are cryptographically signed and verified |
| Web-Bot-Auth Draft | Defines headers and authentication architecture for autonomous agents |

