Security
KMS-sealed at ingest, decrypted only in worker memory for the duration of one call, never stored in plaintext, and redacted in every read and log. The design — and why it fails closed.
klanex engineering · August 2026 · ~6 min read
An AI agent that does anything useful needs a live production credential. A Stripe secret key to issue a refund. A Slack token to post a message. A bearer token to write a row in someone else's system. The moment your agent stops being a chatbot and starts acting, it needs the keys to the things it acts on.
Which raises the uncomfortable question every agent platform has to answer, and that a run of 2025–2026 incidents forced into the open: where does that credential live, and who — or what — can read it back? When third-party keys leak out of an agent tool, the honest post-mortem is rarely "the model misbehaved." It's that the credential was reachable at all — sitting in a store, a log, or an environment that something else could get to.
So klanex starts from a single principle: you cannot leak what you never stored. A credential should be unreadable at rest and reconstructable only at the exact moment it's used, in the one component that has to make the call — and nowhere else. Three properties fall out of that:
Sealed before anything is written; opened only in the private worker, only in memory, only for the call.
The public API marshals the target header map and seals it with Cloud KMS before the execution is persisted. The plaintext is then dropped from the request object.
Firestore records the ciphertext and the header names for audit — never the values. The queue message carries only the execution ID, not the secret.
The private worker decrypts just before the call, in memory only. The plaintext is never written back — not even after the doc is re-read to claim it.
In the execution model, the field that carries credentials is deliberately marked
firestore:"-" — it is structurally impossible to persist it as-is. On
the ingest path, before a single byte is written, klanex JSON-marshals the header
map and hands it to a sealer. In production that's Cloud KMS
symmetric encryption; locally it's AES-256-GCM with a random nonce
and a key that comes from the environment, never disk. What lands in Firestore is
the ciphertext (encrypted_headers) plus a sorted list of the header
names (header_names) for the audit trail. Then the plaintext
map is set to nil.
The same is true when the URL itself is the secret — a Slack incoming webhook, a
presigned S3 URL. Set seal_url and klanex seals the URL and persists
only a redacted scheme://host/[sealed] form. The path that carried the
token never touches the database.
This is what actually sits in Firestore for an execution — and what the queue hands to the worker:
{
"id": "exe_4d0c85a6",
"target": { "method": "POST", "url": "https://hooks.slack.com/[sealed]" },
"header_names": ["Authorization"], # names, for audit
"encrypted_headers": "AY6•••132 bytes of KMS ciphertext•••",
"encrypted_url": "AY6•••96 bytes of KMS ciphertext•••",
"status": "QUEUED"
}
# no key, no token, no secret URL anywhere in the record
# pub/sub message body: just "exe_4d0c85a6"
The worker is a private Cloud Run service. It has no public surface and no auth code of its own — it's invoked only by the Pub/Sub push subscription over OIDC, with Cloud Run IAM as the gate. When a message arrives, the worker loads the execution, then decrypts the headers and any sealed URL into memory only, immediately before the call. Those plaintext fields are never persisted back.
There's a subtlety that shows the intent. Right after decrypting, the worker atomically claims the execution — which re-reads the document from Firestore, and that fresh copy of course has no plaintext. So klanex deliberately re-attaches the in-memory-only fields onto the claimed doc, makes the call, and lets them fall out of scope. At no point is a decrypted credential written anywhere durable.
The most dangerous failure mode for a system like this is a silent downgrade — a misconfigured deploy that quietly starts storing plaintext because the key wasn't wired up. klanex refuses to do that. With no encryption configured, the binary will not boot unless you have explicitly opted into plaintext for local development:
$ KLANEX_MODE=ingest ./klanex # no KLANEX_KMS_KEY, no KLANEX_LOCAL_KEY
fatal: no header encryption configured: set KLANEX_KMS_KEY (prod) or
KLANEX_LOCAL_KEY (dev), or KLANEX_ALLOW_PLAINTEXT=true to
intentionally store credentials in plaintext
Reliability and security meet in one nice detail. If a decrypt fails — a rotated
key, a botched IAM change — that's a configuration problem, not a problem
with the target API. So the worker nacks the message for redelivery without
consuming one of the execution's retry attempts. A key-management mistake
can't quietly exhaust an execution's budget and fail it; fix the config and the
next delivery just works. The same holds for a managed OAuth token that's been
revoked: klanex fails the execution terminally with an llm_hint telling
a human to re-authorize the connection — it never loops, and it never leaks.
Sealing at rest only helps if the plaintext doesn't leak out some other door. So the read and log paths are redacted by construction:
REDACTED — GET an execution and you see "Authorization": "REDACTED", never the token. The MCP tools that proxy the same API inherit this for free.klanex is not your organization's identity provider or a general secrets manager, and it doesn't pretend to be. It seals the credentials used for the calls it makes on your behalf. And yes — for the duration of a single call, the worker holds the plaintext in memory, because you cannot make an authenticated HTTP request without it. That's the irreducible core. What klanex does is shrink the blast radius around it to the smallest possible shape: a private service with no auth surface, decrypting exactly what it's about to use, persisting none of it, logging none of it, and returning none of it. A compromised read path or a leaked log yields nothing. The store, breached, yields ciphertext.
That's the whole idea. You can't leak what you never stored — so don't store it.
Start free — 1,000 executions a month, the full reliability engine, no credit card to explore.