Skip to main content

What You’ll Learn

  • Creating a sandbox with rehydrate_response=True (transparent mode)
  • Creating a sandbox with rehydrate_response=False (strict mode)
  • The five-step flow: send, redact, process, restore, receive
  • When to use each mode

How Rehydration Works

When rehydrate_response=True, the MITM proxy maintains a per-request token mapping:
  1. Send — Code in the sandbox sends an HTTP request containing PII (e.g., john@example.com)
  2. Redact — Proxy replaces PII with a token: [REDACTED_EMAIL_1] and stores the mapping
  3. Process — The external API receives the sanitized request and responds (possibly echoing the token)
  4. Restore — Proxy scans the response, finds [REDACTED_EMAIL_1], and restores john@example.com
  5. Receive — Sandbox code receives the response with the original PII value — completely transparent
With rehydrate_response=False, step 4 is skipped and redaction tokens remain in the response.
PII scanning via the guardrails service is rolling out. This example demonstrates the SDK API for configuring PII rehydration — the policy is accepted and stored today.

Prerequisites

This example is available in Python. TypeScript version coming soon.

Code Walkthrough

Rehydration enabled — sandbox code sees the original PII in responses:
from declaw import Sandbox, SecurityPolicy, PIIConfig

policy = SecurityPolicy(
    pii=PIIConfig(
        enabled=True,
        types=["email", "phone"],
        action="redact",
        rehydrate_response=True,
    )
)

sbx = Sandbox.create(template="base", timeout=300, security=policy)
try:
    print(f"Sandbox created: {sbx.sandbox_id}")
    # When guardrails service is active:
    # POST { "msg": "Contact john@example.com" }
    # -> proxy sends: { "msg": "Contact [REDACTED_EMAIL_1]" }
    # <- API replies: { "reply": "I will email [REDACTED_EMAIL_1]" }
    # -> proxy restores: { "reply": "I will email john@example.com" }
    # Sandbox code receives the restored version.
finally:
    sbx.kill()
Rehydration disabled — redaction tokens remain in responses (strict mode):
policy = SecurityPolicy(
    pii=PIIConfig(
        enabled=True,
        types=["email", "phone"],
        action="redact",
        rehydrate_response=False,
    )
)

sbx = Sandbox.create(template="base", timeout=300, security=policy)
try:
    print(f"Sandbox created: {sbx.sandbox_id}")
    # POST { "msg": "Contact john@example.com" }
    # -> proxy sends: { "msg": "Contact [REDACTED_EMAIL_1]" }
    # <- API replies: { "reply": "I will email [REDACTED_EMAIL_1]" }
    # -> proxy passes through unchanged
    # Sandbox code receives: { "reply": "I will email [REDACTED_EMAIL_1]" }
finally:
    sbx.kill()

Choosing a Mode

Moderehydrate_responseUse When
TransparentTrueApplication must work as if PII was never redacted; best for most LLM workflows
StrictFalseSandbox code must never see original PII in responses; maximum privacy isolation