Metadata-Version: 2.4
Name: smolclaw
Version: 0.2.0
Summary: Lightweight multi-agent framework for personal AI assistants
Project-URL: Homepage, https://github.com/mandgie/smolclaw
Project-URL: Repository, https://github.com/mandgie/smolclaw
Project-URL: Bug Tracker, https://github.com/mandgie/smolclaw/issues
Project-URL: Documentation, https://mandgie.github.io/smolclaw
Author-email: Magnus Friberg <magnus.uno.friberg@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: agent,ai,assistant,chatbot,claude,framework,llm,multi-agent,personal-assistant,telegram
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: claude-agent-sdk>=0.1.48
Requires-Dist: click>=8.0
Requires-Dist: croniter>=6.0
Requires-Dist: fastapi>=0.115.0
Requires-Dist: pydantic>=2.0
Requires-Dist: python-telegram-bot>=21.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: uvicorn>=0.34.0
Provides-Extra: all
Requires-Dist: discord-py>=2.0; extra == 'all'
Requires-Dist: opentelemetry-api>=1.20.0; extra == 'all'
Requires-Dist: opentelemetry-sdk>=1.20.0; extra == 'all'
Requires-Dist: slack-sdk>=3.30.0; extra == 'all'
Requires-Dist: sqlite-vec>=0.1.0; extra == 'all'
Requires-Dist: watchfiles>=1.0.0; extra == 'all'
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest-cov>=6.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.8.0; extra == 'dev'
Provides-Extra: discord
Requires-Dist: discord-py>=2.0; extra == 'discord'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
Requires-Dist: mkdocstrings[python]>=0.27; extra == 'docs'
Provides-Extra: memory
Requires-Dist: sqlite-vec>=0.1.0; extra == 'memory'
Provides-Extra: otel
Requires-Dist: opentelemetry-api>=1.20.0; extra == 'otel'
Requires-Dist: opentelemetry-sdk>=1.20.0; extra == 'otel'
Provides-Extra: otel-otlp
Requires-Dist: opentelemetry-api>=1.20.0; extra == 'otel-otlp'
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.20.0; extra == 'otel-otlp'
Requires-Dist: opentelemetry-sdk>=1.20.0; extra == 'otel-otlp'
Provides-Extra: slack
Requires-Dist: slack-sdk>=3.30.0; extra == 'slack'
Provides-Extra: watch
Requires-Dist: watchfiles>=1.0.0; extra == 'watch'
Description-Content-Type: text/markdown

<p align="center">
  <h1 align="center">smolclaw</h1>
  <p align="center">Lightweight multi-agent framework for personal AI assistants</p>
</p>

<p align="center">
  <a href="https://github.com/mandgie/smolclaw/actions/workflows/ci.yml"><img src="https://github.com/mandgie/smolclaw/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
  <a href="https://codecov.io/gh/mandgie/smolclaw"><img src="https://codecov.io/gh/mandgie/smolclaw/graph/badge.svg" alt="Coverage"></a>
<a href="https://pypi.org/project/smolclaw/"><img src="https://img.shields.io/pypi/v/smolclaw" alt="PyPI"></a>
  <a href="https://pypi.org/project/smolclaw/"><img src="https://img.shields.io/pypi/pyversions/smolclaw" alt="Python"></a>
  <a href="https://github.com/mandgie/smolclaw/blob/main/LICENSE"><img src="https://img.shields.io/github/license/mandgie/smolclaw" alt="License"></a>
  <a href="https://mandgie.github.io/smolclaw"><img src="https://img.shields.io/badge/docs-mkdocs-blue" alt="Docs"></a>
</p>

---

Run multiple AI agents — each with its own personality, skills, and channels — from a single process. Agents are defined as folders with markdown files. No code required.

**Not another enterprise orchestration framework.** smolclaw is for people who want a personal AI assistant that runs on their laptop — not a distributed system that needs a DevOps team. ~10 modules, filesystem-as-config, zero boilerplate.

## Features

- **Filesystem-as-config** — Drop a folder, get an agent. `soul.md` for personality, `agent.yaml` for model/channels, `skills/` for capabilities.
- **Single gateway process** — All agents, channels, scheduler, and API run in one async process. No microservices, no Docker, no infra.
- **Telegram integration** — Each agent gets its own Telegram bot with typing indicators, markdown rendering, and user authorization.
- **Webhook delivery** — POST agent responses to any HTTP endpoint (Slack incoming webhooks, Discord, custom APIs). Zero dependencies.
- **Extensible channels** — Register custom channel adapters via `register_channel()` or distribute them as plugins via entry points. Third-party packages just work.
- **Cron scheduler** — Schedule jobs with cron expressions, deliver results to Telegram. Jobs route through the same message bus as everything else.
- **Semantic memory** — Shared SQLite database with per-agent isolation, FTS5 full-text search, and optional vector search via sqlite-vec with hybrid retrieval (RRF).
- **Hot-reload** — Change a skill, soul, or config file and the agent updates live. No restart needed.
- **Interactive REPL** — `smolclaw chat <agent>` for terminal conversations with session persistence.
- **MCP support** — Connect agents to MCP servers (stdio/SSE/HTTP) for extended tool access.
- **REST API + dashboard** — FastAPI on `:7890` with agent management, messaging, optional API key auth, and a built-in dark-mode dashboard.
- **OpenTelemetry tracing** — Optional OTEL instrumentation for routing, LLM calls, memory, and cron. Zero overhead when disabled. `pip install smolclaw[otel]`.
- **Claude SDK powered** — Built on Anthropic's Claude Agent SDK with session management, extended thinking, and tool support.

## Quick Start

```bash
# With uv (recommended)
uv pip install smolclaw

# Or with pip
pip install smolclaw
```

```bash
smolclaw init --agent tars
# Edit ~/.smolclaw/agents/tars/soul.md — give your agent a personality
smolclaw up
```

This creates a full project at `~/.smolclaw/` with your first agent and starts the gateway. The API + dashboard will be at `http://localhost:7890`.

## How Agents Work

Each agent is a folder:

```
~/.smolclaw/agents/tars/
├── agent.yaml       # Model, channels, memory config
├── soul.md          # Personality & voice
├── agents.md        # Operational rules & tool access
├── skills/          # Folder per skill (or symlinks to shared/)
├── context/         # Extra .md files loaded into system prompt
├── channels/        # Channel credentials (*.env files)
└── prompts/         # Templates for scheduled jobs
```

The system prompt is assembled automatically from these files. With hot-reload enabled, changes take effect immediately — no restart needed.

### Example agent.yaml

```yaml
name: tars
model: claude-opus-4-6
max_budget_usd: 5.0             # Per-run spending limit
fallback_model: claude-sonnet-4-6  # Used if primary model unavailable
enable_file_checkpointing: true # Crash recovery
channels:
  telegram:
    token_env: TARS_TELEGRAM_TOKEN
    authorized_users: []
memory:
  enabled: true
  cross_agent: true
```

### Example soul.md

```markdown
# TARS

You are TARS, a personal virtual assistant. Inspired by Interstellar.

## Voice & Tone
- Humor setting: 60%
- Concise and direct. No filler.
- Dry humor when appropriate.
```

## Why smolclaw?

| | smolclaw | CrewAI | LangGraph | OpenAI Agents SDK |
|---|---|---|---|---|
| **Setup** | `pip install` + folder | `pip install` + code | `pip install` + code | `pip install` + code |
| **Config** | Markdown files | Python classes | Python code | Python decorators |
| **Agents defined as** | Folders with `.md` files | Python code | Graph nodes | Python classes |
| **Multi-model** | Per-agent model selection | Per-agent | Per-node | OpenAI only |
| **Channels** | Telegram built-in, API | No built-in | No built-in | No built-in |
| **Scheduler** | Built-in cron | No built-in | No built-in | No built-in |
| **Dashboard** | Built-in | Studio (paid) | LangSmith (paid) | No built-in |
| **Memory** | Built-in SQLite | External | External | External |
| **Code size** | ~6300 lines | ~15K+ lines | ~25K+ lines | ~5K+ lines |
| **Focus** | Personal assistant | Enterprise teams | Workflows | General agents |

**smolclaw is opinionated:** one process, filesystem-as-config, batteries-included. If you want a personal AI assistant that just works — start here.

## Architecture

```
Gateway (single process)
├── Agent: tars     (Opus, Telegram, cross-agent memory)
├── Agent: coach    (Sonnet, no channel, isolated memory)
├── Scheduler       (croniter, fires through router)
├── Hooks           (pre/post-route middleware)
├── FileWatcher     (hot-reload on config/skill changes)
├── API             (FastAPI :7890, serves dashboard)
└── Router          (any source → correct agent → response)
```

All messages — whether from Telegram, the API, the CLI, or the scheduler — flow through the same router.

## CLI

```bash
smolclaw init                        # Initialize project (first run)
smolclaw up                          # Start gateway (all agents + API)
smolclaw chat <agent>                # Interactive REPL with session persistence
smolclaw status                      # Show agents, jobs, config, issues
smolclaw doctor                      # Check system health and dependencies
smolclaw add <name>                  # Scaffold a new agent
smolclaw remove <name>               # Remove an agent (with confirmation)
smolclaw list                        # List discovered agents
smolclaw send <agent> "message"      # Send a one-shot message
smolclaw logs                        # Tail the gateway log file
smolclaw config                      # View gateway config
smolclaw config get <key>            # Get a config value
smolclaw config set <key> <value>    # Set a config value
smolclaw cron list                   # List scheduled jobs
smolclaw cron add \
  --agent tars \
  --schedule "0 8 * * 1-5" \
  --prompt "morning briefing" \
  --delivery telegram \
  --chat-id 123456789               # Add a cron job with delivery
smolclaw cron edit <job_id> \
  --schedule "0 9 * * 1-5" \
  --prompt "updated prompt"          # Edit an existing job
smolclaw cron run <job_id>           # Manually trigger a job (for debugging)
smolclaw cron enable <job_id>        # Enable a disabled job
smolclaw cron disable <job_id>       # Disable a job without removing
smolclaw memory stats <agent>        # Memory statistics
smolclaw memory list <agent>         # List stored facts
smolclaw memory search <agent> "q"   # Search memory
smolclaw memory add <agent> "fact"   # Add a fact
smolclaw memory get <agent> <id>     # Show a single fact
smolclaw memory update <agent> <id> \
  --content "new text" -c category   # Update a fact
smolclaw memory delete <agent> <id>  # Delete a fact
smolclaw export <agent>              # Export agent as portable .tar.gz
smolclaw import <archive>            # Import agent from .tar.gz archive
smolclaw add-skill <agent> <skill>   # Symlink shared skill to agent
smolclaw install                     # Auto-start on login (macOS LaunchAgent)
smolclaw version                     # Show version
```

## REST API

The gateway exposes a full REST API on `:7890` (auto-documented at `/docs`):

```bash
# Send a message
curl -s localhost:7890/api/agents/tars/send \
  -H "Content-Type: application/json" \
  -d '{"text": "What is the weather?"}' | jq .response

# Search agent memory
curl -s "localhost:7890/api/agents/tars/memory/search?q=weather&mode=hybrid"

# Add a fact to memory
curl -s localhost:7890/api/agents/tars/memory/facts \
  -H "Content-Type: application/json" \
  -d '{"content": "User prefers metric units", "category": "preference"}'

# Get / update / delete a fact
curl -s localhost:7890/api/agents/tars/memory/facts/1 | jq
curl -s -X PUT localhost:7890/api/agents/tars/memory/facts/1 \
  -H "Content-Type: application/json" \
  -d '{"content": "User prefers imperial units"}'

# List agents, health, cron jobs
curl -s localhost:7890/api/agents | jq
curl -s localhost:7890/api/health | jq
curl -s localhost:7890/api/cron/jobs | jq
```

### API Authentication

Protect your API with an optional Bearer token. Add `api_key` to your `config.yaml`:

```yaml
# ~/.smolclaw/config.yaml
api_key: "your-secret-key-here"
```

Then include the key in requests:

```bash
curl -s localhost:7890/api/agents \
  -H "Authorization: Bearer your-secret-key-here" | jq
```

Health (`/api/health`) and dashboard (`/`) are always public. When no `api_key` is set, all endpoints are open (default).

## Dashboard

A built-in dark-mode dashboard runs at `http://localhost:7890` when the gateway starts. Shows agent status, config, and lets you send messages.

The dashboard uses **WebSocket live updates** — changes to agents, jobs, and memory are pushed instantly to all connected browsers. Falls back to 10-second polling automatically if WebSocket is unavailable.

## Custom Channels

smolclaw supports three ways to add channel adapters:

### 1. Programmatic registration

```python
from smolclaw.channel import Channel, register_channel

class WhatsAppChannel(Channel):
    channel_type = "whatsapp"

    async def start(self): ...
    async def stop(self): ...
    async def send(self, chat_id: str, text: str): ...

register_channel("whatsapp", WhatsAppChannel)
```

### 2. Entry-point plugins

Third-party packages declare channel adapters in their `pyproject.toml`:

```toml
[project.entry-points."smolclaw.channels"]
whatsapp = "smolclaw_whatsapp:WhatsAppChannel"
```

Once installed, the channel is automatically available in `agent.yaml`:

```yaml
channels:
  whatsapp:
    token_env: WHATSAPP_TOKEN
    authorized_users: ["+46701234567"]
```

### 3. Built-in channels

`telegram` and `webhook` are included out of the box.

## Development

```bash
git clone https://github.com/mandgie/smolclaw.git
cd smolclaw

# With uv (recommended — fast, handles venv automatically)
uv sync --extra dev
uv run pytest
uv run ruff check smolclaw/

# Or with pip
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest
ruff check smolclaw/
ruff format --check smolclaw/
```

## Project Structure

```
smolclaw/              # Python package (~6300 lines)
├── gateway.py         # Single-process orchestrator
├── agent.py           # Agent class (loads identity, wraps Claude SDK)
├── router.py          # Message routing
├── channel.py         # Channel adapters (Telegram, Webhook)
├── hooks.py           # Pre/post-route message hooks (middleware)
├── memory.py          # Namespaced SQLite memory (FTS5 + vector search)
├── scheduler.py       # Cron scheduler (croniter)
├── tracing.py         # Optional OpenTelemetry instrumentation
├── watcher.py         # Hot-reload file watcher (watchfiles)
├── api.py             # FastAPI REST endpoints
├── config.py          # Filesystem-based agent discovery
├── cli.py             # Click CLI
└── dashboard/
    └── index.html     # Single-file dashboard
```

## Roadmap

- [x] MCP server support (stdio/SSE/HTTP — Claude SDK managed)
- [x] Extended thinking & effort config
- [x] Budget limits, fallback models, structured output, file checkpointing
- [x] REST API + dark-mode dashboard
- [x] Cron scheduler with delivery to Telegram
- [x] CLI: init, status, doctor, add, remove, add-skill, logs, install
- [x] Session persistence (save/resume per agent per chat)
- [x] CLI interactive REPL (`smolclaw chat <agent>`)
- [x] Vector search in memory (sqlite-vec + FTS5 + RRF hybrid)
- [x] Hot-reload on config/skill/context changes
- [x] Cross-agent awareness (peer agents visible in prompts, API-based messaging)
- [x] Multiple Telegram bots (one per agent, unique token per bot)
- [x] Webhook channel (outgoing HTTP POST delivery)
- [ ] Discord / Slack channel adapters
- [x] PyPI publish (v0.2.0 on PyPI)

## Contributing

Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.

## License

[MIT](LICENSE)
