# oAI-Web - Personal AI Agent

A secure, self-hosted personal AI agent. Handles calendar, email, files, web research, Telegram, and more - controlled by you, running on your own hardware.

## Features

- **Chat interface** - conversational UI via browser, with model selector and markdown rendering
- **CalDAV** - read and write calendar events (per-user credentials, configured in Settings)
- **CardDAV / Contacts** - search and manage contacts from your CardDAV server
- **Email** - read inbox, send replies (whitelist-managed recipients)
- **Filesystem** - read/write files in your personal data folder
- **Web access** - tiered: whitelisted domains always allowed, others on request
- **Browser** - headless Chromium via Playwright; fetch pages, take screenshots, click, fill forms, and interact with web UIs (full image only)
- **Push notifications** - Pushover for iOS/Android (set your own User Key in Settings)
- **Telegram** - send and receive messages via your own bot
- **Webhooks** - trigger agents from external services (iOS Shortcuts, GitHub, Home Assistant, etc.)
- **Monitors** - page-change and RSS feed monitors that dispatch agents automatically
- **Scheduled tasks** - cron-based autonomous tasks with declared permission scopes
- **Agents** - goal-oriented runs with model selection and full run history
- **2nd Brain** - personal semantic memory powered by pgvector; capture and search thoughts across sessions
- **MCP Servers** - connect external Model Context Protocol servers and expose their tools to your agents
- **Image generation** - generate images via your configured provider
- **Audit log** - every tool call logged, append-only
- **Multi-user** - each user has their own credentials and settings
- **PWA** - installable on iOS and Android home screens; mobile-optimised layout

---

## Docker Images

Four pre-built images are available. Choose the one that matches your architecture and whether you need the browser tool.

| Image | Architecture | Browser tool |
|-------|-------------|--------------|
| `image.gitlab.pm/rune/oai-web:latest` | amd64 | Yes |
| `image.gitlab.pm/rune/oai-web:latest-no-browser` | amd64 | No |
| `image.gitlab.pm/rune/oai-web:latest_arm64` | arm64 | Yes |
| `image.gitlab.pm/rune/oai-web:latest-no-browser_arm64` | arm64 | No |

**Full image** includes Playwright and a Chromium installation. This adds roughly 350 MB to the image size but enables the browser tool - the agent can fetch pages, take screenshots, click elements, fill forms, and navigate web UIs on your behalf.

**No-browser image** is leaner and faster to pull. All other tools and features are identical. Choose this if you don't need the agent to interact with web pages directly, or if you are constrained on disk space.

---

## Requirements

- Docker and Docker Compose
- An API key from [Anthropic](https://console.anthropic.com) and/or [OpenRouter](https://openrouter.ai) and/or [OpenAI](https://openai.com)
- A PostgreSQL-compatible host (included in the compose file)

---

## Documentation

There is a [documentation site](https://docs.jarvis.pm) with in-depth information on the project.

## Installation

### 1. Get the files

Download or copy these files into a directory on your server:

- `docker-compose.example.yml` - rename to `docker-compose.yml`
- `.env.example` - rename to `.env`
- `SOUL.md.example` - rename to `SOUL.md`
- `USER.md.example` - rename to `USER.md`

```bash
cp docker-compose.example.yml docker-compose.yml
cp .env.example .env
cp SOUL.md.example SOUL.md
cp USER.md.example USER.md
```

### 2. Create the data directory

```bash
mkdir -p data
```

### 3. Configure the environment

Edit `.env` - see the [Environment Variables](#environment-variables) section below.

### 4. Pull and start

```bash
docker compose pull
docker compose up -d
```

Open `http://<your-server-ip>:8080` in your browser.

On first run you will be taken through a short setup wizard to create your admin account.

---

## Environment Variables

Open `.env` and fill in the values. Required fields are marked with `*`.

### Security *

```env
# Master password for the encrypted credential store.
# All your API keys, passwords, and secrets are encrypted with this.
# Choose a strong passphrase and keep it safe - if lost, credentials cannot be recovered.
DB_MASTER_PASSWORD=change-me-to-a-strong-passphrase
```

---

### Server

```env
# Port the web interface listens on (default: 8080)
PORT=8080

# Timezone for display - dates are stored internally as UTC
TIMEZONE=Europe/Oslo
```

---

### Database *

```env
# Main application database
AIDE_DB_URL=postgresql://aide:change-me@postgres:5432/aide

# 2nd Brain database password (pgvector)
BRAIN_DB_PASSWORD=change-me-to-a-strong-passphrase

# Brain connection string - defaults to the bundled postgres service
BRAIN_DB_URL=postgresql://brain:${BRAIN_DB_PASSWORD}@postgres:5432/brain

# Access key for the Brain MCP endpoint (generate with: openssl rand -hex 32)
BRAIN_MCP_KEY=
```

Change the `change-me` passwords in `AIDE_DB_URL` and `BRAIN_DB_PASSWORD` to something strong. They must match - if you change `BRAIN_DB_PASSWORD`, the same value is substituted into `BRAIN_DB_URL` automatically.

---

## Personalising the Agent

### SOUL.md - Agent identity and personality

`SOUL.md` defines who your agent is. The name is extracted automatically from the first line matching `You are **Name**`.

Key sections to edit:

**Name** - change `Jarvis` to whatever you want your agent to be called:
```markdown
You are **Jarvis**, a personal AI assistant...
```

**Character** - describe how you want the agent to behave. Be specific. Examples:
- "You are concise and avoid unnecessary commentary."
- "You are proactive - if you notice something relevant while completing a task, mention it briefly."
- "You never use bullet points unless explicitly asked."

**Values** - define what the agent should prioritise:
- Privacy, minimal footprint, and transparency are good defaults.
- Add domain-specific values if relevant (e.g. "always prefer open-source tools when suggesting options").

**Language** - specify language behaviour explicitly:
- "Always respond in the same language the user wrote in."
- "Default to Norwegian unless the message is in another language."

**Communication style** - tune the tone:
- Formal vs. casual, verbose vs. terse, proactive vs. reactive.
- You can ban specific phrases: "Never start a response with 'Certainly!' or 'Of course!'."

The file is mounted read-only into the container. Changes take effect on the next `docker compose restart`.

---

### USER.md - Context about you

`USER.md` gives the agent background knowledge about you. It is injected into every system prompt, so keep it factual and relevant - not a biography.

**Identity** - name, location, timezone. These help the agent interpret time references and address you correctly.

```markdown
## Identity

- **Name**: Jane
- **Location**: Oslo, Norway
- **Timezone**: Europe/Oslo
```

**Language preferences** - if you want to override SOUL.md language rules for your specific case:

```markdown
## Language

- Respond in the exact language the user's message is written in.
- Do not assume Norwegian because of my location.
```

**Professional context** - role and responsibilities the agent should be aware of:

```markdown
## Context and background

- Works as a software architect
- Primarily works with Python and Kubernetes
- Manages a small team of three developers
```

**People** - names and relationships. Helps the agent interpret messages like "send this to my manager":

```markdown
## People

- [Alice Smith] - Manager
- [Bob Jones] - Colleague, backend team
- [Sara Lee] - Partner
```

**Recurring tasks and routines** - anything time-sensitive the agent should know about:

```markdown
## Recurring tasks and routines

- Weekly team standup every Monday at 09:00
- Monthly report due on the last Friday of each month
```

**Hobbies and interests** - optional, but helps the agent contextualise requests:

```markdown
## Hobbies and Interests

- Photography
- Self-hosting and home lab
- Cycling in summer
```

The file is mounted read-only into the container. Changes take effect on the next `docker compose restart`.

---

## Your Settings

After logging in, go to **Settings** to configure your personal services. Each user has their own credentials - nothing is shared with other users.

### CalDAV / CardDAV

Set up your personal calendar and contacts server under **Settings - CalDAV / CardDAV**:

- Enter your server URL (e.g. `mail.example.com`), username, and password
- Optionally specify a calendar name (leave blank for the default calendar)
- For CardDAV (contacts): tick *Same server as CalDAV* to reuse your credentials, or enter separate details
- Use the **Test** buttons to verify your connection before saving
- Enable **Allow contact writes** if you want agents to be able to create and update contacts

There is no system-wide fallback - if you don't configure it, calendar and contacts tools won't be available to your agents.

### Pushover

To receive push notifications on your iOS or Android device:

1. Create a free account at [pushover.net](https://pushover.net)
2. Copy your **User Key** from the dashboard
3. Go to **Settings - Pushover** and save your User Key

The app is already registered by your admin - you only need your own User Key.

### Webhooks

Create inbound webhooks under **Settings - Webhooks** to trigger your agents from external services:

- Assign a name and target agent, then copy the secret token shown at creation (it's shown only once)
- **POST trigger**: send `{"message": "your message"}` to `/webhook/{token}`
- **GET trigger**: visit `/webhook/{token}?q=your+message` - ideal for iOS Shortcuts URL actions
- Enable or disable webhooks without deleting them

### Telegram

Set your personal bot token under **Settings - Telegram** (or **Settings - Profile - Telegram Bot Token**) if you want your own Telegram bot. Your chat ID must be whitelisted by the admin before messages are processed.

### Email Accounts

Set up your own email accounts under **Settings - Email Accounts**:

- **Trigger account** - dispatches agents based on keyword rules in incoming emails
- **Handling account** - a dedicated AI agent reads and handles each incoming email

### Browser - Trusted Domains

When the agent uses the browser tool to interact with a page (clicking, filling forms), it will ask for confirmation unless the domain is pre-approved. Add trusted domains under **Settings - Browser** to skip the confirmation prompt for those sites.

---

## Updating

```bash
docker compose pull
docker compose up -d
```

---

## Pages

| URL | Description |
|-----|-------------|
| `/` | Chat - send messages, select model, view tool activity |
| `/chats` | Chat history - browse and resume past conversations |
| `/tasks` | Scheduled tasks - cron-based autonomous tasks |
| `/agents` | Agents - goal-oriented runs with model selection and run history |
| `/monitors` | Monitors - page-change watchers and RSS feed monitors |
| `/models` | Model browser - all available models, capabilities, and pricing |
| `/files` | Files - browse, view, and manage your personal data folder |
| `/audit` | Audit log - filterable view of every tool call |
| `/usage` | Usage and costs - token usage and cost tracking across runs |
| `/settings` | Your personal settings: CalDAV, CardDAV, Pushover, Webhooks, Telegram, Email Accounts, and more |

---

## License

oAI is free software licensed under the **GNU Affero General Public License v3.0 (AGPL-3.0)**.

This means you are free to use, study, modify, and distribute oAI, but any modified version you run as a network service must also be made available as free software under the same license.

See [LICENSE](LICENSE) for the full license text, or visit [gnu.org/licenses/agpl-3.0](https://www.gnu.org/licenses/agpl-3.0.html).

## Author

**Rune Olsen**

- Website: https://jarvis.pm
- Blog: [https://blog.rune.pm](https://blog.rune.pm)
- Gitlab.pm: [@rune](https://gitlab.pm/rune)

## Contributing

Contributions are welcome!

---

## Disclaimer

oAI-Web takes real actions on your behalf - it can send emails, write files, make calendar changes, post Telegram messages, and interact with web pages. Review your whitelist and permission settings carefully before use. Content you send is processed by your configured AI provider (Anthropic, OpenRouter, or OpenAI). oAI-Web is provided "as is" without warranty of any kind - the author accepts no responsibility for actions taken by the agent or any consequences thereof. See LICENSE for full terms.

---

**Star this project if you find it useful!**

**Found a bug?** [Open an issue](https://gitlab.pm/rune/oai-web/issues/new)
