agent.pw is a credential vault for AI agents. It stores encrypted credentials, handles OAuth flows (PKCE, refresh, revocation, RFC 9728 discovery), and resolves fresh auth headers at runtime from one stable connection path.
npm install agent.pw
npx skills add https://github.com/smithery-ai/agent.pwThen run:
/setup-agentpw
import { createAgentPw } from "agent.pw";
import { createInMemoryFlowStore } from "agent.pw/oauth";
import { createDb } from "agent.pw/sql";
import { unwrap } from "okay-error";
const db = unwrap(createDb(process.env.DATABASE_URL!));
const agentPw = await unwrap(
createAgentPw({
db,
encryptionKey: process.env.AGENTPW_ENCRYPTION_KEY!,
flowStore: createInMemoryFlowStore(),
}),
);connect.prepare(...) checks for an existing credential, then applies profile HTTP inputs, profile OAuth, or discovery:
const prepared = await unwrap(
agentPw.connect.prepare({
path: "acme.connections.docs",
resource: "https://docs.example.com/mcp",
}),
);
if (prepared.kind === "ready") {
// Credential already exists — use the headers
return prepared.headers;
}
if (prepared.kind === "input_required") {
// Render prepared.input.http to collect the missing values.
// Query inputs stay in the resource URL.
// Header inputs are stored through connect.setHeaders(...).
return prepared.input;
}
// OAuth options are ordered by preference.
const option = prepared.options[0];
if (option?.kind === "oauth") {
const session = await unwrap(
agentPw.connect.startOAuth({
path: "acme.connections.docs",
option,
redirectUri: "https://app.example.com/oauth/callback",
}),
);
return Response.redirect(session.authorizationUrl, 302);
}
throw new Error("This resource is not configured yet");const headers = await unwrap(agentPw.connect.resolveHeaders({ path: "acme.connections.docs" }));
// OAuth tokens are refreshed automatically- Encrypted credential storage — OAuth tokens and API keys stored at rest with AES-GCM
- OAuth lifecycle — PKCE, token refresh, revocation, RFC 9728 discovery
- Credential profiles — admin-configured HTTP input and OAuth guidance for known providers
- Path-based organization — hierarchical
ltreepaths (acme.connections.github) - Scoped access — enforce path-based rights via
agentPw.scope({ rights }) - Embeddable — works with any Postgres-compatible database, no separate server required
- Getting started — setup, connect flow, OAuth callbacks
- API reference — full
connect,credentials,profilesAPI - Credential profiles — admin configuration for HTTP inputs and OAuth overrides
- Architecture — design decisions and data model
- Security model — path-based access, encryption, token scoping
pnpm install
pnpm build # typecheck
pnpm test # run tests (in-memory PGlite)
pnpm run lint # lint
pnpm run db:generate # generate Drizzle migrations from schema changesFSL-1.1-MIT — converts to MIT after two years.
