Skip to main content
A resolved secret is swapped for an opaque, per-process token the model can carry safely; the real value is put back only at the moment a request egresses to an allowlisted host.

Quick Start

1

Mint a sentinel so the model never sees plaintext

The agent holds 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

The plaintext reappears only for the one allowlisted request.

How It Works

The core owns only the sentinelisation seam; the wrapper’s guard decides what may egress. A sentinel is oc-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; desentinelize on 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; desentinelize of text with no known token is a no-op.
  • No performance tax β€” desentinelize only visits token shapes present in the input, so a bulk registry does not slow a single-token request.
  • Belt and braces β€” sentinelize also calls register_secret_for_redaction, so a leaked plaintext is still masked by redact_secrets / redact_outbound.

Common Patterns

Sentinelise the moment a secret is resolved, then reference the token everywhere else.
Implement 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-desentinelize text.
  • has_sentinel returning False means 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

Call sentinelize the moment resolve_secret(...).value becomes available, before passing anything into an Agent, prompt template, or tool argument builder.
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.
An allow_egress that returns True by default defeats the point. Start with an empty allowlist and add hosts explicitly.
Once you substitute back, the plaintext is live. Keep that string on the wire only β€” never in a log, metric, or transcript.
Don’t push proxy or allowlist logic into core. EgressGuardProtocol exists so core stays protocol-only and nothing heavy is imported.

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.