Skip to content

Semantic Tool Filtering policy

Overview

The Semantic Tool Filtering policy dynamically filters the tools provided within an API request based on their semantic relevance to the user query. This policy extracts both the query and the tool definitions from the incoming payload, generates embeddings for the query, and performs a similarity search against the provided tools. It then replaces the original tools array with a filtered subset, optimizing the request before it reaches the LLM.

This policy helps reduce token consumption and improve LLM response quality by sending only the most relevant tools for each request.

Features

  • Semantic similarity-based filtering of tools using embedding vectors.
  • Two selection modes: "By Rank" (top-K) and "By Threshold".
  • Flexible Format Support: Supports both JSON and text-based tool/query extraction.
  • Embedding cache with LRU eviction to minimize redundant API calls.
  • Configurable JSONPath expressions for payload extraction.
  • Mixed mode support (extract query from JSON and tools from text, or vice versa).

Configuration

User Parameters (API Definition)

Parameter Type Required Default Description
selectionMode string Yes By Rank Method used to filter tools: By Rank (selects top-K) or By Threshold (selects based on score).
limit integer No 5 The number of most relevant tools to include (used if selectionMode is By Rank).
threshold number No 0.7 Similarity threshold for filtering (0.0 to 1.0). Only tools with a score above this value are included (used if selectionMode is By Threshold).
queryJSONPath string Yes $.messages[-1].content JSONPath expression to extract the user's query from the request body.
toolsJSONPath string Yes $.tools JSONPath expression to extract the tools definition from the request body. It can point to the array itself, such as $.tools, or to the iterated object inside each array item, such as $.tools[*].function.
userQueryIsJson boolean Yes true Specifies format of user query. true: use queryJSONPath. false: extract from text using <userq> tags.
toolsIsJson boolean Yes true Specifies format of tools definition. true: use toolsJSONPath. false: extract from text using <toolname>/<tooldescription> tags.

System Parameters (From config.toml)

These parameters are configured in the gateway's config.toml to set up the embedding provider.

Parameter Type Required Default Description
embeddingProvider string Yes - Embedding provider: OPENAI, MISTRAL, or AZURE_OPENAI.
embeddingEndpoint string Yes - Endpoint URL for the embedding service.
embeddingModel string Conditional - Model name (e.g., text-embedding-3-small or mistral-embed). Required for OPENAI and MISTRAL; optional for AZURE_OPENAI (deployment name is derived from the endpoint).
apiKey string Yes - API key for the embedding service.

Sample System Configuration

Add the following configuration section under the root level in your config.toml file:

embedding_provider = "MISTRAL" # Supported: MISTRAL, OPENAI, AZURE_OPENAI
embedding_provider_endpoint = "https://api.mistral.ai/v1/embeddings"
embedding_provider_model = "mistral-embed"
embedding_provider_dimension = 1024
embedding_provider_api_key = ""

build.yaml

Add the following entry to the policies section in /gateway/build.yaml:

- name: semantic-tool-filtering
  gomodule: github.com/wso2/gateway-controllers/policies/semantic-tool-filtering@v0

Reference Scenarios

Scenario 1: Filtering Tools by Rank (JSON Format)

This scenario demonstrates filtering tools to select the top 3 most relevant ones based on a user query in a JSON payload.

Configuration:

policies:
  - policy:
      name: semantic-tool-filtering
      parameters:
        selectionMode: "By Rank"
        limit: 3
        queryJSONPath: "$.contents[0].parts[0].text"
        toolsJSONPath: "$.tools[0].function_declarations"
        userQueryIsJson: true
        toolsIsJson: true

Request:

{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "Get weather forecast. what are the tools you have?"
        }
      ]
    }
  ],
  "tools": [
    {
      "function_declarations": [
        {
          "name": "get_weather",
          "description": "Get current weather and 7-day forecast for a location.",
          "parameters": { "type": "OBJECT", "properties": { "location": { "type": "string" } }, "required": ["location"] }
        },
        {
          "name": "book_venue",
          "description": "Reserve a conference room or meeting space.",
          "parameters": { "type": "OBJECT", "properties": { "location": { "type": "string" } }, "required": ["location"] }
        },
        {
           "name": "send_email",
           "description": "Send an email to a specific recipient.",
           "parameters": { "type": "OBJECT", "properties": { "recipient": { "type": "string" } }, "required": ["recipient"] }
        }
      ]
    }
  ]
}

The policy will interpret the request, calculate embeddings, and filter the tools array to include only the top 3 matches (e.g., get_weather, book_venue, send_email).

Scenario 1b: OpenAI/Mistral-style Function Wrappers

If the request wraps each tool as an object with a nested function, configure the iterator path so the policy reads name and description from the nested object while still filtering the parent tools array.

Configuration:

policies:
  - policy:
      name: semantic-tool-filtering
      parameters:
        selectionMode: "By Rank"
        limit: 3
        queryJSONPath: "$.messages[-1].content"
        toolsJSONPath: "$.tools[*].function"
        userQueryIsJson: true
        toolsIsJson: true

Request:

{
  "messages": [
    {
      "role": "user",
      "content": "What tools can help me check the weather?"
    }
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Get current weather"
      }
    },
    {
      "type": "function",
      "function": {
        "name": "send_email",
        "description": "Send an email notification"
      }
    }
  ]
}

Scenario 2: Filtering Tools by Threshold

In this scenario, only tools with a semantic similarity score of 0.7 or higher are included.

Configuration:

policies:
  - policy:
      name: semantic-tool-filtering
      parameters:
        selectionMode: "By Threshold"
        threshold: 0.7
        # Rest of the parameters

Scenario 3: Text Format (XML-like Tags)

This scenario handles cases where the user query and tool definitions are embedded in a text payload using custom tags.

Configuration:

policies:
  - policy:
      name: semantic-tool-filtering
      parameters:
        selectionMode: "By Rank"
        limit: 3
        userQueryIsJson: false
        toolsIsJson: false
        queryJSONPath: "$.messages[-1].content.text"
        toolsJSONPath: "$.messages[-1].content.text"

Request Body:

{
  "contents": [
    {
      "parts": [
        {
          "text": "You are a logistics assistant with access to the following tools:\n\n<toolname>get_weather</toolname><tooldescription>Get current weather and 7-day forecast for a location</tooldescription>\n<toolname>book_venue</toolname><tooldescription>Reserve meeting spaces</tooldescription>\n\n<userq>I'm planning a corporate retreat in Denver next weekend. Check the weather.</userq>"
        }
      ]
    }
  ]
}

The policy extracts <userq> as the query and <toolname>/<tooldescription> as tools, then performs filtering. After the filtering process, the tags are removed.