Skip to main content
Glama
chozzz

manusia

by chozzz

manusia

Human-as-a-Service: your AI agent estimates, posts, and polls a task; a vetted human from a small AU roster answers it from a one-page claim form; you pay them from an operator-funded AUD pool. manusia is brand 1 on a brand-agnostic engine — expanding (Australia → Indonesia, or into a vertical) is spinning up a brand row, not a fork (doc 22).

Stack: pnpm workspaces + Turborepo + TypeScript strict, Node ≥ 22.

Layer

Choice

Brain

apps/api — Fastify: REST + the 7 tool endpoints + in-process workers

Web

apps/web — Next.js (claim one-pager lands at claim.vargos.io)

npx shim

apps/mcp-stdio@manusiamcp/mcp: MCP-SDK stdio → brain HTTPS

DB

packages/db — Prisma + PostgreSQL (homelab manusia / manusia_test)

Auth

packages/auth — magic links for humans, credentials for operators, mk_live_/mk_test_ API keys

Engine

packages/engine — pure domain (state, clocks, fee math, the 7 handlers)

LLM

packages/llm — local vLLM (estimate + posting gate, degraded-safe)

MCP

packages/mcp — tool contracts, error mapping (doc 02)

Notify / mail

packages/notifier (per-brand templates) → packages/mailer (Resend)

Workers

packages/workers — TTL watcher, mock responder (in-process, M1)

CLI

packages/cli — operator plane (brands, humans, categories, requests, payouts)

The spec lives in docs/ (01–23 + plan); docs/23-gap-review.md records the boilerplate reconciliation (Prisma+Postgres over SQLite, TenantBrand, magic links, @haas/* scope per Vadi's locked decisions).

5-minute setup (local)

cp .env.example .env            # fill AUTH_SECRET + homelab DATABASE_URL
docker compose -f infra/docker-compose.yml up -d   # throwaway local postgres (or point at homelab)
pnpm install

pnpm db:migrate                 # apply prisma migrations (base + product schema)
pnpm db:seed                    # brand 1 (manusia, en/AUD, 15%/A$1.00), categories, operator, API key

cp apps/web/.env.example apps/web/.env.local
pnpm dev                        # web → :3000, api → :3001

Run the mock loop with no roster: MANUSIA_MOCK=1 pnpm --filter api dev (mock mk_test_ keys / env mock answer requests after MANUSIA_MOCK_DELAY_MS).

Try the tools (key from db:seed output):

curl -s localhost:3001/v1/tools/capabilities \
  -H "Authorization: Bearer <api key>" -H 'content-type: application/json' -d '{}'

curl -s localhost:3001/v1/tools/request \
  -H "Authorization: Bearer <api key>" -H 'content-type: application/json' \
  -d '{"task":"STP deadline for our first subbie?","category":"accounting-au","budget":25}'

The npx shim (doc 21 §1) — MCP-stdio client → brain HTTPS, no DB in the shim:

{ "mcpServers": { "manusia": { "command": "npx", "args": ["@manusiamcp/mcp"],
  "env": { "MANUSIA_API_KEY": "mk_live_…", "MANUSIA_API_URL": "http://127.0.0.1:8443" } } } }

Checks CI runs:

pnpm turbo run lint typecheck test build   # all pass without a live DB

Related MCP server: AgentHire MCP Server

The 7 tools (locked, doc 19 B1)

human.estimate · human.capabilities · human.request · human.status · human.cancel · human.list · human.upload — pure async, offer-based (budget is the price, doc 20), stable error codes in error.code (doc 02 §5). Contracts in packages/shared/src/tools.ts; handlers in packages/engine.

CI

  • build — lint → typecheck → test → build, no live DB.

  • integration — boots the brain in mock mode against a throwaway CI Postgres (service container, never the homelab), migrates + seeds, then drives the 7 tools end-to-end: estimate → request → (mock) in_progress → answered → status → list, plus idempotency + error-code assertions (apps/api/scripts/integration.ts, doc 19 DoD #1).

Production (baseline)

  • infra/systemd/manusia.service — the brain, PORT=8443.

  • infra/cloudflared/config.ymlmcp.vargos.io → brain :8443, claim.vargos.io → web :3000 (doc 19 B4 — no new domain).

  • infra/backup/backup-nightly.sh — nightly pg_dump → TrueNAS (cron), replaces the spec's sqlite3 .backup (doc 23 G8).

Env

Single source of truth: root .env (Prisma + API load it; web uses apps/web/.env.local). Full list + defaults in .env.example. Homelab DB credentials are still pending — the placeholders in .env.example are placeholders on purpose.

Design notes

  • Source-only workspace packagespackages/* export raw TS ("exports": "./src/index.ts"); web transpiles them, the API runs via tsx.

  • The brain is the sole writer — claim races use UPDATE … WHERE status='pending'; workers are in-process intervals in M1 (the packages/workers seam is the extraction point, doc 21 §8).

  • Brand is a row, not a fork — identity/logo/key prefixes in packages/brand (deployment config); locale/currency/fees/hosts/roster in the brands table (doc 22). Middleware resolves host → path → MANUSIA_DEFAULT_BRAND; everything downstream is brand-scoped.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers