Skip to main content

Hermes-style personal AI agent powered by the Mirai cloud API

Project description

Mirai Agent

A Hermes-style personal AI agent (mirai-agent, Python 3.11+) living in the Mirai monorepo. The model backend is the Mirai cloud API (https://satuapps.com/v1, OpenAI-shaped with tool calling and billing); architecture mirrors Hermes Agent: one agent core, thin I/O shells.

Docs on the website

Install / quickstart / config / skills / gateway notes (en + id): https://satuapps.com/agent. Desktop installers are shipped via satuapps.com /downloads (CI artifacts uploaded by the operator — not a public open-source GitHub Releases channel). Self-host with Docker: see Distribution → Docker below.

Status

  • Phase 1 — agent core: provider, conversation loop, tool registry with 8 built-in tools, permissions, pytest suite.
  • Phase 2 — state, memory, skills: state.db (SQLite + FTS5), SOUL.md / MEMORY.md / USER.md, SKILL.md skills with progressive disclosure, context compression, cron scheduler.
  • Phase 3 — interfaces: interactive CLI (prompt_toolkit + Rich, slash commands) + mirai-agent serve (FastAPI WebSocket JSON-RPC with the approval flow) for the desktop app — see docs/serve-protocol.md.
  • Phase 4 — Electron desktop: desktop/ spawns mirai-agent serve, safeStorage auth, approvals UI, tray/menus.
  • Phase 5 — packaging: PyInstaller sidecar, electron-builder dmg/nsis, electron-updater, PyPI-ready metadata, CI matrix.
  • Phase 6 — messaging gateway: mirai-agent gateway run asyncio daemon with Telegram (long-poll), Discord, Slack Socket Mode, WhatsApp Cloud API, and generic HTTP webhook adapters; allowlist auth, per-chat sessions, pid/lock/state files, graceful shutdown.
  • Phase 7 — website: /agent page (en/id) + READMEs.
  • Hermes bare-min parity: MCP client, delegate_task, web_search, session_search, memory tools, thin pre/post tool hooks — see docs/hermes-parity.md.
  • Web control panel: mirai-agent panel serves a localhost web UI (chat, sessions, skills, cron, gateways, MCP, config, usage) reusing the serve /ws JSON-RPC backend — see docs/panel.md.

Layout

agent/
├── pyproject.toml            # uv-managed, package `mirai-agent` (PyPI-ready)
├── Dockerfile                # single-user self-host image (panel default)
├── docker-compose.yml        # panel + optional serve/gateway profiles
├── packaging/mirai-agent.spec
├── scripts/
│   ├── build_sidecar.sh|.ps1 # PyInstaller onedir for desktop
│   ├── install.sh|.ps1       # end-user install stubs (uv/pip)
│   └── publish.sh            # build sdist/wheel (no upload)
├── docs/serve-protocol.md    # the desktop WebSocket contract (v1)
├── src/mirai_agent/
│   ├── config.py             # MIRAI_API_KEY env → ~/.mirai-agent/config.yaml
│   ├── home.py               # $MIRAI_AGENT_HOME (~/.mirai-agent)
│   ├── permissions.py        # read auto-runs; write/shell need approval
│   ├── core/
│   │   ├── aiagent.py        # AIAgent facade (one core, many shells)
│   │   ├── conversation_loop.py
│   │   └── prompt_builder.py # stable/context/volatile tiers
│   ├── providers/mirai.py    # httpx; JSON tool rounds + simulated SSE
│   ├── tools/                # registry + builtins (files, shell, search,
│   │                         # fetch_url, web_search, memory, session_search,
│   │                         # skill_view, delegate_task) + MCP client
│   ├── hooks.py              # thin pre_tool / post_tool seam
│   ├── state/db.py           # SQLite + FTS5 sessions/messages/usage
│   ├── skills/               # SKILL.md discovery + skill_view tool
│   ├── compression.py        # summarize-oldest-turns compaction
│   ├── cron/                 # jobs.json + background ticker
│   ├── cli/                  # Phase 3: display / slash commands / REPL
│   ├── serve/                # Phase 3: protocol / sessions+approvals /
│   │                         #   FastAPI WS gateway
│   ├── panel/                # Web control panel: FastAPI REST + static UI
│   └── gateway/              # multi-platform runner (pid/lock/state)
│       └── platforms/        # telegram, discord, slack, whatsapp, webhook
└── tests/                    # pytest, fully mocked — no real API calls

Parity notes vs Hermes: docs/hermes-parity.md.

Quick start (dev)

cd agent
uv venv && uv pip install -e ".[dev]"   # dev = all extras + pytest
export MIRAI_API_KEY=mirai-…        # or api_key: in ~/.mirai-agent/config.yaml
mirai-agent                                # interactive REPL
mirai-agent -p "what files are in this repo?"  # one-shot
mirai-agent serve                          # headless WS server on :9199
pytest

End users install from PyPI:

uv tool install "mirai-agent[all]"
# or: pip install "mirai-agent[all]"

Then run mirai-agent, mirai-agent panel, or Docker Compose (see Distribution below). The bare install stays minimal (httpx/pydantic/pyyaml — agent core only); mirai-agent[cli] and mirai-agent[serve] are the individual extras. Helpers: scripts/install.sh / scripts/install.ps1.

Interactive CLI (Phase 3)

prompt_toolkit + Rich: streamed answers, tool/diff rendering, a cost line per turn, a status bar (model · permission mode · cwd · git branch), and persistent prompt history. Slash commands:

/help              Show help            /skills [name]  List or view skills
/model [name]      Show or set model    /memory         Show MEMORY.md
/clear             Fresh session        /compact        Summarize old history
/cost              Tokens & est. cost   /exit           Quit

/model persists to config.yaml; /clear starts a fresh state.db session; write/shell approvals (yes / no / always-project / global) mirror the Node CLI's UX.

Headless serve (Phase 3)

mirai-agent serve [--host 127.0.0.1] [--port 9199] [--yolo|--read-only]

FastAPI + uvicorn. GET /health is the readiness probe; ws://<host>:<port>/ws speaks versioned JSON-RPC 2.0 (protocol: 1): methods ping, server.info, chat.send (streams chat.chunk + chat.tool_* events), tool.approval_response, sessions.list, sessions.get; events server.hello and tool.approval_request (the client answers with once / always-project / always-global / deny). Sessions live in the same state.db, so a desktop session can be resumed from the CLI and vice versa. Full contract with message shapes and examples: docs/serve-protocol.md.

Web control panel

mirai-agent panel serves a localhost web UI on top of the same /ws JSON-RPC backend the desktop app uses — so you can manage your local agent from a browser without the Electron app.

mirai-agent panel                 # http://127.0.0.1:9200
mirai-agent panel --port 8080     # custom port

Sections: Chat (streaming + tool/approval UI over /ws), Sessions (list / search / resume / delete), Skills (list / view), Cron (add / run now / toggle / delete), Gateways (per-platform status, start/stop, allowlist), MCP servers (add / remove / test), Config (edit config.yaml safely, API key redacted), Usage/cost (from state.db).

The built UI ships inside the wheel, so mirai-agent panel works out of the box. To rebuild from source: cd agent/panel && npm install && npm run build (writes src/mirai_agent/panel/static/). Security: binds to 127.0.0.1 only by default; a non-loopback bind requires panel.token in config.yaml and presents that bearer on every request. Full notes: docs/panel.md.

Key design facts

  • The Mirai API replaces client system prompts with its brand prompt server-side. Agent identity (SOUL.md), project context (MIRAI.md / AGENTS.md), and memory therefore travel inside the first user message of each session (<agent_context>…</agent_context>), handled by core/prompt_builder.py.
  • Tool rounds are non-stream JSON; plain assistant text comes back as simulated SSE. The provider tolerates both transparently.
  • 402 means top up — surfaced as PaymentRequiredError with the subscription URL.
  • Permissions: read tools run freely; write/shell ask (once / always project / always global / deny), with --yolo/--auto and --read-only modes. Allowlists live in .mirai/permissions.json (project) and ~/.mirai-agent/permissions.json (global).

Messaging gateway

mirai-agent gateway run starts an asyncio daemon that connects every configured platform, authorizes chats against per-platform allowlists, maps each chat to a persistent state.db session ({platform}-{chat_id}), runs the message through the shared AIAgent core, and delivers the reply.

mirai-agent gateway run            # foreground daemon (Ctrl-C to stop)
mirai-agent gateway status         # pid / state / platforms / offsets

Config (~/.mirai-agent/config.yaml) — enable any subset:

gateway:
  permission_mode: read-only       # SAFE DEFAULT for chat surfaces
  telegram:
    bot_token: "123456:ABC..."     # or MIRAI_TELEGRAM_BOT_TOKEN
    allow_from: [123456789, "@you"]
  discord:
    bot_token: "…"                 # or MIRAI_DISCORD_BOT_TOKEN (needs websockets)
    allow_from: ["1234567890"]
  slack:
    bot_token: "xoxb-…"            # MIRAI_SLACK_BOT_TOKEN
    app_token: "xapp-…"            # MIRAI_SLACK_APP_TOKEN (Socket Mode)
    allow_from: ["U123", "C456"]
  whatsapp:                        # Meta Cloud API (not Baileys)
    access_token: "…"              # MIRAI_WHATSAPP_ACCESS_TOKEN
    phone_number_id: "…"           # MIRAI_WHATSAPP_PHONE_NUMBER_ID
    verify_token: "mirai-verify"
    webhook_port: 8787
    allow_from: ["15551234567"]
  webhook:                         # generic HTTP POST → agent → callback
    host: "127.0.0.1"
    port: 8788
    path: "/hook"
    secret: "…"                    # Bearer / X-Mirai-Secret
    allow_from: ["*"]

Also useful agent features (Hermes bare-min):

mcp_servers:
  filesystem:
    command: npx
    args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]

Built-in tools added for parity: web_search, session_search, memory, delegate_task. Thin pre_tool / post_tool hooks live in mirai_agent.hooks.

Behavior notes:

  • Authorization — only allow_from chats reach the agent (webhook may use "*"). Match by ID or username; empty allowlist denies everyone.
  • Sessions — deterministic {platform}-{chat_id} rows in state.db.
  • Permissions — gateway defaults to read-only; opt in via gateway.permission_mode: auto or allowlists in permissions.json.
  • Process files under ~/.mirai-agent/: gateway.pid, gateway.lock, gateway_state.json.
  • Discord / Slack need the websockets package (mirai-agent[serve] / [all] / [dev]).
  • Deferred (not bare-min): email, Baileys WhatsApp, browser/vision/TTS, ACP, full dashboard — see docs/hermes-parity.md.

Distribution (Phase 5)

Docker (single-user self-host)

Image runs the web panel by default; compose profiles add headless serve and/or the messaging gateway. State is a volume at /data (MIRAI_AGENT_HOME). Non-loopback panel binds need MIRAI_PANEL_TOKEN.

cd agent
export MIRAI_API_KEY=mirai-…
export MIRAI_PANEL_TOKEN=$(openssl rand -hex 16)
docker compose up --build
# Panel: http://127.0.0.1:9200/?token=$MIRAI_PANEL_TOKEN

# Optional:
docker compose --profile serve up          # + :9199 JSON-RPC
docker compose --profile gateway up        # messaging daemon

Files: Dockerfile, docker-compose.yml. This is single-user self-host (your key, your volume) — not a multi-tenant cloud control plane.

Terminal users (PyPI)

Package name: mirai-agent — live on PyPI.

uv tool install "mirai-agent[all]"
# or:
pip install "mirai-agent[all]"

Then:

export MIRAI_API_KEY=mirai-…
mirai-agent                 # interactive CLI
mirai-agent panel           # localhost web UI (:9200)

Docker Compose is under Docker above. Helpers: scripts/install.sh / scripts/install.ps1.

Maintainers — publish a new version:

cd agent
uv build                         # or: bash scripts/publish.sh
uv publish                       # wheel + sdist under dist/

Desktop sidecar (PyInstaller)

Builds a onedir binary with [cli] + [serve] extras for Electron extraResources:

bash scripts/build_sidecar.sh    # macOS / Linux → dist/mirai-agent/mirai-agent
# Windows: .\scripts\build_sidecar.ps1 → mirai-agent.exe

Architecture is native to the builder (Apple Silicon arm64 on macos-14, x64 on windows-latest / ubuntu-latest). Spec: packaging/mirai-agent.spec. Staged copy lands in desktop/resources/mirai-agent/ for electron-builder.

See desktop/README.md for dmg / nsis / AppImage / deb, satuapps.com download hosting (tools/publish-desktop-artifacts.sh), and CI (.github/workflows/desktop.yml).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mirai_agent-0.1.1.tar.gz (189.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mirai_agent-0.1.1-py3-none-any.whl (185.7 kB view details)

Uploaded Python 3

File details

Details for the file mirai_agent-0.1.1.tar.gz.

File metadata

  • Download URL: mirai_agent-0.1.1.tar.gz
  • Upload date:
  • Size: 189.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for mirai_agent-0.1.1.tar.gz
Algorithm Hash digest
SHA256 93f4e0f986a8ef3c122b3e546bdb5b4f8ad9fa7918fd1a4b746007a0b07c2b9f
MD5 faa65251c11110f8456553a546821665
BLAKE2b-256 314ddcaecb869d0f7997e07dc842d0d218c4ee0e98236137ffce983e985f8b12

See more details on using hashes here.

File details

Details for the file mirai_agent-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: mirai_agent-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 185.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for mirai_agent-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 26c9f669f5b8a1b360fbd6d0d947e48de61d87c08da3b33e59bdcb351f699d50
MD5 a6f947332ee3803672a2bb315ac090dc
BLAKE2b-256 cc1f963c9bf09c949644f29e8fbc7458ee378becb4bf367600ca41012ba1c576

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page