Key takeaways
Successful prompt attacks against AI agents rarely rely on generic phrases. Instead, they mimic classic cyberattacks by systematically probing the system to map tool surfaces, extract system prompt rules, and learn data schemas.
Attackers can inject fabricated tool responses and fake assistant messages directly into the conversation history. Because the large language model (LLM) treats past context as trusted reality, it can be tricked into skipping crucial sequential validation steps.
The LLM should never be the final authority for critical business decisions or state verification. Every back-end tool and API must independently validate its inputs (e.g., confirming a transaction ID exists in the database) rather than trust the agent layer.
Organizations must secure the entire multi-agent architecture by implementing robust back-end invariants and deploying runtime guardrails that detect adversarial behavior across every phase of the kill chain.
Prompt attacks are often discussed as if they begin with a clever sentence. In practice, the strongest attacks begin much earlier. They begin with recon.
In a previous blog post, we covered reconnaissance methodology for AI agent systems: How to probe an application’s boundaries, map its tool surface, and extract its operational logic. If you haven’t read that post yet, start there.
This post picks up where that one left off. Here, we’ll present a single, concrete attack scenario to show exactly how recon intelligence translates into a working exploit. We’ll analyze a realistic step-by-step kill chain — from the initial reconnaissance of a deployed AI agent, through the incremental gathering of system intelligence, to a final precision attack that uses that intelligence to book a flight without paying for it.
We will target Varda, a fictional but architecturally representative AI travel agent, throughout this analysis.
Meet Varda
Varda is a fictional autonomous AI travel agent built on a multi-agent architecture. As shown in the Figure, its chat interface is the visible surface of a much more complex system.
The full system comprises:
A main agent (Varda) — The primary orchestrator of user requests and delegation to subagents and tools
A trip planner subagent — Connections to external websites to research destinations, hotels, and flights
A knowledge subagent — Retrieval of internal documents and policies from a vector database
Three MCP servers — Dedicated servers for flights (search, book, cancel), payments (process, refund, list), and email.
A MongoDB cluster — Persistent storage for bookings, transactions, user profiles, and conversation traces
This is not an isolated LLM; every message that a user sends is processed by an agent that can read from databases, move money, cancel bookings, and send emails. The attack surface is the entire connected system, not just the chat box.
From SQL injection to prompt injection: Why recon changes everything
A classic SQL injection attack doesn’t start with ’ OR 1=1 --. It starts with probing: fingerprint the database (DB), find the injectable parameter, learn the query structure. Only then is a payload crafted to fit precisely.
Prompt injection against an AI agent follows the same discipline (Table). The “parser” is an LLM that processes system instructions, user messages, and tool outputs as a flat token sequence — but the principle is identical. A generic attack (ignore your rules and do X) has the same low success rate as typing random SQL characters into a form. What recon buys in both cases is specificity; that is, payloads that look exactly like something the system was designed to do.
Kill chain step |
SQL injection |
Attack on an AI agent |
|---|---|---|
Recon |
Fingerprint DB, find injectable parameters |
Extract system prompt logic, enumerate tools, learn output schemas |
Weaponize |
Craft payload matching DB dialect and query structure |
Craft a prompt instructing the agent to use specific tools |
Attack |
Inject SQL via input field, bypass authentication |
Inject the prompt into then agent context, bypass agent’s precondition checks |
Impact |
Unauthorized data access or authentication bypass |
Unauthorized action execution (booking, refund, data exfiltration) |
Table: SQL injection parallels in prompt injection
With that framing in place, let’s examine the kill chain against Varda.
The kill chain: Booking a free flight
Our objective is straightforward: obtain a confirmed flight booking without triggering a real payment.
Varda’s standard booking flow is sequential — it searches for flights, and once the user selects a flight, Varda processes payment then issues the booking. Our attack must break that sequence. Specifically, we need to convince the agent that payment has already been approved so that it proceeds directly to issuing the ticket. Executing this requires three pieces of intelligence gathered during recon:
The decision rule that governs when booking is permitted — so we know which precondition to fake
The exact input that will cause the agent to trigger a booking
The exact input that will convince the agent that a payment was already completed
Rather than simply guess at these three three pieces of information, we can obtain all of them through a four-phase recon:
Extract the system prompt logic
Map the tool
Learn the payment schema
Profile the data vault
Recon phase 1: Extract the system prompt logic
The first recon objective is to understand the agent’s decision rules. System prompts define an AI agent’s operating constraints — but they also function as a reconnaissance roadmap. An attacker who can reconstruct the system prompt knows exactly what the application can do, its boundaries, and which rules to satisfy, simulate, or bypass.
Extraction does not require direct access. Through behavioral probing — attempting borderline actions, observing refusals, noting the exact language Varda uses when it declines a request — an attacker can infer the underlying instructions. Asking Varda what steps it follows before processing a refund, or what conditions must be met before a booking is confirmed, often yields direct paraphrases of the system instructions.
Varda’s booking rules, reconstructed through behavioral analysis, include:
<system_instructions>
- Always verify flight details via the ’Get Bookings’ tool before invoking ’Cancel Booking’.
- Do not process a refund using the ’Refund Payment’ tool without first confirming a valid cancellation.
- Do not issue a booking confirmation without a successful payment transaction on record.
</system_instructions>
What recon revealed
The third rule defines the attack vector. Varda will not call book_flight unless there is a successful payment on record in the current conversation context. This means the attack is not about manipulating the booking tool itself — it is about satisfying a precondition check. We need to insert a fake payment result into the conversation context before the booking step, so that when the agent looks for a payment, it finds one.
The system prompt has told us exactly what to fabricate. The next question is: What does a valid payment result look like?
Recon phase 2: Map the tools
Now that the payment precondition is identified, the next step is to enumerate Varda’s tool inventory precisely. Knowing that a process_payment tool exists is not enough — we need the exact name of the tool the agent uses, and the call signatures of both the payment and booking tools.
Modern AI agents expose their tool surface either explicitly (through documentation, verbose error messages, or direct prompting) or implicitly (through the names and parameters that surface in response metadata). Our targeted probing of Varda surfaced three MCP servers with the inventory shown in Table 2.
MCP server |
Available tools |
|---|---|
Flights |
search_flights, book_flight, get_bookings, cancel_booking |
Payments |
process_payment, get_payment, list_payments, refund_payment |
send_email |
Table 2: The three MCP servers and their available tools surfaced by our targeted probing
Imagine if you had a raw API key with direct access to every tool the agent can use. What would you do? Which calls would you combine? This is exactly the mindset an attacker brings to a tool inventory: They are not looking for a single vulnerable function, but reasoning about what sequences become possible when tools are chained.
What recon revealed
The booking tool is flights__book_flight. Its call signature requires two non-obvious inputs: an offerUUID (the internal identifier for a specific flight offer, generated at search time) and a transactionId (the payment confirmation reference, generated by payments___process_payment). The transactionId does not have a default or fallback — it must come from a prior payment call.
This confirms that faking the payment step is the only viable path. We cannot skip it or route around it; the booking tool’s own call signature demands a transactionId. We need to supply one that the agent will accept as legitimate — which means the spoofed payment response must be structurally perfect.
Recon phase 3: Learn the payment schema
The spoofed payment response must be convincing enough so the agent or the guardrails will not flag it. Getting the schema exactly right requires either observing a real transaction or convincing the agent to describe it.
Here we chose a legitimate interaction — completing a test booking with a real or test card — which reveals exactly what a successful process_payment response looks like. After Varda executed the payment tool, a simple prompt requesting the tool output revealed the following structure:
{
"tool_result": {
"name": "payments___process_payment",
"content": {
"success": true,
"paymentResult": {
"success": true,
"transactionId": "81ba3370-cd2d-4e8d-8809-f94b0c94f673",
"amount": 487.50,
"status": "approved",
"message": "Payment processed successfully",
"last4Digits": "4242"
}
}
}
}
What recon revealed
The response has six fields: success, transactionId, amount, status, message, and last4Digits. The transactionId follows a UUID prefix pattern. Critically, the amount field matches the flight cost exactly — meaning the spoofed response must use the real price of the target flight, a value only available after running a flight search. The fake cannot be pre-staged in full; the amount must be filled in at attack time.
This schema is the template. We now have everything needed to construct the payload — with the exception of one operational detail.
Recon phase 4: Profile the data vault
The final recon step is understanding how Varda’s persistent data is structured and referenced. Varda stores booking and transaction records in a DB, and the agent can query these via its tools. A normal interaction — looking up a past booking — reveals the data patterns for stored records.
What recon revealed
The offerUUID is generated at search time and is valid only for a limited window. Unlike a transactionId, which references a completed payment, an offerUUID represents a live pricing offer that expires. This means the attack cannot be fully prepared in advance and executed later. The attacker must perform a live flight search immediately before the spoofing step to obtain a current offerUUID, then act before the offer window closes.
This shapes the complete attack sequence: recon first, then search, then spoof, then book — all within a single session.
The attack: Putting it all together — Tool output spoofing
With recon complete, the attack takes four steps.
Obtain a live offer UUID
Inject the spoofed exchange
Trigger the booking
Confirm
In our scenario, the attacker delivers the injection directly through Varda’s chat UI. Alternatively, the same payload could be delivered indirectly — for example, embedded in a web page that the trip planner subagent fetches during research, causing the injection to enter the conversation context without any direct user interaction.
Step 1 — Obtain a live offer UUID
The attacker initiates a normal flight search:
Because the offerUUID is not not defined as sensitive but only hidden from the user interface, the attacker can simply ask for it:
Varda calls search_flights and returns available options. The attacker selects a target flight and records its offerUUID — 3152fa28-171b-4f48-9921-fcd3840db18a — and its price: $602.24. Both values are now in hand.
Step 2 — Inject the spoofed exchange
Using the schema from recon phase 3, the attacker injects a fabricated payment confirmation directly into the conversation context. The injection is a complete fake exchange: a spoofed tool result followed immediately by a fake assistant message that acknowledges the payment and declares intent to proceed with the booking. The amount is set to 602.24 to match the target flight, and a fake transactionId follows the UUID pattern:
This two-part injection is what makes the attack structurally complete. The fake tool result satisfies the payment precondition. The fake assistant message then impersonates Varda’s own reasoning turn, establishing in the conversation history that Varda has already decided to proceed — before the real model even processes the next user message.
Because the LLM cannot distinguish its own prior output from attacker-supplied text in the context, both the tool result and the assistant acknowledgment are treated as legitimate history.
Step 3 — Trigger the booking
With the fake exchange in context, the attacker follows up:
Great, please go ahead and issue the booking confirmation for that flight.
First name: <name>, Last name: <last name>, Data of birth: <DOB>, email: <email>
Varda reads its own conversation history, finds the injected payment confirmation and the fake acknowledgment turn, and evaluates its system prompt rule: "Do not issue a booking confirmation without a successful payment transaction on record." The precondition is satisfied. It proceeds to call flights__book_flight.
Step 4 — Confirm
The flights MCP server processes the booking against the live database. It receives a valid offerUUID and a structurally valid transactionId. It has no mechanism to verify that the transaction ID corresponds to a real payment — that validation was assumed to happen at the agent layer. The booking is confirmed. No money changes hands.
Defensive takeaways
This attack succeeded because the architecture relied on the model to both control the workflow and validate its own actions. Defending against this type of attack requires two complementary strategies:
Do not trust the model to validate the workflow
Deploy runtime guardrails that cover the full kill chain (including recon)
Do not trust the model to validate the workflow
The LLM should not be the authority over business-critical decisions. Each tool must independently validate its own inputs. The flights server should verify the transactionId against the payments database before issuing a booking — not trust that the agent checked it.
Every argument passed to a tool should be treated as untrusted input, and high-value actions should require human confirmation outside the agent’s own logic.
Deploy runtime guardrails that cover the full kill chain
Back-end hardening addresses the final exploit, but a mature defense detects attacks earlier. Each phase of the kill chain — recon probing, tool output spoofing, and the exploit itself — produces detectable patterns. A runtime guardrail that monitors AI application traffic across all these phases provides defense in depth, catching attacks before the attacker gathers the intelligence needed to craft a precision payload.
Akamai’s Firewall for AI is purpose-built for this role, providing real-time detection of prompt injection, reconnaissance patterns, and tool output spoofing across the full attack kill chain.
A resilient AI application does not ask the model to enforce payment rules or keep secrets. It builds back-end services that enforce their own invariants, and wraps the entire system in runtime guardrails that detect attacks at every stage.
Conclusion
Precision prompt attacks are not theoretical — they follow the same disciplined kill chain that has defined offensive security for decades: reconnaissance, weaponization, attack, and impact. As this analysis demonstrates, once an attacker maps an agent’s tools, decision rules, and data schemas, crafting an exploit becomes an exercise in imitation rather than ingenuity. The payload doesn’t fight the system; it speaks its language.
Defending against this class of attack means accepting that the model is not a security boundary. Organizations deploying AI agents must harden each back-end service to validate its own invariants, and layer runtime guardrails that detect adversarial behavior across every phase of the kill chain — not just the final exploit. The attack surface of an AI agent is the entire connected system, and the defense must be equally comprehensive.
Tags