Files
tatlock/PROJECT_CLAUDIFICATION.md
T
jpmschweitzerandClaude Opus 4.5 496f37a538
Build and Push / release (release) Failing after 6s
Build and Push / build (release) Successful in 3m5s
feat: add Claude backend with automatic Ollama fallback (Claudification Phase 1)
All agents now prefer Claude API when ANTHROPIC_API_KEY is configured,
with automatic fallback to Ollama when offline or unconfigured. New
src/anthropic/ module provides model selection via get_model() factory.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 07:19:29 +01:00

17 KiB

Tatlock Enhancement Plan: Bidirectional Claude Integration

Executive Summary

Implement a bidirectional architecture that:

  1. Superpowers Tatlock by swapping Ollama→Claude backend (200k context, better reasoning, same butler personality)
  2. Exposes Tatlock as MCP server for Claude instances on any device (phone, browser, desktop)

This gives you the flexibility to use whichever AI is best/most accessible at any moment.

Key Insight: Blanket Backend Swap (Simpler Than Sidecar)

Instead of adding a Claude "Analyst" sidecar agent, swap the underlying model for ALL agents:

CURRENT:  TatlockAgent → OpenAIChatModel → OllamaProvider → Ollama (mistral-nemo)
PROPOSED: TatlockAgent → AnthropicModel → AnthropicProvider → Claude API
                      ↘ (fallback when offline) → OllamaProvider → Ollama

Why this works:

  • PydanticAI natively supports Anthropic via AnthropicModel + AnthropicProvider
  • The same TATLOCK_SYSTEM_PROMPT is passed to Claude - butler personality preserved
  • Claude is better at following system prompts than mistral-nemo
  • 200k context for ALL queries, not just "complex" ones
  • Simpler architecture: no routing logic, no sidecar delegation

Research Findings

Industry Best Practices (2025-2026)

MCP Protocol Updates (MCP Spec Updates June 2025):

  • Streamable HTTP replaced SSE (March 2025) - better for cloud deployment
  • OAuth 2.0 required for remote servers - MCP servers are OAuth Resource Servers
  • Tool Output Schemas now available - better structured data handling
  • MCP Registry launched (Sept 2025) - community server discovery

Community Patterns (Claude Code Router):

  • Task-based routing is becoming standard: route simple→local, complex→cloud
  • Translation proxies bridge Anthropic Messages API ↔ OpenAI format
  • Cost savings of up to 98% reported with smart routing

Home Automation MCP (ha-mcp):

  • Production-ready MCP servers exist for Home Assistant
  • Support Claude Code, Gemini CLI, Open WebUI, VSCode, Cursor
  • Pattern: expose local tools securely to remote AI clients

Remote MCP Access (mcp-remote):

  • Bridge local MCP servers to Claude Desktop/Browser via proxy
  • Supports authentication headers for security
  • Works with ngrok/Cloudflare Tunnel for HTTPS

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                    BIDIRECTIONAL TATLOCK-CLAUDE ARCHITECTURE                        │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                     │
│  ╔═══════════════════════════════════════════════════════════════════════════════╗  │
│  ║  SCENARIO A: Using Tatlock (Open WebUI, local apps)                           ║  │
│  ║  ─────────────────────────────────────────────────                            ║  │
│  ║                                                                               ║  │
│  ║    Request → Steward → Tatlock → Tools + Expert Delegation                    ║  │
│  ║                            │                                                  ║  │
│  ║                            ├─→ Librarian (Claude) → research, wiki, RAG       ║  │
│  ║                            ├─→ Biographer (Claude) → memory, preferences      ║  │
│  ║                            ├─→ Housekeeper (Claude) → home automation         ║  │
│  ║                            └─→ All powered by Claude with Ollama fallback     ║  │
│  ║                                                                               ║  │
│  ║    Butler personality preserved, 200k context for all queries                 ║  │
│  ╚═══════════════════════════════════════════════════════════════════════════════╝  │
│                                                                                     │
│  ╔═══════════════════════════════════════════════════════════════════════════════╗  │
│  ║  SCENARIO B: Using Claude.ai / Claude Desktop / Phone                         ║  │
│  ║  ────────────────────────────────────────────────────                         ║  │
│  ║                                                                               ║  │
│  ║    Claude ──[MCP over HTTPS]──► Tatlock MCP Server → Household Tools          ║  │
│  ║                                        │                                      ║  │
│  ║                                        ├─→ calculator, datetime               ║  │
│  ║                                        ├─→ web_search, wiki_search            ║  │
│  ║                                        ├─→ hybrid_search (RAG)                ║  │
│  ║                                        ├─→ memory_recall, store_insight       ║  │
│  ║                                        └─→ home_control (lights, climate)     ║  │
│  ║                                                                               ║  │
│  ║    Full 200k context, your local tools accessible from anywhere               ║  │
│  ╚═══════════════════════════════════════════════════════════════════════════════╝  │
│                                                                                     │
│  ╔═══════════════════════════════════════════════════════════════════════════════╗  │
│  ║  SCENARIO C: Offline (internet down)                                          ║  │
│  ║  ──────────────────────────────────                                           ║  │
│  ║                                                                               ║  │
│  ║    Tatlock operates fully locally with Ollama                                 ║  │
│  ║    • All tools work (except web search)                                       ║  │
│  ║    • Graceful degradation with same butler personality                        ║  │
│  ╚═══════════════════════════════════════════════════════════════════════════════╝  │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘

Implementation Plan

Phase 1: Blanket Backend Swap (Claude for All Agents)

Replace Ollama with Claude as the default backend for all PydanticAI agents, with automatic offline fallback.

New Files:

src/anthropic/
├── __init__.py
├── provider.py       # Claude provider with health check
└── model_selector.py # Chooses Claude or Ollama based on availability

Key Implementation (src/anthropic/provider.py):

from pydantic_ai.models.anthropic import AnthropicModel
from pydantic_ai.providers.anthropic import AnthropicProvider
from pydantic_ai.models.openai import OpenAIChatModel
from src.ollama.provider import get_ollama_provider
from src.core.config import config

_anthropic_available: bool | None = None

async def check_anthropic_health() -> bool:
    """Check if Anthropic API is reachable."""
    global _anthropic_available
    try:
        from anthropic import AsyncAnthropic
        client = AsyncAnthropic(api_key=config.ANTHROPIC_API_KEY)
        await client.messages.create(
            model=config.ANTHROPIC_MODEL,
            max_tokens=1,
            messages=[{"role": "user", "content": "hi"}]
        )
        _anthropic_available = True
    except Exception:
        _anthropic_available = False
    return _anthropic_available

def get_model(prefer_cloud: bool = True):
    """Get the best available model. Returns Claude if available, otherwise Ollama."""
    if prefer_cloud and config.ANTHROPIC_API_KEY and _anthropic_available:
        provider = AnthropicProvider(api_key=config.ANTHROPIC_API_KEY)
        return AnthropicModel(
            model_name=config.ANTHROPIC_MODEL,
            provider=provider,
        )
    else:
        return OpenAIChatModel(
            model_name=config.OLLAMA_DEFAULT_MODEL,
            provider=get_ollama_provider()
        )

Modify TatlockAgent (src/agents/tatlock.py):

def _ensure_agent(self):
    if self._agent is not None:
        return

    from src.anthropic.model_selector import get_model

    model = get_model(prefer_cloud=True)

    self._agent = Agent(
        model,
        system_prompt=TATLOCK_SYSTEM_PROMPT,  # Same butler personality!
    )
    self._register_tools()

Phase 2: MCP Server (Expose Tools to Claude)

Create an MCP server that exposes Tatlock's household tools to external Claude instances.

New Files:

src/mcp/
├── __init__.py
├── server.py         # MCP server using mcp Python SDK
├── tool_adapters.py  # Convert PydanticAI tools → MCP schemas
├── auth.py           # API key authentication
└── transport.py      # Streamable HTTP transport

Docker Stack Addition (stacks/agents.yml):

tatlock-mcp:
  image: git.schweitz.internal/jpmschweitzer/tatlock:latest
  command: ["python", "-m", "src.mcp.server"]
  ports:
    - "8002:8002"
  environment:
    - MCP_AUTH_TOKEN=${MCP_AUTH_TOKEN}
  networks:
    - docker-dataplane

Claude Desktop Configuration:

{
  "mcpServers": {
    "tatlock": {
      "command": "npx",
      "args": ["mcp-remote", "https://mcp.schweitz.net/sse", "--header", "Authorization: Bearer ${MCP_AUTH_TOKEN}"]
    }
  }
}

Files to Modify

Phase 1 - Backend Swap

New Files:

File Purpose
src/anthropic/__init__.py Package init
src/anthropic/provider.py Claude provider with health check
src/anthropic/model_selector.py Choose Claude or Ollama based on availability

Modified Files:

File Changes
src/core/config.py Add ANTHROPIC_API_KEY, ANTHROPIC_MODEL, PREFER_CLOUD_BACKEND
src/agents/tatlock.py Use get_model() instead of hardcoded Ollama
src/agents/librarian/agent.py Use get_model() instead of hardcoded Ollama
src/agents/biographer/agent.py Use get_model() instead of hardcoded Ollama
src/agents/steward/agent.py Convert to PydanticAI or add Anthropic API support
src/core/startup.py Add Anthropic health check on startup
requirements.txt Add anthropic>=0.40.0
.env.example Document new environment variables

Phase 2 - MCP Server

New Files:

File Purpose
src/mcp/__init__.py Package init
src/mcp/server.py MCP server implementation
src/mcp/tool_adapters.py PydanticAI → MCP schema conversion
src/mcp/auth.py Token-based authentication

Cost Analysis

  • Claude API: $5-30/month (10-50 calls/day, ~2k input + 1k output tokens/call)
  • MCP via Claude Pro: Included in subscription
  • Total: ~$10-80/month for full bidirectional integration

Verification Plan

Phase 1 Testing

# 1. Run with Claude backend
ANTHROPIC_API_KEY=your-key docker-compose up -d tatlock

# 2. Verify Claude is being used
docker logs tatlock 2>&1 | grep -i "anthropic\|claude"

# 3. Test butler personality
curl -X POST http://tatlock.schweitz.internal:8000/v1/responses \
  -H "Content-Type: application/json" \
  -d '{"model": "Tatlock", "input": "Hello, who are you?"}'

# 4. Test offline fallback
ANTHROPIC_API_KEY="" docker-compose up -d tatlock
docker logs tatlock 2>&1 | grep -i "ollama\|fallback"

Phase 2 Testing

# 1. Start MCP server
docker-compose up -d tatlock-mcp

# 2. Test MCP endpoint
curl -X POST https://mcp.schweitz.net/tools/list \
  -H "Authorization: Bearer $MCP_AUTH_TOKEN"

Implementation Priority

  1. Phase 1: Backend Swap (~1 week)

    • Immediate value: 200k context for ALL queries
    • Low risk: provider abstraction, graceful offline fallback
  2. Phase 2: MCP Server (~2-3 weeks)

    • Enables cross-device access
    • Bidirectional: Tatlock superpowered by Claude AND accessible to Claude

Future Phases (Optional)

  • Phase 3: LiteLLM Gateway - Unified endpoint for all models, config-driven routing
  • Phase 4: Multi-Provider - Add OpenAI, Vertex AI, etc.
  • Phase 5: Smart Routing - Context-aware model selection, cost ceiling enforcement

Offline Behavior

Scenario Behavior
No API key Use Ollama exclusively
API unreachable Use Ollama, log warning
API rate limited Fallback to Ollama
Aspect Claude Ollama
Context 200k tokens ~8k tokens
Latency 1-3s (network) 0.5-1s (local)
Personality Preserved Preserved
Tools All work All work
Cost API charges Free

Implementation Status

Phase 1: Backend Swap - CODE COMPLETE (awaiting API access)

  • Add Anthropic config settings to src/core/config.py
  • Add pydantic-ai-slim[openai,anthropic] to requirements.txt
  • Create src/anthropic/ module (model_selector.py)
  • Add Claude health check to startup.py
  • Refactor all PydanticAI agents to use get_model()
    • Librarian
    • Biographer
    • Housekeeper
    • Tatlock (6 locations)
  • Add Claude API path to Steward agent (direct API calls)
  • Update .env.example with new variables
  • Test Ollama fallback (working)
  • Test with Claude API key (blocked: no API access currently)

Note: Implementation complete. Currently runs in Ollama-only mode. Will automatically use Claude when ANTHROPIC_API_KEY is configured.

Phase 2: MCP Server - NOT STARTED

  • Create src/mcp/ module
  • Tool adapters (PydanticAI → MCP schema)
  • Authentication middleware
  • Streamable HTTP transport
  • Docker stack configuration

Handover documents created in each repo: PROJECT_CLAUDIFICATION_HANDOVER.md

library-desk - HANDOVER CREATED

  • Write handover document
  • Review HybridRAG response size limits
  • Review smart_create endpoint for Claude optimization
  • Evaluate response formats for LLM consumption

core-api - HANDOVER CREATED

  • Write handover document
  • Review list_devices response format
  • Review error messages for LLM consumption
  • Evaluate rate limiting for faster Claude processing

portainer-core - HANDOVER CREATED (blocking for production)

  • Write handover document
  • Update stack with new environment variables
  • Configure secrets management for API key
  • Update CONTAINERS.md documentation

webber - HANDOVER CREATED

  • Write handover document
  • Review content truncation limits
  • Evaluate extraction quality for LLM consumption

tatlock-ui - HANDOVER CREATED

  • Write handover document
  • Test streaming responses with Claude backend
  • Test conversation history with larger context
  • Verify tool call display and reasoning rendering