Quick Start
1
Mint a sentinel so the model never sees plaintext
oc-sent-..., not the real key.2
Detect a sentinel at the egress seam
has_sentinel tells the egress guard a request carries a credential and must pass the host allowlist first.3
Substitute back on allowlisted egress only
How It Works
The core owns only the sentinelisation seam; the wrapperβs guard decides what may egress. A sentinel isoc-sent- followed by 32 hex characters. The plaintext lives in a per-process map guarded by a lock and is also registered for log redaction, so an accidental leak of the real value is still masked.
Which Function Do I Pick?
Each function has one call site in the credential lifecycle.
Full signatures live in the auto-generated SDK reference.
secrets module reference
Auto-generated
sentinelize, desentinelize, has_sentinel, and EgressGuardProtocol API surface.Guarantees
- Opaque β the token reveals nothing about the secretβs length, shape, or content.
- Per-process β a token minted in one process cannot be forged or re-used in another;
desentinelizeon an unknown token is a no-op. - Short-value safe β a 1- or 2-character PIN is hidden exactly like a long key; there is no minimum length.
- Idempotent β repeated
sentinelize(same_value)returns the same token;desentinelizeof text with no known token is a no-op. - No performance tax β
desentinelizeonly visits token shapes present in the input, so a bulk registry does not slow a single-token request. - Belt and braces β
sentinelizealso callsregister_secret_for_redaction, so a leaked plaintext is still masked byredact_secrets/redact_outbound.
Common Patterns
Sentinelise the moment a secret is resolved, then reference the token everywhere else.EgressGuardProtocol in your wrapper to enforce a default-deny host allowlist.
Common Pitfalls
- Logging the sentinelized string is harmless (the token is opaque) β but logging the desentinelized version leaks the secret. Only the socket write should ever see post-
desentinelizetext. has_sentinelreturningFalsemeans no known sentinel. A token-shaped string never minted in this process is not a sentinel.- Sentinelisation is per-process, so a sentinel does not survive serialization across processes. If you fork workers, re-sentinelize in the child or route egress through a shared process.
Best Practices
Sentinelize at the resolver boundary
Sentinelize at the resolver boundary
Call
sentinelize the moment resolve_secret(...).value becomes available, before passing anything into an Agent, prompt template, or tool argument builder.Treat the token as plaintext in your UX
Treat the token as plaintext in your UX
The model may freely place
oc-sent-... into prompts and arguments. The egress guard is the single enforcement point, so the token itself needs no special handling upstream.Default-deny host allowlists
Default-deny host allowlists
An
allow_egress that returns True by default defeats the point. Start with an empty allowlist and add hosts explicitly.Never log desentinelize output
Never log desentinelize output
Once you substitute back, the plaintext is live. Keep that string on the wire only β never in a log, metric, or transcript.
Keep the core seam, host enforcement in the wrapper
Keep the core seam, host enforcement in the wrapper
Donβt push proxy or allowlist logic into core.
EgressGuardProtocol exists so core stays protocol-only and nothing heavy is imported.Related
Outbound Secret Scrub
After-the-fact masking on bot replies β complementary to before-the-fact sentinelisation.
Gateway Secret References
Where resolved secrets come from, before you sentinelize them.
secrets SDK Reference
Auto-generated reference for the sentinel functions and protocol.
Hook Events
The seams where an egress guard plugs into the request path.

