# AGENTS.md

## Project Overview

Memoh is a multi-member, structured long-memory, containerized AI agent system platform. Users can create AI bots and chat with them via Telegram, Discord, Lark (Feishu), Email, and more. Every bot has an independent container and memory system, allowing it to edit files, execute commands, and build itself — providing a secure, flexible, and scalable solution for multi-bot management.

## Architecture Overview

The system consists of three core services:

| Service | Tech Stack | Port | Description |
|---------|-----------|------|-------------|
| **Server** (Backend) | Go + Echo | 8080 | Main service: REST API, auth, database, container management |
| **Agent Gateway** | Bun + Elysia | 8081 | AI chat gateway: handles chat requests, tool execution, and SSE streaming |
| **Web** (Frontend) | Vue 3 + Vite | 8082 | Management UI: visual configuration for Bots, Models, Channels, etc. |

Infrastructure dependencies:
- **PostgreSQL** — Relational data storage
- **Qdrant** — Vector database for memory semantic search
- **Containerd** — Container runtime providing isolated environments per bot (Linux); Apple Virtualization on macOS

## Tech Stack

### Backend (Go)
- **Framework**: Echo (HTTP)
- **Dependency Injection**: Uber FX
- **Database Driver**: pgx/v5
- **Code Generation**: sqlc (SQL → Go)
- **API Docs**: Swagger/OpenAPI (swaggo)
- **Containers**: containerd v2 (Linux), Apple Virtualization (macOS)

### Agent Gateway & Agent Library (TypeScript)
- **Runtime**: Bun
- **Framework**: Elysia (gateway), Vercel AI SDK (agent core)
- **AI Providers**: Anthropic, OpenAI, Google (via Vercel AI SDK)
- **Tools**: MCP, Web Search, Subagent, Skill

### Frontend (TypeScript)
- **Framework**: Vue 3 (Composition API)
- **Build Tool**: Vite
- **State Management**: Pinia + Pinia Colada
- **UI**: Tailwind CSS 4 + custom component library (`@memoh/ui`) + Reka UI
- **i18n**: vue-i18n
- **Markdown**: markstream-vue + Shiki + Mermaid + KaTeX
- **Package Manager**: pnpm monorepo

### Tooling
- **Task Runner**: mise
- **Package Managers**: pnpm (frontend monorepo), Go modules (backend)
- **Linting**: ESLint + typescript-eslint + vue-eslint-parser
- **Testing**: Vitest
- **Typo Checker**: typos
- **Version Management**: bumpp
- **SDK Generation**: @hey-api/openapi-ts

## Project Structure

```
Memoh/
├── cmd/                        # Go application entry points
│   ├── agent/                  #   Main backend server (main.go)
│   ├── mcp/                    #   MCP server binary (stdio transport)
│   └── memoh/                  #   Unified binary wrapper (Cobra CLI)
├── internal/                   # Go backend core code (domain packages)
│   ├── accounts/               #   User account management (CRUD, password hashing)
│   ├── attachment/             #   Attachment normalization (MIME types, base64)
│   ├── auth/                   #   JWT authentication middleware and utilities
│   ├── bind/                   #   Channel identity-to-user binding code management
│   ├── boot/                   #   Runtime configuration provider (container backend detection)
│   ├── bots/                   #   Bot management (CRUD, lifecycle)
│   ├── bun/                    #   Bun runtime manager (agent gateway process lifecycle)
│   ├── channel/                #   Channel adapter system (Telegram, Discord, Feishu, Local, Email)
│   ├── config/                 #   Configuration loading and parsing (TOML)
│   ├── containerd/             #   Container runtime abstraction (containerd / Apple Virtualization)
│   ├── conversation/           #   Conversation management and flow resolver
│   ├── db/                     #   Database connection and migration utilities
│   │   └── sqlc/               #   ⚠️ Auto-generated by sqlc — DO NOT modify manually
│   ├── email/                  #   Email provider and outbox management (Mailgun, generic SMTP)
│   ├── embedded/               #   Embedded filesystem assets (web, agent, bun)
│   ├── embeddings/             #   Embedding model resolver
│   ├── handlers/               #   HTTP request handlers (REST API endpoints)
│   ├── healthcheck/            #   Health check adapter system (MCP, channel checkers)
│   ├── heartbeat/              #   Heartbeat scheduling service (cron-based)
│   ├── identity/               #   Identity type utilities (human vs bot)
│   ├── inbox/                  #   Bot inbox service (notifications, triggers)
│   ├── logger/                 #   Structured logging (slog)
│   ├── mcp/                    #   MCP protocol manager (container lifecycle, tool gateway)
│   ├── media/                  #   Content-addressed media asset service
│   ├── memory/                 #   Long-term memory system (Qdrant, BM25, LLM extraction)
│   ├── message/                #   Message persistence and event publishing
│   ├── models/                 #   LLM model management (CRUD, variants)
│   ├── policy/                 #   Access policy resolution (guest access, bot type)
│   ├── preauth/                #   Pre-authentication key management
│   ├── providers/              #   LLM provider management (OpenAI, Anthropic, etc.)
│   ├── prune/                  #   Text pruning utilities (truncation with head/tail)
│   ├── schedule/               #   Scheduled task service (cron)
│   ├── searchproviders/        #   Search engine provider management (Brave, etc.)
│   ├── server/                 #   HTTP server wrapper (Echo setup, middleware, shutdown)
│   ├── settings/               #   Bot settings management
│   ├── storage/                #   Storage provider interface (filesystem, container FS)
│   ├── subagent/               #   Sub-agent management (CRUD)
│   └── version/                #   Build-time version information
├── agent/                      # Agent Gateway service (Bun/Elysia)
│   └── src/
│       ├── index.ts            #   Elysia server entry point
│       ├── modules/            #   Route modules (chat, stream, trigger)
│       ├── middlewares/         #   CORS, error handling, bearer auth
│       ├── utils/              #   SSE utilities
│       └── models.ts           #   Zod request schemas
├── packages/                   # TypeScript monorepo
│   ├── agent/                  #   Core agent library (@memoh/agent)
│   │   └── src/
│   │       ├── agent.ts        #     Agent creation and streaming logic
│   │       ├── model.ts        #     Model configuration and creation
│   │       ├── tools/          #     Tool implementations (MCP, web, subagent, skill)
│   │       ├── prompts/        #     System/heartbeat/schedule/subagent prompts
│   │       ├── types/          #     TypeScript type definitions
│   │       └── utils/          #     Attachments, headers, filesystem utilities
│   ├── web/                    #   Main web app (@memoh/web, Vue 3)
│   ├── ui/                     #   Shared UI component library (@memoh/ui)
│   ├── sdk/                    #   TypeScript SDK (@memoh/sdk, auto-generated from OpenAPI)
│   ├── cli/                    #   CLI tool (@memoh/cli, Commander.js)
│   └── config/                 #   Shared configuration utilities (@memoh/config)
├── spec/                       # OpenAPI specifications (swagger.json, swagger.yaml)
├── db/                         # Database
│   ├── migrations/             #   SQL migration files
│   └── queries/                #   SQL query files (sqlc input)
├── conf/                       # Configuration templates
│   ├── app.example.toml        #   Default configuration template
│   ├── app.dev.toml            #   Development configuration
│   ├── app.docker.toml         #   Docker deployment configuration
│   ├── app.apple.toml          #   macOS (Apple Virtualization) configuration
│   └── app.windows.toml        #   Windows configuration
├── devenv/                     # Development environment (docker-compose for local infra)
├── docker/                     # Docker build & runtime (Dockerfiles, entrypoints, nginx)
├── docs/                       # Documentation site
├── scripts/                    # Utility scripts
├── assets/                     # Static assets (images, etc.)
├── data/                       # Runtime data directory
├── docker-compose.yml          # Docker Compose orchestration (production)
├── mise.toml                   # mise tasks and tool version definitions
├── sqlc.yaml                   # sqlc code generation config
├── openapi-ts.config.ts        # SDK generation config (@hey-api/openapi-ts)
├── bump.config.ts              # Version bumping config (bumpp)
├── vitest.config.ts            # Test framework config (Vitest)
├── tsconfig.json               # TypeScript monorepo config
├── eslint.config.mjs           # ESLint config
└── typos.toml                  # Typo checker config
```

## Development Guide

### Prerequisites

1. Install [mise](https://mise.jdx.dev/)
2. Install toolchains and dependencies: `mise install`
3. Initialize the project: `mise run setup`
4. Start the dev environment: `mise run dev`

### Common Commands

| Command | Description |
|---------|-------------|
| `mise run dev` | Start the containerized dev environment (all services) |
| `mise run dev:down` | Stop the dev environment |
| `mise run dev:logs` | View dev environment logs |
| `mise run dev:restart` | Restart a service (e.g. `-- server`) |
| `mise run setup` | Copy config + install dependencies |
| `mise run sqlc-generate` | Regenerate Go code after modifying SQL files |
| `mise run swagger-generate` | Generate Swagger documentation |
| `mise run sdk-generate` | Generate TypeScript SDK (depends on swagger-generate) |
| `mise run db-up` | Initialize and migrate the database |
| `mise run db-down` | Drop the database |
| `mise run build-embedded-assets` | Build and stage embedded web/agent/bun assets |
| `mise run build-unified` | Build unified memoh binary |
| `mise run release` | Release new version (bumpp) |
| `mise run release-binaries` | Build release archive for target (requires TARGET_OS TARGET_ARCH) |
| `mise run install-cli` | Install CLI locally |

### Docker Deployment

```bash
docker compose up -d        # Start all services
# Visit http://localhost:8082
```

## Key Development Rules

### Database, sqlc & Migrations

1. **SQL queries** are defined in `db/queries/*.sql`.
2. All Go files under `internal/db/sqlc/` are auto-generated by sqlc. **DO NOT modify them manually.**
3. After modifying any SQL files (migrations or queries), run `mise run sqlc-generate` to update the generated Go code.

#### Migration Rules

Migrations live in `db/migrations/` and follow a dual-update convention:

- **`0001_init.up.sql` is the canonical full schema.** It always contains the complete, up-to-date database definition (all tables, indexes, constraints, etc.). When adding schema changes, you must **also update `0001_init.up.sql`** to reflect the final state.
- **Incremental migration files** (`0002_`, `0003_`, ...) contain only the diff needed to upgrade an existing database. They exist for environments that already have the schema and need to apply only the delta.
- **Both must be kept in sync**: every schema change requires updating `0001_init.up.sql` AND creating a new incremental migration file.
- **Naming**: `{NNNN}_{description}.up.sql` and `{NNNN}_{description}.down.sql`, where `{NNNN}` is a zero-padded sequential number (e.g., `0005`). Always use the next available number.
- **Paired files**: Every incremental migration **must** have both an `.up.sql` (apply) and a `.down.sql` (rollback) file.
- **Header comment**: Each file should start with a comment indicating the migration name and a brief description:
  ```sql
  -- 0005_add_feature_x
  -- Add feature_x column to bots table for ...
  ```
- **Idempotent DDL**: Use `IF NOT EXISTS` / `IF EXISTS` guards (e.g., `CREATE TABLE IF NOT EXISTS`, `ADD COLUMN IF NOT EXISTS`, `DROP TABLE IF EXISTS`) so migrations are safe to re-run.
- **Down migration must fully reverse up**: The `.down.sql` must cleanly undo everything its `.up.sql` does, in reverse order.
- **After creating or modifying migrations**, run `mise run sqlc-generate` to regenerate the Go code, then `mise run db-up` to apply.

### API Development Workflow

1. Write handlers in `internal/handlers/` with swaggo annotations.
2. Run `mise run swagger-generate` to update the OpenAPI docs (output in `spec/`).
3. Run `mise run sdk-generate` to update the frontend TypeScript SDK (`packages/sdk/`).
4. The frontend calls APIs via the auto-generated `@memoh/sdk`.

### Agent Development

- The core agent logic lives in `packages/agent/` (`@memoh/agent`), providing reusable agent streaming, tool execution, and prompt management.
- The Agent Gateway (`agent/`) is a thin Elysia HTTP service that uses `@memoh/agent` for processing.
- AI model providers (Anthropic, OpenAI, Google) are integrated via Vercel AI SDK.
- Tools (MCP, web search, subagent, skill) are defined in `packages/agent/src/tools/`.
- Prompt templates (system, heartbeat, schedule, subagent) are in `packages/agent/src/prompts/`.

### Frontend Development

- Use Vue 3 Composition API with `<script setup>` style.
- Shared components belong in `packages/ui/`.
- API calls use the auto-generated `@memoh/sdk`.
- State management uses Pinia; data fetching uses Pinia Colada.
- i18n via vue-i18n.

### Container Management

- In Docker deployment, containerd runs inside the server container.
- On macOS, Apple Virtualization is used as container backend.
- Each bot has its own isolated container instance.

## Database Tables

| Table | Description |
|-------|-------------|
| `users` | User accounts (username, email, role, display_name, avatar) |
| `channel_identities` | Unified inbound identity subject (cross-platform) |
| `user_channel_bindings` | Outbound delivery config per user/channel |
| `llm_providers` | LLM provider configurations (name, base_url, api_key) |
| `search_providers` | Search engine provider configurations |
| `models` | Model definitions (chat/embedding types, modalities, reasoning) |
| `model_variants` | Model variant definitions (weight, metadata) |
| `bots` | Bot definitions with model references and settings |
| `bot_members` | Bot membership (owner/admin/member) |
| `mcp_connections` | MCP connection configurations per bot |
| `bot_channel_configs` | Per-bot channel configurations |
| `bot_preauth_keys` | Bot pre-authentication keys |
| `channel_identity_bind_codes` | One-time codes for channel identity → user linking |
| `bot_channel_routes` | Conversation route mapping (inbound thread → bot history) |
| `bot_history_messages` | Unified message history under bot scope |
| `bot_history_message_assets` | Message → content_hash asset links |
| `containers` | Bot container instances |
| `snapshots` | Container snapshots |
| `container_versions` | Container version tracking |
| `lifecycle_events` | Container lifecycle events |
| `schedule` | Scheduled tasks (cron) |
| `subagents` | Sub-agent definitions |
| `storage_providers` | Pluggable object storage backends |
| `bot_storage_bindings` | Per-bot storage backend selection |
| `bot_inbox` | Per-bot inbox (notifications, triggers) |
| `bot_heartbeat_logs` | Heartbeat execution records |
| `email_providers` | Pluggable email service backends (Mailgun, generic SMTP) |
| `bot_email_bindings` | Per-bot email provider binding with permissions |
| `email_outbox` | Outbound email audit log |

## Configuration

The main configuration file is `config.toml` (copied from `conf/app.example.toml` or environment-specific templates for development), containing:

- `[log]` — Logging configuration (level, format)
- `[server]` — HTTP listen address
- `[admin]` — Admin account credentials
- `[auth]` — JWT authentication settings
- `[containerd]` — Container runtime configuration (socket path, namespace)
- `[mcp]` — MCP image and data configuration
- `[postgres]` — PostgreSQL connection
- `[qdrant]` — Qdrant vector database connection
- `[agent_gateway]` — Agent Gateway address
- `[web]` — Web frontend address

Configuration templates available in `conf/`:
- `app.example.toml` — Default template
- `app.dev.toml` — Development (connects to devenv docker-compose)
- `app.docker.toml` — Docker deployment
- `app.apple.toml` — macOS (Apple Virtualization backend)
- `app.windows.toml` — Windows

## Web Design

Please refer to `./packages/web/AGENTS.md`.
