JIT
← Notebook
Field notes AI AgentsSecuritySecrets Management

Giving an AI agent the keys, safely

Wiring our identity agent into a secrets manager without handing it the kingdom — read-only by default, segregation of duties, and writes you have to mean.

We run a small fleet of AI agents in the homelab — systems, network, security, identity. Each is a thin shell around a set of skills, where a skill is a tool definition plus the code that calls a real backend. This week the identity agent got a new one: access to Infisical, our secrets manager.

That sentence should make any auditor twitch. An AI agent with reach into the one system whose entire job is to hold the things you most want to protect? The interesting work wasn’t the integration. It was making the integration something you’d actually sign off on.

The need

The brief was easy to say and harder to honour:

  • Read-only by default. The agent observes; it doesn’t mutate unless a human says so.
  • Least privilege. No admin token, no shared “god” credential.
  • Segregation of duties. The identity that reads secrets must not be the one that writes them.
  • No leaks. Secret values never land in a transcript, a log, or a summary by accident.

None of this is novel. It’s the same control set you’d demand of a human operator. The agent doesn’t get a discount on it.

The structure

The skill is deliberately a thin REST client, not a vendor SDK — the official one pulled in a full cloud SDK we’d never use, so we kept the dependency and attack surface small.

Access is split across two machine identities:

IdentityRole in InfisicalUsed for
ReadViewer (read-only)listing and reading secrets, folders, audit logs
Writescoped write rolecreate / update / delete, nothing else

The read identity cannot change anything. The write identity is only ever used for explicit changes, and the code never quietly falls back from one to the other. If no separate write identity is configured, every write is simply refused.

On top of the identities sits a layered guard, each layer cheap and boring on purpose:

  1. Kill switch — writes are off until deliberately enabled.
  2. Two-phase confirm — every change first returns a dry-run preview (“PERMANENTLY delete secret X [env=prod]”) and executes nothing.
  3. Blast-radius acknowledgement — irreversible actions need a second, explicit sign-off.
  4. Audit trail — every attempt is logged, with secret values redacted.
  5. Reveal gate — values are masked by default; showing plaintext takes a separate, explicit opt-in.

Defence in depth means the agent has to clear all of it and still be authorised server-side. The guard is on top of Infisical’s own permissions, not instead of them.

The result

A working integration we verified end to end against the live instance:

  • Reads ran on the Viewer identity; every mutation ran on the separate write identity — confirmed in the logs.
  • The full change path — create, read back, update, delete, verify gone — worked, each step gated by preview and acknowledgement.
  • Secret values stayed redacted throughout, even immediately after writing them.
  • An offline test suite (a dozen checks) proves the guards hold before any network call is made — so the safety logic is testable without ever touching a real secret.

The honest takeaway has very little to do with AI. It’s an old auditing principle — least privilege and segregation of duties — applied to a new kind of operator. Give automation exactly the access it needs, split read from write, make destructive actions deliberate, and keep the receipts. That the operator happens to be an AI agent doesn’t soften the controls. It just makes them non-negotiable.