The Problem
DeepTutor is a collection of four semi-independent projects (deeptutor, web, deeptutor_cli, scripts) totaling 1,012 files with 779 analyzed code files. The repository functions as an agent-native personalized learning assistant, but its architecture spans multiple codebases with shared credentials, circular imports, and committed secrets that affect production readiness.
What This Does
DeepTutor provides an agent-native tutoring system with RAG capabilities, persistent chat, knowledge base management, and a CLI interface. The core deeptutor package (521 files, 395 code files) contains the agent orchestration, LLM configuration, and knowledge management. The web directory (219 files, 196 code files) is a Next.js frontend. The deeptutor_cli (15 files) provides agent-native CLI commands, and scripts (13 files) contains utility scripts.
Key files and their reach:
deeptutor_cli/main.py:142-mainentry point reaching 399 functionsdeeptutor/agents/base_agent.py- 1 class, 19 functions, called from 21 files, calls into 103deeptutor/services/path_service.py- defines file path resolution used across the projectdeeptutor/services/llm/config.py- LLM configuration hub, called from 28 filesdeeptutor/runtime/orchestrator.py:36-handleentry point reaching 399 functionsdeeptutor/agents/chat/agentic_pipeline.py:163-runentry point reaching 402 functions
The deeptutor/services/llm/config.py module is a high-blast-radius hub: 43 modules depend on it, and it carries instability 0.1 from its own circular dependency with deeptutor/services/llm/__init__.py and deeptutor/services/config/__init__.py.
How It Is Wired
Execution flows through a few concentrated entry points. From main in deeptutor_cli/main.py, control reaches 399 functions including get_prompt (called from 37 places), get_llm_config (33 places), and stream_llm (30 places). The run function in deeptutor/agents/chat/agentic_pipeline.py:163 similarly reaches 402 functions and is the primary path for message processing.
Traced paths from entry points to external effects:
main -> fetch_github_api[network via urllib.request.Request]handle -> _run[subprocess via subprocess.run]run -> save_to_json[filesystem via Path(filepath).parent.mkdir]start -> build[network via session.get("compressed_summary")]
The internal call graph has 6000 resolved call edges. Key hub functions include model_dump (51 callers), post (44), _t (43), and _run (38). The deeptutor/services/llm/config.py hub has 43 importers, making changes there high-radius.
Four circular dependency cycles exist involving deeptutor/services/llm/__init__.py, deeptutor/services/config/__init__.py, deeptutor/book/blocks/base.py, and associated modules. These increase cognitive load for any modification touching LLM or config code.
How To Use It
Setup: The repository uses pyproject.toml as the Python manifest and web/package.json for the frontend. No single install command covers the full stack; deeptutor requires Python 3.11+ dependencies resolved through the package manager, and web requires npm install.
Configuration: Environment variables are defined in .env.example and .env.example_CN. The deeptutor/services/llm/config.py file handles OpenAI-compatible binding setup via _set_openai_env_vars and _setup_openai_env_vars_early. The web/.env.local file is tracked despite being gitignored, containing active credentials.
Running it:
# CLI entry point
python -m deeptutor_cli.main
# Or the package CLI
deeptutor <command>
The README documents release tags from v0.2.0 through v1.3.5, with docker-compose files for development and GHCR deployment.
Real-World Use
A tutor agent processes a user message through the pipeline: _process_message constructs an OutboundMessage, which flows through execute -> ToolResult and get_definition -> ToolParameter. The agent calls call_llm or stream_llm for generation, persists conversation state via deeptutor/services/session/sqlite_store.py (78 functions, reads/writes a database), and may invoke RAG pipelines that make outbound network calls to embedding endpoints. A complete request from message entry to database write typically traverses 5-7 resolved call hops.
Code Health & Issues
Static analysis of 779 files found 411 issues across 6 kinds:
- [CRITICAL] Rotate credentials in committed
.env.example_CN-SILICONFLOW_API_KEY,COHERE_API_KEYhold generated values loaded at boot - [HIGH] Untrack
web/.env.localthough.gitignoreexcludes it - contains active credentials - [HIGH] Pin GitHub Actions to commit SHAs -
docker/setup-qemu-action@v3,docker/login-action@v3etc. use mutable tags - [HIGH] Add lockfile for
pyproject.toml- manifest without committed lockfile means tested and shipped artifacts can differ - [HIGH] Remove committed
.envand rotate credentials -.env.example_CNis tracked - [MEDIUM] Enable Dependabot or Renovate - 3 manifests, no update bot configured
- [MEDIUM] Pin container base images by digest -
python:3.11-slim,node:22-slimuse mutable tags - [MEDIUM] Gate PRs on dependency vulnerability scan - no dependency scan in CI
- [MEDIUM] Set
persist-credentials: falseon checkout -tests.ymlcheckout keeps the token
Additional measured findings: 8 import cycle members, 21 deep nesting instances across base_agent.py, path_service.py, manager.py, 5 oversized files (610+ lines each), and 8 hub modules with high blast radius.
The Bottom Line
DeepTutor is a substantial, functional agent-native tutoring system with working RAG, persistent chat, and CLI capabilities across four codebases. The architecture is coherent within each project but fragile at the boundaries: circular imports between LLM and config modules, committed credentials in example files, and mutable Docker base tags introduce real production risk. The codebase will suit teams that need a personalized learning assistant out of the box and have operational bandwidth to rotate secrets and pin dependencies. Teams requiring minimal operational overhead or strict supply-chain guarantees should look elsewhere, as the current state demands credential rotation, lockfile commitment, and cycle breaking before production use.