Redaction
AgentGem's core safety rule: secrets are redacted at capture. The moment config is read,
secret values are stripped — before anything crosses a boundary. This page specifies the
rules and the data that carries them, as implemented in src/gem/redact.ts.
The trust boundary
Redaction runs inside introspect (see the pipeline), so the
ConfigInventory is already redacted before it reaches a REST response, an MCP result, the
live preview in the UI, or the built Gem. Serving config over HTTP and MCP doesn't weaken
this — it's the same redaction the original CLI enforced. Secrets stay on the machine; what
leaves is a config shape with <redacted> in place of every sensitive value.
buildGem adds a second line: any MCP/hook artifact that arrives without secretRefs is
re-redacted before it enters a Gem. A Gem therefore cannot be constructed from un-redacted
input, even if a caller skips introspection.
What counts as a secret
redactMcpConfig(config) walks the config recursively and redacts a string value when any of
these hold:
Key name matches the secret pattern:
/(api[_-]?key|token|secret|password|passwd|bearer|sk-|ghp_|gho_|xox[a-z]-|credential)/iThis catches
api_key/apiKey/api-key,token,secret,password,bearer, and provider prefixes likesk-…,ghp_…,gho_…,xox….Value looks like a credential:
- a whitespace-free string that matches the pattern above or is a high-entropy token
(32+ chars of
[A-Za-z0-9_-]); or - a multi-word string in which any token is high-entropy (so a sentence that happens to contain a pasted key is still caught, while ordinary prose mentioning the word "token" is not).
- a whitespace-free string that matches the pattern above or is a high-entropy token
(32+ chars of
Context defaults: values under an
envorheadersmap are treated as secret by default, since those are where credentials normally live.
When a value is redacted it becomes the literal string "<redacted>", and a reference is
recorded.
What it records — SecretRef
interface SecretRef {
name: string; // leaf key, e.g. "OPENAI_API_KEY"
location: string; // dotted path within the artifact config, e.g. "env.OPENAI_API_KEY"
}
buildGem aggregates these into the Gem's declared secret surface:
interface SecretRequirement {
name: string; // e.g. "OPENAI_API_KEY"
artifact: string; // owning artifact, e.g. mcp server "context7"
location: string; // re-injection path, e.g. "env.OPENAI_API_KEY"
}
So a Gem says which secrets it needs and where they plug in — never their values. Deploy
backends use this to wire up secret references (e.g. AgentCore maps each one to a token-vault
placeholder; managed publish collects them as vaultSecrets) without AgentGem ever handling
the real secret.
Server credentials are different
The secrets above are artifact secrets and are always redacted. Separately, the AgentGem
server needs its own credentials to talk to deploy backends (e.g. ANTHROPIC_API_KEY,
VERCEL_TOKEN, CLOUDFLARE_API_TOKEN). Those are stored on the machine in
~/.agentgem/.env (mode 0600) via credentials.ts and loaded at startup — they are
server config, never part of a Gem. See Testbed & run.
Related
- The build pipeline — where redaction sits in the flow
- Archive format — how
secretRefs/requiredSecretsare stored - Concepts — the conceptual framing