mech.app
AI Agents

Out-of-Band Intent Verification: How Agentic Tool Calls Escape the Prompt Injection Surface

Moving authorization decisions outside the LLM context window to prevent prompt injection attacks on high-stakes tool calls in financial agents.

Source: hyperautomation.substack.com
Out-of-Band Intent Verification: How Agentic Tool Calls Escape the Prompt Injection Surface

An agent with tool-calling privileges and a poisoned context window is a credential with extra steps. The audit log will show your identity attached to the tool invocation, but it will not show that the parameters came from a retrieval result you never read, a system message you did not write, or a chat history the agent synthesized from three conflicting sources.

In-prompt confirmation flows live inside the same context the attacker controls. If the agent asks “Are you sure you want to transfer $50,000?” and the user says yes, that approval is text in a buffer. The next retrieval call can inject “The user confirmed the $75,000 transfer” and the agent has no cryptographic way to distinguish the two.

Out-of-band intent verification solves this by moving the authorization decision to a separate channel the LLM cannot read or write. The user signs a structured payload on a device the agent does not control. The signature binds consent to specific parameters: recipient, amount, action type. The agent receives a token it can present to the tool, but it cannot forge or modify the underlying intent.

The Four-Boundary Agent Stack

Financial agents that ship in production typically enforce four security boundaries:

  1. Identity propagation: The agent carries the user’s credential through the execution graph.
  2. Tool authorization: Each tool checks whether the identity has permission to invoke it.
  3. Parameter validation: The tool rejects malformed or out-of-range inputs.
  4. Intent attestation: The tool verifies that the user explicitly consented to this specific call with these specific parameters.

The first three boundaries are table stakes. Identity propagation is OAuth or mTLS. Tool authorization is RBAC or ABAC. Parameter validation is JSON schema plus business rules.

Intent attestation is the missing primitive. Without it, the agent can execute any call the user is authorized to make, as long as the parameters pass validation. The context window becomes the attack surface.

Out-of-Band Verification Protocol

The protocol separates intent capture from tool execution:

Step 1: Intent capture
The user initiates an action through a trusted interface (mobile app, hardware token, or separate browser session). The interface presents a structured request: action type, parameters, timestamp. The user reviews and signs it with a private key the agent never sees.

Step 2: Token issuance
The signing device returns a signed JWT or FIDO assertion. The payload includes the action parameters and a nonce. The signature is verifiable by the tool but not forgeable by the agent.

Step 3: Agent execution
The agent receives the signed token as an opaque string. It plans the tool call, binds parameters, and includes the token in the invocation. The agent cannot read or modify the token payload.

Step 4: Tool verification
The tool extracts the signed payload, verifies the signature, checks the nonce for replay, and compares the payload parameters to the actual call parameters. If they match, the tool executes. If they diverge, the tool rejects and logs the discrepancy.

Implementation Patterns

Three patterns are shipping in production financial systems:

FIDO-Based Signing

The agent requests a payment. The user’s phone receives a push notification showing the recipient and amount. The user authenticates with biometrics. The phone’s secure enclave signs the transaction and returns a FIDO assertion. The agent passes the assertion to the payment API, which verifies it against the registered public key.

# Agent-side: request intent token
intent_request = {
    "action": "transfer",
    "recipient": "acct_xyz",
    "amount": 50000,
    "currency": "USD",
    "nonce": secrets.token_urlsafe(16)
}

# User device signs the request
# (happens out-of-band, agent does not see private key)
signed_token = await user_device.sign(intent_request)

# Agent includes token in tool call
result = await payment_tool.execute(
    recipient="acct_xyz",
    amount=50000,
    currency="USD",
    intent_token=signed_token
)
# Tool-side: verify intent matches execution
def execute_transfer(recipient, amount, currency, intent_token):
    # Verify signature
    payload = verify_fido_assertion(intent_token, user_public_key)
    
    # Check nonce freshness
    if not nonce_store.check_and_consume(payload["nonce"]):
        raise ReplayAttackError()
    
    # Compare intent to actual parameters
    if (payload["recipient"] != recipient or
        payload["amount"] != amount or
        payload["currency"] != currency):
        log_intent_mismatch(payload, locals())
        raise IntentMismatchError()
    
    # Execute
    return bank_api.transfer(recipient, amount, currency)

Time-Locked Confirmation

The agent proposes a high-stakes action. The system sends an email or SMS with a unique confirmation code and a summary of the parameters. The code expires in 5 minutes. The user reads the summary on their phone, verifies it matches their intent, and enters the code. The agent polls for confirmation and proceeds only after receiving it.

This pattern trades latency for simplicity. No cryptographic keys, no hardware tokens. The separate channel (email/SMS) provides the out-of-band property. The time lock prevents the agent from brute-forcing codes.

Signed Intent Logs

The user interface maintains a cryptographically signed log of every action the user initiates. Each log entry includes a timestamp, action type, and parameters. The log is append-only and stored outside the agent’s context. When the agent invokes a tool, it includes the log entry hash. The tool fetches the log entry, verifies the signature, and checks that the parameters match.

This pattern works well for batch workflows where the user queues multiple actions upfront. The agent executes them over time, but each execution is bound to a specific log entry the user signed.

Comparison to Existing Patterns

PatternAttack SurfaceLatencyKey ManagementReplay Protection
In-prompt confirmationFull context windowNoneNoneNone
Out-of-band FIDOSigning device only2-5 secondsHardware enclaveNonce + timestamp
Time-locked codeEmail/SMS channel10-60 secondsNoneExpiration + single-use
Signed intent logLog storageNone (async)User keypairAppend-only log
OAuth scopesToken issuanceNoneOAuth providerToken expiration

OAuth scopes are not intent attestation. A scope grants permission to call a class of APIs (e.g., “write:payments”). It does not bind consent to specific parameters. An agent with a write:payments scope can execute any payment the user is authorized to make, regardless of what the user actually asked for.

Where Intent Verification Fits in the Stack

Intent verification runs after tool selection and parameter binding, but before tool execution. The agent has already decided which tool to call and what parameters to pass. The verification step checks whether the user consented to that specific call.

In a typical LangGraph or AutoGen flow:

  1. The LLM selects a tool and generates parameters.
  2. The orchestrator validates the parameters against the tool schema.
  3. The orchestrator requests an intent token from the user device.
  4. The user reviews and signs the request.
  5. The orchestrator passes the signed token to the tool.
  6. The tool verifies the token and executes.

If verification fails, the orchestrator can retry with corrected parameters, escalate to a human operator, or abort. The key property is that the LLM never sees the signing key and cannot forge the token.

Failure Modes

Token expiration: The user signs a token but the agent delays execution. The token expires before the tool receives it. The tool rejects the call. The agent must request a fresh token.

Parameter drift: The agent modifies parameters between token issuance and tool invocation. The tool detects the mismatch and rejects. The audit log shows both the signed intent and the actual call, making the attack visible.

Replay attacks: An attacker captures a signed token and replays it. The nonce check catches this if the tool maintains a nonce store. If the tool does not check nonces, the attacker can replay any historical token.

User fatigue: High-frequency trading agents or batch workflows generate dozens of signing requests per minute. Users start approving without reading. This is a UX failure, not a protocol failure. The solution is to batch related actions into a single signed intent or to use risk-based thresholds (e.g., only require signing for transfers above $10k).

Observability

Intent verification generates three log streams:

  1. Intent requests: The agent requested a signature for action X with parameters Y. Logged by the orchestrator.
  2. Intent signatures: The user signed (or rejected) the request. Logged by the signing device.
  3. Verification outcomes: The tool verified the signature and compared parameters. Logged by the tool.

Correlating these three streams shows the full chain of custody. If the agent invokes a tool without a corresponding intent request, that is anomalous. If the tool receives a token that does not match any recent signature, that is a replay attempt. If the tool rejects a token due to parameter mismatch, that is a potential injection attack.

Deployment Shape

Out-of-band verification requires infrastructure the agent does not control:

  • A signing device or service with key material isolated from the agent runtime.
  • A nonce store shared between the signing service and the tool (Redis, DynamoDB, or a distributed cache).
  • A secure channel for delivering intent requests to the user (push notification, SMS, or a separate authenticated session).

For financial agents running in AWS, the typical shape is:

  • Agent runtime: ECS or Lambda with no access to signing keys.
  • Signing service: Separate Lambda function with KMS-backed keys or a mobile app with hardware-backed keys.
  • Nonce store: ElastiCache or DynamoDB with TTL-based expiration.
  • Tool runtime: Lambda function with read-only access to the nonce store and the user’s public key.

The agent and tool communicate through API Gateway. The signing service is invoked directly by the user’s device, not by the agent.

Technical Verdict

Use out-of-band intent verification when:

  • The agent can invoke high-stakes tools (payments, trades, infrastructure changes).
  • The context window includes untrusted content (retrieval results, user-uploaded documents, third-party API responses).
  • Regulatory requirements demand explicit user consent for specific actions (PSD2, SOX, HIPAA).
  • The audit log must distinguish between “the user is authorized” and “the user consented to this specific call.”

Avoid it when:

  • The agent only reads data or invokes low-risk tools.
  • The user is present and actively supervising every tool call in real time.
  • Latency requirements are sub-second and the user cannot tolerate a signing round-trip.
  • The deployment environment cannot support a separate signing service or secure channel.

Intent attestation is not a replacement for guardrails, parameter validation, or tool authorization. It is a complementary primitive that binds user consent to specific tool invocations. The cryptographic separation makes it robust against prompt injection, but it introduces latency and operational complexity. For financial agents, that trade-off is usually worth it.