# Additional filters

Additional filters can be used to subset the data in a single collection manually in addition to whatever filters the Query Agent decides to use in a particular search.

These persistent filters are defined at the specification of the collection, and combined with agent-generated filters using logical `AND` operations at search time.

Additional filters are available in both [Ask Mode](../modes/ask-mode.md) and [Search Mode](../modes/search-mode.md).

The syntax used is that of a standard Weaviate filter, [see more on filtering in Weaviate for details.](../how-to-query-search/filters.md)

These can be specified at **instantiation of the Query Agent**.

:::code-group{sync="languages"}
```python title="Python"
from weaviate.agents.query import QueryAgent
from weaviate.agents.classes import QueryAgentCollectionConfig
from weaviate.classes.query import Filter

qa = QueryAgent(
    client=client,
    collections=[
        QueryAgentCollectionConfig(
            name="Weather",
            additional_filters=Filter.by_property("temperature").greater_than(10)
        ),
    ],
```

```typescript title="JavaScript/TypeScript"
import { QueryAgent } from 'weaviate-agents';

const qa = new QueryAgent(client, {
    collections: [
        {
            name: 'Weather',
            additionalFilters: weatherCollection.filter.byProperty('temperature').greaterThan(10),
        },
    ],
});
```
:::

Or at **runtime of Ask or Search Mode**.

:::code-group{sync="languages"}
```python title="Python"
runtime_config = QueryAgentCollectionConfig(
    name="Weather",
    additional_filters=Filter.by_property("humidity").equal(39)
)

response = qa.ask(
    query="Provide a summary of the weather patterns", 
    collections=[runtime_config]
)
```

```typescript title="JavaScript/TypeScript"
const runtimeConfig = {
    name: 'Weather',
    additionalFilters: weatherCollection.filter.byProperty('humidity').equal(39),
};

const response = await qa.ask("Provide a summary of the weather patterns", {
    collections: [runtimeConfig],
});
```
:::

The additional filters are an argument to `QueryAgentCollectionConfig`, and used as part of collection configuration. [See the page on collection configuration for more detail](advanced-collections.md).

You can add as many layers of complexity to the custom filter as you need - a single filter on one property, or multiple nested filters across multiple properties.

## How is it used?

The filters are applied in addition to any filters determined by any agent in a run of the Query Agent. The Query Agent could decide one or many filters, and these are combined with the additional filters specified when the final result set is being retrieved.

In addition, a sample of data from the collection is provided to the agents to better understand the data they have access to. This data subset is also filtered using the additional filters provided.

## Use cases

Additional filters reduce the sample space of data to be retrieved. If you have a large data collection but only want to use the Query Agent across a subset of that data, specifying a filter enforces only a portion of the data can be used.

Since the Query Agent is a non-deterministic process (via the usage of LLMs), if you want to enforce a particular property is always being filtered, you can do so here.

For example, instead of directly trying to enforce the filter in the prompt, you could replace

:::code-group{sync="languages"}
```python title="Python"
response = qa.ask(
    query=(
        "What type of contracts have been signed and who were the authors?"
        "IMPORTANT: Only look at contracts from 2025."
    ),
    collections=["FinancialContracts"]
)
```

```typescript title="JavaScript/TypeScript"
const badResponse = await qa.ask(
    `What type of contracts have been signed and who were the authors? 
    IMPORTANT: Only look at contracts from 2025.`,
    {
        collections: ['FinancialContracts'],
    }
);
```
:::

with

:::code-group{sync="languages"}
```python title="Python"
from datetime import datetime, timezone

start_date = datetime(2025, 1, 1, tzinfo=timezone.utc)
end_date = datetime(2026, 1, 1, tzinfo=timezone.utc)

response = qa.ask(
    query="What type of contracts have been signed and who were the authors?",
    collections=[
        QueryAgentCollectionConfig(
            name="FinancialContracts",
            additional_filters=(
                Filter.all_of(
                    [
                        Filter.by_property("date").greater_than(start_date),
                        Filter.by_property("date").less_than(end_date)
                    ]
                )
            )
        )
    ]
)
```

```typescript title="JavaScript/TypeScript"
import { Filters } from 'weaviate-client';
const goodResponse = await qa.ask(
    `What products were sold last month?`,
    {
        collections: [
            {
                name: 'FinancialContracts',
                additionalFilters: Filters.and(
                    financialCollection.filter.byProperty('date').greaterThan(new Date(2025, 0, 1)),
                    financialCollection.filter.byProperty('date').lessThan(new Date(2026, 0, 1)),
                ),
            },
        ],
    }
);
```
:::

:::accordion{title="Additional Information"}
You would expect both examples to provide the same (or similar) output. The directness in the first prompt is very likely to ensure that the agent provides an accurate filter based on the request.

However, since the LLM agent is a non-deterministic process, it is never guaranteed. Directly passing the filter ensures it will always be used.
:::

Another example could be in a user-facing app, if you want to restrict search results to only a single user ID, you can directly pass the filter instead of relying on the agent to use the correct filter.

## Basic filtering

A single filter, such as limiting the search to only a single category, can be constructed simply.

:::code-group{sync="languages"}
```python title="Python"
QueryAgentCollectionConfig(
    name="ECommerce",
    additional_filters=Filter.by_property("category").equal("Tops")
)
```

```typescript title="JavaScript/TypeScript"
const basicFilterConfig = {
    name: 'ECommerce',
    additionalFilters: ecommerceCollection.filter.byProperty('category').equal('Tops'),
};
```
:::

## Nested filtering

If you want to provide more than one filter, you can wrap it in either a logical `AND` or `OR` using Weaviate filter construction, such as:

:::code-group{sync="languages"}
```python title="Python"
QueryAgentCollectionConfig(
    name="ECommerce",
    additional_filters=Filter.any_of(
        [
            Filter.by_property("category").equal("Shoes"),
            Filter.all_of(
                [
                    Filter.by_property("price").greater_than(50),
                    Filter.by_property("price").less_than(100)
                ]
            )
        ]
    )
)
```

```typescript title="JavaScript/TypeScript"
const nestedFilterConfig = {
    name: 'ECommerce',
    additionalFilters: Filters.or(
        ecommerceCollection.filter.byProperty('category').equal('Shoes'),
        Filters.and(
            ecommerceCollection.filter.byProperty('price').greaterThan(50),
            ecommerceCollection.filter.byProperty('price').lessThan(100),
        ),
    ),
};
```
:::

## Questions and feedback

Have a question or feedback? Here's how to reach us.

::::card-grid
:::card{title="Community Forum" href="https://forum.weaviate.io/c/support" icon="messages-square"}
Ask questions and connect with other developers on our **Community forum**.
:::

:::card{title="Support" href="/guides/support-overview" icon="life-buoy"}
Weaviate Cloud user or customer? Find the right channel on the **Support page**.
:::
::::

## Related pages

- [Agents](./agents-index.md)
- [AI-assisted Weaviate code generation](./ai-assisted-vibe-coding-index.md)
- [APIs](./apis-index.md)
- [Authorization and authentication](./authorization-and-authentication-index.md)
- [Benchmarks](./benchmarks-index.md)
- [Best practices](./best-practices-index.md)
- [Client libraries](./clients-index.md)
- [Client Libraries / SDKs](./client-libraries-index.md)
- [Cloud](./cloud-index.md)
- [Cloud account management](./cloud-account-management-index.md)

# Agent Instructions

This portal answers questions programmatically. To receive a synthesized,
source-cited answer instead of crawling page by page, append the `?ask=`
query parameter to any page URL on this site:

    /guides/quickstart?ask=how+do+I+authenticate

Optional parameters:

- `&goal=<what-you-are-trying-to-do>` steers the answer toward your
  objective (e.g. `&goal=write+a+python+client`).
- `&version=<label>` scopes the answer to a mounted version when the
  portal publishes more than one.

The response is `text/markdown`: the answer followed by a `# Sources` list
of the portal pages it was grounded in. Status codes are the contract:

- `200` — the answer; `402` — the portal owner’s plan or answer credits are
  exhausted (surface this to your operator; do NOT retry); `429` — you are
  rate-limited; back off for the `Retry-After` seconds; `503` — the answer
  lane is temporarily unavailable; fall back to crawling the `.md` pages.

For the full corpus map read `llms.txt` at the site root; for the tool
surface (search + page fetch as MCP tools) see `/mcp`.
