Dify External Knowledge Integration#
RAGFlow exposes a Dify-compatible retrieval API that lets Dify treat any RAGFlow knowledge base as an external knowledge source. The integration is implemented in api/apps/restful_apis/dify_retrieval_api.py and is automatically registered with the Quart/Flask app via the dynamic blueprint loader in api/apps/__init__.py .
Endpoints#
| Method | Path | Description |
|---|---|---|
POST / GET | /api/v1/dify/retrieval | Chunk retrieval for a knowledge base |
GET | /api/v1/dify/retrieval/health | Connectivity health-check |
The retrieval endpoint accepts both POST (JSON body) and GET (query string) . Required fields are knowledge_id and query; optional fields live under retrieval_setting .
Request Shape#
{
"knowledge_id": "<kb_id>",
"query": "user question",
"use_kg": false,
"retrieval_setting": {
"top_k": 1024,
"score_threshold": 0.0
},
"metadata_condition": {
"logic": "and",
"conditions": [
{ "name": "brand_name", "comparison_operator": "is", "value": "Pampers" }
]
}
}
Response Shape#
The endpoint returns a records array where each item contains content, score, title, and a metadata object . The metadata always includes doc_id and document_id (the same value) — the latter is required by Dify's external retrieval contract .
Retrieval Logic#
The handler executes the following steps:
- Auth & access control — Validates the API key and checks cross-tenant access .
- Metadata pre-filter — If
metadata_conditionis present, callsmeta_filter+convert_conditionsfromcommon/metadata_utils.pyto compute a whitelist of matchingdoc_ids. If the filter produces no matches, a sentinel value ("-999") is passed so the retrieval returns zero results instead of bypassing the filter . - Vector retrieval — Calls
settings.retriever.retrieval(...)with the embedding model configured on the KB, passing thedoc_idswhitelist . - Child-chunk expansion — Optionally expands parent-level chunks to their children via
retrieval_by_children. - Knowledge graph (KG) augmentation — If
use_kg=true, a KG retrieval result is prepended to the ranked chunks .
Metadata Filtering#
Metadata filtering is handled in common/metadata_utils.py:
convert_conditionsnormalizes Dify operator names (e.g."is"→"=","not is"→"≠",">="→"≥") before passing conditions tometa_filter.meta_filterfilters document IDs in-memory across 14+ operators including equality, inequality, range (>,<,≥,≤),contains,in,empty,start with,end with. String comparisons are case-insensitive; date comparisons require strictYYYY-MM-DDformat on both sides .
The logic key ("and" / "or") controls how multiple conditions are combined; it defaults to "and" .
Historical note: Prior to the metadata filtering implementation,
metadata_conditionwas silently ignored and the API returned all documents regardless of filter values . This has since been fixed. See issue #8301 for historical context.
Go Backend Implementation#
A parallel production-ready Go implementation was added in PR #15704 (internal/handler/dify_retrieval_handler.go) and the metadata utilities were ported to Go in PR #15648 (internal/common/metadata_utils.go). The Go handler supports the same metadata_condition shape and uses a named sentinel (service.NoMatchDocIDSentinel) for no-match behavior .
Key Source Files#
| File | Purpose |
|---|---|
api/apps/restful_apis/dify_retrieval_api.py | Python retrieval handler + route definitions |
common/metadata_utils.py | meta_filter and convert_conditions utilities |
internal/handler/dify_retrieval_handler.go | Go handler (added PR #15704) |
internal/common/metadata_utils.go | Go metadata utilities (added PR #15648) |