Personal AI assistant powered by Strands Agents SDK
Project description
AETHON
A self-hosted, provider-agnostic personal AI assistant — Web UI, CLI, and messaging bots, with memory, multi-agent specialists, SOPs, a scheduler, telemetry, and a live dashboard.
By default, AETHON runs Claude (Opus 4.8) on your Claude Max subscription quota through the local Meridian proxy — no per-token API bills. It still works with any Strands provider (Anthropic API, OpenAI, Ollama, Bedrock, Gemini, LiteLLM, Mistral) if you prefer.
What is AETHON?
AETHON is a personal AI assistant you run yourself. It is a single Python package that ships every entry point you need to talk to one persistent, memory-backed assistant:
- a terminal CLI for interactive chat,
- a Web UI (WebChat) in your browser,
- messaging bots for Telegram, Discord, Slack, and (experimentally) WhatsApp,
- a live dashboard to watch sessions, memory, telemetry, agents, and SOPs in real time,
- webhooks so other systems can trigger the assistant,
- and a cron scheduler so the assistant can run jobs on a timetable.
Under the hood, AETHON is built on the Strands Agents SDK. A main orchestrator agent can delegate to specialist sub-agents (Coder, Researcher, Analyst, Planner), keep long-term vector memory of what matters to you, follow SOPs (Standard Operating Procedures — reusable, slash-invoked workflows), and call tools (files, shell, scheduling, messaging, MCP servers).
The headline value is the default model backend. Instead of paying per token to an API, AETHON defaults to Claude Opus 4.8 served through Meridian — a small local proxy that bridges the Claude Code SDK to Anthropic using your Claude Max subscription. You install Meridian once, log in with your Claude account, and AETHON auto-starts the proxy for you. Because everything is local-first (services bind to 127.0.0.1 by default and your data lives under ~/.aethon), you stay in control of your data and your bill.
Provider-agnostic by design: flip one line in your config (model.provider) to switch to the Anthropic API, OpenAI, a fully-local Ollama model, Bedrock, Gemini, LiteLLM, or Mistral.
- Author: Mert Özbaş
- Repository: https://github.com/mertozbas/aethon
- Version: 0.1.0
- License: PolyForm Noncommercial 1.0.0 (source-available; free for noncommercial use)
Features
Model backends
- Defaults to Claude Opus 4.8 via the Meridian proxy on your Claude Max quota — no API key, no per-token cost.
- Auto-starts Meridian in the background on
aethon start(no extra terminal to babysit). - Works with any Strands provider:
meridian,anthropic,openai,ollama,bedrock,gemini,litellm,mistral(plusfake/echofor testing). - Guided setup wizard (
aethon init) and a diagnostics command (aethon doctor).
Channels (all in one package)
- CLI — terminal chat with history and Markdown rendering.
- WebChat — a browser chat UI served by FastAPI/uvicorn.
- Telegram, Discord, Slack — messaging bots (libraries ship with the core install).
- WhatsApp — experimental, via the optional
whatsappextra.
Assistant intelligence
- Long-term vector memory — SQLite-backed embeddings with cosine-similarity search.
- Multi-agent specialists — Coder, Researcher, Analyst, Planner, reachable from the main agent via
ask_*delegation tools. (Swarm/Graph team & pipeline orchestration exists internally but isn't yet wired into the runtime — see Roadmap.) - SOPs — built-in
/code-assist,/pdd,/codebase-summary, plus your own custom*.sop.mdworkflows. - Workspace persona files —
SOUL.md,TOOLS.md,CONTEXT.mddefine identity, preferences, and live state. - Tools — file read/write/edit, shell, scheduling, context updates, messaging, and MCP tools.
Operations & visibility
- Live dashboard — overview, live company (pixel-agents), live monitor, sessions, memory, config, logs, agents, SOPs.
- Scheduler — cron jobs that run SOPs and deliver results to a channel.
- Webhooks —
POST /webhook/triggerandPOST /webhook/{channel}with optional HMAC-SHA256 verification. - Telemetry — event history with summaries surfaced in the dashboard.
- MCP — optional Model Context Protocol server integration.
Deployment
- pip install (core covers CLI + WebChat + dashboard + Telegram/Discord/Slack + memory + SOPs + scheduler).
- Docker image + Compose (headless, with an optional local-Ollama profile).
- CI on Python 3.10 / 3.11 / 3.12, with wheel/sdist build and Docker image build.
Security & privacy
- Local-first: services bind to
127.0.0.1by default; your data lives in~/.aethon. - Workspace boundary + blocked-command filtering + approval hooks.
- Dashboard auth token, secret masking in API config dumps, and a memory guard that keeps secrets out of long-term memory.
Table of Contents
- What is AETHON?
- Features
- Quick Start
- Installation
- Model Backends
- Configuration
- Usage
- Core Concepts
- CLI Reference
- Security
- Troubleshooting
- FAQ
- Architecture
- Development
- Roadmap
- License
- Acknowledgements
Quick Start
The fastest path runs AETHON on your Claude Max quota via Meridian — no API key required.
# 1) Install Meridian once (Node/npm), and log in with your Claude account.
npm install -g @rynfar/meridian
claude login # one-time; uses your Claude subscription
# 2) Install AETHON. (The PyPI distribution is named "aethon-ai";
# the command and import stay "aethon".)
pip install aethon-ai
# 3) Start. The first run launches the setup wizard if no config exists,
# and auto-starts the Meridian proxy in the background for you.
aethon start
# 4) Open the Web UI.
# http://127.0.0.1:18790
That's it. You can also chat right in your terminal (the CLI channel is on by default), and visit the dashboard at http://127.0.0.1:18790/dashboard.
If you'd rather not run on Claude Max, see Model Backends for the Anthropic API, OpenAI, and fully-local Ollama paths.
Installation
Requirements
- Python 3.10, 3.11, or 3.12 (
requires-python = ">=3.10"). - For the default Meridian/Claude-Max backend: Node.js + npm (to install
@rynfar/meridian) and a Claude subscription (claude login). - For vector memory with the default settings: a running Ollama with the
nomic-embed-textmodel pulled (see Memory). Memory is enabled by default but only needs Ollama when you keep the defaultollamaembedding provider. - Build backend:
hatchling(only relevant if you build from source).
Install with pip
pip install aethon-ai
Note on names: the PyPI distribution is
aethon-ai(the plainaethonname was already taken), but the importable package and the CLI command are bothaethon— so you runaethon startandimport aethonas usual. To track the latestmaininstead, install from GitHub:pip install "git+https://github.com/mertozbas/aethon.git".
The core install ships every entry point in one package: CLI + WebChat + dashboard + Telegram (aiogram) + Discord (discord.py) + Slack (slack-bolt) + memory (aiosqlite) + SOPs (strands-agents-sops) + scheduler (apscheduler), plus the Strands core and the default strands-meridian provider.
Optional extras
Request an extra with pip install "aethon-ai[ollama]". From a local clone, the equivalent is pip install ".[ollama]" (see Development).
| Extra | Install | Adds | Purpose |
|---|---|---|---|
ollama |
pip install "aethon-ai[ollama]" |
ollama>=0.3.0 |
Local-inference provider (run models fully offline). |
whatsapp |
pip install "aethon-ai[whatsapp]" |
neonize>=0.3.0 |
WhatsApp channel (experimental). |
mcp |
pip install "aethon-ai[mcp]" |
mcp>=1.0.0 |
MCP (Model Context Protocol) server support. |
all |
pip install "aethon-ai[all]" |
aethon-ai[ollama,whatsapp,mcp] |
Bundles the three feature extras above. |
dev |
pip install "aethon-ai[dev]" |
pytest>=8.0.0, pytest-asyncio>=0.23.0, httpx>=0.27.0 |
Test/dev tooling. |
Install with Docker
The image is headless (web UI + dashboard + webhook + messaging bots; the interactive CLI is disabled inside a container). It defaults to talking to a Meridian proxy running on your host at http://host.docker.internal:3456, so start meridian on the host first.
Docker Compose (recommended):
docker compose up --build
# open http://127.0.0.1:18790
Plain docker run:
docker build -t aethon .
docker run -p 18790:18790 \
--add-host host.docker.internal:host-gateway \
aethon
Bundle the Ollama client at build time (for the local-inference path):
docker compose build --build-arg EXTRAS=ollama
# or: docker build --build-arg EXTRAS=ollama -t aethon .
Fully-local inference with the Compose local profile (runs an ollama/ollama service named aethon-ollama on port 11434):
docker compose --profile local up --build
# Then, in the data volume's config.yaml, set:
# model.provider: ollama
# model.host: http://ollama:11434
# (and build the image with EXTRAS=ollama so it has the Ollama client)
Docker facts worth knowing:
- Base image: multi-stage
python:3.12-slim(builder + runtime), runs as non-root useraethon(uid 10001) atWORKDIR /home/aethon. - State/config live in the named volume
aethon-datamounted at/home/aethon/.aethon. The seededdocker/config.docker.yamlis copied to/home/aethon/.aethon/config.yamlonly when the volume is empty — a mounted config/volume takes precedence. - WebChat binds
0.0.0.0:18790inside the container so the18790:18790port mapping reaches it. - Meridian auto-start is OFF in Docker (the slim image has no Node runtime) — run Meridian on the host.
- Memory is disabled by default in the image (it needs an Ollama embedding backend).
- Healthcheck probes
http://127.0.0.1:18790/healthinside the container. - API-key alternative: uncomment
ANTHROPIC_API_KEYindocker-compose.ymland switchprovider: anthropicin the config. SetAETHON_DASHBOARD_TOKENto enable dashboard auth when exposing beyond localhost.
Install from source
git clone https://github.com/mertozbas/aethon.git
cd aethon
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]" # editable install with dev tooling
aethon --version
Model Backends
AETHON picks the provider from model.provider in ~/.aethon/config.yaml. The default is meridian (Claude on your Claude Max quota). The setup wizard (aethon init) offers a provider menu of meridian / anthropic / openai / ollama, defaulting to meridian.
The default path — Claude on Claude Max via Meridian (step by step)
- Install Meridian (one time, on the host):
npm install -g @rynfar/meridian
- Log in with your Claude account (one time):
claude login - Start AETHON. Because
model.providerismeridianandmeridian.auto_startistrue, AETHON checks whether the proxy is reachable athttp://127.0.0.1:3456and, if not, spawns it detached in the background for you:aethon startOn start you'll see lines likeMeridian: starting in the background…thenMeridian: started in the background (pid …; logs: …).
What Meridian does: it bridges the Claude Code SDK to the Anthropic API using your Claude Max subscription, so you don't pay per token and you don't need an API key. The proxy listens on http://127.0.0.1:3456. AETHON launches it from a neutral working directory (~/.aethon) so another project's CLAUDE.md doesn't leak into the assistant's context, logs to ~/.aethon/logs/meridian.log, and writes its pid to ~/.aethon/meridian.pid.
Default model config (no key needed):
model:
provider: meridian
model_id: claude-opus-4-8 # 1M context included with Claude Max
# host is ignored by Meridian; the proxy is used at 127.0.0.1:3456
meridian:
auto_start: true # set false to manage Meridian yourself
Prefer to run Meridian by hand? Set
meridian.auto_start: falseand startmeridianyourself beforeaethon start.
Anthropic API
model:
provider: anthropic
model_id: claude-opus-4-8
api_key: ${ANTHROPIC_API_KEY} # resolved from the environment
OpenAI
Requires the OpenAI SDK (not bundled): pip install openai.
model:
provider: openai
model_id: gpt-4o
api_key: ${OPENAI_API_KEY}
Ollama (fully local)
Install the extra (pip install "aethon-ai[ollama]"), then:
model:
provider: ollama
model_id: llama3.1
host: http://localhost:11434
Other providers (bedrock / gemini / litellm / mistral)
These are also supported by the model factory. Set provider accordingly and supply the parameters each backend needs — for example region (default us-west-2) for Bedrock-style backends, and api_key for Gemini / Mistral. The litellm provider only uses model_id (configure credentials via LiteLLM's own environment variables, not model.api_key). model.extra is forwarded only for the ollama provider (merged into its sampling options); bedrock/gemini/litellm/mistral ignore extra.
Each of these backends needs its own SDK installed (none is bundled with aethon's core or an extra): pip install boto3 (Bedrock), google-genai (Gemini), litellm (LiteLLM), or mistralai (Mistral).
model:
provider: bedrock
model_id: anthropic.claude-3-5-sonnet
region: us-west-2
Note:
temperatureis intentionally omitted forclaude-opus-4-8requests.
Let the wizard do it: aethon init
aethon init
The wizard sets the provider, model, and memory and writes the config file for you. Use --config / -c to choose a path (default ~/.aethon/config.yaml) and --force to overwrite an existing config without asking. After configuring, verify everything with:
aethon doctor
aethon doctor prints your provider/model, runs a provider availability check, reports Meridian status, and shows whether memory is enabled and which embedding provider it uses.
Configuration
- File location:
~/.aethon/config.yaml(override with--config / -con any command). - Format: YAML, validated with Pydantic. A missing or empty file produces a fully-defaulted config — every section falls back to its defaults.
- Writing: the wizard and tooling write YAML with
sort_keys=Falseandallow_unicode=True, creating parent directories as needed.
${ENV_VAR} resolution
A string value is treated as an environment-variable reference only if it starts with ${ and ends with } (whole-string only — no partial or interpolated substitution). The inner name is looked up via os.environ. A missing env var resolves to an empty string "", not an error. Resolution recurses into dicts and lists; ints, bools, floats, and None pass through unchanged.
channels:
telegram:
enabled: true
token: ${TELEGRAM_BOT_TOKEN} # actual secret supplied via the environment
Docs suggest keeping secrets in files like
~/.aethon/credentials/telegram.envand exporting them into the environment.
Complete reference
model
| Field | Type | Default | Meaning |
|---|---|---|---|
provider |
str | "meridian" |
Model provider backend (meridian, anthropic, openai, ollama, …). |
host |
str | "http://localhost:11434" |
Ollama host URL; Meridian ignores it and uses 127.0.0.1:3456. |
model_id |
str | "claude-opus-4-8" |
Model identifier; 1M context included with Claude Max. |
api_key |
str | "" |
API key for the provider. |
temperature |
float | 1.0 |
Sampling temperature. |
top_p |
float | 0.95 |
Nucleus sampling probability mass. |
top_k |
int | 40 |
Top-k sampling cutoff. |
max_tokens |
int | 8192 |
Max tokens to generate per response. |
region |
str | "us-west-2" |
Provider region (e.g. for Bedrock-style backends). |
extra |
dict | {} |
Arbitrary extra provider params. |
meridian
| Field | Type | Default | Meaning |
|---|---|---|---|
auto_start |
bool | true |
Auto-start Meridian in the background on aethon start if not running; set false to manage it yourself. |
channels
channels.cli
| Field | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | true |
Enable the CLI channel. |
channels.webchat
| Field | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | true |
Enable the web chat channel. |
port |
int | 18790 |
Web chat listen port. |
host |
str | "127.0.0.1" |
Bind address; loopback only by default. Set 0.0.0.0 to expose (also set dashboard.auth_token). |
channels.telegram
| Field | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | false |
Enable the Telegram channel. |
token |
str | "" |
Telegram bot token. |
channels.discord
| Field | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | false |
Enable the Discord channel. |
token |
str | "" |
Discord bot token. |
channels.slack
| Field | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | false |
Enable the Slack channel. |
bot_token |
str | "" |
Slack bot token (xoxb-…). |
app_token |
str | "" |
Slack app-level token (xapp-…). |
channels.whatsapp
| Field | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | false |
Enable the WhatsApp channel (experimental; no other fields). |
security
| Field | Type | Default | Meaning |
|---|---|---|---|
workspace_only |
bool | false |
When true, confine file tools to ~/.aethon/workspace; when false (default), allow anywhere under $HOME except blocked system/credential paths. |
require_approval |
list[str] | ["shell", "file_write", "send_message"] |
Reserved; not currently enforced. Approval gating is configured in the approval section. |
blocked_commands |
list[str] | ["rm -rf /", "sudo", "mkfs"] |
Shell command substrings that are blocked. |
allowed_senders |
dict[str, list[str]] | {} |
Per-channel allowlist of sender identifiers. |
session
| Field | Type | Default | Meaning |
|---|---|---|---|
storage_dir |
str | "~/.aethon/sessions" |
Directory where session state is stored. |
conversation_manager |
str | "summarizing" |
Conversation manager strategy. |
summary_ratio |
float | 0.3 |
Fraction of history to summarize when compacting. |
preserve_recent_messages |
int | 10 |
Number of recent messages kept verbatim. |
memory
| Field | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | true |
Enable vector memory. |
embedding_provider |
str | "ollama" |
Embedding provider (ollama, openai). |
embedding_model |
str | "nomic-embed-text" |
Embedding model name. |
embedding_api_key |
str | "" |
API key for the embedding provider. |
db_path |
str | "~/.aethon/memory.sqlite" |
SQLite path for the vector store. |
multi_agent
| Field | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | true |
Enable the multi-agent system. |
max_handoffs |
int | 10 |
Max agent-to-agent handoffs. |
max_iterations |
int | 10 |
Max iterations per run. |
execution_timeout |
float | 300.0 |
Overall execution timeout (seconds). |
node_timeout |
float | 120.0 |
Per-node timeout (seconds). |
sops
| Field | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | true |
Enable SOP execution. |
builtin_sops_enabled |
bool | true |
Enable built-in SOPs. |
approval
| Field | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | false |
Enable the interrupt-based approval hook. |
requires_approval |
list[str] | ["shell", "file_write"] |
Action types requiring approval via this hook. |
telemetry
| Field | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | true |
Enable the telemetry hook. |
max_history |
int | 10000 |
Max telemetry events retained. |
memory_guard
| Field | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | true |
Enable the memory guard hook. |
custom_patterns |
list[str] | [] |
Additional patterns the guard should catch. |
scheduler
| Field | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | true |
Enable the scheduler. |
default_channel |
str | "cli" |
Default channel for scheduled outputs. |
jobs |
dict | {} |
Scheduled job definitions. |
dashboard
| Field | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | true |
Enable the web dashboard. |
pixel_agents |
bool | true |
Enable the pixel-agents visualization. |
auth_token |
str | "" |
Optional shared token; empty = no auth. Gates /dashboard and protected /api/* + /ws/dashboard via ?token=, Authorization: Bearer, or the aethon_dash cookie. |
webhook
| Field | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | true |
Enable the webhook endpoint. |
secret |
str | "" |
Shared secret to validate incoming webhooks (HMAC-SHA256). |
mcp
| Field | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | false |
Enable MCP server integration. |
servers |
list[dict] | [] |
List of MCP server definitions. |
performance
| Field | Type | Default | Meaning |
|---|---|---|---|
model_warmup |
bool | false |
Send a real model request on boot to reduce first-message latency (off by default; spends quota). |
session_cache_size |
int | 10 |
Number of sessions cached in memory. |
embedding_cache_size |
int | 100 |
Number of embeddings cached. |
paths
| Field | Type | Default | Meaning |
|---|---|---|---|
workspace |
str | "~/.aethon/workspace" |
Workspace root directory. |
sessions |
str | "~/.aethon/sessions" |
Sessions directory. |
memory_db |
str | "~/.aethon/memory.sqlite" |
Vector memory SQLite path. |
logs |
str | "~/.aethon/logs" |
Logs directory. |
credentials |
str | "~/.aethon/credentials" |
Credentials directory. |
Notes:
~in path-valued fields is stored literally; it is expanded only for the config-file path itself inload()/write(). Some values overlap intentionally (e.g.memory.db_pathandpaths.memory_dbboth default to~/.aethon/memory.sqlite;session.storage_dirandpaths.sessionsboth~/.aethon/sessions).
Usage
When you run aethon start, the console prints a status block: the provider and model, the WebChat URL (http://127.0.0.1:18790), the Meridian/memory/multi-agent/SOP/scheduler/telemetry status, and (when enabled) the dashboard and webhook URLs and the list of active channels. Then the gateway starts.
Interactive CLI
The CLI channel is enabled by default. After aethon start, type at the you > prompt. Responses render as Markdown. Input history is saved to ~/.aethon/cli_history. Exit with exit, quit, q, or Ctrl-C / EOF.
you > what's on my plate today?
you > /code-assist refactor the auth module
you > exit
Web UI (WebChat)
Open http://127.0.0.1:18790 in your browser. It's a minimal dark chat UI (header, message list, input + Send) that connects over a WebSocket (/ws/chat) and renders bot replies as Markdown. You send plain text; you get one reply per message.
Useful endpoints on the same app/port:
GET /api/status→{"status": "running", "version": "0.1.0"}(not gated).GET /health→{"status": "ok"}(deliberately ungated, for container/load-balancer probes).
To expose WebChat on your network, set channels.webchat.host: 0.0.0.0 — and also set dashboard.auth_token (see Security).
Dashboard
Open http://127.0.0.1:18790/dashboard. The dashboard is a single-page app (self-hosted fonts/CSS, works offline) with these panels:
| Route | Panel |
|---|---|
#/overview |
Overview |
#/company |
Live Company (pixel-agents) |
#/monitor |
Live Monitor |
#/sessions |
Sessions |
#/memory |
Memory |
#/config |
Config (secrets masked to ***) |
#/logs |
Logs |
#/agents |
Agents |
#/sops |
SOPs |
The dashboard mounts on the WebChat app and is only available when WebChat is enabled and dashboard.enabled is true.
Authentication (dashboard.auth_token): empty = no auth (fine for the default localhost bind). When set, an HTTP middleware gates /dashboard and the protected /api/* prefixes (/api/sessions, /api/memory, /api/config, /api/scheduler, /api/telemetry, /api/sops, /api/agents) and /ws/dashboard. Note /api/status and /health stay open. The token is accepted (in precedence order) via the aethon_dash cookie, an Authorization: Bearer <token> header, or a ?token=<token> query param.
The usual flow when a token is set:
# Open once with the token; the server sets the aethon_dash cookie for you.
http://127.0.0.1:18790/dashboard?token=YOUR_TOKEN
# API calls (Bearer header):
curl -H "Authorization: Bearer YOUR_TOKEN" http://127.0.0.1:18790/api/config
# WebSocket (cookie or ?token=):
ws://127.0.0.1:18790/ws/dashboard?token=YOUR_TOKEN
Liveness/health: GET /health always returns {"status": "ok"}, even when a dashboard token is set.
Messaging bots
Enable a channel under channels.<name> and supply its token(s) (typically via ${ENV_VAR}). The gateway starts only enabled channels and won't crash on missing tokens — it logs the error and keeps going.
Telegram — create a bot via BotFather to get the token.
channels:
telegram:
enabled: true
token: ${TELEGRAM_BOT_TOKEN}
Discord — create a bot in the Discord Developer Portal and grant it the MESSAGE CONTENT intent. The bot responds to DMs or messages that @mention it.
channels:
discord:
enabled: true
token: ${DISCORD_BOT_TOKEN}
Slack — create a Slack App, enable Socket Mode, and subscribe to events message.channels, message.im, app_mention. You need both a Bot Token and an App-Level Token.
channels:
slack:
enabled: true
bot_token: ${SLACK_BOT_TOKEN} # xoxb-…
app_token: ${SLACK_APP_TOKEN} # xapp-…
WhatsApp (experimental) — install the extra (pip install "aethon-ai[whatsapp]"), enable the channel, and on first start scan the QR code with your WhatsApp app to link the session.
channels:
whatsapp:
enabled: true
Webhooks
Webhooks mount on the WebChat app and require webhook.enabled (default true) with WebChat enabled. Both endpoints respond {"status":"ok","response": <agent reply text or null>}. If webhook.secret is set, requests must include X-Aethon-Signature: <hex hmac-sha256 of the raw body> or they're rejected with 403.
Run a SOP and get the reply back (POST /webhook/trigger):
curl -X POST http://127.0.0.1:18790/webhook/trigger \
-H 'Content-Type: application/json' \
-d '{"sop_name": "code-assist", "text": "summarize the repo"}'
Push the reply out to another channel too:
curl -X POST http://127.0.0.1:18790/webhook/trigger \
-H 'Content-Type: application/json' \
-d '{"text": "deploy finished", "channel": "telegram", "recipient": "123456"}'
Channel-specific inbound (POST /webhook/{channel}) — the response is returned in the HTTP body:
curl -X POST http://127.0.0.1:18790/webhook/github \
-H 'Content-Type: application/json' \
-d '{"text": "PR #42 merged"}'
Scheduler (cron jobs)
The scheduler (APScheduler) runs cron jobs that execute an SOP and deliver the result to a channel (default channel from scheduler.default_channel, which is cli). It requires SOPs to be enabled (sops.enabled: true, the default). Define jobs in config:
scheduler:
enabled: true
default_channel: cli
jobs:
weekday-standup:
cron: "0 9 * * 1-5" # weekdays at 9 AM
sop_name: codebase-summary
channel: telegram # optional; overrides default_channel
recipient: "123456789" # the destination chat/channel id (see note)
Recipients:
cliandwebchatneed norecipient. For messaging channels (telegram,discord,slack,recipientto the destination chat/channel id — otherwise delivery is skipped with a warning.
The assistant can also manage jobs at runtime with the schedule_task, list_scheduled_jobs, and remove_scheduled_job tools (see Agent tools).
Core Concepts
Workspace files (SOUL / TOOLS / CONTEXT)
On aethon start, AETHON ensures the workspace at ~/.aethon/workspace exists and seeds three Markdown files (each written only if it doesn't already exist — your edits are preserved):
SOUL.md— the assistant's persona/system identity. Sections: Identity (be pragmatic and direct; own mistakes; say when you don't know), Communication (speaks English and Turkish, replies in the user's language; short focused answers; Markdown formatting), Decision Making (do simple tasks directly; propose a plan for complex tasks; pick the simplest approach).TOOLS.md— your preferences and capabilities. Sections: Code Standards (Python 3.10+, type hints, f-strings, asyncio + OOP, no needless comments, test against real data), Expert Delegation (ask_coder,ask_researcher,ask_analyst,ask_planner), Memory (save withmanage_memory; categories preferences/projects/decisions/learnings; never store secrets), Context (keepCONTEXT.mdcurrent withupdate_context).CONTEXT.md— live working state, seeded with empty placeholders for Active Project, Recent Decisions, and Notes.
It also creates <workspace>/sops, the sessions directory, the logs directory, and (if memory is enabled) the memory DB's parent directory.
Memory (vector + embeddings)
Long-term memory is a SQLite vector store with provider embeddings and cosine-similarity search (a brute-force full scan; no ANN index). Storage lives at ~/.aethon/memory.sqlite by default.
- Ollama embeddings (default): uses
config.model.host(defaulthttp://localhost:11434) and modelnomic-embed-text. Requires Ollama running with that model pulled. - OpenAI embeddings: set
memory.embedding_provider: openaiandmemory.embedding_api_key.
The assistant manages memory with the manage_memory tool — actions store, search, list, and forget, with categories like preferences, projects, decisions, learnings. The memory guard hook keeps secrets out of long-term memory.
Multi-agent specialists + delegation (ask_*)
A main orchestrator agent can delegate complex work to four specialists (all share the runtime's model):
| id | name | focus | tools |
|---|---|---|---|
coder |
Coder | writing code, testing, debugging, refactoring (TDD) | file_read, file_write, editor, shell, python_repl, think |
researcher |
Researcher | web research, reading docs, gathering info (cites sources) | http_request, file_read, think, current_time |
analyst |
Analyst | data analysis, calculations, charts, reports | python_repl, calculator, file_read, file_write, think |
planner |
Planner | breaking complex tasks into concrete steps, prioritization | file_read, file_write, think |
Delegation tools: ask_coder(task), ask_researcher(query), ask_analyst(data_task), ask_planner(planning_task). The orchestrator is instructed to handle simple tasks itself and delegate complex ones.
Beyond ask_*, two team modes exist internally: a collaborative mode (a Strands Swarm with handoffs, governed by multi_agent.max_handoffs / max_iterations / execution_timeout / node_timeout) and a pipeline mode (a deterministic GraphBuilder sequence; default pipeline ["planner", "researcher", "coder"]).
SOPs (Standard Operating Procedures)
SOPs are reusable workflows invoked with a slash command. Built-ins:
/code-assist /pdd /codebase-summary
(from the strands-agents-sops package; toggle with sops.builtin_sops_enabled, and the whole subsystem with sops.enabled).
Invoking: a message that starts with / is treated as an SOP command; the first token after / is the SOP name and the rest is your input. It only matches loaded SOPs.
Authoring a custom SOP: create a Markdown file at:
~/.aethon/workspace/sops/<name>.sop.md
The SOP name is the filename with .sop.md removed, so weekly-report.sop.md is invoked as /weekly-report. A ## Overview section is parsed for the SOP's description (first 200 chars), shown in listings (the dashboard SOPs panel and /api/sops). The agent's system prompt lists the available SOP slash-commands by name. Custom SOPs are merged with built-ins.
## Overview
Generate a concise weekly status report from recent commits and notes.
## Steps
1. Summarize recent activity.
2. Highlight blockers and decisions.
3. Output a Markdown report.
You can also create/edit/delete custom SOPs from the dashboard's SOPs panel (built-ins can't be deleted).
Agent tools
The main agent always has: file_read, file_write, editor, shell, think, current_time, plus update_context(action, key, value) (maintains CONTEXT.md; actions update, get, list) and send_message(channel, text, recipient) (pushes a message out to any enabled channel — e.g. telegram, discord, slack, webchat). Conditionally added:
- memory —
manage_memory(action, content, query, category, memory_id)when vector memory is active. - delegate —
ask_coder / ask_researcher / ask_analyst / ask_plannerwhen the multi-agent system is on. - scheduler —
schedule_task(cron_expression, sop_name, job_id, channel, recipient),list_scheduled_jobs(),remove_scheduled_job(job_id)when the scheduler is running. - MCP tools — appended when MCP is enabled.
Telemetry
The telemetry hook records events (up to telemetry.max_history, default 10000) and surfaces summaries and recent metrics in the dashboard (/api/telemetry, the Live Monitor, and Agents/history views).
CLI Reference
aethon [--version] <command> [options]
| Command | Description | Options |
|---|---|---|
aethon init |
Set up AETHON (provider, model, memory) and write the config file. | --config, -c <path> (default ~/.aethon/config.yaml); --force (overwrite an existing config without asking). |
aethon doctor |
Diagnose the current configuration and provider availability (provider/model, provider check, Meridian status, memory). | --config, -c <path> (default ~/.aethon/config.yaml). |
aethon start |
Start AETHON (runs the setup wizard first if no config exists; auto-starts Meridian when applicable; launches the gateway and all enabled channels). | --config, -c <path> (default ~/.aethon/config.yaml). |
aethon --version |
Print aethon, version 0.1.0 and exit. |
— |
Security
AETHON is local-first and ships safe defaults:
- Loopback binding: WebChat (and the dashboard/webhooks mounted on it) bind to
127.0.0.1by default. To expose beyond localhost, setchannels.webchat.host: 0.0.0.0and adashboard.auth_token. - Dashboard auth token: when
dashboard.auth_tokenis set,/dashboard, the protected/api/*prefixes, and/ws/dashboardrequire the token (viaaethon_dashcookie,Authorization: Bearer, or?token=)./api/statusand/healthstay open for probes. - File-access sandbox: by default, file tools may read/write anywhere under your home directory except a blocklist of system and credential paths (
/etc,/usr,/bin,~/.ssh,~/.gnupg,~/.aethon/credentials, …). Setsecurity.workspace_only: trueto confine file tools strictly to~/.aethon/workspace. - Blocked commands: the security hook refuses shell commands containing any
security.blocked_commandsentry (defaultrm -rf /,sudo,mkfs, plus a built-in danger list). - Approval gating: an optional interrupt-based hook can require approval for the actions in
approval.requires_approval(defaultshell,file_write) — it is off by default (approval.enabled: false). (Thesecurity.require_approvalfield is reserved and not currently enforced.) - Sender allowlists:
security.allowed_senderscan restrict who may message each channel. - Secret masking: the dashboard
GET /api/configdump masks sensitive keys (api_key,token,bot_token,app_token,secret,password) to***. - Memory guard: the memory guard hook blocks secrets from being written to long-term memory.
- Webhook verification: set
webhook.secretto require an HMAC-SHA256X-Aethon-Signatureon incoming webhooks. - Credential isolation: keep tokens out of the config file by referencing
${ENV_VAR}s and storing secrets under~/.aethon/credentials/.
Troubleshooting
Meridian not reachable / Provider not ready. Ensure Meridian is installed and you're logged in:
npm install -g @rynfar/meridian
claude login
AETHON auto-starts Meridian on aethon start (when provider: meridian and meridian.auto_start: true). If auto-start times out, check the log at ~/.aethon/logs/meridian.log and re-run claude login if needed. The proxy listens on http://127.0.0.1:3456. Run aethon doctor to see Meridian status.
Provider not ready (other backends). aethon start runs an availability check; if it fails it prints Provider not ready: <msg> and a hint. Run aethon init to reconfigure or aethon doctor to diagnose. For API providers, confirm the api_key (or its ${ENV_VAR}) is actually set — remember missing env vars resolve to an empty string.
Port already in use (18790). Another process holds the WebChat port. Change channels.webchat.port, or stop the other process. In Docker, adjust the 18790:18790 mapping.
Memory needs Ollama. With the default ollama embedding provider, vector memory requires Ollama running with nomic-embed-text:
ollama pull nomic-embed-text
On start you'll see Memory: nomic-embed-text not found — ollama pull nomic-embed-text if it's missing, or Memory: Ollama connection error if Ollama isn't reachable. Alternatively switch to embedding_provider: openai (with embedding_api_key), or disable memory.
Docker can't reach host Meridian. The container talks to host Meridian at http://host.docker.internal:3456. Make sure meridian is running on the host, and that host.docker.internal resolves — Compose sets extra_hosts: host.docker.internal:host-gateway; for plain docker run, add --add-host host.docker.internal:host-gateway.
Messaging bot didn't start. Missing libs log a warning and missing tokens log a ValueError — the gateway keeps running. Check that the channel is enabled: true, the token env var is set, and (Discord) the MESSAGE CONTENT intent / (Slack) Socket Mode + event subscriptions are configured.
FAQ
Do I need an API key?
No — not for the default path. With provider: meridian and a Claude subscription (claude login), AETHON runs Claude Opus 4.8 on your Claude Max quota with no API key and no per-token bill. API keys are only needed if you choose the Anthropic API, OpenAI, etc.
Where does AETHON store my data?
Under ~/.aethon — config (config.yaml), workspace (workspace/), sessions (sessions/), logs (logs/), vector memory (memory.sqlite), and credentials (credentials/).
Is AETHON open source? It's source-available under PolyForm Noncommercial 1.0.0 — free for noncommercial use, but not OSI-approved open source (commercial use isn't permitted). See License.
Can I run it fully offline / locally?
Yes. Install the ollama extra, set provider: ollama, and use Ollama embeddings for memory. No cloud calls are required in that configuration.
How do I expose the Web UI on my network?
Set channels.webchat.host: 0.0.0.0 and also set dashboard.auth_token. Then reach the dashboard with ?token=YOUR_TOKEN to set the auth cookie.
Which channels need extra installs?
Only WhatsApp (the whatsapp extra). CLI, WebChat, Telegram, Discord, and Slack all ship in the core install.
How do I add my own workflow?
Drop a *.sop.md file in ~/.aethon/workspace/sops/ (with an ## Overview section) and invoke it as /<name>. See SOPs.
Does the assistant remember things between sessions? Yes, when memory is enabled. It stores embeddings in SQLite and retrieves them by similarity. The memory guard prevents secrets from being saved.
Architecture
AETHON is a Strands-Agents application with a single FastAPI/uvicorn server (owned by the WebChat adapter) that also hosts the dashboard and webhook routers, so everything shares one host/port. A gateway instantiates the enabled channel adapters and routes inbound messages to the agent runtime, which composes a system prompt from the workspace files, holds the vector memory, wires up the specialist factory and SOP runner, and exposes the tools. Cross-cutting hooks provide telemetry, approval, and the memory guard. Optional MCP servers extend the toolset.
For deeper reference, see the documentation under docs/:
docs/product/ARCHITECTURE.md— system architecture.docs/product/PRODUCT.md— product overview.docs/product/GETTING-STARTED.md— getting started.docs/product/CONFIGURATION.md— configuration guide.docs/product/API-REFERENCE.md— HTTP/WebSocket API reference.docs/development/SECURITY.md— security model & threat analysis.docs/development/ROADMAP.md— roadmap.
Development
git clone https://github.com/mertozbas/aethon.git
cd aethon
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
Run tests (the e2e marker spawns a subprocess and binds a socket; the ollama marker needs a running Ollama):
pytest # full suite
pytest -q # quiet
pytest -m "not e2e" # skip end-to-end boot tests
Lint (the error-level gate CI enforces):
ruff check --select E9,F63,F7,F82 aethon
CI (.github/workflows/ci.yml, name CI, on push/PR to main) runs three jobs:
test— matrix on Python 3.10 / 3.11 / 3.12;pip install -e ".[dev]"; ruff error-level lint;pytest -q.build—python -m build+twine check dist/*on 3.12.docker— builds imageaethon:ci(no push).
Contributions follow the same noncommercial terms; see CONTRIBUTING.md.
Roadmap
v1 (0.1.0) ships: the full provider-agnostic assistant — CLI + WebChat + dashboard, Telegram/Discord/Slack channels, SQLite vector memory, multi-agent specialists with ask_* delegation, built-in and custom SOPs, scheduler, webhooks, telemetry, the Meridian/Claude-Max default backend with background auto-start, and Docker + CI infrastructure.
Deferred to v2:
- Response streaming.
- Team / pipeline orchestration (Swarm/Graph) wired into the runtime and exposed as a command/tool (the orchestration code exists but isn't connected yet).
- Per-specialist multi-model configuration.
- Tool Builder and Agent Builder agents.
- Phase 7 AI Capabilities Expansion.
See docs/development/ROADMAP.md for details.
License
AETHON is licensed under the PolyForm Noncommercial License 1.0.0.
- Free for any noncommercial use — personal, research, education, and hobby use are all permitted.
- Commercial use is not permitted under this license.
- Source-available, not OSI open source — you can read and modify the source within the noncommercial terms, but it is not an OSI-approved open-source license.
See the full text in LICENSE.
Acknowledgements
- Strands Agents SDK — the agent framework AETHON is built on.
- Meridian (
@rynfar/meridian) — the local proxy that bridges the Claude Code SDK to Anthropic using your Claude Max subscription. - strands-meridian — the Strands provider that wraps Meridian (AETHON's default backend).
- Anthropic Claude — the default model (Claude Opus 4.8).
Built by Mert Özbaş · github.com/mertozbas/aethon
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aethon_ai-0.1.1.tar.gz.
File metadata
- Download URL: aethon_ai-0.1.1.tar.gz
- Upload date:
- Size: 361.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ececaa16917e9ae697aee609704babee1fd63dc15d1dd3890b4f706cb9751bd2
|
|
| MD5 |
56003e17ec6bdf3fa5f8a25b65ea1e47
|
|
| BLAKE2b-256 |
22627d98fb2345e8fa7ee308d131ef7bee00c666a7e68954be57fe41c8cd8f8b
|
File details
Details for the file aethon_ai-0.1.1-py3-none-any.whl.
File metadata
- Download URL: aethon_ai-0.1.1-py3-none-any.whl
- Upload date:
- Size: 242.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f7407d334455d235483256e5be73f70689192e22fda3c1975f8ddb9bda515184
|
|
| MD5 |
c16006ae9f43c30a7182144a9f3748a5
|
|
| BLAKE2b-256 |
a785edfd94ab08d75315b4cf75525d13fcac674cd9cd869843f12aa181acfe11
|