Files
cleveragents-core/docs/adr/ADR-005-technical-stack.md
T
Jeffrey Phillips Freeman 339b7de700
CI / lint (push) Successful in 15s
CI / typecheck (push) Successful in 30s
CI / security (push) Successful in 24s
CI / quality (push) Successful in 16s
CI / integration_tests (push) Successful in 5m6s
CI / build (push) Successful in 15s
CI / unit_tests (push) Successful in 16m32s
CI / docker (push) Successful in 9s
CI / coverage (push) Has been cancelled
Docs: Added ADRs and improved TOC handling
2026-02-16 22:11:01 -05:00

193 lines
10 KiB
Markdown

# ADR-005: Technical Stack
**Status:** Accepted
**Date:** 2026-02-16
**Supersedes:** None
**Author(s):** Jeffrey Phillips Freeman <Jeffrey.Freeman@CleverThis.com>
**Approver(s):** Jeffrey Phillips Freeman <Jeffrey.Freeman@CleverThis.com>
## Context
CleverAgents requires a cohesive technology stack that supports a CLI-first interface, LLM orchestration with multiple providers, structured data persistence, code intelligence indexing (full-text, vector, and graph), reactive event processing, sandboxed execution, and both local and server deployment modes. The stack must be Python-only for consistency and alignment with the LLM ecosystem. Every technology choice must have a clear rationale and defined minimum version.
## Decision
CleverAgents is built on **Python >= 3.13** as the sole implementation language. The stack is organized by functional area, with specific libraries chosen for CLI, LLM runtime, data persistence, indexing, configuration, testing, code quality, infrastructure, and observability.
## Design
### Core Runtime
| Technology | Min Version | Role |
|---|---|---|
| Python | >= 3.13 | Primary language. Type hint maturity, async/await, pattern matching, performance. |
| Hatchling | >= 1.21.0 | PEP 517 build backend. Lightweight, standards-compliant. |
| uv | >= 0.8.0 | Package installer and resolver. 10-100x faster than pip. Used in CI, Docker, and Nox. |
### CLI and Presentation
| Technology | Min Version | Role |
|---|---|---|
| Typer | >= 0.9.0 | CLI framework. Automatic help, type inference, Rich integration, nested command groups. |
| Rich | (transitive) | Terminal rendering. Panel, Table, Tree, Syntax, Progress, Spinner, Markdown. |
| Textual | (future) | TUI framework. Reactive terminal UI, servable as web app via Textual Web. |
### LLM and AI Runtime
| Technology | Min Version | Role |
|---|---|---|
| LangChain | >= 0.2.14 | LLM abstraction. Provider-agnostic chat models, embeddings, output parsing, tool calling. |
| LangGraph | (transitive) | Stateful workflow orchestration. `StateGraph` with conditional edges, checkpointing, streaming. |
| LangChain Provider Packages | varies | `langchain-openai` (>= 0.2.0), `langchain-google-genai` (>= 0.2.0), `langchain-anthropic`, `langchain-groq`, `langchain-together`, `langchain-cohere`. |
| LangChain Community | >= 0.2.14 | FAISS vector store, FakeListLLM/FakeEmbeddings for testing. |
| RxPY | >= 3.2.0 | Reactive streams. Subject, operators (map, filter, flat_map, debounce, throttle, scan) for event routing and backpressure. |
| MCP SDK | >= 1.4.0 | Model Context Protocol client. Tool discovery and invocation against MCP servers. |
### Data and Persistence
| Technology | Min Version | Role |
|---|---|---|
| SQLite | (system) | Primary database. Zero-config, file-based, ACID, WAL mode for concurrent reads. |
| SQLAlchemy | (transitive) | ORM. Declarative mapping, session management, Unit of Work, dialect abstraction. |
| Alembic | >= 1.13.1 | Database migrations. Version-controlled schema upgrade/downgrade. Auto-applied on init. |
| python-ulid | >= 2.7.0 | ULID generation. Lexicographically sortable by creation time for all entity IDs. |
### Indexing and Code Intelligence
| Technology | Min Version | Role |
|---|---|---|
| Tantivy (tantivy-py) | configurable | Full-text search. Rust-based, sub-millisecond. Alternative: SQLite FTS5. |
| FAISS (faiss-cpu) | >= 1.7.4 | Vector similarity search. Approximate nearest neighbor for semantic code search. |
| Qdrant | configurable | Vector search alternative for production horizontal scaling. |
| Neo4j | configurable | Knowledge graph for structural code relationships. Alternative: rdflib. |
| rdflib | >= 7.1.4 | In-process RDF graph store for lightweight structural analysis. |
| OpenAI Embeddings | configurable | Default embedding provider (`text-embedding-3-small`). Alternatives: Anthropic, local models. |
### Configuration and Validation
| Technology | Min Version | Role |
|---|---|---|
| Pydantic | >= 2.7.0 | Data validation and modeling for all domain models and config objects. |
| Pydantic Settings | >= 2.11.0 | Environment configuration with `CLEVERAGENTS_` prefix and `.env` support. |
| Jinja2 | >= 3.1.0 | Template rendering for actor prompts, YAML interpolation, prompt templates. |
| TOML (tomllib) | stdlib | Global configuration format. Native nested table support. |
| YAML (PyYAML) | (transitive) | Entity configuration format. All entity definitions use YAML. |
### Testing
| Technology | Min Version | Role |
|---|---|---|
| Behave | >= 1.2.6 | BDD feature tests. Gherkin scenarios, custom parallel runner. |
| Robot Framework | >= 7.3.2 | Integration tests. Keyword-driven CLI workflow tests, parallel via pabot. |
| pytest | >= 8.0.0 | Unit tests. Fixtures, parametrization, plugin support. |
| pytest-asyncio | >= 0.23.0 | Async test support for LangGraph workflows and RxPY streams. |
| pytest-cov / coverage | >= 7.11.0 | Coverage reporting. Target: 85% line coverage. |
| Hypothesis | >= 6.136.6 | Property-based testing for invariant verification and merge strategies. |
| ASV | >= 0.6.5 | Performance benchmarks. Plan generation latency, CLI startup, indexing throughput. |
### Code Quality
| Technology | Min Version | Role |
|---|---|---|
| Ruff | >= 0.1.0 | Linting and formatting. Rules: E, F, W, B, UP, I, SIM, RUF. Line length 88, double quotes. |
| Pyright | >= 1.1.350 | Static type checking in strict mode for the entire codebase. |
### Infrastructure and Deployment
| Technology | Min Version | Role |
|---|---|---|
| Docker | multi-stage | `python:3.13-slim`, non-root user (`appuser`, uid 1000). Entrypoint: `python -m cleveragents`. |
| Helm | (chart) | Kubernetes deployment for server mode. Chart in `k8s/`. |
| Nox | >= 2025.4.22 | Task automation. Sessions for lint, test, build, docs, benchmarks, coverage. Uses uv backend. |
| Forgejo CI | (workflow) | CI pipeline: lint → typecheck → behave (matrix 3.11/3.12/3.13) → build → docker → helm. |
### Monitoring and Observability
| Technology | Min Version | Role |
|---|---|---|
| structlog | >= 24.4.0 | Structured JSON logging with context binding (plan_id, decision_id, actor_name, tool_name). |
| LangSmith | (optional) | LLM observability. Tracing, token usage, latency, cost. Via `CLEVERAGENTS_LANGSMITH_*` env vars. |
### Additional Libraries
| Technology | Min Version | Role |
|---|---|---|
| dependency-injector | >= 4.41.0 | DI container. DeclarativeContainer with Singleton, Factory, Configuration providers. |
| watchdog | >= 4.0.0 | File system monitoring. Auto re-indexing on file changes. |
| numpy | >= 2.1.0 | Vector operations for embedding similarity and confidence score aggregation. |
| uvicorn | >= 0.30.1 | ASGI server for server mode REST API (FastAPI). |
## Constraints
- The entire codebase is Python-only. No secondary languages for core functionality.
- Version constraints are minimum versions; newer compatible versions are acceptable.
- All dependencies must be installable via `uv` and declared in `pyproject.toml`.
- Configurable backends (Tantivy vs. SQLite FTS5, FAISS vs. Qdrant, Neo4j vs. rdflib) must be swappable via configuration without code changes, enabled by the hexagonal architecture.
- The Docker production image must use `python:3.13-slim` with a non-root user.
## Consequences
### Positive
- A single language across the entire stack simplifies hiring, tooling, and maintenance.
- The LLM ecosystem (LangChain, MCP SDK) is Python-native, avoiding FFI overhead.
- Configurable backends at every infrastructure layer allow adaptation to different deployment scales.
- The testing stack (Behave + Robot + pytest + Hypothesis) covers behavioral, integration, unit, and property-based testing.
### Negative
- Python's runtime performance is lower than compiled languages; CPU-intensive operations (embedding computation, large index operations) rely on native extensions (numpy, FAISS, Tantivy).
- The large dependency tree increases the attack surface and requires active dependency management.
- Supporting multiple configurable backends per infrastructure layer increases the testing matrix.
### Risks
- Major version upgrades to LangChain or Pydantic could require significant migration effort.
- Tantivy and FAISS are native extensions that may have platform-specific build issues.
- The breadth of the stack means that not all developers will be expert in every component.
## Alternatives Considered
None — specification-driven requirement. The technical stack is enumerated in the specification with specific version constraints and rationales for each choice.
## Compliance
- **Dependency pinning**: `pyproject.toml` declares minimum versions for all dependencies. `uv.lock` pins exact versions for reproducible builds.
- **CI matrix**: The Forgejo CI pipeline tests against Python 3.11, 3.12, and 3.13 to ensure version compatibility.
- **Vulnerability scanning**: Automated dependency vulnerability scanning (e.g., `pip-audit` or `safety`) runs in CI.
- **Build verification**: Docker image builds are tested in CI to catch platform-specific build failures for native extensions.
- **Performance benchmarks**: ASV tracks key performance metrics across commits to detect regressions from dependency changes.
## Related ADRs
| ADR | Title | Relationship |
|-----|-------|-------------|
| [ADR-001](ADR-001-layered-architecture.md) | Layered Architecture | Stack choices are organized according to the four-layer structure |
| [ADR-003](ADR-003-dependency-injection.md) | Dependency Injection | `dependency-injector` is a core stack choice for service wiring |
| [ADR-004](ADR-004-data-validation.md) | Data Validation | Pydantic V2 is a core stack choice for validation and modeling |
| [ADR-019](ADR-019-storage-and-persistence.md) | Storage and Persistence | SQLAlchemy and SQLite/PostgreSQL are the chosen persistence stack |
| [ADR-021](ADR-021-cli-and-output-rendering.md) | CLI and Output Rendering | Typer and Rich are the chosen CLI stack |
| [ADR-022](ADR-022-langchain-langgraph-integration.md) | LangChain/LangGraph Integration | LangChain and LangGraph are the chosen LLM orchestration stack |
| [ADR-025](ADR-025-observability-and-logging.md) | Observability and Logging | structlog is the chosen logging stack |
## Acceptance
### Votes For
| Voter | Comment |
|-------|---------|
| Jeffrey Phillips Freeman <Jeffrey.Freeman@CleverThis.com> | This stack balances maturity, ecosystem support, and alignment with our architectural goals |
**Total: 1**
### Votes Against
| Voter | Comment |
|-------|---------|
**Total: 0**
### Abstentions
| Voter | Comment |
|-------|---------|
**Total: 0**