← Articles and guides

Choose AccessKey or Ed25519 credentials for an agent

Compare agent access keys and Ed25519 public-key sign-in, scope credentials to applications, and plan independent rotation and revocation.

An agent needs its own credential so you can rotate or revoke its access without replacing your personal sign-in. Sudomimus supports an AccessKey secret and Ed25519 public-key sign-in for the same Agent identity. Choose based on how the runtime stores secrets and signs requests.

An Agent belongs to your account; it is not another user account. Use an Agent for software that reads context and chooses tools or next steps. Use an Automation for a fixed workflow, such as a scheduled backup. Both credential families support both kinds. See Agents and automation for the product overview.

1. Choose the credential your runtime can protect

Question AccessKey Ed25519 public key
What does the runtime keep? A credential identifier and long-lived secret. A credential identifier and private key.
What does Sudomimus receive at sign-in? The identifier and secret, over HTTPS. A short-lived signed assertion; the private key stays with you.
Where can it authenticate? The application selected at creation. The immutable application and sector coverage selected at registration.
What must the runtime implement? A protected HTTPS credential exchange. Ed25519 signing, fresh replay identifiers, and an exact request-body hash.
How is it rotated? Create a replacement, switch the runtime, then revoke the old key. Register a replacement public key, switch the signer, then revoke the old key.

Choose AccessKey when a protected runtime already has a secret store and you want the simpler integration. Choose public-key sign-in when you have reliable private-key storage and signing support. A private key still needs protection; this choice does not make a compromised runtime harmless.

The public-key assertion authenticates the session-issuance request. The resulting access token is still a bearer token. Ed25519 sign-in does not add DPoP, mTLS, or a signature to every application resource request.

If a person launches your CLI and can approve login in a browser, consider Device Authorization instead of storing a long-lived credential.

2. Create the Agent and admit its exact credential type

In the With portal, open Programmatic access → Agents and create one identity for the task and environment. Select that Agent when creating an access key or registering a public key. A credential created for your Account remains an Account credential; it cannot be reassigned to an Agent.

The target application needs the exact authentication method:

Principal AccessKey method Public-key method
Agent AGENT_ACCESS_KEY_DIRECT AGENT_PUBLIC_KEY_DIRECT
Automation AUTOMATION_ACCESS_KEY_DIRECT AUTOMATION_PUBLIC_KEY_DIRECT

Allowing Account AccessKeys does not also allow Agent AccessKeys. The application also needs an account-admission rule that admits the owning account and a DIRECT_ISSUE return rule. Activate it before testing. All three rule layers apply.

Profile data comes from the owning account’s current sharing policy and grants. A headless runtime cannot invent consent. AccessKey creation can collect the target application’s sharing decision in the portal. If public-key issuance requires missing consent or account data, complete the returned browser remediation flow before retrying.

3. Keep coverage as narrow as the task needs

An AccessKey targets one application. A public key can cover named applications or sectors. A sector entry includes applications assigned to that sector later. Use an application entry when the Agent needs only one application.

Public-key coverage cannot be edited after registration. To change it, register a replacement, update the runtime, and revoke the old credential. Use separate credentials for development and production.

Coverage determines where the credential can authenticate. It does not grant a role, database access, or permission to call a business operation. Your application evaluates those permissions after verifying the session. The owner’s pairwise sub and the Agent’s pairwise act.sub identify different responsibilities; do not treat the Agent as the human owner or accept unverified token fields.

4. Exchange a credential from a protected runtime

For AccessKey, store the identifier and secret immediately after creation. The portal cannot reveal the secret later. Send them only from your protected runtime:

agent/access-key-login.tsTypeScript
const response = await fetch(
"https://native-api.sudomimus.com/direct-issue/access-key",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
applicationAnchor: process.env.SUDOMIMUS_APPLICATION_ANCHOR,
accessKeyIdentifier: process.env.SUDOMIMUS_ACCESS_KEY_ID,
accessKeySecret: process.env.SUDOMIMUS_ACCESS_KEY_SECRET,
}),
},
);
if (!response.ok) {
throw new Error(`Agent sign-in failed (${response.status})`);
}
const { accessToken, refreshToken } = await response.json();

For public-key sign-in, generate an Ed25519 key pair in the portal or your own system. Register only the public key. On macOS or Linux with OpenSSL, these commands create a local pair:

Terminal windowShell
umask 077
openssl genpkey -algorithm Ed25519 -out agent.private.pem
openssl pkey -in agent.private.pem -pubout -out agent.public.pem

Paste only agent.public.pem into the portal and select the Agent and its coverage. The portal converts the public PEM to the accepted public JWK. Never paste the private PEM. Configure the returned public-key credential identifier and private-key path in your runtime.

This Node.js example hashes the exact body it sends and signs a fresh assertion for that request. The Ed25519 credential belongs to the Agent; it is separate from an application’s Connect client-auth signing key.

agent/public-key-login.tsTypeScript
import { createHash, createPrivateKey, randomBytes, sign } from "node:crypto";
import { readFileSync } from "node:fs";
function requiredEnvironment(name: string): string {
const value = process.env[name];
if (!value) {
throw new Error(`Missing runtime environment variable: ${name}`);
}
return value;
}
const credentialIdentifier = requiredEnvironment("SUDOMIMUS_PUBLIC_KEY_ID");
const privateKey = createPrivateKey(readFileSync(
requiredEnvironment("SUDOMIMUS_PRIVATE_KEY_FILE"),
));
const body = JSON.stringify({
applicationAnchor: requiredEnvironment("SUDOMIMUS_APPLICATION_ANCHOR"),
});
const now = Math.floor(Date.now() / 1000);
const encode = (value: object) => Buffer.from(JSON.stringify(value)).toString("base64url");
const header = encode({
alg: "EdDSA",
typ: "vnd.sudomimus.public-key-assertion+jwt",
kid: credentialIdentifier,
});
const payload = encode({
iss: credentialIdentifier,
aud: "sudomimus-native-public-key",
iat: now,
exp: now + 60,
jti: randomBytes(16).toString("base64url"),
requestHash: createHash("sha256").update(body).digest("base64url"),
});
const signingInput = `${header}.${payload}`;
const signature = sign(null, Buffer.from(signingInput), privateKey).toString("base64url");
const response = await fetch(
"https://native-api.sudomimus.com/direct-issue/public-key",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `SudomimusPublicKeyJWT ${signingInput}.${signature}`,
},
body,
},
);
if (!response.ok) {
throw new Error(`Agent sign-in failed (${response.status})`);
}
const { accessToken, refreshToken } = await response.json();

For every retry, generate a new assertion with a new jti; do not resend a used assertion. Keep the runtime clock synchronized. Validate returned tokens with the token verification guide, retain the credentials on the server, and use Session API for refresh and logout. Neither example logs secrets or tokens.

5. Test rotation and revocation independently

Test a permitted application, an application outside credential coverage, and a suspended Agent. For public keys, also test a changed request body and a replayed assertion. Both must be denied.

For routine rotation, create and test a replacement before revoking the old credential. Revoke a possibly leaked credential immediately. Suspending or revoking the Agent invalidates its earlier session authority; resuming it does not revive old sessions. An application that uses only offline JWT verification cannot observe revocation immediately. Use live Session introspection when an operation requires current session authority.

Start with access-key management or public-key registration. For a fixed background workflow, follow the scheduled-job identity guide.