ToolMinimize: Why 81–88% of LLM Agent Tool Calls Over-Share Private Data — and What Codex CLI's PreToolUse Hook Can Do About It
ToolMinimize: Why 81–88% of LLM Agent Tool Calls Over-Share Private Data — and What Codex CLI’s PreToolUse Hook Can Do About It
The Structural Over-Sharing Problem
When a coding agent submits a tool call — whether to an MCP server, a REST API, or a shell command — it passes arguments to a third-party service. LLMs, trained to be maximally helpful, habitually include every piece of context they hold that might conceivably be relevant. This turns every tool invocation into an uncontrolled data disclosure boundary.
Li and Xu (Peking University) quantified the problem in ToolMinimize: Auditing and Rewriting LLM Agent Tool Calls to Minimize Privacy Exposure (arXiv:2608.24957, August 2026).1 Their controlled measurement across GPT-4o, Claude 3.5 Sonnet, and Llama-3.3-70B found that 81–88% of tool calls include unnecessary privacy-sensitive data (PSD) under default prompts. Explicit privacy instructions reduce this only to 36–76% — with Llama improving barely at all (81% → 76%).
The examples are mundane:
- A weather query passes
"9500 Euclid Avenue, Cleveland OH"when the API needs only"Cleveland, OH". - A calendar event is titled
"Couples Counselling with Dr. Patricia Hoffman"instead of"Appointment". - An email to a manager includes
"severe anxiety and panic attacks since the layoffs"when a day-off request requires no diagnosis. - One model transmitted a user’s SSN and income level to an accountant tool.
None of this is prompt-injection. The agents are not compromised — they are just extraordinarily forthcoming.2
Why Existing Defences Fall Short
Prior defences either gate tool calls (allow/block) or label information flows. Both fail the same way: they cannot rewrite argument values.
| Approach | PCS Residual | Task Completion (TCR) |
|---|---|---|
| No mitigation | 11.68 | 100% |
| Prompt (system) | 6.71 | 100% |
| PII detection | 4.29 | 100% |
| Blocking (PrivacyChecker) | 0.47 | 3% |
| ToolMinimize | 0.59 | 100% |
ToolMinimize achieves 7.3× lower residual PCS than PII detection while maintaining full task validity.1 The blocking approach (PrivacyChecker) reduces privacy cost to nearly zero — but it does so by refusing to execute most tool calls. Useless in production.
There is also a detection gap: classical PII tooling misses implicit PSD. The string "Memorial Sloan Kettering Cancer Center, 1275 York Ave" does not match a phone-number regex, yet it reveals a cancer diagnosis through the facility name. ToolMinimize’s semantic classifier catches these cases via a facility-name lookup and cross-field inference.1
The Privacy Cost Metric
ToolMinimize formalises the problem with a Privacy Cost (PC) metric computed per tool call argument:
PC(t, args) = Σ S(pⱼ) · E(f) · N(pⱼ, f)
Where:
- S(p): Sensitivity level (1–4) drawn from a 10-category taxonomy grounded in GDPR Article 93
- E(f): Trust level of the receiving function (0.2 for local, 1.0 for uncontracted third-party)
- N(p, f): Binary necessity indicator — 1 if the PSD item is not minimum-necessary for the tool
The 10-category taxonomy covering sensitivity 1–4:
| Category | S | Examples |
|---|---|---|
| Direct Identifiers | 4 | SSN, email, phone, full name |
| Health | 4 | Conditions, medications, diagnoses |
| Financial | 4 | Account numbers, income, transactions |
| Quasi-Identifiers | 3 | Age, ZIP, occupation, date of birth |
| Location | 3 | Street addresses, GPS coordinates |
| Relational | 3 | Family associations, relationships |
| Behavioural | 2 | Habits, substance use, preferences |
| Temporal Patterns | 2 | Schedules, routines |
| Intent | 2 | Inferred goals, plans |
| Implicit Context | 1 | Contextual implications |
In practice, 69.4% of observed PSD items fall into critical-sensitivity categories (DI 33.0%, H 26.6%, F 9.8%).1
The metric is ordinal-stable: Kendall’s τ = 1.0 across 110 weight perturbations, so the ranking of tool calls by privacy risk is robust to parameterisation choices.1
The Four Minimisation Operations
ToolMinimize’s rewriting layer applies four operations in decreasing invasiveness:
- Removal — delete optional fields that carry PSD but are not required by the tool schema
- Generalisation — coarsen a value to the minimum-necessary granularity (street address → city, GPS to one decimal place, ZIP+4 to ZIP-5)
- Substitution — insert a synthetic schema-valid placeholder (
user@example.com,Appointment,John Doe) - Truncation — shorten free-text fields to remove PSD-carrying suffixes
The system processes these through a four-stage pipeline:
flowchart LR
TC[Tool Call Args] --> CL[Classify PSD]
CL --> SC[Score PC]
SC --> AN[Schema\nAnalysis]
AN --> RW[Rewrite]
RW --> OUT[Scrubbed Args]
SC -->|Audit log| LOG[(Privacy Log)]
AN -->|Optional| SEM[Semantic\nNecessity LLM]
SEM --> RW
The SchemaAnalyzer parses the tool’s JSON Schema to distinguish required fields from optional ones, and applies tool-specific minimum-necessary handlers (weather → city level, calendar → generic title, maps → destination only). A base64-decoding preprocessor defeats 9 of 10 common encoding evasions.1
Latency: median 1.77ms on the schema-only path; the optional LLM content-aware extension adds ~800ms but raises reduction from 88.9% to 91.6%.
Benchmark Results
On the 307-call live validation set and the AgentPrivBench benchmark (90 curated scenarios: healthcare, finance, workplace, travel, legal):
| Model | PCS Before | PCS After | Reduction |
|---|---|---|---|
| GPT-4o | 3.95 | 0.40 | 90.0% |
| Claude Sonnet | 5.20 | 0.42 | 92.0% |
| Llama-3.3-70B | 3.05 | 0.57 | 81.2% |
| Average | 4.10 | 0.46 | 88.9% |
Argument-level task validity (TCR) is 100% across all three models. Equivalence confirmed by TOST at p < 0.001 with Δ = 1.0.1
Domain performance: near-zero residual PCS in finance (0.08), healthcare (0.43), personal (0.42), and workplace (0.00). Travel remains higher (2.00) — booking systems genuinely require named entities.
On 25 real-world MCP server schemas (Shopify, GitHub, Discord, and others, with no minimum-necessary annotations): 79.0% cost reduction with no task failures.1 On cross-agent delegation scenarios (15 Stage E transfers), PCS dropped from 12.60 to 0.00 at 100% TCR.
MCP Integration and the Codex CLI Connection
The paper explicitly describes MCP integration: ToolMinimize intercepts tools/call JSON-RPC requests at the client transport layer before they are dispatched to MCP servers.1
Codex CLI routes MCP tool calls through exactly this layer. The PreToolUse hook is Codex CLI’s native intercept point — it fires before any tool execution with the tool name and full argument payload, and an exit code of 2 blocks the call.4
sequenceDiagram
participant Agent as Codex Agent
participant Hook as PreToolUse Hook
participant MCP as MCP Server
participant Log as Privacy Log
Agent->>Hook: tool=mcp_tool name=create_issue args={...}
Hook->>Hook: Classify PSD in args
Hook->>Hook: Score PC(t, args)
Hook->>Log: Append audit record
alt PC > threshold
Hook-->>Agent: exit 2 (block)
else
Hook->>Hook: Rewrite args
Hook->>MCP: Scrubbed tool call
MCP-->>Agent: Result
end
A minimal PreToolUse hook implementing the ToolMinimize pattern in Python:
#!/usr/bin/env python3
"""
pretooluse-privacy-scrub.py
Intercepts MCP tool calls and blocks calls exceeding a privacy cost threshold.
Exits with code 2 to block; 0 to allow (with optional rewriting via stdout).
"""
import json
import re
import sys
# Load the hook input from Codex CLI
event = json.loads(sys.stdin.read())
tool = event.get("tool", {})
tool_name = tool.get("name", "")
args = tool.get("input", {})
# --- Simplified PSD detection ---
PSD_PATTERNS = {
"ssn": (re.compile(r"\b\d{3}-\d{2}-\d{4}\b"), 4),
"email": (re.compile(r"[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+"), 4),
"street": (re.compile(r"\b\d+\s+[A-Z][a-z]+\s+(St|Ave|Rd|Blvd|Dr|Ln)\b"), 3),
"phone": (re.compile(r"\b\d{3}[-.\s]\d{3}[-.\s]\d{4}\b"), 4),
}
EXTERNAL_TRUST = 1.0 # uncontracted third-party MCP server
def compute_pc(args_str: str) -> float:
pc = 0.0
for _, (pattern, sensitivity) in PSD_PATTERNS.items():
if pattern.search(args_str):
pc += sensitivity * EXTERNAL_TRUST # N=1 (unnecessary assumed)
return pc
args_str = json.dumps(args)
pc = compute_pc(args_str)
THRESHOLD = 4.0 # Block if PC >= S=4 (Direct Identifier or Health exposure)
if pc >= THRESHOLD:
result = {
"decision": "block",
"reason": f"Privacy cost {pc:.1f} exceeds threshold {THRESHOLD}. "
f"Tool call to '{tool_name}' contains potential PSD. "
"Review and strip sensitive fields before retrying.",
}
print(json.dumps(result))
sys.exit(2)
sys.exit(0)
Register in hooks.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "mcp_.*",
"hooks": [
{
"type": "command",
"command": "python3 ~/.codex/hooks/pretooluse-privacy-scrub.py"
}
]
}
]
}
}
AGENTS.md Privacy Context Declaration
Codex CLI’s AGENTS.md is the right place to declare minimum-necessary field policies — the equivalent of ToolMinimize’s schema annotations. This allows the agent’s reasoning to apply the right generality before the hook fires as a backstop:
## Privacy and Data Minimisation
Tool calls to external MCP servers MUST follow the principle of minimum necessary disclosure:
- **Location fields**: Use city-level precision only (e.g., "London" not "14 Baker Street, London W1U 7AF")
- **User references**: Use display names, not email addresses or account IDs, unless the tool schema explicitly requires them
- **Calendar events**: Use generic titles ("Meeting", "Appointment") not diagnostic or relationship-revealing titles
- **Email bodies**: Strip personal health, financial, or relational context not required for the request
- **Cross-agent messages**: Do not forward PII received in one tool result to the next tool's arguments
If uncertain whether a value is minimum-necessary, use a generalised form or omit it.
Multi-Agent Delegation: The Hidden Amplifier
The most alarming result in the paper is the cross-agent delegation scenario (Stage E). When agents chain tool calls — forwarding the result of one MCP invocation as the input to another — PCS compounds across the chain. In ToolMinimize’s 15 cross-agent scenarios, the baseline PCS reached 12.60 before middleware intervention, the highest in any evaluation partition. After ToolMinimize: 0.00 at 100% TCR.1
Codex CLI’s multi_agent_v2 mode creates exactly this pattern: a coordinator agent spawns subagents, which make their own MCP tool calls, passing results back up the chain. Each agent turn is a new disclosure boundary. A PreToolUse hook operating at every level of the agent hierarchy — not just the top-level session — is therefore critical.
Codex CLI’s multi_agent_v2 hooks currently apply to both coordinator and subagent turns via the SubagentStart/Stop hook lifecycle.4 A privacy scrubbing PreToolUse hook will fire at each level, providing defence-in-depth across the entire delegation chain.
Gaps and Limitations
No native minimum-necessary schema in Codex CLI config.toml: ToolMinimize’s schema-aware analysis requires per-tool minimum-necessary field annotations. Codex CLI’s MCP configuration (config.toml [mcp_servers.*]) has no field for this. Developers must encode field policies in AGENTS.md and hook scripts.
Semantic classifier latency: The optional LLM content-aware extension (~800ms per call) is incompatible with Codex CLI’s synchronous PreToolUse hook model for high-frequency tool calls. Use it only for high-sensitivity tool namespaces or switch to an async PostToolUse audit pattern.
No privacy audit trail in rollout JSONL: Codex CLI’s session logs record tool calls but not the argument-level PSD analysis. A PostToolUse hook writing to a separate privacy-audit.jsonl fills this gap.
Travel and booking domains: ToolMinimize itself acknowledges that named-entity booking identifiers are often genuinely minimum-necessary. Hook policies should be domain-aware rather than applying blanket generalisation.
False positives on benign strings: The paper reports a 20% false detection rate and 10% rewrite false positive rate on benign scenarios.1 A hook that exits 2 on any PSD detection will block legitimate tool calls. Use the hook to rewrite (exit 0 with modified args) rather than block, reserving hard blocks for confirmed high-sensitivity patterns.
Summary
ToolMinimize demonstrates that LLM agents are structurally inclined to over-share private data in tool calls — privacy instructions help modestly, and PII detection tools miss implicit PSD entirely. Schema-aware argument-level rewriting achieves 81–92% privacy cost reduction with zero task validity impact at sub-2ms median latency.
For Codex CLI users:
- PreToolUse hook is the native intercept point for MCP tool call argument scrubbing — equivalent to ToolMinimize’s client-transport interceptor.
- AGENTS.md minimum-necessary declarations establish the semantic layer; the hook enforces it mechanically.
- multi_agent_v2 amplifies disclosure risk through agent chaining — hooks at every delegation level are necessary, not optional.
- Privacy audit JSONL (via PostToolUse) provides the compliance record that Codex CLI’s rollout logs omit.
Citations
-
Li, W. & Xu, Y. (2026). ToolMinimize: Auditing and Rewriting LLM Agent Tool Calls to Minimize Privacy Exposure. arXiv:2608.24957. https://arxiv.org/abs/2608.24957 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11
-
ToolPrivacyBench (arXiv:2606.28061) established a complementary benchmark for purpose-bound privacy in tool-using agents, covering 25 tool categories and consent-scope violations. ToolMinimize addresses the argument-value layer; ToolPrivacyBench addresses the purpose-binding layer. https://arxiv.org/abs/2606.28061 ↩
-
European Parliament and Council (2016). General Data Protection Regulation (GDPR), Article 9: Processing of special categories of personal data. https://gdpr-info.eu/art-9-gdpr/ ↩
-
OpenAI. Codex CLI hooks reference. Codex documentation, 2026. https://developers.openai.com/codex/cli/reference ↩ ↩2