Important
MADFAM-ENCLII-FIRST-LEGACY-RAW v1: This document contains legacy raw infrastructure command examples.
Routine production operations must use Enclii web, API, or CLI. Treat raw
kubectl, helm, SSH, provider CLI/API, docker exec, and direct container
access as platform bootstrap or documented break-glass only, and record any
missing Enclii adapter gap.
Gamified multi-agent business orchestration platform. Manage your digital enterprise as an Auto Chess-style RPG -- draft AI agents, assign them to departments, and approve their actions from a 2D virtual office using a gamepad.
Selva Office is a polyglot monorepo with TypeScript frontends and Python backends.
Office UI (Next.js + Phaser) <---> Colyseus (real-time state sync)
|
Nexus API (FastAPI) <---> Workers (LangGraph)
| |
PostgreSQL Redis (task queue)
|
Gateway (OpenClaw heartbeats)
See docs/ARCHITECTURE.md for the full component diagram and data flow documentation.
# 1. Run first-time setup
bash scripts/setup.sh
# 2. Start PostgreSQL and Redis
make docker-dev
# 3. Start all services
make devselva-redis-pool: Standardized Redis dependency for async pub/sub and distributed locking.selva-permissions: Strict Janua RBAC dependency injecting FastAPI role assertions globally, and the platform/tenant audience boundary for tools and skills.selva-orchestrator: Swarm orchestration engine (synergy rules, Thompson Sampling bandit, puppeteer mode) integrated with the Enclii platform lifecycle.selva-workflows: YAML-defined LangGraph workflows for autonomous multi-agent execution.selva-skills: Procedural skills registry (core + community tiers) with the AgentSkills SKILL.md format and locale variants.selva-tools: 240+ built-in tools across file ops, code exec, git, web, data, comms, artifacts, MCP, and Mexican-market integrations (Karafiel, Dhanam, PhyndCRM, Tezca).selva-permissions: HITL permission engine with skill-based overrides and audience guard.selva-memory: Per-agent FAISS vector store and Experience/Reflexion learning loop.selva-calendar: Google + Microsoft calendar adapters.selva-observability: Shared structured logging, request-id correlation, Sentry, OTel.selva-a2a: Agent-to-Agent protocol package (AgentCard discovery, task exchange, SSE).selva-plugins: Plugin loader for third-party agent extensions.selva-sdk: Python async/sync client +selvaCLI for dispatching tasks programmatically.madfam-inference: LLM provider routing (OpenAI, Anthropic, Ollama, DeepInfra, Together, Fireworks, SiliconFlow, Moonshot) with task-type assignment and vision support.madfam-revenue-loop-probe: Shared revenue-loop instrumentation primitives.
selva-office/
apps/
nexus-api/ FastAPI -- central orchestration API
office-ui/ Next.js + Phaser -- spatial office UI
admin/ Next.js -- admin dashboard
colyseus/ Colyseus -- game state server
gateway/ OpenClaw -- heartbeat daemon
workers/ LangGraph -- task execution
packages/
shared-types/ Shared TypeScript types
ui/ Shared React components (incl. Pixelact namespace)
config/ ESLint, TypeScript, and logging presets
orchestrator/ Swarm orchestration (Python)
permissions/ HITL permission engine + audience boundary (Python)
inference/ LLM provider routing (Python, `madfam_inference`)
skills/ Procedural skills registry (Python, `selva_skills`)
tools/ Built-in tool library (Python, `selva_tools`)
workflows/ YAML→LangGraph compiler (Python, `selva_workflows`)
memory/ Per-agent FAISS + Experience/Reflexion (Python)
calendar/ Google + Microsoft adapters (Python)
a2a/ Agent-to-Agent protocol (Python)
sdk/ Python SDK + `selva` CLI
redis-pool/ Shared Redis singleton with circuit breaker (Python)
observability/ Logging, OTel, Sentry helpers (Python)
plugins/ Plugin loader (Python)
revenue-loop-probe/ Revenue-loop instrumentation (Python)
infra/
docker/ Dockerfiles and Compose
k8s/ Kubernetes manifests (production base + staging overlay)
argocd/ ArgoCD Application manifests
cloudflare/ DNS + redirect rules
scripts/ Setup, seed, asset generation, and map generation scripts
docs/ Architecture and development guides
See docs/PORTS.md for canonical port assignments.
| Port | Service |
|---|---|
| 4300 | Nexus API |
| 4301 | Office UI |
| 4302 | Admin Dashboard |
| 4303 | Colyseus |
| 4304 | Gateway (heartbeat daemon health + metrics HTTP) |
| 4305 | Workers (health + metrics HTTP) |
| 5432 | PostgreSQL |
| 6379 | Redis |
These ports do not conflict with Janua (4100-4104) or Enclii (4200-4204).
- Architecture Overview
- Development Guide
- Human-in-the-Loop Flow
- MADFAM Integration Guide
- Autonomous Cleanroom Protocol (ACP)
- Ecosystem Context (self-contained)
Selva Office is part of the MADFAM platform and integrates with:
- Janua -- OpenID Connect authentication (ports 4100-4104)
- Dhanam -- Billing, subscriptions, and compute token budgets
- Enclii -- Deployment orchestration via ArgoCD (ports 4200-4204)
Tenant swarms can submit text posts to a single subreddit via the
reddit_post tool (packages/tools/src/selva_tools/builtins/reddit_tools.py).
The tool is gated by:
- Mandatory creds — env vars
REDDIT_CLIENT_ID,REDDIT_CLIENT_SECRET,REDDIT_USER_AGENT,REDDIT_REFRESH_TOKEN. Missing any one raisesToolNotConfiguredError(no placeholder ever shipped). - Per-subreddit policy ConfigMap — mounted at
/etc/selva/subreddit_policies.yaml(sample atinfra/k8s/configmaps/subreddit-policies-default.yaml). Default for any unlisted subreddit:disclosure_required: true. - Mandatory AI disclosure footer — appended automatically when the per-subreddit policy requires it. Idempotent — agents that pre-stamp the footer are not double-stamped.
- 30-min Redis rate-limit per subreddit —
selva:reddit:last_post:{subreddit}key with 30-min TTL. - HITL gate via the
reddit_promo_v1built-in playbook —require_approval=True,financial_cap_cents=0,token_budget=20_000.
- Create a Reddit "script-type" OAuth app at https://www.reddit.com/prefs/apps.
- Use the script-app installed-flow to mint a refresh token (see PRAW docs).
- Store the four secrets in Vault, sync to the
autoswarmnamespace K8s Secret used by the worker Deployment. kubectl apply -f infra/k8s/configmaps/subreddit-policies-default.yamlto ship the policy ConfigMap.- Mount the ConfigMap on workers + nexus-api. Bump the worker Deployment annotation to force re-roll on policy changes.
- Publish a real disclosure page at https://madfam.io/ai-disclosure before going live (the footer URL is a placeholder until then).
X (Twitter), LinkedIn, and crossposting are explicitly out of scope
for this MVP.
Tenant swarms can submit text posts to Bluesky via the bluesky_post
tool (packages/tools/src/selva_tools/builtins/bluesky_tools.py). The
tool mirrors the Reddit MVP shape and is gated by:
- Mandatory per-persona credentials — env vars
BLUESKY_HANDLE_<PERSONA_ID>(e.g.madfam.bsky.social) andBLUESKY_APP_PASSWORD_<PERSONA_ID>(16-char app password, NOT the account login password). Missing either raisesToolNotConfiguredError(no placeholder ever shipped). - 300-character hard limit, including the disclosure footer —
Bluesky's per-post limit is 300 chars. The mandatory disclosure
footer is ~36 chars, leaving ~264 chars for promo content. If user
text alone overflows 300, or text + footer overflows, the tool
raises
PostTooLongError(no silent truncation — agent must rewrite tighter). Document any longer drafts as a thread-of-replies (out of scope for v1; v2 ships threading helpers). - Mandatory AI disclosure footer — every post gets the suffix
\n\n— Posted by an AI agent on behalf of MADFAMappended automatically. Idempotent — agents that pre-stamp the footer are not double-stamped. - 30-min Redis rate-limit per persona —
selva:bluesky:last_post:{persona_id}key with 30-min TTL. Bluesky's underlying API limit is high (5000 points/hr); the conservative cadence here is for promo content, not API hygiene. langsfield — default["en"]. Passlangs=["es"]for Karafiel/Dhanam Spanish promo copy so Bluesky's discovery feeds surface the post to the right audience.- HITL gate via the
bluesky_promo_v1built-in playbook —require_approval=True,financial_cap_cents=0,token_budget=20_000.
- For each persona that will post (e.g.
default,growth-bot-1,karafiel-es), log in to https://bsky.app/settings/app-passwords under the persona's Bluesky account. - Generate a NEW app password (16 chars, displayed once). Treat it
like an API token — rotate quarterly per
docs/SECRET_ROTATION_POLICY.md. - Store the handle + app password as Vault secrets, sync to the
autoswarmnamespace K8s Secret used by the worker Deployment. Naming convention:BLUESKY_HANDLE_DEFAULT=madfam.bsky.socialBLUESKY_APP_PASSWORD_DEFAULT=xxxx-xxxx-xxxx-xxxx- (uppercase + hyphens replaced with underscores)
- Install the
blueskyextra in the worker image:pip install selva-tools[bluesky](pulls inatproto>=0.0.46). - Quote-posts, image attachments, and threading are explicitly out of scope for this v1; v2 will add them.
X (Twitter) parity is still tracked in ROADMAP. Bluesky's tech-
leaning audience fits Selva (B2B founders/CTOs) and Yantra4D
(technical maker community) — that's why we ship it before X.
Tenant swarms can submit a status (toot) to a Mastodon instance via the
mastodon_post tool
(packages/tools/src/selva_tools/builtins/mastodon_tools.py). The tool
mirrors the Reddit pattern's defense-in-depth and adds a few
fediverse-specific gates:
- Per-persona access tokens — env vars
MASTODON_INSTANCE_URL(shared) andMASTODON_ACCESS_TOKEN_<PERSONA_ID>(per persona, upper-cased + non-alphanumerics replaced with underscores). Missing either raisesToolNotConfiguredError(no placeholder ever shipped). - Per-instance policy ConfigMap — mounted at
/etc/selva/mastodon_policies.yaml(sample atinfra/k8s/configmaps/mastodon-policies-default.yaml). Default for any unlisted instance:disclosure_required: true,allowed_visibilities: ["unlisted"],rate_limit_minutes: 30. - Default visibility =
unlisted— accessible by URL but absent from the local + federated public timelines. The fediverse social contract is significantly more sensitive to public-timeline promo spam than Reddit's subreddit model. Per-instance policy can pin it stricter; ops must opt-in topublicper instance after the moderators have approved the bot account. - Mandatory AI disclosure footer — appended automatically when the per-instance policy requires it (default: always). Idempotent.
- Per-instance Redis rate-limit —
selva:mastodon:last_post:{instance}key with the configured TTL (default 30 min, per-instance override possible — fosstodon.org defaults to 60 min). - HITL gate via the
mastodon_promo_v1built-in playbook —require_approval=True,financial_cap_cents=0,token_budget=20_000.
For each persona that will post from a given instance:
- Sign in to the persona's account on the target instance (e.g. https://mastodon.social/).
- Navigate to Settings → Development → New application.
- Set the application name (e.g.
selva-growth-bot) and grant thewrite:statusesscope. Other scopes are not required for text posts. - Copy the resulting access token (NOT the client id / client secret — Mastodon tokens for owned-account use are a single long- lived bearer string).
- Store the token in Vault under
mastodon/access_token/<persona_id>. Selva's Vault → K8s Secret sync materialises it on the worker Deployment asMASTODON_ACCESS_TOKEN_<PERSONA_ID>(upper-cased, non-alphanumerics →_). - Set
MASTODON_INSTANCE_URLonce per worker Deployment to the home instance's base URL (e.g.https://mastodon.social). kubectl apply -f infra/k8s/configmaps/mastodon-policies-default.yamlto ship the policy ConfigMap; mount it on workers + nexus-api at/etc/selva/mastodon_policies.yaml. Bump the worker Deployment annotation to force re-roll on policy changes.- Publish a real disclosure page at https://madfam.io/ai-disclosure before going live (the footer URL is a placeholder until then; same caveat as the Reddit tool).
X (Twitter) and LinkedIn parity tracked separately.
- Create a feature branch from
main. - Use conventional commits:
feat(scope): description,fix(scope): description. - Open a pull request -- CI must pass before merge.
- Commits are enforced by commitlint via husky pre-commit hooks.
AGPL-3.0