When an AI agent calls a tool, the call's arguments leave your side of the boundary. A webhook connector, a CRM write, an SMS dispatch: each receives the payload exactly as the model composed it. Orbit scrubs the model's replies, the tool results that re-enter the conversation, and the error surfaces a run produces. None of that touches the argument object, and the model builds those arguments from a conversation your end users type.
That asymmetry is the subject of this post. The failure mode is not a hallucinated answer. It is a tool call that succeeds with a real identifier the operator never intended to send, while every output-side guard reads clean. What follows is the control Devotel Orbit ships for that path: an opt-in egress scrub on the agent's safety configuration, what its detector floor actually covers, the honest limit for tools that parse their arguments, the write contract around the flag, and how the guard composes with the rest of the safety stack.
The failure mode is a successful tool call
Most AI-safety conversations start with hallucination, a model inventing facts. On the egress side the dangerous outcome is the opposite: fidelity. A user who writes "email my records to me@example.com" or reads out a phone number gets a model that copies that value faithfully into a tool argument, and a dispatch that succeeds. The identifier is now outside every perimeter you scrub, carried by a connector you approved for a different purpose.
The fraud bulletins that shaped this year's buyer questions read the same way. Cloned-voice and agentic-fraud attacks work because a real identifier reaches a real channel with nobody in between, the mechanic our deepfake voice fraud explainer walks for voice. The same mechanic applies inside your own workspace when an agent's tool surface can carry a customer's phone number or email out through a webhook.
Under a data-minimization boundary, GDPR Art. 5(1)(c) or HIPAA's minimum-necessary rule, a tool argument carrying a customer identifier to a third-party connector is an egress event and it needs an owned control. The posture buyers now ask about in security reviews (see our CPaaS vendor security review guide) is tenant-owned: the operator decides which agents run with the guard, and the platform never flips the posture for you.
What Orbit ships: an opt-in last-pass scrub
The control is a boolean on the agent's safety configuration, pii_egress, written through the same endpoint as any agent update, PUT /api/v1/agents/:id, with POST /api/v1/agents accepting the same body at creation:
{
"safety_config": { "pii_egress": true }
}With the flag on, the executor takes one last pass over a tool call's arguments before dispatch: every string value anywhere in the payload is scanned, and a hit is rewritten in place. The scrub is structure-preserving. Keys, numbers, booleans, and nulls are untouched, and when nothing matches the payload goes out byte-identical to what the model composed, so size checks and audit rows see no delta on the clean path.
The default detector set is the universal floor every output-side guard already uses: email addresses, E.164 phone numbers, US Social Security numbers, and credit card numbers. Before and after, for a webhook-style tool call:
// Composed by the model from the user's instruction
{
"subject": "Your records export",
"to": "me@example.com",
"callback": "+4915123456789",
"note": "Export for the account we discussed"
}// After the egress guard, before dispatch
{
"subject": "Your records export",
"to": "[REDACTED]",
"callback": "[REDACTED]",
"note": "Export for the account we discussed"
}Regional identifiers are a tenant decision, not a default. IBANs and national ID numbers join the scan only when the agent has opted into the matching locale bundle via safety_config.locale_pii_patterns, and the egress guard layers the same codes the output side already uses, so the two surfaces never disagree about what counts as PII. If your security review names IBANs, opt the agent into the iban bundle and the egress scrub follows. The full model, including the fail-open posture, is documented on the PII egress guard concept page.
The honest limit: tools that parse what you redact
Redaction turns a value into a sentinel, and some tools parse their arguments instead of reading them. The canonical example is orbit_send_sms, whose to field must parse as an E.164 number. Enable the guard on an agent that sends SMS to user-provided numbers, and a redacted recipient turns a dispatchable call into a failed one at send time. The write succeeded, the argument was scrubbed, and the failure surfaces on the tool call, where the run's tool history shows it.
That is the design, not a defect: a silent send to a mangled recipient would be worse than a visible dispatch failure. The practical rule is to pair redaction with an explicit tool allow-list per agent:
- Enable the flag for agents whose tools treat arguments as opaque text: webhook connectors, CRM field writes, tools on your own MCP server.
- Leave it off where a tool parses strict identifiers, and cover those agents with the output-side guards plus the approval gate in the next section.
There is deliberately no platform-wide mandate. The update accepts the flag on any agent because tool tolerance is a fact only the operator knows, and validation checks the shape of the write, not the tolerance of the tools that will run under it.
The write contract: 400, 422, and no half-applies
Two reject shapes, both before anything persists:
- Not valid JSON. The body is rejected with 400 Bad Request before schema validation runs.
- Valid JSON, wrong shape. The body is rejected with 422 Unprocessable Entity and the agent is left untouched.
"pii_egress": "yes", a numeric1, or asafety_configthat is a string or an array all fail here, and sibling fields are policed the same way.
// Rejected with 422: pii_egress must be a boolean
{
"safety_config": { "pii_egress": "yes" }
}The property that matters in a security review is that a rejected write leaves the running agent exactly as it was. A malformed safety configuration never lands half-applied, and an agent cannot end up with the flag on while a sibling field silently dropped.
Composing the guard with approvals and authored rules
The egress guard is one layer of a three-layer posture, and the layers compose because they act at different times:
- Before dispatch, deterministic. The egress guard rewrites the argument itself.
- Before dispatch, human. Human-in-the-loop tool approvals pause a call until an owner or admin signs off, with the proposed arguments on the pause card. Where a tool must receive the real identifier, an approval gate is the right control and redaction is the wrong one. Gate the few calls that move money or carry PII; let the lookups run.
- After the fact. The custom guardrail DSL adds tenant-authored
warnrules for post-hoc review of what the model said, complementing what the egress scrub does to what the model sent.
A reviewer-readable summary: redact what a tool does not need, gate what it does, and review the rest.
Choose per agent, audit per dispatch
The posture that holds up in review is tenant-owned on both axes. Choose per agent: the flag defaults off and changes behavior only on the agents you enable. Audit per dispatch: a scrubbed argument that breaks a strict tool fails visibly on the tool call; a gated call writes a pending row that records the proposed arguments and the decider; both leave a record an auditor can actually read. Nothing about the control is platform-mandated, and that is the point. A data-minimization boundary is yours, so the switch that enforces it is yours too.
Frequently asked questions
Is the guard on by default?
No. pii_egress defaults off and agents without it behave exactly as before. The platform never enables it on your behalf.
Does it scrub IBANs and national IDs out of the box?
Only if you opt the agent into the matching locale bundle. The default floor is email, E.164 phone, US SSN, and credit card, the same always-on set the output-side guards use. Opting into the iban bundle or a national-ID bundle extends the output side and the egress side together.
What happens to an SMS send when the recipient is redacted?
The dispatch fails at send time: orbit_send_sms parses to as E.164 and a redacted value does not parse. The failure shows on the tool call in the run record. For agents whose job is sending to user-provided numbers, use approvals instead of redaction.
Can a bad write leave an agent half-configured?
No. A non-JSON body gets 400 before validation; a shape violation gets 422 and leaves the agent untouched.
How does this relate to output redaction?
It is beside it, not above it. Output redaction scrubs what the model says to a user; the egress guard scrubs what the model sends through a tool. Neither substitutes for the other, and both read from the same detector set.
---
For the structure-preserving scrub model and the fail-open posture, read the PII egress guard concept page. For the pre-execution gate that covers tools redaction cannot, read the human-in-the-loop approvals guide.