# How Response Validation Detects Unknown Tools in Forge

> Forge's ResponseValidator detects unknown tools with a whitelist, comparing incoming ToolCall objects to allowed names and nudging when mismatches occur. Understand how this validation works.

- Repository: [Antoine/forge](https://github.com/antoinezambelli/forge)
- Tags: how-to-guide
- Published: 2026-05-22

---

**Forge's ResponseValidator uses a whitelist-based approach to detect unknown tools by comparing incoming `ToolCall` objects against a predefined list of allowed tool names, triggering a corrective nudge when mismatches are found.**

In the `antoinezambelli/forge` repository, response validation serves as a critical safety mechanism to prevent Large Language Models (LLMs) from invoking undefined or unauthorized tools. The `ResponseValidator` class implements a strict whitelist verification system that intercepts tool calls at validation time, ensuring only explicitly registered tools can execute within a workflow.

## The Whitelist Mechanism in ResponseValidator

The detection logic centers on a simple but effective whitelist check implemented in [`src/forge/guardrails/response_validator.py`](https://github.com/antoinezambelli/forge/blob/main/src/forge/guardrails/response_validator.py). When instantiated, the validator receives a definitive catalog of permissible tool names and stores them for subsequent comparison operations against any model-generated tool calls.

### Storing Allowed Tool Names

The `ResponseValidator` initialization accepts a list of valid tool identifiers through the `tool_names` parameter. This list becomes the authoritative reference set stored as `self.tool_names`, against which all incoming tool calls are evaluated during the validation phase.

```python
from forge.guardrails.response_validator import ResponseValidator

# Allowed tools for this workflow

valid_tools = ["search", "calculate", "summarize"]

validator = ResponseValidator(tool_names=valid_tools)

```

### Scanning Incoming Tool Calls

During the `validate` method execution, the code specifically handles responses that are already parsed as lists of `ToolCall` objects. At lines 81-84 of the source file, the validator constructs a filtered list comprehension to identify any calls whose `tool` attribute falls outside the allowed set:

```python
unknown = [tc for tc in tool_calls if tc.tool not in self.tool_names]

```

This single line performs the core detection logic, identifying any tool names not present in `self.tool_names` and collecting them for subsequent error handling.

## Triggering Recovery Through Nudge Generation

When unknown tools are detected, the validator does not raise exceptions or silently fail. Instead, it generates a structured recovery prompt using the `unknown_tool_nudge` function defined in [`src/forge/prompts/nudges.py`](https://github.com/antoinezambelli/forge/blob/main/src/forge/prompts/nudges.py).

### Constructing the ValidationResult

If the `unknown` list contains any entries, the validator returns a `ValidationResult` with `needs_retry` set to `True` and a populated `Nudge` object. The nudge includes a user-facing message that explicitly names the invalid tool and lists all available alternatives according to the following implementation pattern:

```python
return ValidationResult(
    tool_calls=None,
    nudge=Nudge(
        role="user",
        content=unknown_tool_nudge(unknown[0].tool, self.tool_names),
        kind="unknown_tool",
    ),
    needs_retry=True,
)

```

### Workflow Integration and Retry Logic

The surrounding workflow inspects the `needs_retry` flag and automatically injects the nudge content back into the conversation context. This creates a feedback loop where the model receives immediate correction about the available tool catalog and can issue a valid tool call on the subsequent attempt.

## Practical Implementation Examples

The following examples demonstrate the complete detection flow using the `ResponseValidator` with `ToolCall` objects defined in [`src/forge/core/workflow.py`](https://github.com/antoinezambelli/forge/blob/main/src/forge/core/workflow.py).

### Detecting an Unknown Tool Call

When a model responds with a call to a tool not present in the whitelist, the validator flags it immediately:

```python
from forge.core.workflow import ToolCall

# Model responded with a call to a non-existent tool "translate"

response = [ToolCall(tool="translate", args={"text": "hola"})]

result = validator.validate(response)

assert result.needs_retry          # True – a nudge will be sent

assert result.nudge.kind == "unknown_tool"
print(result.nudge.content)

# → "Tool 'translate' does not exist. Available tools: search, calculate, summarize. Call one of them."

```

### Processing a Valid Tool Call

For tool calls that match the whitelist, the validator passes them through without triggering retry mechanisms:

```python
response = [ToolCall(tool="search", args={"query": "latest AI news"})]

result = validator.validate(response)

assert not result.needs_retry      # False – the call is accepted

assert result.tool_calls == response

```

## Summary

- **Whitelist validation** occurs in [`src/forge/guardrails/response_validator.py`](https://github.com/antoinezambelli/forge/blob/main/src/forge/guardrails/response_validator.py) where `ResponseValidator` maintains an authoritative list of allowed tool names in `self.tool_names`.
- **Unknown tool detection** uses a list comprehension at lines 81-84 to filter `ToolCall` objects whose `tool` attribute is not present in the whitelist.
- **Recovery mechanism** generates a `ValidationResult` with `needs_retry=True` and a `Nudge` object created by `unknown_tool_nudge`, guiding the model back to valid tools.
- **Workflow integration** automatically handles the retry logic by injecting nudge content into the conversation when validation fails.

## Frequently Asked Questions

### How does Forge determine which tools are considered "known"?

Forge determines known tools through the `tool_names` parameter passed during `ResponseValidator` instantiation. This list represents the complete whitelist of executable tools for a specific workflow, and any `ToolCall` with a `tool` attribute not present in this list is immediately flagged as unknown.

### What happens when the validator detects an unknown tool?

When an unknown tool is detected, the `validate` method returns a `ValidationResult` with `needs_retry` set to `True` and a `Nudge` object containing a corrective message. The workflow then automatically injects this nudge into the conversation history, prompting the LLM to select a valid tool from the available catalog on its next turn.

### Where is the validation logic located in the codebase?

The core validation logic resides in [`src/forge/guardrails/response_validator.py`](https://github.com/antoinezambelli/forge/blob/main/src/forge/guardrails/response_validator.py), specifically within the `ResponseValidator.validate` method. The error message templates are defined in [`src/forge/prompts/nudges.py`](https://github.com/antoinezambelli/forge/blob/main/src/forge/prompts/nudges.py), while the data structures `ToolCall` and `ValidationResult` are implemented in [`src/forge/core/workflow.py`](https://github.com/antoinezambelli/forge/blob/main/src/forge/core/workflow.py).

### Can a workflow recover automatically from an unknown tool call?

Yes, workflows recover automatically through the nudge mechanism. Because the validator returns `needs_retry=True` rather than raising an exception, the orchestration layer can seamlessly append the guidance message to the conversation context and request a new response from the model without interrupting the overall task execution.