> ## Documentation Index
> Fetch the complete documentation index at: https://phidatainc-redirect-agent-platform-overview.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Filter Knowledge

> Use filter expressions through the Agno API for precise knowledge base filtering.

When using the AgentOS API, you can apply filters to precisely control which knowledge base documents your agents search, without changing your agent code.
Filter expressions serialize to JSON and are automatically reconstructed server-side for powerful, programmatic filtering.

## Two Approaches to Filtering

Agno supports two ways to filter knowledge through the API:

* Use **dictionary filters** for simple "field = value" lookups
* Use **filter expressions** when you need OR/NOT logic or ranges

### 1. Dictionary Filters (Simple)

Best for straightforward equality matching. Send a JSON object with key-value pairs:

```json theme={null}
{"docs": "agno", "status": "published"}
```

### 2. Filter Expressions (Advanced)

Best for complex filtering with full logical control. Send structured filter objects:

```json theme={null}
{"op": "AND", "conditions": [
  {"op": "EQ", "key": "docs", "value": "agno"},
  {"op": "GT", "key": "version", "value": 2}
]}
```

<Tip>
  **When to use which:**

  * Use **dict filters** for simple queries like filtering by category or status
  * Use **filter expressions** when you need OR logic, exclusions (`NOT`), range queries (`GT`/`LT`/`GTE`/`LTE`), inequality (`NEQ`), or substring/prefix matching (`CONTAINS`/`STARTSWITH`)
</Tip>

## Filter Operators

Filter expressions support comparison, string-matching, and logical operators.

### Comparison Operators

* **`EQ(key, value)`** - Equality: field equals value
* **`NEQ(key, value)`** - Inequality: field does not equal value
* **`GT(key, value)`** - Greater than: `field > value`
* **`GTE(key, value)`** - Greater than or equal: `field >= value`
* **`LT(key, value)`** - Less than: `field < value`
* **`LTE(key, value)`** - Less than or equal: `field <= value`
* **`IN(key, [values])`** - Inclusion: field in list of values

### String Matching Operators

* **`CONTAINS(key, value)`** - field contains the substring (case-insensitive)
* **`STARTSWITH(key, value)`** - field starts with the given prefix

### Logical Operators

* **`AND(*filters)`** - All conditions must be true
* **`OR(*filters)`** - At least one condition must be true
* **`NOT(filter)`** - Negate a condition

<Note>
  **Nesting limit:** Filter expressions can be nested up to 10 levels deep. Deeper expressions are rejected during deserialization, fall into the error-handling path, and the request proceeds without filters (with a warning logged).
</Note>

### Python operator overloads

Filter expressions support Python's bitwise operators as shorthand for `AND`, `OR`, and `NOT`:

```python theme={null}
from agno.filters import EQ, GT

# These two are equivalent
EQ("status", "published") & GT("views", 1000)
AND(EQ("status", "published"), GT("views", 1000))

# OR
EQ("priority", "high") | EQ("urgent", True)

# NOT
~EQ("status", "draft")
```

## Serialization Format

Filter expression objects use a dictionary format with an `"op"` key that distinguishes them from regular dict filters. Field names differ per operator: `IN` takes `values` (plural); `NOT` takes `condition` (singular); `AND`/`OR` take `conditions` (plural); everything else takes `value`.

### Comparison and string operators

All comparison operators (`EQ`, `NEQ`, `GT`, `GTE`, `LT`, `LTE`) and string operators (`CONTAINS`, `STARTSWITH`) share the same shape:

```json theme={null}
{"op": "EQ", "key": "status", "value": "published"}
{"op": "GTE", "key": "views", "value": 1000}
{"op": "CONTAINS", "key": "title", "value": "agno"}
```

### IN takes values (plural)

```json theme={null}
{"op": "IN", "key": "category", "values": ["tech", "science"]}
```

Passing `"value"` instead of `"values"` is rejected by the deserializer.

### AND and OR take conditions (plural)

```json theme={null}
{
  "op": "AND",
  "conditions": [
    {"op": "EQ", "key": "status", "value": "published"},
    {"op": "GT", "key": "views", "value": 1000}
  ]
}
```

### NOT takes condition (singular)

```json theme={null}
{
  "op": "NOT",
  "condition": {"op": "EQ", "key": "status", "value": "archived"}
}
```

### Round-trip example

```python theme={null}
from agno.filters import EQ, GT, AND

filter_expr = AND(EQ("status", "published"), GT("views", 1000))
filter_expr.to_dict()
# {
#   "op": "AND",
#   "conditions": [
#     {"op": "EQ", "key": "status", "value": "published"},
#     {"op": "GT", "key": "views", "value": 1000}
#   ]
# }
```

<Note>
  The presence of the `"op"` key tells the API to deserialize the filter as a filter expression. Regular dict filters (without `"op"`) continue to work for backward compatibility.
</Note>

## Using Filters Through the API

In all examples below, you pass the serialized JSON string via the `knowledge_filters` field when creating a run.

### Dictionary Filters (Simple Approach)

For basic filtering, send a JSON object with key-value pairs. All conditions are combined with AND logic:

<CodeGroup>
  ```python Python Client theme={null}
  import requests
  import json

  # Simple dict filter
  filter_dict = {"docs": "agno", "status": "published"}

  # Serialize to JSON
  filter_json = json.dumps(filter_dict)

  # Send request
  response = requests.post(
      "http://localhost:7777/agents/agno-knowledge-agent/runs",
      data={
          "message": "What are agno's key features?",
          "stream": "false",
          "knowledge_filters": filter_json,
      }
  )

  result = response.json()
  ```

  ```bash cURL theme={null}
  curl -X 'POST' \
    'http://localhost:7777/agents/agno-knowledge-agent/runs' \
    -H 'accept: application/json' \
    -H 'Content-Type: multipart/form-data' \
    -F 'message=What are agno'\''s key features?' \
    -F 'stream=false' \
    -F 'session_id=' \
    -F 'user_id=' \
    -F 'knowledge_filters={"docs": "agno"}'
  ```
</CodeGroup>

**More Dict Filter Examples:**

```python theme={null}
# Filter by single field
{"category": "technology"}

# Filter by multiple fields (AND logic)
{"category": "technology", "status": "published", "year": 2024}

# Filter with different data types
{"active": True, "priority": 1, "department": "engineering"}
```

### Filter Expressions (Advanced Approach)

For complex filtering with logical operators and comparisons:

<CodeGroup>
  ```python Python Client theme={null}
  import requests
  import json
  from agno.filters import EQ

  # Create filter expression
  filter_expr = EQ("category", "technology")

  # Serialize to JSON
  filter_json = json.dumps(filter_expr.to_dict())

  # Send request
  response = requests.post(
      "http://localhost:7777/agents/my-agent/runs",
      data={
          "message": "What are the latest tech articles?",
          "stream": "false",
          "knowledge_filters": filter_json,
      }
  )

  result = response.json()
  ```

  ```bash cURL theme={null}
  curl -X 'POST' \
    'http://localhost:7777/agents/my-agent/runs' \
    -H 'Content-Type: multipart/form-data' \
    -F 'message=What are the latest tech articles?' \
    -F 'stream=false' \
    -F 'knowledge_filters={"op": "EQ", "key": "category", "value": "technology"}'
  ```
</CodeGroup>

### Multiple Filter Expressions

Send multiple filter expressions as a JSON array:

<CodeGroup>
  ```python Python Client theme={null}
  from agno.filters import EQ, GT

  # Create multiple filters
  filters = [
      EQ("status", "published"),
      GT("date", "2024-01-01")
  ]

  # Serialize list to JSON
  filters_json = json.dumps([f.to_dict() for f in filters])

  response = requests.post(
      "http://localhost:7777/agents/my-agent/runs",
      data={
          "message": "Show recent published articles",
          "stream": "false",
          "knowledge_filters": filters_json,
      }
  )
  ```

  ```bash cURL theme={null}
  curl -X 'POST' \
    'http://localhost:7777/agents/my-agent/runs' \
    -H 'Content-Type: multipart/form-data' \
    -F 'message=Show recent published articles' \
    -F 'stream=false' \
    -F 'knowledge_filters=[{"op": "EQ", "key": "status", "value": "published"}, {"op": "GT", "key": "date", "value": "2024-01-01"}]'
  ```
</CodeGroup>

## Error Handling

### Invalid Filter Structure

When filters have errors, they're gracefully ignored with warnings:

```bash theme={null}
# Missing required fields
curl ... -F 'knowledge_filters={"op": "EQ", "key": "status"}'
# Result: Filter ignored, warning logged

# Unknown operator
curl ... -F 'knowledge_filters={"op": "UNKNOWN", "key": "status", "value": "x"}'
# Result: Filter ignored, warning logged

# Invalid JSON
curl ... -F 'knowledge_filters={invalid json}'
# Result: Filter ignored, warning logged

# Filter nested deeper than 10 levels
curl ... -F 'knowledge_filters={"op": "NOT", "condition": {"op": "NOT", "condition": ...}}'
# Result: Filter ignored, warning logged (depth limit exceeded)
```

<Warning>
  When filters fail to parse, the search proceeds **without filters** rather than throwing an error. Always verify your filter JSON is valid and check server logs if results seem unfiltered.
</Warning>

### Client-Side Validation

Add validation before sending requests:

```python theme={null}
def validate_and_send_filter(filter_expr, message):
    """Validate filter before sending to API."""
    try:
        # Test serialization
        filter_dict = filter_expr.to_dict()
        filter_json = json.dumps(filter_dict)
        
        # Verify it's valid JSON
        json.loads(filter_json)
        
        # Send request
        return send_filtered_agent_request(message, filter_expr)
        
    except (AttributeError, TypeError, json.JSONDecodeError) as e:
        print(f"Filter validation failed: {e}")
        return None
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Advanced Filtering Guide" icon="filter" href="/knowledge/concepts/filters/advanced-filtering">
    Learn about filter expressions and metadata design in detail
  </Card>

  <Card title="Agent OS API" icon="code" href="/agent-os/api/usage">
    Explore the full Agent OS API reference
  </Card>

  <Card title="Knowledge Bases" icon="database" href="/knowledge/knowledge-bases">
    Understand knowledge base architecture and setup
  </Card>

  <Card title="Search & Retrieval" icon="magnifying-glass" href="/knowledge/concepts/search-and-retrieval/overview">
    Optimize your search strategies
  </Card>

  <Card title="Filter Expressions Example" icon="code" href="/knowledge/concepts/filters/advanced-filtering">
    See working examples of filter expressions via API
  </Card>
</CardGroup>
