How to Implement Tool Parameter Fidelity to Prevent Silent Input Transformation Bugs in Agents

Enforce strict JSON Schema contracts for every tool, validate all required arguments in a centralized dispatch method, and isolate tool sets by execution stage to guarantee that Large Language Models cannot silently omit or mutate parameters before tool execution.

Silent input transformation bugs occur when an LLM drops required arguments, injects null values, or coerces types before calling an external tool. The bojieli/ai-agent-book repository demonstrates a robust pattern for tool parameter fidelity in its staged-system-prompt implementation, using explicit schema definitions and fail-fast validation to eliminate this class of errors.

Define Strict JSON Schemas for Every Tool

Tool parameter fidelity starts with an unambiguous contract. In chapter10/staged-system-prompt/tools.py, the repository defines a helper function _tool that constructs OpenAI-compatible function definitions with strict validation rules.

The helper forces developers to declare every argument in properties, mark truly required fields in required, and explicitly forbids extra keys via additionalProperties: False:


# chapter10/staged-system-prompt/tools.py

def _tool(name: str, description: str, properties: dict, required: list) -> dict:
    return {
        "type": "function",
        "function": {
            "name": name,
            "description": description,
            "parameters": {
                "type": "object",
                "properties": properties,
                "required": required,
                "additionalProperties": False,  # Rejects undeclared keys

            },
        },
    }

# Example: strict schema for file writing

WRITE_FILE = _tool(
    name="write_file",
    description="Write a text file to the workspace.",
    properties={
        "path": {"type": "string", "description": "Relative file path"},
        "content": {"type": "string", "description": "File contents"},
    },
    required=["path", "content"],
)

Setting additionalProperties: False is critical for tool parameter fidelity because it prevents the LLM from injecting unexpected fields that could be misinterpreted by downstream logic.

Validate Arguments Before Tool Dispatch

Schema definitions alone do not prevent runtime errors. The repository implements a centralized _dispatch_tool method that validates every incoming tool call against its registered schema before executing the underlying function.

According to the source code, the validation logic performs two critical checks:

  1. Presence verification: Ensures every key in the schema's required list exists in the incoming arguments dict and is not None
  2. Type verification: Confirms each argument matches its declared JSON Schema type

# Conceptual implementation as seen in the agent logic

def _dispatch_tool(self, tool_name: str, arguments: dict):
    schema = self._tool_schemas[tool_name]["function"]["parameters"]
    
    # Verify required fields are present and non-null

    for key in schema["required"]:
        if key not in arguments or arguments[key] is None:
            raise ValueError(f"Missing required argument '{key}' for tool '{tool_name}'")
    
    # Verify types match schema definition

    for key, spec in schema["properties"].items():
        if key in arguments:
            expected_type = _type_from_json(spec["type"])
            if not isinstance(arguments[key], expected_type):
                raise TypeError(f"Argument '{key}' must be of type {spec['type']}")
    
    # Only execute if validation passes

    return getattr(self, f"_tool_impl_{tool_name}")(arguments)

This fail-fast approach ensures that any silent transformation—such as the LLM omitting the content field or passing null for path—surfaces immediately as a clear exception rather than causing obscure failures in the tool implementation.

Isolate Tools by Execution Stage

The repository enforces stage-specific tool sets via the STAGE_TOOLS mapping in tools.py. This dictionary maps each execution phase to a distinct subset of tools, ensuring that a tool from a later stage cannot be invoked prematurely with an incomplete argument set.

The test file test_stage_contracts_are_distinct_and_tool_gated.py verifies that stages never share the same tool name, guaranteeing schema isolation. This design eliminates cross-stage leakage bugs where an agent might call a tool early with arguments intended for a different context.

Fail Fast on Malformed or Null Input

To maintain tool parameter fidelity under edge cases, the repository includes dedicated regression tests that intentionally violate schemas:

These tests serve as regression guards. Any code change that reintroduces silent argument dropping or coercion will cause immediate test failures, preventing the bug from reaching production.

Summary

  • Define explicit schemas using additionalProperties: False to prevent LLMs from injecting unexpected fields
  • Centralize validation in a _dispatch_tool method that checks required fields and types before execution
  • Isolate tool sets by stage using STAGE_TOOLS to prevent cross-stage invocation with incompatible schemas
  • Write negative tests that pass null or malformed arguments to ensure the agent fails fast rather than silently transforming inputs

Frequently Asked Questions

What is tool parameter fidelity in AI agents?

Tool parameter fidelity is the guarantee that every argument passed to an external tool exactly matches its declared schema without silent omission, type coercion, or null injection. It ensures that the LLM cannot "forget" required fields or mutate values before tool execution, preventing hard-to-debug runtime failures.

How does JSON Schema prevent silent input transformation?

By declaring properties, required fields, and additionalProperties: False in the JSON Schema, the agent creates a machine-readable contract that is enforced at runtime. The _dispatch_tool method validates incoming arguments against this schema, raising explicit errors for missing keys or type mismatches rather than allowing the tool to execute with corrupted inputs.

Why is stage isolation important for tool validation?

Stage isolation via STAGE_TOOLS prevents an agent from calling a tool intended for a later execution phase with arguments collected during an earlier phase. This eliminates cross-stage leakage where incomplete context could lead to partial argument sets, ensuring each tool is only available when its full schema can be satisfied.

What tests should I write to enforce tool parameter fidelity?

Write unit tests that intentionally violate your schemas: pass None for required arguments (as in test_null_tool_args.py), submit malformed JSON (as in test_malformed_tool_json.py), and attempt to invoke tools outside their designated stages. These negative tests act as regression guards against silent input transformation bugs.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →