Skip to main content

Local first personal AI agent powered by the Mirai cloud API

Project description

Mirai Agent

A local first 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 is one agent core with thin I/O shells.

Docs on the website

Install, quickstart, config, skills, and gateway notes (en and 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.
  • Core agent capabilities: MCP client, delegate_task, web_search (DuckDuckGo, no API key), browser, session_search, memory tools, thin pre and post tool hooks plus session and turn plugins. See docs/feature-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, browser, memory,
│   │                         # session_search, skill_view, delegate_task,
│   │                         # vision_understand, speech_*) + MCP client
│   ├── hooks.py              # pre/post tool + session/turn/error hooks
│   ├── extensions/           # plugins loader + speech provider 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, email IMAP
└── tests/                    # pytest, fully mocked, no real API calls

Feature parity notes: docs/feature-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:

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

Built-in tools for parity: web_search (DuckDuckGo, no API key), browser (open and links), fetch_url, session_search, memory, delegate_task, plus optional vision_understand and speech_* (off until enabled). Hooks: pre_tool and post_tool plus session, turn, and error events. Plugins: drop flat *.py or folders with plugin.json into ~/.mirai-agent/plugins/ (see examples/plugins/). Panel Plugins tab lists, enables, and reloads them.

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 and Slack need the websockets package (mirai-agent[serve] / [all] / [dev]).
  • Email IMAP: gateway.email with provider presets (gmail, yahoo, hotmail, outlook, custom), app passwords, IMAP poller with IDLE when available, and SMTP replies. Panel: POST /api/gateways/email/test.
  • Optional: vision (vision.enabled), speech providers (speech.enabled), WhatsApp Baileys via Extras download. See docs/feature-parity.md. Out of scope: Matrix, Signal, Teams.

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 and scripts/install.ps1.

Maintainers, publish a new version:

cd agent
# bump version in pyproject.toml + src/mirai_agent/__init__.py
uv build                         # or: bash scripts/publish.sh
uv publish                       # needs UV_PUBLISH_TOKEN / PyPI API token

0.1.2 adds Bugbot gateway and plugin unload fixes. PyPI still serves 0.1.1 until uv publish runs with a token. Desktop installers on https://github.com/satuapps/mirai-releases/releases/latest ship the bundled sidecar; rebuild desktop after bumping so Win/Linux users get 0.1.2.

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, GitHub Releases hosting on mirai-releases (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.2.tar.gz (226.4 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.2-py3-none-any.whl (223.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: mirai_agent-0.1.2.tar.gz
  • Upload date:
  • Size: 226.4 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.2.tar.gz
Algorithm Hash digest
SHA256 06ab4cbedf627e05903add82add7bf381d514b776a8ad2bec7554599a993e6e7
MD5 0f69e73841b749dbc7e20dbfd0e61adc
BLAKE2b-256 f094a7c15809f4c06abf0c248e8c098b3a90fad3b86712d64ed392640cc0edf2

See more details on using hashes here.

File details

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

File metadata

  • Download URL: mirai_agent-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 223.0 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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 543021cb5f7d2c537fdda516a3f9572f115daffb627392645fb184e6e9af0576
MD5 f77c3abd06a66bdda791117c5eb47398
BLAKE2b-256 04722d498a5f788117a26cdac10580a9ac13c2ade4678f63df8c70146d0d8492

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