Skip to main content

Tool Policies

Tool Policies is a registry of every tool the proxy has seen in traffic (OpenAI and Anthropic request tools, response tool calls, and MCP tool calls), with an input policy and an output policy per tool. Tools are discovered automatically as requests pass through the proxy, and a newly discovered tool starts with input_policy: "untrusted" and output_policy: "untrusted". The Tool Policy Guardrail reads this registry and enforces the policies on requests and responses

The registry keeps the tool name, origin, policy values, call count, the team and key that used it when available, user agent, and first and last seen timestamps. Changing a policy never resets the call count, and later calls never reset a policy you set

Tool Policies and the Tool Permission Guardrail​

Tool Policies manages trust relationships between tools. Its input policy can allow untrusted input, require trusted input, or block a tool. Its output policy marks output as trusted or untrusted. A blocked input policy or a team or key override rejects a tool call. A trusted input policy rejects a tool when the conversation contains output from a tool whose output policy is untrusted

An untrusted input policy accepts any input, including data from untrusted tool outputs. A trusted input policy requires trusted input. A blocked input policy prohibits the tool. An untrusted output policy may contain unsafe content and can trigger downstream trust-chain blocks. A trusted output policy is treated as verified safe and does not trigger those blocks

The Tool Permission Guardrail provides a separate rule-based control. It matches configured tool names and, optionally, tool types and arguments, then applies its configured allow or deny action. Use Tool Permission Guardrail rules when authorization depends on matching configured patterns. Use Tool Policies when the control is based on the trust classification of a discovered tool and the trust chain between tool outputs and inputs. Both guardrails can run on the same proxy, and a request has to pass each one that is configured

Quick start​

The current Admin UI route is http://localhost:4000/ui/tool-policies. The legacy URL http://localhost:4000/ui/?page=tool-policies redirects to this route

Tool Policies is only available to proxy admins. Other roles see a message that the page is admin only

The overview displays counts for tools discovered today, total discovered tools, blocked tools, and active teams. It can also display newly discovered tools that still have the default untrusted input policy. The table supports search, policy and team or key filters, refresh, and client-side pagination. Its columns include discovery time, tool name, input policy, output policy, call count, team name, key hash, key name, and user agent

Select a tool name to open its detail view. The detail view shows the origin, call count, user agent, first discovery time, and last use time. Use the Input Policy and Output Policy selectors to save global policy values. Input policies are untrusted, trusted, and blocked. Output policies are untrusted and trusted

The detail view also displays team and key overrides that block the tool. To add an override, choose a team or key and save the blocked input policy. To remove an override, select Remove next to that team or key. The detail view includes recent usage logs for the selected tool

Management API​

All Tool Policy management routes require proxy authentication. Send the proxy master key in the Authorization header

List tools​

GET /v1/tool/list returns an object with tools and total. Each tool row includes its policies and registry metadata. You can filter by the input policy with the input_policy query parameter

curl "http://localhost:4000/v1/tool/list" \
-H "Authorization: Bearer $LITELLM_MASTER_KEY"

To list only blocked tools:

curl "http://localhost:4000/v1/tool/list?input_policy=blocked" \
-H "Authorization: Bearer $LITELLM_MASTER_KEY"

Get one tool​

GET /v1/tool/{tool_name} returns a single tool row. URL-encode the tool name when it contains characters that have meaning in a URL

curl "http://localhost:4000/v1/tool/example_tool" \
-H "Authorization: Bearer $LITELLM_MASTER_KEY"

GET /v1/tool/{tool_name}/detail returns the tool row together with its overrides list. The detail route is used by the Admin UI

curl "http://localhost:4000/v1/tool/example_tool/detail" \
-H "Authorization: Bearer $LITELLM_MASTER_KEY"

The detail response has the following shape:

{
"tool": {
"tool_id": "tool-id",
"tool_name": "example_tool",
"input_policy": "untrusted",
"output_policy": "untrusted"
},
"overrides": []
}

The complete tool row can also contain origin, call_count, assignments, key_hash, team_id, key_alias, user_agent, last_used_at, created_at, updated_at, created_by, and updated_by

Get policy options​

GET /v1/tool/policy/options returns the supported input and output policy values with their labels and descriptions

curl "http://localhost:4000/v1/tool/policy/options" \
-H "Authorization: Bearer $LITELLM_MASTER_KEY"

The response has input_policies and output_policies arrays. Each option contains value, label, and description:

{
"input_policies": [
{
"value": "untrusted",
"label": "Untrusted",
"description": "Tool accepts any input, including data from untrusted tool outputs. Default for newly discovered tools."
}
],
"output_policies": [
{
"value": "trusted",
"label": "Trusted",
"description": "Tool output is verified safe. Will not trigger trust-chain blocks on downstream tools."
}
]
}

Update a global policy​

POST /v1/tool/policy accepts a JSON body containing tool_name and at least one of input_policy or output_policy. The input policy accepts trusted, untrusted, or blocked. The output policy accepts trusted or untrusted

curl -X POST "http://localhost:4000/v1/tool/policy" \
-H "Authorization: Bearer $LITELLM_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{
"tool_name": "example_tool",
"input_policy": "blocked",
"output_policy": "untrusted"
}'

The endpoint upserts the registry row when necessary and returns tool_name, the submitted policy fields, and updated: true. Omitting both policy fields returns HTTP 400 with At least one of input_policy or output_policy must be provided

Add or remove a team or key override​

The same update route can add or remove a block for one team or one key. Include exactly one of team_id or key_hash. Set input_policy to blocked to add the override

curl -X POST "http://localhost:4000/v1/tool/policy" \
-H "Authorization: Bearer $LITELLM_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{
"tool_name": "example_tool",
"input_policy": "blocked",
"team_id": "team-id"
}'

For a key override, use key_hash instead of team_id. The request model also accepts key_alias for the key metadata returned by the update route

curl -X POST "http://localhost:4000/v1/tool/policy" \
-H "Authorization: Bearer $LITELLM_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{
"tool_name": "example_tool",
"input_policy": "blocked",
"key_hash": "key-hash",
"key_alias": "production-key"
}'

To remove an override, use DELETE /v1/tool/{tool_name}/overrides with exactly one query parameter:

curl -X DELETE "http://localhost:4000/v1/tool/example_tool/overrides?team_id=team-id" \
-H "Authorization: Bearer $LITELLM_MASTER_KEY"

The delete route returns {"deleted": true, "tool_name": "example_tool"} when the override is removed. Supplying both team_id and key_hash is rejected with Provide either team_id or key_hash, not both

Get usage logs​

The detail view reads invoked-tool logs from GET /v1/tool/{tool_name}/logs. It supports page, page_size, start_date, and end_date query parameters. The date values use YYYY-MM-DD

curl "http://localhost:4000/v1/tool/example_tool/logs?page=1&page_size=50" \
-H "Authorization: Bearer $LITELLM_MASTER_KEY"

The response contains logs, total, page, and page_size. A log entry can include the request ID, timestamp, model, spend, total tokens, and an input snippet

Enforcement​

Add the Tool Policy Guardrail to the proxy configuration to enable policy enforcement:

guardrails:
- guardrail_name: "tool_policy"
litellm_params:
guardrail: tool_policy
mode: post_call

The guardrail supports pre_call, post_call, and during_call event hooks. On a request it reads tool names from the request tools or from the request route when the tools list is absent. On a response it reads tool names from response tool calls

When a tool has input_policy: "blocked", or a team or key override blocks it, the guardrail raises HTTP 400. Its caller-visible exception detail is:

{
"detail": {
"error": "Violated tool policy",
"blocked_tools": ["example_tool"],
"message": "Tool(s) ['example_tool'] are blocked by policy."
}
}

When a tool has input_policy: "trusted" and the conversation contains output from a tool with output_policy: "untrusted", the guardrail also raises HTTP 400. The detail includes blocked_tools, untrusted_sources, and a message stating that the trusted-input tool requires trusted input

The HTTP 400 response has this shape:

{
"detail": {
"error": "Violated tool policy",
"blocked_tools": ["trusted_tool"],
"untrusted_sources": ["untrusted_tool"],
"message": "trusted_tool requires trusted input but conversation contains untrusted output from untrusted_tool."
}
}

If the in-memory policy registry is not initialized, the guardrail returns the inputs without applying Tool Policies. The proxy initializes the registry from the database when its tool database objects are loaded, and policy updates resynchronize the registry when it has already been initialized

Configuration​

TOOL_POLICY_CACHE_TTL_SECONDS is an environment variable with a default of 60. The configuration reference describes it as the TTL in seconds for caching Tool Policy Guardrail results:

export TOOL_POLICY_CACHE_TTL_SECONDS=60

See Proxy configuration settings for the complete environment variable reference

Discovery behavior​

Tools are registered asynchronously after the request completes, as part of the same background flush that records spend, so a tool can take a few seconds to appear in the registry. Tool names are taken from MCP tool call metadata, OpenAI-format request tools, Anthropic Messages request tools, and response tool calls. Usage logs on a tool's detail page only include requests where the model actually invoked the tool