oAI-Web - Personal AI Agent

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

Features

  • Chat interface - conversational UI via browser, with model selector
  • 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
  • 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
  • Audit log - every tool call logged, append-only
  • Multi-user - each user has their own credentials and settings

Requirements

  • Docker and Docker Compose
  • An API key from Anthropic and/or OpenRouter and/or OpenAI
  • A PostgreSQL-compatible host (included in the compose file)

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
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

mkdir -p data

3. Configure the environment

Edit .env - see the Environment Variables section below.

4. Pull and start

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 *.

AI Provider

# Which provider to use as default: anthropic | openrouter | openai
DEFAULT_PROVIDER=anthropic

# Override the default model (leave empty to use the provider's default)
# DEFAULT_MODEL=claude-sonnet-4-6

# Model pre-selected in the chat UI (leave empty to use provider default)
# DEFAULT_CHAT_MODEL=claude-sonnet-4-6

Your actual API keys are not set here - they are entered via the web UI under Settings - Credentials and stored encrypted in the database.


Security *

# 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

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

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

Agent Limits

# Maximum number of tool calls per agent run
MAX_TOOL_CALLS=20

# Maximum number of autonomous (scheduled/agent) runs per hour
MAX_AUTONOMOUS_RUNS_PER_HOUR=10

Both values can also be changed live from Settings - General without restarting.


Database *

# 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:

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.

## Identity

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

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

## 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:

## 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":

## People

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

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

## 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:

## 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
  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

Updating

docker compose pull
docker compose up -d

Pages

URL Description
/ Chat - send messages, select model, view tool activity
/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
/files Files - browse, download, and manage your personal data folder
/audit Audit log - filterable view of every tool call
/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 for the full license text, or visit gnu.org/licenses/agpl-3.0.

Author

Rune Olsen

Contributing

Contributions are welcome!


Star this project if you find it useful!

🐛 Found a bug? Open an issue

Description
A secure, self-hosted personal AI agent powered by Claude. Chat, email, calendar, files, Telegram and scheduled tasks — running on your own hardware. For Mac users also check out oAI for Mac @ https://iurl.no/macoai
https://jarvis.pm
Readme AGPL-3.0 3.5 MiB
Languages
Python 55%
HTML 22.8%
JavaScript 20.7%
CSS 1.4%
Dockerfile 0.1%