# Vishwakarma

> System design and architecture standards — module boundaries, config, API design, sync vs async decisions. Use when designing a new system or feature, choosing an architecture or pattern, structuring modules, or deciding between queue and synchronous processing.

- Skill: `arjuncrevathi/vishwakarma` (Agent Skill)
- Install (CLI): `npx skillmds@latest add arjuncrevathi/vishwakarma`
- Raw SKILL.md: https://api.skillmd.com/api/skills/arjuncrevathi/vishwakarma/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: arjuncrevathi (https://skillmd.com/u/arjuncrevathi)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/arjuncrevathi/vishwakarma

---


# Vishwakarma — The Divine Architect (System Design)

Vishwakarma governs how systems are shaped before a line of code is written.

## Defaults for a startup

- Boring technology bias: Postgres, Redis, FastAPI, React. Each novel technology is an innovation token — spend at most one per project, on the thing that differentiates you.
- Monolith-first. One deployable Python backend, one frontend. Split a service out only when a specific pain (independent scaling, team ownership, isolation) demands it — never preemptively.
- Optimize for deletability: small modules with narrow interfaces are easy to remove or rewrite.

## Module boundaries (domain-driven-lite)

- Organize by domain, not by layer: `billing/`, `ingestion/`, `agents/` — not `models/`, `services/`, `utils/` at top level.
- Dependency direction is one-way: core domain logic never imports adapters (DB clients, HTTP clients, LLM SDKs). Adapters import the core. Enforce with `import-linter` (Python) / `eslint-plugin-boundaries` (TS).
- Cross-module access goes through the module's public interface (its `__init__.py` / `index.ts` exports), never deep imports.
- `utils/` is a code smell. If it grows past a few files, its contents belong in a domain.

## Configuration (12-factor)

- All config from environment variables; typed and validated at startup (`pydantic-settings` in Python, `zod` on `process.env` in TS). Crash on missing config, don't limp.
- One `.env.example` kept current. No environment-specific `if PROD:` branches in business logic.

## API design

- REST conventions: plural nouns (`/invoices`), standard verbs, standard status codes (201 on create, 404 not 200-with-error).
- Version from day one: `/v1/` prefix. Breaking changes get `/v2/`, never a silent change.
- Every endpoint has typed request/response models (Pydantic / zod) — validation at the boundary, trusted types inside.

## Queue vs sync

- Sync if: < 2 s, the caller needs the result to proceed, failure should surface to the user immediately.
- Queue (Celery/arq + Redis) if: > 2 s, retryable, fan-out, or the caller only needs an acknowledgment. LLM batch work is always queued.
- Every queued job is idempotent and has a dead-letter path (see `hanuman`).

## AI-native specifics

- Separate the prompt layer from business logic: prompts live in their own module with typed inputs/outputs; business code calls `summarize(doc) -> Summary`, never builds prompt strings inline.
- Design for model swappability: one gateway interface over providers (or LiteLLM); model IDs and temperatures in config, not code.
- Mark human-in-the-loop points explicitly in the design: which outputs ship straight to users vs require review, and what the review UI is.
- Eval-driven development: before building an LLM feature, define the golden dataset and pass criteria (see `agni`). No evals, no feature.

## Before building — checklist

- [ ] Fits the monolith, or written justification for a new service
- [ ] Module placed in a domain; dependencies point inward
- [ ] Config via validated env vars, `.env.example` updated
- [ ] API versioned with typed request/response models
- [ ] Sync/queue decision made against the 2 s rule
- [ ] LLM calls behind the prompt layer, with evals defined

