# RAGFlow Instructions Use this file as the local operating guide for the current codebase. Prefer the code and the current AGENTS.md over any older convention or remembered project shape. ## Core Stance - Treat legacy code as liability, not as a compatibility target. - Prefer deletion over shims, deprecated branches, wrapper APIs, and dual-track migration notes. - If old and new implementations coexist, converge to one path unless an external contract forces compatibility. - Remove dead tests, commented-out code, stale docs, and "move later" notes instead of preserving them. - Reduce public surface area when a helper can be made private or internal. - Keep refactors centered on the owning abstraction, not on adjacent compatibility layers. ## Current stack - Backend: Go implements the API, admin, ingestor, and syncer modes in `cmd/ragflow_server.go`; the CLI runs from `cmd/ragflow-cli.go`. The Docker entrypoint starts the Go services according to its command-line flags, and the frontend development server uses fixed Go backend proxy routes. The Python API, admin, and workers are still present pending removal. - Frontend: React + TypeScript + Vite in `web/`. When working under `web/`, read and follow `web/AGENTS.md` for frontend conventions. - The Go module contains the server, ingestion, parsing, agent runtime, CLI, and supporting services. - Runtime services commonly include MySQL/PostgreSQL, Kvrocks, NATS JetStream, MinIO, ClickHouse, and Elasticsearch/Infinity/OpenSearch depending on configuration. ## Go-only target - Remove all Python code and Python-specific dependencies, scripts, containers, CI jobs, documentation, SDKs, and tests from the repository. Do not add new Python code while this removal is in progress. Replace Python-based preparation of Go native libraries, DeepDoc models, and the BPE table before removing the existing download scripts. - Move any still-required behavior and test coverage into the Go backend or the frontend before deleting the old implementation. Do not preserve a Python server, compatibility layer, fallback, or dual-backend path. - Before deleting `rag/`, move the Go DeepDoc `.ort` models and `ocr.res` out of `internal/rag/res/deepdoc/`, then update model discovery, dependency preparation, Docker packaging, and tests together. - Remove the frontend's Go/Python backend variants and update `web/CLAUDE.md` when the frontend no longer needs them. Until then, treat its dual-backend instructions as migration-only guidance; new frontend work should target the Go API. - Update Docker's default entrypoint, dependency image, and CI workflows when removing their remaining Python paths. Keep the frontend development proxy routes aligned with the Go API and Admin ports in `web/vite.config.ts`. - Keep this guide aligned with the checked-in tree. Once the Python directories are deleted, remove their migration inventory below. ## Code Layout to Expect - `cmd/ragflow_server.go`: Go entrypoint for the API, admin, ingestor, and syncer modes (`--api`, `--admin`, `--ingestor`, `--syncer`). - `cmd/ragflow-cli.go`: Go CLI entrypoint. - `api/`, `rag/`, `deepdoc/`, and `agent/`: legacy Python implementation pending deletion. Do not add features or extend dependencies there. - `internal/`: main Go application code. Important subtrees: - `internal/agent/`: Go agent runtime, canvas execution, components, tool bindings, workflow helpers. - `internal/admin/`: Go admin routes, handlers, and services. - `internal/binding/cpp/`: C++ tokenizer binding built by `build.sh` for the Go server. - `internal/cli/`: CLI parsing, HTTP transport, command execution, response formatting. - `internal/dao/`: Go data-access layer and persistence-facing helpers. - `internal/deepdoc/`: Go DeepDOC integrations, especially native-backed PDF/DOCX parsing. - `internal/engine/`: search/index backends such as Elasticsearch and Infinity. - `internal/entity/`: shared Go entities and model definitions. - `internal/handler/`: HTTP handlers and route-facing request logic. - `internal/ingestion/`: Go ingestion pipeline, canvas adapter, components, wiring, service orchestration. - `internal/ingestion/component/`: stage implementations such as file/parser/chunker/tokenizer/extractor. - `internal/ingestion/pipeline/`: DSL translation, canvas-driven execution, checkpoints, resume/run logic. - `internal/parser/`: parser and chunk libraries used by ingestion and other Go paths. - `internal/parser/parser/`: typed parse-result parsers for markdown/html/pdf/docx/xlsx/text and related families. - `internal/parser/chunk/`: chunk operator library and DSL/typed execution helpers. - `internal/service/`: higher-level business services used by handlers and server flows. - `internal/storage/`: storage backends and in-memory test doubles. - `internal/router/`: HTTP route registration. - `internal/server/`: server bootstrap/config wiring. - `internal/syncer/`: Go file synchronization service and connectors. - `internal/rag/`: Go retrieval and RAG logic. - `internal/harness/`: Go runtime harness and supporting execution code. - `web/`: frontend application. - `docker/`: local and production compose files. - `sdk/python/`: legacy Python client SDK pending deletion. - `tools/scripts/download_dev_deps.py` and `deps/download_deps.py`: Python downloaders for the Go build's dependencies. `download_dev_deps.py` pulls the native static libraries (pdfium, pdf_oxide, office_oxide, onnxruntime) that `build.sh` links; `download_deps.py` pulls the runtime resources (cl100k BPE table, DeepDoc models, embedding tokenizer assets) and installs the stagehand server into the SDK cache. Versions and URLs are defined inline in each downloader (`tools/scripts/download_dev_deps.py` for native static libraries, `deps/download_deps.py` for runtime resources); the tokenizer assets are inlined as `TOKENIZER_ASSETS` in each downloader. Replace these with non-Python preparation before removing Python dependencies. - `test/`: contains Python tests, including tests that import the legacy Python implementation directly. Migrate needed coverage to Go tests or frontend tests, then remove the Python tests; keep only tests for supported code. ## Go-Specific Rules - Treat `internal/ingestion`, `internal/parser`, and `internal/deepdoc` as actively refactored code. Prefer collapsing duplicate paths over preserving transitional wrappers. - Do not add or preserve deprecated Go APIs just to ease migration inside the repo. - Remove commented-out Go code instead of leaving recovery notes in place. - Keep package comments and doc comments aligned with the current runtime path, not with migration history. ## GORM query traps - **Never pass a bare string ID as the second argument to `Take`/`First`** (e.g. `Take(&x, id)`). Under GORM v1.25.7 a non-numeric string is treated as a raw SQL condition and concatenated into the `WHERE` clause: `Take(&x, "88b17c7a...")` emits `WHERE 88b17c7a... LIMIT 1`, which MySQL rejects with `Error 1054 (42S22): Unknown column '...' in 'where clause'`. Only strings that parse via `strconv.Atoi` are treated as primary-key values, so this bug is invisible for integer IDs and catastrophic for UUID primary keys. Always bind explicitly: `Take(&x, "id = ?", id)` or `Where("id = ?", id).Take(&x)`. - When you change a query form across many files, verify the generated SQL with a `Session(&gorm.Session{DryRun: true})` probe before relying on it. A passing unit test with no rows and a broken `WHERE` clause look identical unless the SQL is inspected. ## Shared database schema (Go + Python) The Go services and the Python API write to the same MySQL/PostgreSQL schema, and both own parts of it. Neither is authoritative over the whole. Each ORM derives index names differently: - Go (`internal/entity/`): GORM derives `idx_