Managed auth for every user, every app.
Setu runs the sign-in flow for each app, keeps the tokens in an encrypted vault, and refreshes them before they expire. Your users click Authorize once.
Connect Slack to your agent
Acme Assistant would like to act on your behalf.
One link per connection.
Ask Setu for a connect link, show it to the user, and wait for the connection to turn active. The same call works for every OAuth app in the catalog.
- State, PKCE and redirect checks handled for you
- Your own redirect URL, on an allow-list
- Custom OAuth apps supported for brands that need their own consent screen
const conn = await setu.connections.initiate({
userId: "user_1",
toolkit: "github",
redirectUrl: "https://app.example.com/connected",
});
console.log(conn.connectUrl);
await conn.waitUntilActive();A vault, not a database column.
Every token is encrypted with its own key, wrapped by a master key, and bound to its connection so ciphertext cannot be moved between rows. Keys rotate without asking users to reconnect.
- AES-256-GCM envelope encryption
- Pluggable key provider for your own KMS
- Tokens exist in plaintext only in memory, for one call
Connection lifecycle
Token sealedAES-256-GCM, key k2DoneRefresh scheduled5 minutes before expiryDoneRevoked on disconnectSecrets erasedDone
Refresh and reconnect, automatically.
Tokens refresh in the background and once more on demand if a call returns 401. When a provider revokes access, the connection flips to needs-reauth and the API hands back a new connect link.
- Single-flight refresh to avoid races
- Typed CONNECTION_NEEDS_REAUTH errors
- Webhook and dashboard signals when a user must reconnect
try {
await setu.execute({ userId, action: "slack.post_message", input });
} catch (e) {
if (e.code === "CONNECTION_NEEDS_REAUTH") {
const c = await setu.connections.initiate({ userId, toolkit: "slack" });
// send c.connectUrl to the user
}
}API keys and multiple accounts.
Not every app uses OAuth. Store an API key for the toolkits that need one, and connect more than one account per toolkit when users have several.
- API-key toolkits use the same execute call
- Pass connection_id to choose between accounts
- Per-user quotas protect shared apps
await setu.connections.connectApiKey({
userId: "user_1",
toolkit: "sentry",
apiKey: process.env.USER_SENTRY_TOKEN,
});Give your agent real hands.
Connect an app, hand your agent the tools, and watch it finish the job.