Files
Aetheel/docs/spec-phase3-features.md
tanmay11k 6d73f74e0b feat: config-driven architecture, install wizard, live runtime switching, usage tracking, auto-failover
Major changes:
- Config-driven adapters: all channels (Slack, Discord, Telegram, WebChat, Webhooks) controlled via config.json with enabled flags and token auto-detection, no CLI flags required
- Runtime engine field: runtime.engine selects opencode/claude from config
- Interactive install script: 8-phase setup wizard with AI runtime detection/installation, token setup, identity file personalization (personality presets), aetheel CLI command, background service (launchd/systemd)
- Live runtime switching: /engine, /model, /provider commands hot-swap the AI runtime from chat without restart, changes persisted to config.json
- Usage tracking: per-request cost extraction from Claude Code JSON output, cumulative stats via /usage command
- Auto-failover: rate limit detection on both runtimes, automatic switch to other engine on quota errors with user notification
- Chat commands work without / prefix (Slack intercepts / in channels), commands: engine, model, provider, config, usage, reload, cron, subagents, status, help
- /config set for editing config.json from chat with dotted key notation
- Security audit saved to docs/security-audit.md
- Full command reference in docs/commands.md
- Future changes doc with NanoClaw agent teams analysis
- Logo added to README and WebChat UI
- README fully rewritten with all features documented
2026-02-18 01:07:12 -05:00

561 lines
18 KiB
Markdown

# Aetheel Phase 3 Feature Spec
> Specification for implementing heartbeat, CLI, webchat, self-modification, agent-to-agent communication, and tool/MCP/web search integration.
---
## Table of Contents
1. [Runtime Capabilities Audit](#1-runtime-capabilities-audit)
2. [Tool System, MCP & Web Search](#2-tool-system-mcp--web-search)
3. [Heartbeat / Proactive System](#3-heartbeat--proactive-system)
4. [CLI Interface](#4-cli-interface)
5. [WebChat Interface](#5-webchat-interface)
6. [Self-Modification](#6-self-modification)
7. [Agent-to-Agent Communication](#7-agent-to-agent-communication)
8. [Implementation Order](#8-implementation-order)
---
## 1. Runtime Capabilities Audit
Before building anything, here's what OpenCode and Claude Code already provide natively that Aetheel can leverage without custom implementation.
### OpenCode Built-in Tools
OpenCode ships with these tools enabled by default (no config needed):
| Tool | Description | Aetheel Status |
|------|-------------|----------------|
| `bash` | Execute shell commands | ✅ Available via runtime |
| `read` | Read file contents | ✅ Available via runtime |
| `write` | Create/overwrite files | ✅ Available via runtime |
| `edit` | Modify files via string replacement | ✅ Available via runtime |
| `grep` | Regex search across files | ✅ Available via runtime |
| `glob` | Find files by pattern | ✅ Available via runtime |
| `list` | List directory contents | ✅ Available via runtime |
| `websearch` | Web search via Exa AI (no API key needed) | ✅ Available — no setup required |
| `webfetch` | Fetch and read web pages | ✅ Available via runtime |
| `skill` | Load SKILL.md files | ✅ Available via runtime |
| `todowrite` / `todoread` | Task tracking | ✅ Available via runtime |
| `lsp` | Code intelligence (experimental) | ✅ Available via runtime |
| `patch` | Apply diffs | ✅ Available via runtime |
| Custom tools | User-defined JS/TS tools | 🟡 Available but not wired |
| MCP servers | External tool servers | 🟡 Available but not configured |
### Claude Code Built-in Tools
Claude Code provides these tools natively:
| Tool | Description | Aetheel Status |
|------|-------------|----------------|
| `Bash` | Shell execution | ✅ Available via runtime |
| `Read`, `Write`, `Edit` | File operations | ✅ Available via runtime |
| `Glob`, `Grep` | File search | ✅ Available via runtime |
| `WebSearch`, `WebFetch` | Web access | ✅ Available via runtime |
| `Task`, `TaskOutput`, `TaskStop` | Subagent spawning | ✅ Available via runtime |
| `TeamCreate`, `TeamDelete`, `SendMessage` | Agent teams | ✅ Available via runtime |
| `Skill` | Load skills | ✅ Available via runtime |
| MCP servers | Via `.mcp.json` config | 🟡 Available but not configured |
### Key Insight
Both runtimes already have web search, file ops, bash, and subagent tools built in. Aetheel doesn't need to implement these — it just needs to stop blocking them. Currently Aetheel's system prompt doesn't tell the agent about these capabilities, and Claude Code's `--allowedTools ""` (no_tools=true) actively disables them.
---
## 2. Tool System, MCP & Web Search
### What Needs to Change
**Problem**: Aetheel currently runs both runtimes in "pure chat" mode — tools are disabled or not mentioned in the system prompt.
**Solution**: Enable tool access and configure MCP servers.
### 2.1 Enable Runtime Tools
For OpenCode (CLI mode), tools are enabled by default. No change needed.
For OpenCode (SDK mode), tools are enabled by default on the server. No change needed.
For Claude Code, change `no_tools` default from `true` to `false` in config, and set a sensible `allowedTools` list:
```python
# config.py — ClaudeConfig
@dataclass
class ClaudeConfig:
no_tools: bool = False # Changed from True
allowed_tools: list[str] = field(default_factory=lambda: [
"Bash", "Read", "Write", "Edit", "Glob", "Grep",
"WebSearch", "WebFetch",
"Task", "Skill",
])
```
### 2.2 Update System Prompt
Add tool awareness to `build_aetheel_system_prompt()`:
```
# Your Tools
- You have access to shell commands, file operations, and web search
- Use web search to look up current information when needed
- You can read and write files in the workspace (~/.aetheel/workspace/)
- You can execute shell commands for system tasks
```
### 2.3 MCP Server Configuration
Create an `opencode.json` in the workspace for OpenCode MCP config, or a `.mcp.json` for Claude Code. This lets users add external tool servers.
Add to `~/.aetheel/config.json`:
```json
{
"mcp": {
"servers": {
"example": {
"command": "uvx",
"args": ["some-mcp-server"],
"env": {}
}
}
}
}
```
Aetheel writes this to the appropriate config file (`opencode.json` or `.mcp.json`) in the workspace directory before launching the runtime.
### 2.4 Implementation Tasks
1. Change `ClaudeConfig.no_tools` default to `False`
2. Add `allowed_tools` to `ClaudeConfig` with sensible defaults
3. Update `_build_cli_args()` in `claude_runtime.py` to pass `--allowedTools` from config
4. Update `build_aetheel_system_prompt()` to mention available tools
5. Add `mcp` section to `config.py` and `config.json`
6. Write MCP config files to workspace before runtime launch
7. Add `TOOLS.md` to workspace identity files (like PicoClaw/OpenClaw)
### Inspiration
- **NanoClaw**: Passes `allowedTools` list to `query()` call, runs custom MCP server for IPC
- **PicoClaw**: Built-in tool registry in `pkg/tools/`, `TOOLS.md` describes tools to agent
- **OpenClaw**: Tool registry with streaming, `TOOLS.md` in workspace
---
## 3. Heartbeat / Proactive System
### How Inspiration Repos Do It
**PicoClaw**: Reads `HEARTBEAT.md` every 30 minutes. Quick tasks run directly, long tasks spawn subagents. The heartbeat file contains prompts like "Check if any cron jobs need attention" or "Review MEMORY.md for stale entries."
**Nanobot**: Has a `heartbeat/` module that triggers periodic agent runs.
**NanoClaw**: Uses scheduled tasks via MCP tools — the agent itself schedules recurring tasks using `schedule_task` with cron expressions. No separate heartbeat file.
**OpenClaw**: Cron system + wakeups. Heartbeat runs are suppressed from WebChat broadcast when `showOk: false`.
### Design for Aetheel
Combine PicoClaw's `HEARTBEAT.md` approach (simple, file-based) with Aetheel's existing scheduler:
### 3.1 HEARTBEAT.md
Create `~/.aetheel/workspace/HEARTBEAT.md` as a user-editable file:
```markdown
# Heartbeat Tasks
Tasks that run periodically. Each section is a task prompt.
## Every 30 minutes
- Check if any scheduled reminders need attention
- Review recent session logs for anything worth remembering
## Every morning (9:00 AM)
- Summarize yesterday's conversations
- Check for any pending follow-ups in MEMORY.md
## Every evening (6:00 PM)
- Update MEMORY.md with today's key learnings
```
### 3.2 Heartbeat Runner
New module: `heartbeat/heartbeat.py`
```python
class HeartbeatRunner:
def __init__(self, runtime, send_fn, workspace_dir, scheduler):
...
def start(self):
"""Register heartbeat tasks with the scheduler."""
# Parse HEARTBEAT.md
# Register cron jobs for each section
# Jobs route through ai_handler with synthetic messages
def _parse_heartbeat_md(self) -> list[HeartbeatTask]:
"""Parse HEARTBEAT.md into structured tasks."""
...
def _on_heartbeat(self, task: HeartbeatTask):
"""Called when a heartbeat fires. Routes to AI handler."""
...
```
### 3.3 Integration
- Parse `HEARTBEAT.md` at startup, register tasks with existing `Scheduler`
- Heartbeat tasks create synthetic `IncomingMessage` with `source="heartbeat"`
- Results can be sent to a configured channel or logged silently
- Add `heartbeat` section to config:
```json
{
"heartbeat": {
"enabled": true,
"default_channel": "slack",
"default_channel_id": "C123456",
"silent": false
}
}
```
### 3.4 Implementation Tasks
1. Create `heartbeat/` module with `HeartbeatRunner`
2. Create default `HEARTBEAT.md` in workspace (like SOUL.md bootstrap)
3. Parse markdown sections into cron expressions + prompts
4. Register with existing `Scheduler` at startup
5. Add heartbeat config section
6. Wire into `main.py` initialization
---
## 4. CLI Interface
### How Inspiration Repos Do It
**Nanobot**: `nanobot agent -m "..."`, `nanobot gateway`, `nanobot status`, `nanobot cron add/list/remove`
**OpenClaw**: `openclaw gateway`, `openclaw agent --message "..."`, `openclaw doctor`, `openclaw pairing approve`
**PicoClaw**: Binary with subcommands via Go's `cobra` library
### Design for Aetheel
Use Python's `click` library for a clean CLI with subcommands.
### 4.1 CLI Structure
```
aetheel # Start with default adapters (same as current main.py)
aetheel start # Start with all configured adapters
aetheel start --discord # Start with specific adapters
aetheel chat "message" # One-shot chat (no adapter, just AI)
aetheel status # Show runtime status
aetheel cron list # List scheduled jobs
aetheel cron remove <id> # Remove a job
aetheel sessions list # List active sessions
aetheel sessions clear # Clear stale sessions
aetheel config show # Print current config
aetheel config edit # Open config in $EDITOR
aetheel config init # Reset to defaults
aetheel memory search "q" # Search memory
aetheel memory sync # Force memory re-index
aetheel doctor # Diagnostics (check runtime, tokens, etc.)
```
### 4.2 Implementation
New file: `cli.py`
```python
import click
@click.group()
def cli():
"""Aetheel — AI-Powered Personal Assistant"""
pass
@cli.command()
@click.option("--discord", is_flag=True)
@click.option("--telegram", is_flag=True)
@click.option("--claude", is_flag=True)
@click.option("--model", default=None)
@click.option("--test", is_flag=True)
@click.option("--log", default="INFO")
def start(discord, telegram, claude, model, test, log):
"""Start Aetheel with configured adapters."""
# Current main() logic moves here
...
@cli.command()
@click.argument("message")
def chat(message):
"""One-shot chat with the AI (no adapter needed)."""
...
@cli.group()
def cron():
"""Manage scheduled jobs."""
pass
@cron.command("list")
def cron_list():
...
@cron.command("remove")
@click.argument("job_id")
def cron_remove(job_id):
...
# ... etc
```
### 4.3 Entry Point
Add to `pyproject.toml`:
```toml
[project.scripts]
aetheel = "cli:cli"
```
### 4.4 Implementation Tasks
1. Add `click` dependency to `pyproject.toml`
2. Create `cli.py` with command groups
3. Move `main()` logic into `start` command
4. Add `chat`, `status`, `cron`, `sessions`, `config`, `memory`, `doctor` commands
5. Add entry point to `pyproject.toml`
6. Keep `main.py` as backward-compatible wrapper
---
## 5. WebChat Interface
### How Inspiration Repos Do It
**OpenClaw**: Full WebSocket-based WebChat as an internal channel. Messages routed through the gateway with `messageChannel: "webchat"`. Has a web UI built with React.
**Nanobot/NanoClaw/PicoClaw**: No webchat.
### Design for Aetheel
A lightweight HTTP server with WebSocket support, served as a new adapter.
### 5.1 Architecture
```
Browser ←→ WebSocket ←→ WebChatAdapter ←→ ai_handler ←→ Runtime
Static HTML/JS
```
### 5.2 Implementation
New adapter: `adapters/webchat_adapter.py`
Use `aiohttp` for both the static file server and WebSocket handler:
- `GET /` — Serves the chat UI (single HTML file with embedded JS/CSS)
- `WS /ws` — WebSocket for real-time chat
- Each WebSocket connection = one conversation (session isolation)
- Messages flow through the same `BaseAdapter._dispatch``ai_handler` path
### 5.3 Chat UI
Single self-contained HTML file at `static/chat.html`:
- Minimal chat interface (message list + input box)
- WebSocket connection to the local server
- Markdown rendering for AI responses
- No build step, no npm, no framework — just vanilla HTML/JS/CSS
### 5.4 Config
```json
{
"webchat": {
"enabled": false,
"port": 8080,
"host": "127.0.0.1"
}
}
```
### 5.5 Implementation Tasks
1. Add `aiohttp` dependency
2. Create `adapters/webchat_adapter.py` extending `BaseAdapter`
3. Create `static/chat.html` — self-contained chat UI
4. Add webchat config section
5. Wire into `main.py` / CLI `start` command with `--webchat` flag
6. Add to `_adapters` dict like other adapters
---
## 6. Self-Modification
### Can the Runtime Do This?
**Yes.** Both OpenCode and Claude Code have `Write`, `Edit`, and `Bash` tools that can modify any file the process has access to. The agent can already:
- Edit `~/.aetheel/config.json` (via file write tools)
- Create new skill files in `~/.aetheel/workspace/skills/<name>/SKILL.md`
- Update `SOUL.md`, `USER.md`, `MEMORY.md`
- Modify `HEARTBEAT.md` to add/remove periodic tasks
### What Aetheel Needs to Do
The agent just needs to be told it can do this. Update the system prompt:
```
# Self-Modification
- You can edit your own config at ~/.aetheel/config.json
- You can create new skills by writing SKILL.md files to ~/.aetheel/workspace/skills/<name>/SKILL.md
- You can update your identity files (SOUL.md, USER.md, MEMORY.md)
- You can modify HEARTBEAT.md to change your periodic tasks
- After editing config, tell the user to restart for changes to take effect
- After adding a skill, it will be available on next restart (or use /reload if implemented)
```
### 6.1 Hot Reload (Optional Enhancement)
Add a `/reload` command that re-reads config and skills without restart:
```python
if text_lower in ("reload", "/reload"):
cfg = load_config()
_skills.reload()
return "🔄 Config and skills reloaded."
```
### 6.2 Implementation Tasks
1. Update system prompt to mention self-modification capabilities
2. Ensure tools are enabled (see section 2)
3. Add `/reload` command to `ai_handler`
4. Add workspace path to system prompt so agent knows where files are
---
## 7. Agent-to-Agent Communication
### Can the Runtime Do This?
**OpenCode**: Has `Task` tool for spawning subagents. Subagents run in child sessions. No direct inter-session messaging.
**Claude Code**: Has `Task`, `TaskOutput`, `TaskStop` for subagent management, plus `TeamCreate`, `TeamDelete`, `SendMessage` for agent teams. `SendMessage` allows agents to communicate within a team.
### How Inspiration Repos Do It
**NanoClaw**: Uses Claude Code's `TeamCreate` + `SendMessage` tools. The `allowedTools` list includes both. Agent teams allow multiple agents to work together with message passing.
**OpenClaw**: `sessions_send` tool allows one session to send a message to another session. Supports fire-and-forget or wait-for-reply modes. Visibility config controls which sessions can see each other.
### Design for Aetheel
Aetheel already has `SubagentManager` for spawning background tasks. What's missing is the ability for subagents to communicate back to the main agent or to each other.
### 7.1 Approach: Leverage Runtime's Native Tools
Since both OpenCode and Claude Code have subagent/team tools built in, the simplest approach is to enable them:
For Claude Code, add to `allowed_tools`:
```python
["Task", "TaskOutput", "TaskStop", "TeamCreate", "TeamDelete", "SendMessage"]
```
For OpenCode, these are enabled by default.
### 7.2 Aetheel-Level Inter-Subagent Messaging
For Aetheel's own `SubagentManager`, add a message bus:
```python
class SubagentBus:
"""Simple pub/sub for subagent communication."""
def __init__(self):
self._channels: dict[str, list[Callable]] = {}
def subscribe(self, channel: str, callback: Callable):
self._channels.setdefault(channel, []).append(callback)
def publish(self, channel: str, message: str, sender: str):
for cb in self._channels.get(channel, []):
cb(message, sender)
```
Wire into `SubagentManager` so subagents can:
- Publish results to a channel
- Subscribe to messages from other subagents
- Send messages to the originating user via `_send_fn`
### 7.3 Implementation Tasks
1. Enable `TeamCreate`, `SendMessage`, `Task` tools in Claude Code config
2. Update system prompt to mention subagent capabilities
3. Add `SubagentBus` to `agent/subagent.py`
4. Wire bus into `SubagentManager.spawn()` so subagents can communicate
5. Add `/subagents` command to list active subagents and their status
---
## 8. Implementation Order
Ordered by dependency and impact:
### Phase 3A: Enable What Already Exists (1-2 days)
1. **Tool enablement** — Change `no_tools` default, update allowed tools, update system prompt
2. **Self-modification** — Just system prompt changes + `/reload` command
3. **Agent-to-agent** — Enable runtime tools + system prompt
### Phase 3B: New Modules (3-5 days)
4. **CLI interface**`cli.py` with click, move main() logic
5. **Heartbeat system**`heartbeat/` module, `HEARTBEAT.md`, scheduler integration
### Phase 3C: WebChat (3-5 days)
6. **WebChat adapter** — aiohttp server, WebSocket handler, static HTML UI
### Dependencies
```
Tool enablement ──→ Self-modification (needs tools enabled)
──→ Agent-to-agent (needs tools enabled)
──→ Heartbeat (agent needs tools for heartbeat tasks)
CLI ──→ WebChat (webchat flag in CLI)
Heartbeat ──→ (standalone, uses existing scheduler)
```
### New Dependencies to Add
```toml
[project.dependencies]
# ... existing ...
click = ">=8.1.0"
aiohttp = ">=3.9.0"
```
### New Files
```
Aetheel/
├── cli.py # CLI entry point
├── heartbeat/
│ ├── __init__.py
│ └── heartbeat.py # HeartbeatRunner
├── adapters/
│ └── webchat_adapter.py # WebChat adapter
├── static/
│ └── chat.html # WebChat UI
└── ~/.aetheel/workspace/
├── HEARTBEAT.md # Periodic task prompts
└── TOOLS.md # Tool descriptions for agent
```