- Add agent_workspaces/{ilia,family,wife} skeletons (AGENTS, USER, SOUL, memory)
- Add scripts/init-agent-workspaces.sh to populate ~/.nanobot/workspaces/
- Mount ~/.nanobot/workspaces/{ilia,family,wife} in multi compose as /workspace
- Document Step 0 and layout in DOCKER_MULTI_BOT_GUIDE.md
- Track docs/mcp_and_skills_backlog.md (force-add; docs/ is gitignored)
Made-with: Cursor
Multi-bot compose mounts **separate** workspace directories so each bot has its own `AGENTS.md`, `SOUL.md`, `USER.md`, and `memory/` (no shared `./workspace`).
On the host, from the repo root:
```bash
./scripts/init-agent-workspaces.sh
```
This creates:
```
~/.nanobot/workspaces/
ilia/ # nanobot-user1 — dev / infra persona
family/ # nanobot-user2 — household persona
wife/ # nanobot-user3 — personal assistant persona
```
Templates live in-repo under `agent_workspaces/`. Re-run the script anytime: it **skips** files that already exist. Adjust ownership if Docker runs as root:
These directories are **templates** for per-agent workspaces on the host:
`~/.nanobot/workspaces/ilia/`
`~/.nanobot/workspaces/family/`
`~/.nanobot/workspaces/wife/`
Each contains bootstrap files (`AGENTS.md`, `USER.md`, `SOUL.md`) and `memory/` (`MEMORY.md`, `HISTORY.md`) loaded by nanobot’s `ContextBuilder` and `MemoryStore`.
**Role:** Primary operator of this nanobot stack; dev and infra.
## Edit this file
Add preferences, timezone, important contacts, repos, and anything this agent should remember about *you* (not generic assistant behavior — that belongs in `SOUL.md` / `AGENTS.md`).
| **Agent architecture** | 3 named agents, each running as a **separate Docker container** with its own workspace, personality, and memory (Option B). See below. |
| **Config schema** | `tools.mcpServers` → `MCPServerConfig` (stdio or HTTP), `tools.toolProfiles` → `ToolProfileConfig` can further filter tools within a single agent. See `nanobot/config/schema.py`. |
### Agent Workspaces
Each agent is a separate nanobot instance (Docker container) with an isolated workspace under `~/.nanobot/workspaces/`. The workspace contains bootstrap files (`AGENTS.md`, `SOUL.md`, `USER.md`) that define the agent's personality and instructions, plus a `memory/` directory for long-term memory that is private to that agent.
```
~/.nanobot/workspaces/
├── ilia/ # @ilia — personal dev, infra, research
│ ├── AGENTS.md # Dev/infra-focused instructions
│ ├── USER.md # Ilia's profile, preferences
│ ├── SOUL.md # Personality: technical, concise
│ └── memory/
│ └── MEMORY.md
├── family/ # @family — shared household agent
│ ├── AGENTS.md # Family scheduling, coordination
│ ├── USER.md # Family members, kids' info
│ ├── SOUL.md # Personality: warm, organized
│ └── memory/
│ └── MEMORY.md
└── wife/ # @wife — personal assistant for wife
├── AGENTS.md # Personal tasks, calendar, email
├── USER.md # Wife's profile, preferences
├── SOUL.md # Personality: friendly, helpful
└── memory/
└── MEMORY.md
```
Each container mounts its workspace and its own `config.json` (with agent-specific MCP servers, channels, and `allowFrom` lists). Compose service names are `nanobot-user1` … `user3`.
| Service | Persona | Config dir | Workspace (host → `/workspace`) | Typical channels |
- **Safety**: Phase 1 deploys with `PVEAuditor` role (read-only). Write operations (start/stop/snapshot) added in Phase 2 behind confirmation prompts. Restricted to `@ilia` profile only — never exposed to `@family`.
| **Augments** | Built-in `web_fetch` tool (which does basic HTTP GET without JS rendering) |
| **Target agents** | All three — `@ilia`, `@family`, `@wife` |
#### User stories
- **US-W1**: As `@ilia`, I can say "fetch the Proxmox release notes page and summarize what's new" and the agent renders the JS-heavy page and extracts content.
- **US-W2**: As `@family`, I can say "get the lunch menu from the school website" and the agent scrapes the dynamically loaded content.
- **US-W3**: As `@ilia`, I can say "grab the pricing table from this SaaS page" and get structured data back.
- **US-W4**: As `@wife`, I can say "find me the best-rated recipe for lasagna" and the agent fetches and summarizes real recipe pages.
- **Resource note**: Headless Chromium uses ~200–400 MB RAM per instance. Consider setting a process timeout or pool limit.
- **Safety**: Read-only by nature. No write side-effects. Safe for both `@ilia` and `@family`.
---
## Backlog — Later
Items below are future candidates, not yet scheduled. Grouped by domain. Each includes a candidate upstream project where one exists.
### Family / Life
| # | Integration | Upstream candidate | Notes |
|---|---|---|---|
| B-F1 | **CalDAV MCP** | `github.com/dominik1001/caldav-mcp` (Python, v0.4.0) | Universal calendar protocol. Enables Nextcloud, iCloud, ownCloud calendars. Useful if family moves off Google. |
| B-F2 | **Shared Todo / Household Tasks MCP** | `github.com/thijs-hakkenberg/mcp_todo` (Python, git-backed) | Git-backed collaborative task list with assignees, due dates, priorities, Kanban web UI, and Telegram bot. Good fit for family chores and grocery lists. |
| B-F3 | **Microsoft To Do MCP** | `github.com/akkilesh-a/microsoft-todo-mcp-server-self-hosted` (TypeScript) | Self-hosted HTTP transport. 15 tools for full task CRUD. Only relevant if family adopts Microsoft ecosystem. |
| B-F4 | **Home Assistant MCP** | TBD (community projects emerging) | Smart home control — lights, thermostat, locks, sensors. Requires Home Assistant instance on LAN. |
| B-F5 | **Shared Documents MCP** | TBD (Nextcloud WebDAV or Google Drive MCP) | Access family shared documents, photos, notes from chat. |
### Research
| # | Integration | Upstream candidate | Notes |
|---|---|---|---|
| B-R1 | **PDF RAG MCP** | `github.com/wesleygriffin/pdfrag` (Python, ChromaDB + sentence-transformers) | Semantic search over PDF papers. OCR support for scanned docs. Persistent vector index. |
| B-D5 | **Backup Status MCP** | TBD (Proxmox Backup Server API or restic wrapper) | Check last backup timestamps, success/failure, storage usage. Could be a thin wrapper skill rather than full MCP. |
| B-D6 | **Database MCP** | TBD (PostgreSQL / SQLite MCP servers exist) | Run read-only queries against app databases for debugging and reporting. |
---
## Skill Catalog
Skills are higher-level task patterns that compose one or more tools (built-in or MCP) into a reusable workflow. Each skill lives as a `SKILL.md` in `nanobot/skills/<name>/` and is loaded by the skills system.
Because agents are **separate containers with separate workspaces**, a skill is available to an agent only if (a) the skill file is present in that workspace's `skills/` dir or in the shared bundled skills, and (b) the MCP servers it depends on are configured in that agent's `config.json`.
### Legend
| Column | Meaning |
|---|---|
| **Skill** | Natural-language trigger name |
| **Description** | What the skill does |
| **MCP deps** | Which MCP servers must be connected in the agent's config |
| **Built-in deps** | Which nanobot built-in tools are also needed |
| **Target agents** | Which agent containers should have this skill deployed (`@ilia`, `@family`, `@wife`) |
| **Safety tier** | `read-only` / `write-confirm` (mutates after user confirmation) / `admin` (restricted + confirm) |
| **Plan my week** | List events across all calendars for the next 7 days, highlight conflicts, suggest time blocks for focus work | Google Calendar MCP | — | `@ilia`, `@family`, `@wife` | read-only |
| **Reschedule meeting** | Find a specific event, propose 3 alternative conflict-free times, update the event after user picks one | Google Calendar MCP | — | `@ilia`, `@wife` | write-confirm |
| **Find conflict-free times** | Query free/busy across calendars for a given duration and date range, return available slots | Google Calendar MCP | — | `@ilia`, `@family`, `@wife` | read-only |
| **Draft replies** | For each action-required email, generate a draft reply. Present drafts for user approval before sending | Gmail MCP | — | `@ilia`, `@wife` | write-confirm |
| **Summarize today's mail** | Produce a concise digest of all emails received today, grouped by sender or topic | Gmail MCP | `read_emails` | `@ilia`, `@family`, `@wife` | read-only |
| **Find relevant papers** | Web-search for papers on a given topic, fetch top results, return title + abstract + URL for each | Web Fetch MCP | `web_search` | `@ilia` | read-only |
| **Summarize URL/PDF** | Fetch a URL (with JS rendering if needed) or read a local PDF, produce a structured summary | Web Fetch MCP | `read_file` | `@ilia`, `@family`, `@wife` | read-only |
| **Generate experiment checklist** | Given a goal description, produce a structured checklist of steps, tools needed, and success criteria | — | — | `@ilia` | read-only |
| **Show VM status** | List all VMs/containers across Proxmox nodes with state, CPU%, RAM%, and uptime | Proxmox MCP | — | `@ilia` | read-only |
| **Restart non-critical service** | Stop and start a VM by name, but only if it is tagged `non-critical`. Refuse if tagged `critical`. Requires confirmation | Proxmox MCP | — | `@ilia` | admin |
| **Summarize cluster resources** | Aggregate CPU, RAM, and storage usage across all Proxmox nodes, flag any node above 80% utilization | Proxmox MCP | — | `@ilia` | read-only |
| **Pre-upgrade snapshot** | Before a maintenance window, create a named snapshot of specified VMs. Requires confirmation | Proxmox MCP | — | `@ilia` | admin |
| **Summarize open PRs** | List all open PRs on the nanobot repo with title, author, age, review status, and CI state | Gitea MCP | — | `@ilia` | read-only |
| **Triage Gitea issues** | Fetch open issues, group by label, suggest priority ordering based on age and activity | Gitea MCP | — | `@ilia` | read-only |
| **Search codebase** | Search Gitea-hosted code for a symbol or string pattern, return matching files and line numbers | Gitea MCP | — | `@ilia` | read-only |
| **Create issue from chat** | Turn a conversation excerpt into a well-formatted Gitea issue with title, description, and labels. Requires confirmation | Gitea MCP | — | `@ilia` | write-confirm |
---
## Phase 1 Priorities
These are the items we commit to implementing first, chosen for maximum daily value with manageable complexity.
### Phase 1 MCP Integrations
| Priority | MCP Server | Rationale |
|---|---|---|
| **P1** | **Gitea MCP** | Directly replaces fragile curl-based Gitea access scattered across `AGENTS.md` and the `gitea` skill. Token and network route already exist. Aligns with daily dev workflow — PRs, issues, code search are used every day. |
| **P2** | **Google Calendar MCP** | Complements the existing built-in `calendar` tool with multi-calendar views and free/busy queries. OAuth is already a solved pattern from Gmail MCP. Deployed to all three agents — `@ilia` (work calendar), `@family` (shared family calendar), `@wife` (personal calendar). |
| **P3** | **Proxmox MCP** | Homelab infrastructure is checked frequently but currently requires opening the Proxmox web UI. Starting with read-only (`PVEAuditor`) makes it safe to deploy immediately. Write ops follow in a later phase. |
### Phase 1 Skills
| Priority | Skill | MCP dep | Agents | Safety | Why first |
| **S2** | Plan my week | Google Calendar MCP | `@ilia`, `@family`, `@wife` | read-only | High value for every agent; validates Calendar MCP |
| **S3** | Triage inbox | Gmail MCP (already live) | `@ilia`, `@wife` | read-only | Formalizes an existing ad-hoc pattern; no new MCP needed |
| **S4** | Show VM status | Proxmox MCP | `@ilia` | read-only | Safe first infra skill; validates Proxmox MCP |
| **S5** | Summarize today's mail | Gmail MCP (already live) | `@ilia`, `@family`, `@wife` | read-only | Daily value for all agents; no new MCP needed |
cd fetch-browser && npm install && npm run build && cd ..
```
To update a server: `cd mcp-servers/<name> && git pull && <rebuild>`. Pin to a known-good commit with `git checkout <sha>` for production stability.
### Per-agent MCP wiring
Since each agent is a separate Docker container, MCP servers are configured in each agent's own `config.json`. An agent only gets the MCP servers listed in its config -- no routing needed.
**`~/.nanobot-user1/config.json`** (@ilia — all MCP servers):
- `@family` and `@wife` never see Gitea or Proxmox tools -- those MCP servers are simply absent from their configs.
- `@family` has no email MCP (it's a shared household bot, not tied to one inbox). It still has the built-in `calendar` and `web` tools.
- Each container spawns its own MCP server processes via stdio from the shared `mcp-servers/` directory (mounted read-only into all containers).
### Safety tiers
| Tier | Behavior | Implementation |
|---|---|---|
| **read-only** | Tool executes immediately, no confirmation prompt | Default for query/list/search operations |
| **write-confirm** | Agent presents a summary of what it will do, waits for user "yes" before executing | Enforced in SKILL.md instructions: "Before calling `create_event`, show the user the details and ask for confirmation" |
| **admin** | Same as write-confirm but tool is only available in the `@ilia` container | Enforced by omitting the MCP server from other agents' `config.json` + SKILL.md confirmation instructions |
With separate containers, the strongest security boundary is **not configuring an MCP server at all** in an agent's config. Proxmox and Gitea are never in `@family` or `@wife` configs, so those agents physically cannot call those tools.
Phase 1 deploys **only read-only skills**. Write skills (draft replies, reschedule meeting, create issue, restart VM) are Phase 2 once we validate the read paths.
### Skill file template
New skills follow the existing format in `nanobot/skills/`:
```markdown
---
name: summarize-open-prs
description: "List and summarize all open pull requests on the nanobot Gitea repo."
User asks about open PRs, pending reviews, or code review status.
## Steps
1. Call `mcp_gitea_list_pulls` with state=open.
2. For each PR, extract: title, author, created date, review status, CI status.
3. Format as a numbered list sorted by age (oldest first).
4. Highlight PRs with no reviews or failing CI.
## Safety
Read-only. No confirmation needed.
```
### Docker considerations
All three containers (`nanobot-user1`, `nanobot-user2`, `nanobot-user3`) share the same Docker image. MCP server processes are spawned inside each container as needed. The Dockerfile must include:
- **Node.js 18+** (for Calendar MCP and Fetch Browser)
- **Python pip deps** (for Proxmox MCP — install into the same venv or a sidecar)
- **Chromium** (for Fetch Browser headless rendering — `npx puppeteer browsers install chrome` or use Playwright)
The `mcp-servers/` directory is mounted read-only into all containers so each agent can spawn the MCP servers listed in its config. Alternatively, build MCP binaries in a multi-stage Docker build and copy only the artifacts into the image.
Week 6: Retrospective, update this document, plan Phase 2 write-skills
```
---
## Changelog
| Date | Change |
|---|---|
| 2026-03-30 | Updated to reflect multi-container workspace architecture (Option B). Added `@wife` as third agent. Rewrote per-agent MCP wiring with separate config.json per container. Updated skill assignments across all three agents. |
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.