Plugin Structure
File layout, manifest format, and data isolation for ANIMA plugins.
Directory Layout
A minimal plugin needs two files: plugin.toml and plugin.py. A full plugin looks like this:
my-plugin/
├── plugin.toml # REQUIRED: manifest
├── plugin.py # REQUIRED: AnimaPlugin subclass
├── config/
│ └── settings.toml # Plugin-specific settings
├── corpus/ # Default corpus documents (optional)
│ └── *.md, *.txt, *.pdf
├── dashboard/ # Web UI (optional)
│ ├── app.py # Flask/FastAPI app
│ └── templates/
│ └── dashboard.html
├── requirements.txt # Python dependencies (optional)
└── README.md
Required Files
- plugin.toml — metadata, port, permissions, model requirements
- plugin.py — must contain a class that inherits from
AnimaPlugin
Plugin Manifest (plugin.toml)
The manifest declares your plugin's identity, permissions, and routing preferences.
Full example
[plugin]
name = "my-plugin" # unique identifier (lowercase, hyphens)
version = "1.0.0" # semver
description = "What this plugin does"
author = "Author Name"
license = "free" # free | proprietary | pro_required
port = 8905 # default web server port
min_core_version = "1.0.0" # minimum ANIMA core version
max_core_version = "1.99.99" # optional: max compatible version
[plugin.hub] # optional: for hub-published plugins
repository = "https://github.com/author/my-plugin"
categories = ["analysis", "science"]
screenshots = ["screens/overview.png", "screens/dashboard.png"]
price = "0" # "0" = free, "29.99" = one-time
[plugin.permissions] # optional: declares what the plugin needs
network = ["api.example.com"] # allowed external endpoints
filesystem = ["read:corpus/"] # beyond own data dir
subprocess = false # can it spawn subprocesses?
[plugin.models]
required_roles = ["extraction"] # at least one online model must have these
preferred_tier = "large" # hint: large | medium | small
Task Routing
Define how this plugin's work gets routed to models:
[tasks.extraction]
reasoning = "low" # low | medium | high
prefer = "speed" # speed | quality
safe_fallback = true # fall back to another model if busy
[tasks.dreams]
reasoning = "high"
prefer = "quality"
[tasks.chat]
reasoning = "medium"
prefer = "quality"
safe_fallback = true
Routing Modes
Control how models are assigned to this plugin:
[routing]
mode = "shared" # shared | scoped | prefer
assigned_models = ["local-primary", "cloud-assist"]
| Mode | Behavior |
|---|---|
shared | Use any available model (default) |
scoped | Only use assigned models |
prefer | Use assigned first, fall back to shared pool |
Governance
Governance controls what happens after beliefs pass quality gates. Add to your plugin's config/settings.toml:
[governance]
preset = "monarchy" # monarchy | llm | auto
| Preset | Behavior | Use Case |
|---|---|---|
monarchy | All beliefs queued for human approval | Research, knowledge work (default) |
llm | Auto-accept beliefs, manual corrections/lessons | Coding, supervised automation |
auto | Auto-accept everything | Game worlds, consumer plugins |
Governance resolves to three capability flags:
allow_auto_accept = false # auto-accept beliefs that pass quality gates
allow_auto_corrections = false # auto-accept corrections without approval
allow_auto_lessons = false # auto-accept lessons without approval
Quality gates always run. Governance only controls what happens after a belief passes all quality checks. A belief that fails triage is rejected regardless of governance preset.
Data Directory
Each plugin gets an isolated data directory at runtime. Plugins must not access other plugins' data.
~/.anima/data/{plugin-name}/
├── sqlite/
│ └── persistence.db # Belief database (per-plugin instance)
├── chroma/ # Vector embeddings
└── telemetry.db # Cycle metrics
Isolation is enforced. Plugins must not access other plugins' data directories. All storage paths are injected by the core — never resolve paths from __file__.
Versioning
The plugin API follows semver:
- Major (1.x → 2.x) — breaking changes to hook signatures or engine API
- Minor (1.1 → 1.2) — new hooks or engine methods added (backward compatible)
- Patch (1.1.1 → 1.1.2) — bug fixes only
Plugins declare min_core_version in plugin.toml. The core refuses to load plugins that require a newer version.