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

> Prevent silent input transformation bugs in AI agents. Implement tool parameter fidelity using JSON Schema contracts and validation to ensure accurate parameter passing during tool execution.

- Repository: [Bojie Li/ai-agent-book](https://github.com/bojieli/ai-agent-book)
- Tags: best-practices
- Published: 2026-07-30

---

**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`](https://github.com/bojieli/ai-agent-book/blob/main/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`:

```python

# 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

```python

# 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`](https://github.com/bojieli/ai-agent-book/blob/main/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`](https://github.com/bojieli/ai-agent-book/blob/main/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:

- **[`test_null_tool_args.py`](https://github.com/bojieli/ai-agent-book/blob/main/test_null_tool_args.py)**: Passes `None` for required arguments and confirms the agent raises `ValueError`
- **[`test_null_question.py`](https://github.com/bojieli/ai-agent-book/blob/main/test_null_question.py)**: Verifies the agent refuses a `null` question before dispatch
- **[`test_malformed_tool_json.py`](https://github.com/bojieli/ai-agent-book/blob/main/test_malformed_tool_json.py)**: Feeds invalid JSON to the agent and verifies it returns a diagnostic error instead of parsing partial data

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`](https://github.com/bojieli/ai-agent-book/blob/main/test_null_tool_args.py)), submit malformed JSON (as in [`test_malformed_tool_json.py`](https://github.com/bojieli/ai-agent-book/blob/main/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.