Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions clawdbot/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# ClawdBot Environment Configuration
# Copy to .env and fill in values

# PostgreSQL
PG_USER=clawdbot
PG_PASS=changeme_pg_password

# Redis
REDIS_PASSWORD=changeme_redis_password

# API Keys (also store in secrets/ directory for Docker secrets)
# ANTHROPIC_API_KEY=sk-ant-...
# MOONSHOT_API_KEY=sk-...
23 changes: 23 additions & 0 deletions clawdbot/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Secrets (never commit)
secrets/
.env
*.key
*.pem

# Python
__pycache__/
*.py[cod]
*.egg-info/
.venv/

# Docker volumes
pgdata/
redis_data/

# IDE
.idea/
.vscode/
*.swp

# OS
.DS_Store
96 changes: 96 additions & 0 deletions clawdbot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# ClawdBot — Multi-Agent Docker System

A three-bot Docker system powered by Claude Opus 4.6 and Kimi K2.5, designed for deployment from Docker Desktop to Digital Ocean.

## Architecture

```
Nginx (reverse proxy, SSL, rate limiting)
|
├── Orchestrator Gateway (intent routing, cross-agent coordination)
│ ├── Personal Assistant (Claude Opus 4.6 + Google Calendar)
│ ├── Business Advisor (Kimi K2.5 primary, Claude fallback)
│ └── Code Generator (Claude Opus 4.6 + sandbox execution)
|
├── Redis 7 (Streams + Pub/Sub + Cache)
└── PostgreSQL 17 + pgvector (State / Memory / RAG)
```

## Quick Start

```bash
# 1. Copy environment template
cp .env.example .env
# Edit .env with your credentials

# 2. Create secret files
mkdir -p secrets
echo "sk-ant-..." > secrets/anthropic_key.txt
echo "sk-..." > secrets/moonshot_key.txt
echo "changeme" > secrets/pg_password.txt
# Optional: copy Google credentials JSON
# cp ~/google_credentials.json secrets/google_credentials.json

# 3. Start the stack
docker compose up -d

# 4. Verify health
curl http://localhost:8000/health
curl http://localhost:8000/agents
```

## API Usage

```bash
# Auto-route to the best agent
curl -X POST http://localhost:80/api/chat \
-H "Content-Type: application/json" \
-d '{"message": "Schedule a meeting for tomorrow at 2pm", "agent": "auto"}'

# Target a specific agent
curl -X POST http://localhost:80/api/chat \
-H "Content-Type: application/json" \
-d '{"message": "Write a Python function to merge two sorted lists", "agent": "codegen"}'
```

## Agents

| Agent | Model | Purpose |
|-------|-------|---------|
| **Personal Assistant** | Claude Opus 4.6 | Calendar, scheduling, reminders, daily briefings |
| **Business Advisor** | Kimi K2.5 (Claude fallback) | Market research, strategic analysis, SWOT |
| **Code Generator** | Claude Opus 4.6 | Code generation, review, sandboxed execution |

## Deployment to Digital Ocean

```bash
# One-time droplet setup (run as root on a Docker 1-Click Droplet)
bash scripts/setup-droplet.sh

# Deploy (run from your local machine)
bash scripts/deploy.sh <droplet-ip>
```

## Project Structure

```
clawdbot/
├── docker-compose.yml # Full stack definition
├── .env.example # Environment template
├── agents/
│ ├── base/Dockerfile # Shared base image pattern
│ ├── orchestrator/ # Gateway + intent router
│ ├── personal-assistant/ # Calendar + scheduling bot
│ ├── business-advisor/ # Research + analysis bot
│ ├── code-generator/ # Code gen + review bot
│ └── sandbox/ # Isolated code execution
├── shared/
│ └── messaging.py # Redis Streams inter-agent comms
├── nginx/
│ ├── nginx.conf # Reverse proxy config
│ └── certs/ # SSL certificates
├── scripts/
│ ├── deploy.sh # Digital Ocean deployment
│ └── setup-droplet.sh # One-time server setup
└── secrets/ # API keys (git-ignored)
```
21 changes: 21 additions & 0 deletions clawdbot/agents/base/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Base Dockerfile for ClawdBot agents
# Individual agents extend this with their own requirements
FROM python:3.12-slim AS builder
WORKDIR /build
COPY requirements.txt .
RUN pip install --no-cache-dir --target=/deps -r requirements.txt

FROM python:3.12-slim
RUN groupadd -r agent && useradd -r -g agent -s /bin/bash agent \
&& apt-get update && apt-get install -y --no-install-recommends curl \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=builder /deps /usr/local/lib/python3.12/site-packages
COPY . .
RUN chown -R agent:agent /app
USER agent
ENV PYTHONPATH=/usr/local/lib/python3.12/site-packages
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
19 changes: 19 additions & 0 deletions clawdbot/agents/business-advisor/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM python:3.12-slim AS builder
WORKDIR /build
COPY requirements.txt .
RUN pip install --no-cache-dir --target=/deps -r requirements.txt

FROM python:3.12-slim
RUN groupadd -r agent && useradd -r -g agent -s /bin/bash agent \
&& apt-get update && apt-get install -y --no-install-recommends curl \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=builder /deps /usr/local/lib/python3.12/site-packages
COPY . .
RUN chown -R agent:agent /app
USER agent
ENV PYTHONPATH=/usr/local/lib/python3.12/site-packages
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Empty file.
153 changes: 153 additions & 0 deletions clawdbot/agents/business-advisor/app/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
"""Business Advisor Bot.

Provides strategic analysis, market research, and decision support.
Uses Kimi K2.5 as primary model (with Agent Swarm for complex queries)
and Claude Opus 4.6 as fallback.
"""

from __future__ import annotations

import json
import os
from pathlib import Path

from anthropic import AsyncAnthropic
from fastapi import FastAPI
from openai import AsyncOpenAI
from pydantic import BaseModel

app = FastAPI(title="Business Advisor Bot")


def read_secret(name: str) -> str:
"""Read a Docker secret file, falling back to environment variable."""
path = Path(f"/run/secrets/{name}")
return path.read_text().strip() if path.exists() else os.environ.get(name.upper(), "")


# Kimi K2.5 via OpenAI-compatible API (primary)
kimi_client = AsyncOpenAI(
api_key=read_secret("moonshot_key"),
base_url="https://api.moonshot.ai/v1",
)

# Claude Opus 4.6 (fallback)
claude_client = AsyncAnthropic(api_key=read_secret("anthropic_key"))


# ── Tool definitions (OpenAI format for Kimi) ────────────────

ADVISOR_TOOLS = [
{
"type": "function",
"function": {
"name": "web_search",
"description": (
"Search the web for market data, news, "
"competitor info, or industry analysis"
),
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Search query",
}
},
"required": ["query"],
},
},
},
{
"type": "function",
"function": {
"name": "analyze_data",
"description": "Run quantitative analysis on provided data",
"parameters": {
"type": "object",
"properties": {
"data": {"type": "string"},
"analysis_type": {
"type": "string",
"enum": [
"trend",
"comparison",
"forecast",
"swot",
"financial",
],
},
},
"required": ["data", "analysis_type"],
},
},
},
]

SYSTEM_PROMPT = """You are a 24/7 business advisor providing strategic \
analysis, market research, and decision support. You have access to web \
search for real-time market data and analysis tools. When conducting \
research, be thorough -- search multiple sources, cross-reference data, \
and synthesize findings into actionable insights. Always cite your \
reasoning and flag uncertainty levels. For complex multi-faceted \
questions, break the research into parallel streams."""


class InvokeRequest(BaseModel):
message: str
session_id: str | None = None
context: dict | None = None


@app.post("/invoke")
async def invoke(req: InvokeRequest):
"""Route to Kimi K2.5 (primary) or Claude Opus 4.6 (fallback)."""
try:
response = await kimi_client.chat.completions.create(
model=os.environ.get("PRIMARY_MODEL", "kimi-k2.5"),
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": req.message},
],
tools=ADVISOR_TOOLS,
tool_choice="auto",
temperature=0.7,
max_tokens=8192,
)
text = response.choices[0].message.content or ""
return {
"response": text,
"session_id": req.session_id,
"summary": text[:100],
"metadata": {
"model": "kimi-k2.5",
"tokens": {
"input": response.usage.prompt_tokens,
"output": response.usage.completion_tokens,
},
},
}
except Exception:
# Fallback to Claude Opus 4.6
fallback_model = os.environ.get("FALLBACK_MODEL", "claude-opus-4-6")
response = await claude_client.messages.create(
model=fallback_model,
max_tokens=8192,
system=SYSTEM_PROMPT,
messages=[{"role": "user", "content": req.message}],
)
text = "".join(
b.text for b in response.content if hasattr(b, "text")
)
return {
"response": text,
"session_id": req.session_id,
"summary": text[:100],
"metadata": {"model": fallback_model, "fallback": True},
}


@app.get("/health")
async def health():
"""Health check endpoint."""
return {"status": "healthy", "agent": "business-advisor"}
6 changes: 6 additions & 0 deletions clawdbot/agents/business-advisor/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fastapi>=0.115,<1
uvicorn[standard]>=0.34,<1
openai>=1.60,<2
anthropic>=0.45,<1
redis>=5.2,<6
pydantic>=2.10,<3
19 changes: 19 additions & 0 deletions clawdbot/agents/code-generator/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM python:3.12-slim AS builder
WORKDIR /build
COPY requirements.txt .
RUN pip install --no-cache-dir --target=/deps -r requirements.txt

FROM python:3.12-slim
RUN groupadd -r agent && useradd -r -g agent -s /bin/bash agent \
&& apt-get update && apt-get install -y --no-install-recommends curl \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=builder /deps /usr/local/lib/python3.12/site-packages
COPY . .
RUN chown -R agent:agent /app
USER agent
ENV PYTHONPATH=/usr/local/lib/python3.12/site-packages
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Empty file.
Loading