Add SearXNG-powered web search tool and update agent persona to "Tatlock", a helpful British butler assistant. Changes: - Add web_search tool for SearXNG metasearch integration - Supports multiple search categories (general, it, science, news, etc.) - Configurable max_results (1-20) - Privacy-focused (no tracking via SearXNG) - Formatted results with titles, URLs, and descriptions - Proper error handling for timeouts and failures - Endpoint: http://searxng:8080/search - Update agent persona to "Tatlock" (British butler) - Formal yet personable tone - Addresses users as "sir" - Fact verification emphasis - Slight snark and puns when appropriate - Clear tool categorization in prompt - Enhance prompt with tool organization - Core tools: web_search, calculate, time/date - Infrastructure tools: core_api__* prefix for system management - Clear usage guidelines for each category Web Search Categories Supported: - general: Web search (Google, Bing, DuckDuckGo) - it: Programming/technical (StackOverflow, GitHub) - science: Academic (arXiv, PubMed, Semantic Scholar) - news: News articles - images/videos: Media search - map: Geographic queries Integration: Requires SearXNG service running on docker-dataplane network. See stacks/searxng.yml for deployment. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Core-AI Service
Simplified AI service for testing LiteLLM → Ollama → Model integration without ADK complexity.
Purpose
This service strips away the ADK layer to isolate and debug the fundamental LiteLLM/Ollama integration. It provides:
- Direct LiteLLM integration - No ADK overhead
- OpenAI-compatible API - Drop-in replacement for testing
- Comprehensive diagnostics - Layered testing to identify issues
- Minimal complexity - Easy to understand and debug
Architecture
HTTP Request → SimpleLiteLLMAgent → LiteLLM → Ollama → Model → Response
Bypassed: Google ADK, tool calling, complex orchestration
Quick Start
1. Install Dependencies
pip install -r requirements.txt
2. Configure Environment
Create .env file or set environment variables:
OLLAMA_BASE_URL=http://ollama:11434
AGENT_MODEL=gemma2:9b-instruct-q5_K_M
SYSTEM_PROMPT_VARIANT=minimal_agent
HOST=0.0.0.0
PORT=8086
3. Run Diagnostics
# Check Ollama connectivity
python diagnostics/check_ollama.py
# Test direct LiteLLM
python diagnostics/test_litellm_direct.py
# Run full test suite
bash tests/run_all_tests.sh
4. Start Service
python main.py
Service will be available at http://localhost:8086
5. Test It
curl -X POST http://localhost:8086/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"messages": [
{"role": "user", "content": "What is the capital of France?"}
]
}'
API Endpoints
GET /health
Health check endpoint
Response:
{
"status": "ok",
"service": "core-ai"
}
POST /v1/chat/completions
OpenAI-compatible chat completions endpoint
Request:
{
"model": "test",
"messages": [
{"role": "user", "content": "Your question here"}
],
"stream": false
}
Response (non-streaming):
{
"id": "chatcmpl-...",
"object": "chat.completion",
"created": 1234567890,
"model": "test",
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "Response here"
},
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": 0,
"completion_tokens": 0,
"total_tokens": 0
}
}
Streaming: Set "stream": true for Server-Sent Events response
Project Structure
services/core-ai/
├── main.py # HTTP server (aiohttp)
├── src/
│ ├── agent.py # SimpleLiteLLMAgent
│ ├── config.py # Configuration (Pydantic)
│ ├── prompts.py # System prompts
│ └── tools.py # (Unused in this version)
├── diagnostics/
│ ├── check_ollama.py # Ollama connectivity check
│ └── test_litellm_direct.py # Direct LiteLLM test
├── tests/
│ ├── test_01_environment.py # Config tests
│ ├── test_02_litellm_raw.py # Raw LiteLLM tests
│ ├── test_03_message_format.py # Message formatting
│ ├── test_04_agent.py # Agent logic tests
│ ├── test_05_api.py # API endpoint tests
│ ├── run_all_tests.sh # Run all tests
│ └── README.md # Test documentation
├── requirements.txt
├── Dockerfile
└── README.md (this file)
Configuration
Configuration is managed via src/config.py using Pydantic Settings.
Environment Variables
| Variable | Default | Description |
|---|---|---|
HOST |
0.0.0.0 |
Server host |
PORT |
8086 |
Server port |
OLLAMA_BASE_URL |
http://ollama:11434 |
Ollama API URL |
AGENT_MODEL |
gemma2:9b-instruct-q5_K_M |
Model name |
SYSTEM_PROMPT_VARIANT |
minimal_agent |
Prompt variant to use |
DEBUG |
false |
Enable debug mode |
LOG_LEVEL |
INFO |
Logging level |
Testing
See tests/README.md for comprehensive testing documentation.
Quick test:
bash tests/run_all_tests.sh
This runs 5 layers of tests to isolate issues:
- Environment & Configuration
- Raw LiteLLM Connection
- Message Formatting
- Agent Logic
- API Integration
Docker Deployment
Build
docker build -t core-ai:latest .
Run
docker run -d \
--name core-ai \
-p 8086:8086 \
-e OLLAMA_BASE_URL=http://ollama:11434 \
-e AGENT_MODEL=gemma2:9b-instruct-q5_K_M \
--network docker-dataplane \
core-ai:latest
Using Docker Compose
docker-compose -f ../../stacks/core-ai.yml up
Troubleshooting
Service won't start
- Check logs:
docker logs core-ai - Verify Ollama is running:
docker ps | grep ollama - Run diagnostics:
python diagnostics/check_ollama.py
No response or timeout
- Check Ollama logs:
docker logs ollama - Model may be loading (first run takes 30-60s)
- Verify model exists:
docker exec ollama ollama list - Test directly:
docker exec ollama ollama run gemma2:9b-instruct-q5_K_M "test"
Wrong or empty responses
- Check system prompt is loaded (see agent logs)
- Verify prompt variant exists in
src/prompts.py - Run Layer 3 tests:
pytest tests/test_03_message_format.py -v
Connection refused
- Check network:
docker network inspect docker-dataplane - Verify both services are on the same network
- Try using container IP instead of hostname
Development
Adding New Prompts
Edit src/prompts.py:
PROMPTS = {
"minimal_agent": "You are a helpful assistant.",
"my_new_prompt": "Your custom system prompt here."
}
Update environment variable:
SYSTEM_PROMPT_VARIANT=my_new_prompt
Modifying Agent Behavior
Edit src/agent.py - specifically the SimpleLiteLLMAgent class.
Key methods:
__init__()- Initialization and configurationchat()- Streaming chat handlerchat_completion()- Non-streaming completion handler
Adding Tests
Add to appropriate test layer in tests/:
- Configuration changes →
test_01_environment.py - LiteLLM behavior →
test_02_litellm_raw.py - Message formatting →
test_03_message_format.py - Agent logic →
test_04_agent.py - API changes →
test_05_api.py
Comparison with Core-API
| Feature | Core-AI | Core-API |
|---|---|---|
| ADK Integration | ❌ No | ✅ Yes |
| Tool Calling | ❌ No | ✅ Yes |
| System Orchestration | ❌ No | ✅ Yes |
| Complexity | Low | High |
| Purpose | Debugging | Production |
| Direct LiteLLM | ✅ Yes | ❌ No |
| Diagnostics | ✅ Comprehensive | Limited |
Next Steps
If Tests Pass
- ✅ Foundation is solid
- Consider migrating fixes to core-api
- Add ADK layer back in phases
- Test tool calling integration
If Tests Fail
- Run diagnostics to identify layer
- Fix that specific layer
- Re-run tests
- Proceed once all pass
Contributing
When making changes:
- Run diagnostics first
- Make changes
- Run full test suite
- Update relevant documentation
- Test in Docker environment
License
Part of the tower-of-joy project.