TUTORIALS 10 min read

Tool Result Validation for AI Agents: Treat Every Response as Untrusted Input

A tool call can succeed and still return dangerous data. Validate structure, provenance, freshness, scope, and semantics before an AI agent can act on it.

By EgoistAI ·
Tool Result Validation for AI Agents: Treat Every Response as Untrusted Input

The API returned HTTP 200. The agent still should not trust it.

A search result can contain prompt injection. A CRM response can be stale. A calendar tool can return events from the wrong tenant. A payment API can represent money in minor units while the model reads it as dollars.

Tool results are untrusted inputs crossing a security and correctness boundary. Validate them before they enter model context and again before they justify a side effect.

Start With a Typed Envelope

Wrap every tool response in a consistent envelope that separates transport status from business data. Include tool name and version, request ID, subject or tenant scope, retrieval time, source revision, and validation state.

The tool adapter—not the model—should parse raw JSON, enforce size limits, reject unknown critical fields where appropriate, and normalize types.

type ToolEnvelope<T> = {
  tool: string;
  version: string;
  requestId: string;
  tenantId: string;
  observedAt: string;
  data: T;
  warnings: string[];
};

Schema validation catches missing fields and wrong types. It does not prove that the data is current, authorized, or true. Treat it as the first gate.

Validate Scope and Provenance

Bind every call to the authenticated actor and intended resource. If an agent requests order 123 for tenant A, the adapter must verify that the returned order belongs to tenant A. Do not rely on the model to notice a mismatch.

Record where each consequential field came from. A number extracted from a web page is not equivalent to a signed response from a payment provider. Provenance should survive summarization so later steps can distinguish evidence from commentary.

For aggregating tools, label each record individually. One trustworthy domain in a search page does not bless every result.

Enforce Freshness and State

Many agent failures are time-of-check/time-of-use problems. Eligibility was true when retrieved, but another process changed the account before execution.

Add observedAt, version, ETag, or revision identifiers. Define freshness by use case: a public documentation page may remain useful for days, while a bank balance could be stale in seconds.

Before a mutating action, re-read critical state or use an atomic API with preconditions. Include an idempotency key so retries cannot duplicate the effect.

await refunds.create({
  paymentId,
  amountMinor,
  ifPaymentVersion: payment.version,
  idempotencyKey: actionId,
});

The model’s plan can be old even when every individual tool response was valid when received.

Separate Data From Instructions

Web pages, emails, documents, and ticket comments can contain text telling the agent to ignore policy or call another tool. That text is content, not authority.

Mark untrusted spans in the tool envelope and present them to the model with explicit boundaries. Strip active HTML, hidden text, scripts, and oversized encoded payloads before context assembly. Do not automatically follow URLs or commands found inside retrieved content.

Use allowlisted transitions. A search tool result should not grant permission to send email. Authorization comes from policy and the user, not from text the tool happened to return.

Prompt injection detection can add a warning, but no classifier is a complete defense. Architectural separation of data and authority is the reliable control.

Check Domain Semantics

Valid structure can still encode nonsense. Add deterministic invariants for units, ranges, relationships, and business rules.

Examples include confirming that a refund does not exceed the captured amount, an end time follows a start time, a cited document supports the stated account, and an email recipient is inside the approved set.

Normalize currencies, time zones, Unicode identifiers, and nullable values before the model sees them. Preserve the original alongside the normalized form for audit.

If multiple tools disagree, do not ask the model to average truth. Define a precedence rule, retrieve fresher evidence, or escalate. Model confidence is not a reconciliation protocol.

Control Size and Shape

Tool outputs can become denial-of-wallet attacks. Cap response bytes, item count, nesting depth, and per-field length before sending data to a model.

Project large responses into the smallest typed view needed for the next decision. Keep raw artifacts outside the context and reference them by immutable ID. If truncation occurs, label it explicitly. An agent must not mistake the first 100 records for the complete set.

Pagination belongs to the workflow. A model should see hasMore: true and the cost of fetching another page, not assume completeness.

Make Failures Explicit

Adapters should return distinct states for timeout, unavailable, unauthorized, invalid response, stale data, partial result, and empty-but-valid. Collapsing them all into null encourages unsafe guesses.

Give the agent a small set of allowed recovery paths: retry with bounded backoff, choose an approved fallback, request missing input, or stop. Do not let it invent data to keep the workflow moving.

Record validation failures with redacted samples and schema versions. Repeated failures often reveal provider changes or an adapter bug, not model behavior.

Revalidate at the Action Boundary

An agent may combine several individually valid facts into an invalid action. Before execution, validate the final canonical payload against policy, current state, and user approval.

Bind approval to the exact payload hash. If a later repair changes the amount, target, or scope, require fresh approval. Display the source evidence beside the proposed action for reviewers.

High-risk tools should accept only typed values produced by trusted code. Never pass a free-form model string directly into SQL, shell, or a recipient field.

Test the Adversarial Cases

Build fixtures with wrong tenants, stale revisions, duplicate records, malicious document instructions, malformed Unicode, extreme nesting, partial pages, unit mismatches, and successful HTTP responses containing business errors.

Replay those fixtures whenever a prompt, schema, model, or tool adapter changes. Measure rejected unsafe actions, unnecessary refusals, recovery success, and the time from provider drift to detection.

The production principle is simple: tool use does not make an agent grounded by default. Grounding emerges when evidence has validated structure, provenance, freshness, and scope—and when execution checks those properties again.

Share this article

> Want more like this?

Get the best AI insights delivered weekly.

By subscribing, you agree to our Privacy Policy. You can unsubscribe at any time.

> Related Articles

Tags

AI agentstool usevalidationprompt injectionsecurity

> Stay in the loop

Weekly AI tools & insights.