Input & Output Controls
Tool Validation
tool-validation limits which tools a client may offer to the model. A request that declares a tool outside your allow list is blocked. It also checks that the JSON schemas you configure for your tools compile, and can ask an external validator model for a second opinion.
It does not check the arguments that the model generates against those schemas. Validate arguments and permissions in your tool executor.
Configuration
pack:
name: tool-validation-example-1
version: "1.0.0"
enabled: true
policies:
chain:
- tool-validation
policy:
tool-validation:
declared_tools:
- web_search
- database_query
allow_undeclared: falseVerify the allow list
Save this JSON test next to policy-config.yaml. The tools go in input.request:
{
"name": "blocks-undeclared-tool",
"input": {
"messages": [
{
"role": "user",
"content": "Search the documentation."
}
],
"request": {
"tools": [
{
"type": "function",
"function": {
"name": "delete_database"
}
}
]
}
},
"expected": {
"verdict": "block",
"reason_code": "tool-validation.invalid"
}
}verdictan policy lint --file policy-config.yaml
verdictan policy test --jsonThe test passes. Copy it, change the tool name to web_search and the expected result to allow and ok. That test passes too, with a nested tool-validation.ok.
Fields
| Field | Type | Default | Description |
|---|---|---|---|
declared_tools | string[] | [] | Allowed tool names. An empty list allows every name. |
schemas | object | {} | JSON Schema objects by tool name. Lint and the gateway compile each as Draft 7. |
allow_undeclared | boolean | false | With false, a name outside declared_tools blocks. With true, it is allowed and recorded. |
semantic_validation.enabled | boolean | false | Turns on the external validator call |
semantic_validation.endpoint | string | OpenAI-compatible Chat Completions URL of the validator. Required when enabled. | |
semantic_validation.model | string | "judge" | Model name in the validator request |
semantic_validation.secret_key_ref | { env: string } | Variable with the validator bearer token | |
semantic_validation.timeout_ms | integer | 3000 | Timeout of the validator request |
How it works
- The gateway reads each tool name from
tools[*].function.name, or fromtools[*].name. - With a non-empty
declared_tools, names outside the list are undeclared. - Each entry in
schemasis compiled as Draft 7. Schemas that do not compile are listed. - A schema that does not compile, or an undeclared tool with
allow_undeclared: false, blocks withtool-validation.invalid. - If those checks pass and semantic validation is on, the gateway asks the validator. See Semantic validation. An error or
valid: falseblocks withtool-validation.invalid. - Otherwise, the request is allowed with
tool-validation.ok. - The details record
requested_tools,undeclared_tools,invalid_schemas,semantic_validated, andsemantic_reason.
Semantic validation
This optional step sends your tool definitions to another model. Turn it on after the allow list works:
policy:
tool-validation:
declared_tools: [web_search, database_query]
allow_undeclared: false
semantic_validation:
enabled: true
endpoint: https://replace-with-validator-host/v1/chat/completions
model: replace-with-validator-model
secret_key_ref:
env: VERDICTAN_VALIDATOR_API_KEY
timeout_ms: 3000The gateway sends a Chat Completions request with the configured model, one user message, and a response_format for a JSON object with valid and reason. The message is a JSON string with declared_tools, schemas, and request_tools.
It reads the result from:
- A top-level
validboolean, with an optionalreason, or else - A JSON object with
validand an optionalreasoninchoices[0].message.content.
A response without valid, a non-2xx status, a timeout, or invalid JSON counts as a failed validation, and blocks. The cause is in semantic_reason.
Phase and verdicts
| Item | Value |
|---|---|
| Input phase | The declared tools, before dispatch. The result reports the phase as pre_request. |
| Output phase | Not checked |
| Verdicts | allow, block |
| Passed | tool-validation.ok |
| Failed | tool-validation.invalid |
Examples
Allow list only
policy:
tool-validation:
declared_tools:
- searchRecord undeclared tools without a block
policy:
tool-validation:
declared_tools:
- web_search
allow_undeclared: trueLimits and failure behavior
- Schemas are compiled, not applied to tool call arguments.
- An empty
declared_toolsallows every tool. Set the list before you rely on the block. - Names must match exactly, including case.
- Lint rejects a schema that is not valid Draft 7.
- The validator runs only when the local checks pass. A validator error always blocks. There is no fail-open setting.
- The validator sees the declared tools, the schemas, and the request
tools, not the messages. - For pattern and entity checks on the whole request, use Tool Security.
Next steps
- Tool Security: attack patterns and sensitive data in the request.
- Tool Budget:
max_tokensper declared tool.