# Tatlock - Your Homelab Butler > **📖 For the complete system vision and architectural philosophy, see [PHILOSOPHY.md](PHILOSOPHY.md)** A privacy-first, offline-capable personal assistant system that coordinates specialized AI agents to help with research, development, home automation, and daily organization. ## Current Status - ✅ **Production-ready API** with OpenAI Responses API format - ✅ **Open WebUI integration** with reasoning bubbles (`` tags) - ✅ **Two-tier architecture** - The Steward analyzes requests, Tatlock coordinates execution - ✅ **Multi-agent coordination** - Expert household staff for specialized tasks - ✅ **Memory system** - User profile, preferences, and semantic recall - ✅ **Comprehensive testing** - 399 tests with good coverage ### The Household Staff | Agent | Role | Status | |-------|------|--------| | **Tatlock** | The Butler - Primary interface with witty personality | ✅ Active | | **The Steward** | Request analysis and capability recommendation | ✅ Active | | **The Librarian** | Research, wiki management, knowledge synthesis | ✅ Active | | **The Biographer** | User memory - profiles, preferences, facts | ✅ Active | | **The Developer** | Code assistance, debugging, architecture | 🔜 Planned | | **The Secretary** | Scheduling, calendars, reminders | 🔜 Planned | | **The Handyman** | System administration, monitoring | 🔜 Planned | | **The Housekeeper** | Home automation (Home Assistant) | 🔜 Planned | ## Features ### API Endpoints - **Responses API** (`/v1/responses`) - OpenAI Responses API format with structured output - Reasoning items for displaying thinking process - Function call items for tool execution - Message items for assistant responses - Streaming and non-streaming support - **Chat Completions** (`/v1/chat/completions`) - OpenAI Chat Completions compatibility - Automatic reasoning conversion to `` tags for Open WebUI - Full OpenAI API compatibility - Streaming support - **Models** (`/v1/models`) - List available models ### Advanced Capabilities - **Conversation History**: Auto-generated IDs, configurable max turns (default: 20) - **Context Management**: Token counting, automatic trimming, usage statistics - **Parameter Validation**: Temperature (0.0-2.0), reasoning effort levels, max tokens, stop sequences - **Real-time Enforcement**: Stop sequence detection and max token limits during streaming ### Available Models - **lorem-tester**: Full-featured mock agent with realistic behavior - Configurable reasoning effort levels - Random tool/function calls - Error triggers for testing (rate_limit, context_overflow) - **Tatlock**: Real PydanticAI agent with butler personality - **LLM Backend**: Ollama (mistral-nemo:latest by default) - **Personality**: Witty British butler, research-oriented - **Core Tools**: - **Calculator**: Safe mathematical expression evaluation - **Date/Time Toolkit**: Current time, relative dates, time differences - **Web Search**: Privacy-preserving search via SearXNG - **Household Coordination**: - **The Steward**: Analyzes requests and recommends capabilities - **The Librarian**: Research via library-desk HybridRAG + wiki - **The Biographer**: User memory and preference management - **Capabilities**: Streaming, reasoning, tool calling, multi-agent delegation ## Requirements - Python 3.12+ (Python 3.12.11 recommended) - **External Services** (must be running separately): - **Ollama**: LLM inference (mistral-nemo:latest, nomic-embed-text) - **Redis**: Caching and session memory - **Qdrant**: Vector storage for The Biographer's memory - **SearXNG**: Web search (optional) - **library-desk**: Research API for The Librarian (optional) ## Quick Start ### Installation ```bash # Clone the repository git clone https://git.schweitz.net/jpmschweitzer/tatlock.git cd tatlock # Create virtual environment python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate # Install dependencies pip install -r requirements.txt ``` ### Run the Server ```bash uvicorn src.main:app --reload ``` API available at `http://localhost:8000` ## Usage Examples ### Responses API Generate a response with reasoning: ```bash curl http://localhost:8000/v1/responses \ -H "Content-Type: application/json" \ -d '{ "model": "lorem-tester", "input": [ {"role": "user", "content": "Explain quantum computing"} ], "reasoning": { "effort": "medium", "summary": "auto" }, "max_output_tokens": 500, "stream": false }' ``` **Response Structure:** ```json { "id": "resp_abc123", "object": "response", "created_at": 1733529600, "model": "lorem-tester", "status": "completed", "output": [ { "type": "reasoning", "summary": ["Analyzing the request...", "Considering quantum mechanics..."] }, { "type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "Quantum computing uses..."}] } ], "usage": { "input_tokens": 10, "output_tokens": 50, "reasoning_tokens": 20, "total_tokens": 80 } } ``` ### Chat Completions (OpenAI-compatible) ```bash curl http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "lorem-tester", "messages": [ {"role": "user", "content": "Hello!"} ], "temperature": 0.7, "stream": true }' ``` ### List Models ```bash curl http://localhost:8000/v1/models ``` ### Conversation History Optionally track conversations using metadata: ```bash curl http://localhost:8000/v1/responses \ -H "Content-Type: application/json" \ -d '{ "model": "lorem-tester", "input": [{"role": "user", "content": "Hello"}], "metadata": {"conversation_id": "conv_abc123"} }' ``` **Note**: Client must send full conversation history in `input` array (OpenAI compatible). Server optionally tracks via `metadata.conversation_id` for future features. ### Using Tatlock with Tools Tatlock automatically uses his permanent tools when appropriate: ```bash # Mathematical calculation curl http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "Tatlock", "messages": [{"role": "user", "content": "What is sqrt(144) + 25?"}] }' # Date/time queries curl http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "Tatlock", "messages": [{"role": "user", "content": "What was the date 2 weeks ago?"}] }' # Web search for current information curl http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "Tatlock", "messages": [{"role": "user", "content": "Search for recent Python 3.12 features"}] }' ``` **Tatlock's Tool Usage Philosophy:** - Uses calculator for ALL mathematics (even simple arithmetic) - Uses date/time tools instead of guessing dates - Searches for current/volatile information to verify facts - Maintains a researcher's mindset with tool-assisted verification ## Open WebUI Integration ### Connection If running Open WebUI in Docker and API on host: ```bash # Use Docker bridge gateway IP http://172.17.0.1:8000/v1/chat/completions ``` ### Reasoning Display The Chat Completions endpoint automatically: 1. Enables reasoning generation 2. Converts reasoning to `` tags 3. Streams thinking before the response Open WebUI displays this as thought bubbles separate from the main response. ### Testing Error Handling Use special triggers in user messages: - `"trigger_rate_limit"` - Simulates rate limit error - `"trigger_context_overflow"` - Simulates context length error ## API Documentation Interactive documentation available at: - **Swagger UI**: `http://localhost:8000/docs` - **ReDoc**: `http://localhost:8000/redoc` ## Testing ```bash # Run all tests pytest # Run unit tests only (no external services needed) pytest --ignore=tests/e2e --ignore=tests/integration # Run with coverage pytest --cov=src --cov-report=term-missing # Current: ~400 tests ``` **Test Categories:** - Unit tests: Agent tools, capabilities, schemas, memory service - Integration tests: Full API stack with real Ollama - End-to-end tests: Chat completions, responses API ## Deployment ### Production Server ```bash # Multiple workers for production uvicorn src.main:app --host 0.0.0.0 --port 8000 --workers 4 ``` ### Recommendations - Use reverse proxy (nginx/caddy) for HTTPS - Enable rate limiting - Set up monitoring and logging - Configure resource limits - Use process manager (systemd/supervisor) ## Configuration Create a `.env` file for custom configuration: ```env # API Configuration API_HOST=0.0.0.0 API_PORT=8000 # Ollama Configuration OLLAMA_HOST=http://localhost:11434 OLLAMA_DEFAULT_MODEL=mistral-nemo:latest OLLAMA_EMBEDDING_MODEL=nomic-embed-text OLLAMA_TIMEOUT=120 # Redis Configuration REDIS_HOST=localhost REDIS_PORT=6379 REDIS_MEMORY_DB=2 REDIS_MEMORY_TTL_HOURS=24 # Qdrant Configuration (for memory) QDRANT_HOST=localhost QDRANT_PORT=6333 QDRANT_EMBEDDING_DIM=768 # Library-desk Configuration (for The Librarian) LIBRARY_DESK_HOST=http://localhost:8089 LIBRARY_DESK_TIMEOUT=60 # SearXNG Configuration (for web search) SEARXNG_HOST=http://localhost:8087 SEARXNG_TIMEOUT=30 # Logging LOG_LEVEL=INFO # CORS (default: allow all) CORS_ORIGINS=["*"] ``` See `.env.example` for full configuration options. ## Troubleshooting ### Streaming not working - Verify SSE-Starlette is installed - Check client supports Server-Sent Events - Test with: `pytest tests/responses/ -k streaming` ### Open WebUI can't connect - Use Docker bridge gateway IP: `172.17.0.1:8000` - Check firewall settings - Verify server is running on `0.0.0.0` ### Reasoning not showing - Ensure using Chat Completions endpoint (auto-enables reasoning) - Or manually enable in Responses API: `"reasoning": {"effort": "medium", "summary": "auto"}` - Check Open WebUI version supports `` tags ### Tatlock agent errors - Verify Ollama is running: `curl http://localhost:11434/api/tags` - Check model is downloaded: `ollama list` - Review environment variables: `OLLAMA_HOST`, `OLLAMA_DEFAULT_MODEL` - Check logs: `tail -f logs/server.log` ### Web search not working - Verify SearXNG is running: `curl http://localhost:8087/` - Check `SEARXNG_HOST` environment variable - SearXNG is optional - Tatlock will note if search is unavailable ## Project Structure ``` tatlock/ ├── src/ │ ├── agents/ # Agent implementations │ │ ├── biographer/ # The Biographer - memory management │ │ ├── librarian/ # The Librarian - research & wiki │ │ ├── steward/ # The Steward - request analysis │ │ ├── tatlock_core/ # Core butler tools │ │ ├── tatlock.py # Tatlock PydanticAI agent │ │ ├── coordination.py # Multi-agent coordination │ │ ├── delegation.py # Expert delegation wrappers │ │ └── protocol.py # Agent communication protocol │ ├── responses/ # Responses API (primary endpoint) │ ├── chat/ # Chat Completions wrapper │ ├── models/ # Models listing │ ├── core/ # Shared infrastructure │ │ ├── config.py # Configuration management │ │ ├── context.py # Request context (ContextVar) │ │ ├── memory_service.py # Direct memory access │ │ ├── memory_cache.py # Redis session cache │ │ ├── embeddings.py # Ollama embedding client │ │ ├── qdrant.py # Vector database client │ │ └── multi_tenancy.py # User isolation utilities │ └── main.py # Application entry point ├── tests/ # Comprehensive test suite ├── PHILOSOPHY.md # System vision and architecture ├── IMPLEMENTATION_ROADMAP.md # Development phases ├── CHANGELOG.md # Version history └── README.md # This file ``` ## Development For LLM agent development guidelines and architectural decisions, see [AGENTS.md](AGENTS.md). ## Contributing 1. Fork the repository 2. Create a feature branch 3. Make changes with tests 4. Ensure tests pass: `pytest` 5. Submit pull request ## Documentation - **System Philosophy**: [PHILOSOPHY.md](PHILOSOPHY.md) - Vision, goals, and architectural patterns - **User Guide**: This file - Installation, usage, and examples - **Developer Guidelines**: [AGENTS.md](AGENTS.md) - LLM agent development patterns - **Version History**: [CHANGELOG.md](CHANGELOG.md) - Changes and releases ### External References - **OpenAI Responses API**: https://platform.openai.com/docs/api-reference/responses - **FastAPI**: https://fastapi.tiangolo.com/ - **PydanticAI**: https://ai.pydantic.dev/ ## License [Add your license here] ## Version Current version: **1.2.2** - CI fix --- **Note**: Tatlock is a production-ready homelab butler. All household staff use PydanticAI with Ollama for local LLM inference.