Anima/docs/superpowers/specs/2026-04-12-anima-system-design.md
Till Wegmueller 4ec0a366eb
Add Anima system design spec
Comprehensive design covering service architecture (anima-server,
anima-mail, anima-agent, anima-ai, anima-desktop), domain model,
gRPC API, Slint desktop client, mail integration via Stalwart/JMAP,
agent VM lifecycle, embedded MCP server, RBAC, and crate structure.
2026-04-12 01:00:55 +02:00

22 KiB

Anima System Design

Date: 2026-04-12 Status: Draft Author: Till Wegmueller + Claude

Overview

Anima is a strategic work coordination platform for developers who manage projects, AI agents, and collaborative workflows. It is not an IDE — it is the command post layer above, where you assign work, track AI progress, manage discussions (including email threads), and surface documentation.

The system is server-authoritative. The desktop client is a terminal into the command post — it caches for responsiveness but does not own data.

Service Architecture

Services

Service Role Runtime
anima-server Core API + embedded MCP server. Projects, work items, plans, workflows, teams, settings, RBAC. gRPC for desktop client. Forge integration. Seshat's Library client. Rust binary, always running
anima-mail Polls Stalwart via JMAP, routes inbound mail to work item threads, sends outbound mail on behalf of work items. Creates/manages mailboxes via Stalwart admin API. Rust binary, async worker
anima-agent v1: Single-agent manager. Provisions VM/container, deploys skills, manages agent lifecycle. Interface designed for future multi-provider orchestration. Rust binary, on-demand
anima-ai Light AI inference — summaries, gap analysis triggers, thread updates, description generation, mail classification. Stateless, horizontally scalable. Rust binary, scalable
anima-desktop Slint desktop client. gRPC to anima-server. Caches for responsiveness, doesn't own data. Slint/Rust app

External Dependencies

Dependency Purpose
PostgreSQL Primary relational store
Stalwart Mail server (JMAP + admin API + plus-addressing)
Seshat's Library Document library, vector search (pgvector), blob storage for files/patches/attachments
Forge APIs GitHub/Gitea/GitLab — PR metadata, issue migration, read-only

Data Flow

Desktop ──gRPC──► anima-server ──SQL──► PostgreSQL
                      │  ╰── MCP (embedded)
                      ├──► Seshat's Library (docs, vectors, blobs)
                      ├──► anima-mail ──JMAP──► Stalwart
                      ├──► anima-ai (light inference, N instances)
                      ├──► anima-agent ──► VM/Container
                      └──► Forge APIs (read-only)

AI in VM ──MCP──► anima-server (scoped token, work item context only)

Domain Model

Entities

Project

  • Name, description, status (active/archived)
  • Has many Plans, Work Items, Repositories, Mailboxes
  • Links to team members with roles via RBAC

Plan

  • Belongs to a Project
  • Title, description, progress (derived from child work items)
  • Has many Work Items
  • Phases derived from its Workflow

Work Item

  • Belongs to a Project, optionally to a Plan
  • Title, description (versioned — every update creates a new revision, revertable), status, priority
  • Follows a Workflow (determines phases and required AI skills)
  • Has a Discussion Thread (messages, email attachments, AI/Akh contributions)
  • Has Patches/PRs (attachments, linked to forge PRs)
  • Has Documents (stored in Seshat's Library)
  • Has many Agent Sessions (long-running, parallel or sequential)
  • Has Capabilities (derived from what the work needs — repo access, API keys, network zones). Agent sessions inherit these.
  • Phase tracking within its workflow

Workflow

  • Template defining phases (e.g., Analysis → Implementation → Review & Audit)
  • Each phase declares required AI Skills
  • Ships with defaults, user-customizable
  • Future: marketplace for sharing

Discussion Thread

  • Belongs to a Work Item
  • Ordered messages from: humans, AI (via Akh), email (inbound/outbound)
  • AI contributions are promotable to update work item description (creates new revision)
  • Email messages carry headers linking back to work item via plus-addressing

Agent Session

  • Belongs to a Work Item (many sessions per work item)
  • Represents heavy work running in a VM/container
  • Status (provisioning, running, paused, completed, failed)
  • Has Tasks (sub-units of work within the session)
  • Skills deployed, capabilities inherited from work item
  • Akh identity configured (persona for thread contributions)
  • Long-running once started, persists while work item is open
  • Admins can login (SSH) to inspect/debug — audit logged

Akh

  • AI persona/identity from the Akh domain
  • Agents assume an Akh when writing in discussion threads
  • Gives AI contributions a consistent voice and attribution

Repository

  • Belongs to a Project
  • Forge type (GitHub/Gitea/GitLab), remote URL
  • Has Worktrees (checked-out branches, managed by agents in VMs)
  • PRs/patches linked to Work Items

Document

  • Stored in Seshat's Library (blob + vector embedding)
  • Linked to Project and/or Work Item
  • Types: markdown, text, patches, attachments
  • Searchable by AI via vector queries

Team Member

  • User identity, role bindings per project (via RBAC)
  • Settings, notification preferences

Mailbox

  • Belongs to one or more Projects (no global unattached box)
  • A "gather" mailbox is one linked to multiple projects
  • Managed via Stalwart admin API
  • Plus-address routing rules

Relationships

Project ─┬─► Plans ──► Work Items ─┬─► Discussion Thread (messages, emails, Akh-authored)
         │                         ├─► Patches/PRs
         ├─► Repositories          ├─► Agent Sessions (many, long-running, loginable)
         ├─► Team Members          │     └─► Tasks
         └──►┐                     ├─► Documents (→ Seshat's Library)
     Mailboxes (shared across      ├─► Capabilities (derived, inherited by sessions)
      multiple projects)           ├─► Description Revisions (versioned, revertable)
                                   └─► Workflow (phases, skills)

Akh ──► identity assumed by AI in discussions

gRPC API Design

Public Services (desktop client, embedded MCP)

ProjectService

  • ListProjects, GetProject, CreateProject, UpdateProject, ArchiveProject
  • ListProjectMembers, AddProjectMember, RemoveProjectMember

PlanService

  • ListPlans, GetPlan, CreatePlan, UpdatePlan, DeletePlan

WorkItemService

  • ListWorkItems, GetWorkItem, CreateWorkItem, UpdateWorkItem, DeleteWorkItem
  • GetDescriptionRevisions, RevertDescription — versioned description management
  • ListCapabilities, UpdateCapabilities — derived capabilities attached to work items

WorkflowService

  • ListWorkflows, GetWorkflow, CreateWorkflow, UpdateWorkflow, DeleteWorkflow
  • Ships with built-in defaults, user workflows stored alongside

ThreadService

  • GetThread, PostMessage, PromoteMessage — promote AI message to update work item description (creates new revision)
  • StreamThread — server-streaming RPC for live thread updates

AgentSessionService

  • ListSessions, GetSession, StartSession, StopSession
  • LoginSession — returns connection info for admin SSH/shell access
  • ListTasks, GetTask, UpdateTaskStatus
  • StreamSessionStatus — server-streaming for live status

RepositoryService

  • ListRepositories, AddRepository, RemoveRepository
  • ListPatches, AttachPatch — link forge PRs to work items

MailboxService

  • ListMailboxes, CreateMailbox, DeleteMailbox
  • LinkProjects, UnlinkProjects — manage which projects a mailbox serves

DocumentService

  • ListDocuments, GetDocument, UploadDocument, DeleteDocument
  • Delegates storage to Seshat's Library

AkhService

  • ListAkhs, GetAkh, CreateAkh, UpdateAkh, DeleteAkh

TeamService

  • ListUsers, GetUser, CreateUser, UpdateUser, DeleteUser
  • Roles and permissions per project via RBAC

DashboardService

  • GetDashboard — aggregated view: pending decisions, active sessions, work item status across projects
  • StreamDashboardUpdates — live updates

Internal Services (not exposed to desktop)

AnimaAiService (anima-server → anima-ai)

  • Summarize, AnalyzeGap, GenerateDescription, ClassifyMail

AgentProviderService (anima-server → anima-agent)

  • ProvisionVM, DestroyVM, DeploySkills, GetVMStatus, GetLoginCredentials

API Patterns

  • Streaming for anything real-time: threads, agent sessions, dashboard
  • Pagination via cursor-based tokens on all List RPCs
  • Field masks on Update RPCs for partial updates
  • Standard error model with domain-specific error codes

Desktop Client (anima-desktop)

Technology

  • Slint for UI rendering (native, cross-platform: macOS, Wayland, X11, Windows)
  • Rust for all client logic
  • tonic gRPC client for server communication
  • Local SQLite cache for responsiveness (read cache, server is source of truth)

Screen Map

Screen Purpose Key Data
Dashboard Morning command view. Pending human decisions, active agent sessions, work item status summaries. DashboardService
Project List Grid/list of all projects with status, stats, AI activity indicators. ProjectService
Project Detail Plans-centric view. Plans with progress bars, nested work items, phase indicators, repositories, skills. PlanService, WorkItemService, RepositoryService
Work Item Detail Full work item view. Versioned description, thread (messages + emails + Akh contributions), patches, phases, capabilities, agent sessions. WorkItemService, ThreadService, AgentSessionService
Work Item Email Mode Same work item focused on email thread. Inbound/outbound mail, share buttons. ThreadService, MailboxService
Library Document browser. Search, read, manage documents across projects. DocumentService (→ Seshat's Library)
Workflows Browse/create/edit workflow templates. Phase editor, skill assignment. WorkflowService
Settings Server connection, user preferences, notification settings. TeamService
Team/People Team member management, roles per project. TeamService

Client Architecture

┌─────────────────────────────┐
│         Slint UI Layer       │
│  (.slint files, components)  │
├─────────────────────────────┤
│       View Models (Rust)     │
│  Translate domain → UI state │
├─────────────────────────────┤
│       gRPC Client Layer      │
│  tonic, streaming listeners  │
├─────────────────────────────┤
│       Local Cache (SQLite)   │
│  Read cache, invalidated by  │
│  streaming updates from server│
└─────────────────────────────┘

Caching Strategy

  • On startup: fetch current state, populate SQLite cache
  • gRPC streams (threads, dashboard, sessions) push updates → invalidate/update cache → UI reacts
  • Stale cache is acceptable for offline viewing but all writes go to server
  • Cache is disposable — can be wiped and rebuilt from server

Design System

  • Headings: Inter
  • Body: Geist
  • Captions: Funnel Sans
  • Color palette: Violet Void (dark theme)
  • Roundness: Basic
  • Elevation: Sharp depth
  • Decorative: Neon streak overlays

Mail Integration (anima-mail)

Inbound Flow

External sender
  → sends to workitem+WI-123@project.anima.example
  → Stalwart receives, stores in project mailbox
  → anima-mail polls via JMAP
  → parses plus-address to extract work item ID
  → calls ThreadService.PostMessage on anima-server (as email-type message)
  → work item thread updated, desktop streams update

Outbound Flow

User clicks "Send" on work item thread (email mode)
  → desktop calls ThreadService.PostMessage (outbound email)
  → anima-server notifies anima-mail
  → anima-mail composes email with:
      - Reply-To: workitem+WI-123@project.anima.example
      - Custom headers: X-Anima-WorkItem, X-Anima-Project
  → sends via JMAP submission to Stalwart
  → recipient replies → inbound flow catches it

Mailbox Management

  • anima-mail uses Stalwart's admin API to create/delete mailboxes
  • One or more mailboxes per project, linked via MailboxService
  • "Gather" mailboxes link to multiple projects — routing uses plus-address to disambiguate
  • Compromised addresses get rotated, old mailbox dropped

Spam Handling

  • Simple screener on inbound: reject unknown senders on work-item-specific addresses
  • Gather mailboxes are more open but can have basic filtering rules
  • Compromised addresses get rotated, old mailbox dropped

Mail Classification

  • anima-mail calls anima-ai ClassifyMail to route ambiguous inbound mail when plus-addressing isn't present
  • Classification always runs on the smallest/cheapest AI model available — it is a simple routing task, not a reasoning task. anima-ai supports model tiers and mail classification always uses the minimal tier.

Agent System (anima-agent)

v1 Scope

Single-agent interaction. One provider (configurable — local Docker, bare-metal hypervisor, or cloud VM). The interface is designed for future multi-provider orchestration but v1 runs one provider.

Lifecycle

Work Item needs heavy work
  → anima-server calls AgentProviderService.ProvisionVM
  → anima-agent provisions VM/container with:
      - Capabilities from work item (repo access, API keys, network rules)
      - AI skills deployed for current workflow phase
      - Akh identity configured (persona for thread contributions)
  → Agent starts working, reports progress via tasks
  → Agent writes to discussion thread as its Akh
  → Session is long-running, persists while work item is open
  → Admin can LoginSession to SSH in and inspect/debug (audit logged)
  → When work completes or is stopped: VM can be kept or destroyed

Capabilities

  • Defined on the Work Item, derived from what the work needs
  • Examples: access to specific repos, GCP service accounts, k8s API, database credentials, network zones
  • anima-agent translates capabilities into VM provisioning config (mounted secrets, firewall rules, IAM bindings)
  • No allowlisting needed — the VM only has what the work item declares

Skills Deployment

  • Workflow phases declare required AI skills
  • anima-agent deploys skills into the VM before the agent starts
  • Skills are versioned and stored (future: pulled from marketplace)

Admin Access

  • LoginSession returns SSH connection details
  • For when AI gets stuck and a human needs to inspect VM state
  • Audit logged

MCP Server (embedded in anima-server)

The MCP server exists to give agents running inside VMs access to Anima data relevant to their work item. It is not a general integration point for external tools.

  • Scoped tokens: Each agent session gets a token that identifies it. Permissions and scope are stored server-side in the database — looked up on each request.
  • No external tool access: The desktop UI is the interface for humans. The MCP is the interface for Anima's own agents only.
  • Read-heavy: Agents read work item descriptions, thread history, documents, workflow phase requirements
  • Limited writes: Post to thread (as Akh), update task status, flag for human review
  • Token lifecycle: Token provisioned when agent session starts, scope stored in DB, revoked on session end
anima-agent provisions VM
  → generates MCP token (identifies agent session)
  → scope stored in DB (work item context, allowed permissions)
  → deploys token into VM alongside skills
  → AI agent inside VM uses MCP to read context and report back
  → token revoked on session end

Future: Multi-Provider Orchestration

The v1 AgentProviderService interface supports future expansion:

  • An Agent Orchestrator sits in front of multiple providers
  • Providers register capabilities (GCP provider, bare-metal provider, corporate-net provider, Docker provider)
  • Orchestrator matches work item capabilities to provider capabilities and dispatches
  • Each provider manages its own VM pool
  • Scheduler places work on providers based on access requirements (GCP for GCP deployments, corporate-net machine for firewalled k8s API, etc.)

anima-ai Service

Model Tiers

anima-ai supports multiple model tiers. Callers specify the tier, not the model — the service maps tiers to configured models.

Tier Use Cases Model Characteristics
Minimal Mail classification, spam screening, routing Smallest/cheapest available
Standard Summaries, description generation, thread digests Mid-range, good at text
Reasoning Gap analysis triggers, code review decisions, capability derivation Stronger reasoning, higher cost

API (internal gRPC, called by anima-server)

  • ClassifyMail(mail) → work_item_id, confidence — minimal tier
  • Summarize(thread/document) → summary — standard tier
  • GenerateDescription(context) → description — standard tier
  • AnalyzeGap(plan, implementation_state) → gap_report — reasoning tier
  • ShouldReview(work_item, changes) → review_decision — reasoning tier
  • DeriveCapabilities(work_item) → capabilities — reasoning tier

Design Principles

  • Stateless: no persistent state, reads context from anima-server per request
  • Horizontally scalable: run N instances behind a load balancer
  • Model-agnostic: tier mapping is configuration, swap models without code changes
  • Cost-conscious: always use the cheapest model that can do the job

Authentication & Authorization

Authentication

  • Users (humans): Session-based auth against anima-server. Login via credentials (v1), future: OIDC/SSO.
  • Desktop client: Authenticates on launch, receives a session token, attaches to all gRPC calls.
  • Inter-service: anima-mail, anima-ai, anima-agent authenticate to anima-server with service tokens (pre-shared, rotatable).
  • Agent MCP tokens: Tokens identify the agent session only. Scope and permissions are stored server-side in the database, looked up on each request. Revocation is instant.

RBAC System

Full role-based access control:

  • Permissions: granular actions (e.g., workitem.create, workitem.read, thread.post, plan.update, agent.login, mailbox.manage)
  • Roles: named collections of permissions, stored in database (e.g., Owner, Admin, Member, Viewer)
  • Role bindings: user + project + role, stored in database
  • Custom roles are a configuration change, not a code change. v1 ships with sensible defaults.
Concept Storage Example
Permission Code-defined enum, referenced in DB workitem.update, agent.login
Role DB row, has many permissions "Admin" → [workitem., plan., agent.login, ...]
Role Binding DB row: user + project + role Till → Project Anima → Owner
MCP Token DB row: token ID → agent session ID Token abc123 → Session S-42
MCP Scope DB row: session → work item → allowed permissions S-42 → WI-17 → [thread.post, workitem.read]

v1 Simplifications

  • No OIDC/SSO, just username/password
  • Service tokens are static config, rotated manually

Crate & Repository Structure

Workspace Layout

anima/
├── proto/                          # Protobuf definitions
│   └── anima/v1/                   # Versioned API
│       ├── project.proto
│       ├── plan.proto
│       ├── workitem.proto
│       ├── workflow.proto
│       ├── thread.proto
│       ├── agent.proto
│       ├── repository.proto
│       ├── mailbox.proto
│       ├── document.proto
│       ├── akh.proto
│       ├── team.proto
│       ├── dashboard.proto
│       └── ai.proto               # Internal: anima-server → anima-ai
│
├── crates/
│   ├── anima-core/                 # Domain types, RBAC, shared logic
│   ├── anima-db/                   # PostgreSQL migrations, queries (sqlx)
│   ├── anima-proto/                # Generated protobuf code (tonic-build)
│   ├── anima-server/               # Main server binary + embedded MCP
│   ├── anima-mail/                 # Mail worker binary
│   ├── anima-agent/                # Agent manager binary
│   ├── anima-ai/                   # AI inference service binary
│   └── anima-desktop/              # Slint desktop client
│
├── docs/
│   └── superpowers/specs/          # Design specs
│
├── main.pen                        # Penpot design file
├── projectbrief.txt                # Project brief
├── Cargo.toml                      # Workspace root
└── README.md

Crate Dependencies

Crate Type Depends On
anima-core lib
anima-proto lib anima-core
anima-db lib anima-core
anima-server bin anima-core, anima-proto, anima-db
anima-mail bin anima-proto, anima-core
anima-agent bin anima-proto, anima-core
anima-ai bin anima-proto, anima-core
anima-desktop bin anima-proto, anima-core

Key Rust Dependencies

  • tonic / prost — gRPC server & client, protobuf
  • sqlx — async PostgreSQL with compile-time query checking
  • slint — desktop UI
  • tokio — async runtime
  • jmap-client or custom — JMAP protocol for Stalwart

Forge Integration

  • Read-only forge API integration for GitHub, Gitea, GitLab
  • Pull PR/merge request metadata, link to work items
  • Issue migration path: import existing issues as work items
  • Anima owns work items — no dual issue tracking on forges
  • Git operations (clone, commit, push) only happen inside agent VMs (heavy work)
  • Patches and documents are attachments stored in Seshat's Library for AI ingestion
  • AI reads forge data via MCP when needed during agent sessions