The Return Trip Problem: Your Agent's Data Leaves Through the Response, Not the Request
5 min read Fullmakt Team
- data-ownership
- governance
- agentic-actions
- traceability
- observability
- mcp
- a2a
- credentials
- agents
An AI agent is granted read access to a customer API so it can answer support
questions. The request is fine: GET /customers/4812, a scoped credential,
an approved tool. The response is the problem. It contains the customer’s
national ID, a payment card fragment, and a free-text notes field where a
colleague once pasted a password. All of it lands in the model’s context, is
summarized into a chat reply, and is copied into a third-party tool the agent
also has access to. No rule was broken. Every call was authorized. The data
still left.
Most agent governance is built around the outbound half of the exchange: who is calling, with which credential, against which tool. That’s necessary. But data ownership is decided on the return trip, because that is where data crosses from a system you control into a context you don’t.
Three ways data escapes on the way back
1. Over-broad responses. APIs return whole records because human-facing UIs filter them later. An agent has no UI. Everything in the payload becomes model context, and model context is easy to forward: into logs, into other tool calls, into an A2A hand-off to another agent that has a different owner, different retention rules, and possibly a different jurisdiction.
2. Context that becomes an instruction or a payload. Once sensitive data is in context, a poisoned document or indirect prompt injection can ask the agent to send it somewhere. The attacker never needs your credential. They only need the agent to have already read the data.
3. Observability that copies the data again. Teams add tracing so they can see what agents do, then log full response bodies to do it. The audit trail becomes a second, less-protected copy of the sensitive data, which is the credential-leak-in-the-log-pipeline problem we’ve described applied to personal data.
Why “least privilege on the request” isn’t enough
Least privilege limits which endpoints an agent can reach. It says nothing about which fields come back from an endpoint it legitimately needs. Support agents need the customer’s name and order status. They do not need the ID number, and no amount of tighter OAuth scopes will remove it from a response the upstream API insists on returning in full.
This is also why the login handshake, whether OAuth, token exchange or sender-constrained tokens, can’t solve it. Authentication answers who is asking. It has no opinion on what they are handed.
What a response-side control looks like
A workable design puts a decision point on the return path as well as the outbound path:
- Field-level sanitization before the model sees it. Sensitive properties are replaced with a placeholder at any depth in the JSON, including inside arrays, so the agent works with what it needs and never holds the rest.
- Deny-by-name is a floor, not a ceiling. Name-based redaction catches the fields you know about. It won’t catch a secret pasted into a free-text notes field, or non-JSON bodies. Treat it as one layer alongside policy on which tools and hosts an agent may reach at all, and be explicit about what it does not cover.
- Audit metadata, not payloads. A traceable record needs who, what, when, status and a hash of the parameters. It does not need the response body. Keeping bodies out of the audit log means the trail proves what happened without becoming a new copy of the data. It’s the difference between observability and traceability.
- Ownership stays attached to the source. If the agent never receives the sensitive field, there is nothing to forward to another agent, nothing to retain, and nothing to erase later when a data-subject request arrives.
Where Fullmakt fits
Fullmakt is the broker that sits between an agent and the systems it acts on. Every MCP or A2A call passes through it, which makes the return path a natural control point rather than an afterthought:
- Response sanitization per collection. A policy lists the sensitive field
names for a set of tools, for example
ssnorcredit_card. Fullmakt replaces matching values with***in the response body the agent receives, at any depth and inside arrays, before it reaches the model. - Credentials the agent never holds. The agent asks Fullmakt to act; the broker resolves the scoped credential and makes the upstream call. The same boundary that keeps secrets out of the prompt keeps sensitive response fields out of it.
- Audit without a data copy. Each call is recorded with status, error and a parameter hash rather than the response body, so the audit trail is evidence, not exposure.
- Approval for the calls that matter. Reads that touch regulated data can be routed to a human first, rather than discovered later in a log.
The business case
The commercial argument is simple. Teams stall agent pilots because legal and security can’t answer one question: what data can this agent see, and where can it go from there? A request-only control gives a partial answer. A control that covers both directions, with a credential the agent never holds, fields it never receives and an audit trail that doesn’t duplicate the data, gives a complete one. That’s the difference between an agent that stays a demo and one that reaches production against real customer systems.
If you are deciding how much of your data an AI agent should be allowed to hold, start with the return trip. Try Fullmakt and put a decision point on the response as well as the request.
FAQ
Does OAuth or MCP authentication prevent an agent from receiving sensitive data? No. Authentication and scopes decide who may call which endpoint. They don’t filter the fields in the response. You need a control on the return path.
What is response sanitization for AI agents? Replacing sensitive fields in an upstream response with a placeholder before the agent or model sees them, so the data can’t be summarized, forwarded to another agent or logged.
Can field-name redaction catch everything? No. It covers the property names you list. It won’t detect secrets placed under other names, in free text, or in non-JSON bodies, so combine it with tool and host policy and human approval for sensitive reads.
Should audit logs store response bodies? Generally not. Store who, what, when, status and a parameter hash. That keeps the record traceable without creating another copy of personal data.