Frappe_Claude_Skill_Package frappe-agent-architect
git clone https://github.com/OpenAEC-Foundation/Frappe_Claude_Skill_Package
T=$(mktemp -d) && git clone --depth=1 https://github.com/OpenAEC-Foundation/Frappe_Claude_Skill_Package "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/source/agents/frappe-agent-architect" ~/.claude/skills/openaec-foundation-frappe-claude-skill-package-frappe-agent-architect && rm -rf "$T"
skills/source/agents/frappe-agent-architect/SKILL.mdMulti-App Architecture Agent
Designs Frappe/ERPNext multi-app architectures by analyzing business requirements, deciding app boundaries, and generating implementation roadmaps.
Purpose: Make the right architecture decisions BEFORE writing code — prevent costly refactoring later.
When to Use This Agent
ARCHITECTURE TRIGGER | +-- New project with multiple modules | "We need CRM, inventory, and custom billing" | --> USE THIS AGENT | +-- Deciding whether to extend ERPNext or build custom | "Should we customize Sales Invoice or create our own DocType?" | --> USE THIS AGENT | +-- Multiple teams building on same Frappe instance | "Team A does HR, Team B does manufacturing" | --> USE THIS AGENT | +-- Existing monolith needs splitting | "Our single custom app has 50 DocTypes" | --> USE THIS AGENT | +-- Cross-app communication needed | "App A needs to react when App B creates a document" | --> USE THIS AGENT
Architecture Workflow
STEP 1: ANALYZE REQUIREMENTS Business needs → DocTypes, workflows, integrations STEP 2: DECIDE APP BOUNDARIES Single app vs multiple apps decision framework STEP 3: DESIGN CROSS-APP DEPENDENCIES required_apps, shared DocTypes, hook contracts STEP 4: DESIGN DATA MODEL DocTypes, relationships, naming conventions STEP 5: GENERATE IMPLEMENTATION ROADMAP Build order, milestones, team assignments
See references/workflow.md for detailed steps.
Step 1: Requirement Analysis Matrix
Map each business requirement to Frappe mechanisms:
| Requirement Type | Frappe Mechanism | Example |
|---|---|---|
| Data storage | DocType | "Track customer contracts" |
| Business rules | Controller/Server Script | "Auto-calculate totals" |
| Approval flow | Workflow | "Manager must approve orders >10k" |
| Scheduled tasks | Scheduler/hooks.py | "Daily report email" |
| External sync | Integration/API | "Sync with Shopify" |
| Custom UI | Client Script/Page | "Dashboard for warehouse" |
| Reports | Script Report/Query Report | "Monthly sales by region" |
| Permissions | Role Permission | "Sales team sees own data only" |
| Print output | Print Format (Jinja) | "Custom invoice layout" |
| Portal access | Website/Portal | "Customer can view orders" |
Step 2: App Boundary Decision Framework
Single App: Use When
- Total DocTypes < 15
- Single team maintains the code
- All DocTypes share the same business domain
- No plans to distribute/sell components separately
- All DocTypes have tight data dependencies
Multiple Apps: Use When
- Total DocTypes > 15
- Multiple teams with separate release cycles
- Clear domain boundaries exist (HR vs Manufacturing vs CRM)
- Components may be installed independently
- Some modules are reusable across projects
- Different licensing needs per module
Decision Tree
HOW MANY DOCTYPES? | +-- < 15 total | +-- Single domain? --> SINGLE APP | +-- Multiple domains? --> Consider splitting | +-- 15-30 total | +-- Tight coupling between all? --> SINGLE APP (with modules) | +-- Clear domain boundaries? --> 2-3 APPS | +-- > 30 total | --> ALWAYS SPLIT into multiple apps | Group by domain/team/release cycle
See references/decision-tree.md for the complete decision framework.
Step 3: Cross-App Dependency Patterns
required_apps Declaration
ALWAYS declare dependencies explicitly in
hooks.py:
# myapp/hooks.py required_apps = ["frappe", "erpnext"] # NEVER omit frappe
Dependency Rules
- NEVER create circular dependencies (App A requires App B requires App A)
- ALWAYS declare ALL dependencies (direct and indirect)
- ALWAYS put shared/base apps first in required_apps
- NEVER depend on a specific version — use compatible APIs only
Dependency Diagram Pattern
frappe (base framework) └── erpnext (ERP modules) ├── custom_manufacturing (extends Manufacturing) └── custom_crm (extends CRM) └── crm_analytics (extends custom_crm) RULE: Dependencies flow DOWN only. Never up, never sideways.
Cross-App Communication Patterns
| Pattern | Mechanism | Use When |
|---|---|---|
| Hook Events | in hooks.py | App B reacts to App A's documents |
| Shared DocType | Link fields to other app's DocTypes | Apps share reference data |
| API Call | to whitelisted method | Loose coupling between apps |
| Custom Fields | with Custom Field | Extend another app's DocType without modifying it |
| Override | (v16) or | Modify another app's behavior |
| Signals | | Real-time notifications between apps |
Step 4: Data Model Design
DocType Relationship Types
| Relationship | Implementation | Example |
|---|---|---|
| One-to-Many | Child Table DocType | Invoice → Invoice Items |
| Many-to-One | Link field | Invoice → Customer |
| Many-to-Many | Link DocType (intermediary) | Student → Course (via Enrollment) |
| One-to-One | Link field + unique validation | Employee → User |
| Self-referential | Link to same DocType | Employee → Reports To (Employee) |
Naming Conventions
| Element | Convention | Example |
|---|---|---|
| App name | lowercase, underscores | |
| DocType name | Title Case, spaces | |
| Field name | lowercase, underscores | |
| Controller | snake_case filename | |
| Module | Title Case | |
Data Model Rules
- NEVER duplicate data that exists in another DocType — use Link fields
- ALWAYS define autoname/naming_series for every DocType
- ALWAYS add created_by and modified_by awareness (built-in)
- NEVER use Data fields for references — use Link fields
- ALWAYS set mandatory fields for data integrity
- ALWAYS define permissions at DocType level
App Composition Patterns
Pattern 1: Base + Vertical
base_app (shared DocTypes, utilities) ├── vertical_retail (retail-specific DocTypes) ├── vertical_manufacturing (manufacturing-specific DocTypes) └── vertical_services (services-specific DocTypes)
Use when: Building industry-specific solutions on shared foundation.
Pattern 2: Core + Extensions
erpnext (standard ERP) ├── custom_fields_app (Custom Fields only, no DocTypes) ├── custom_reports_app (Script Reports and dashboards) └── custom_workflows_app (Workflows and automation)
Use when: Extending ERPNext without modifying core. Keeps upgrades clean.
Pattern 3: Shared Utilities
frappe_utils (shared library: PDF generation, email templates, etc.) ├── app_crm (uses frappe_utils) ├── app_hr (uses frappe_utils) └── app_projects (uses frappe_utils)
Use when: Multiple apps need the same utility functions.
Pattern 4: Marketplace App
standalone_app (zero dependencies beyond frappe) ├── Works on any Frappe site ├── Self-contained DocTypes and logic └── Optional ERPNext integration via hooks
Use when: Building for distribution/sale on Frappe marketplace.
ERPNext Extension Patterns
Custom Fields vs Custom DocTypes vs Override
| Approach | Use When | Pros | Cons |
|---|---|---|---|
| Custom Fields | Adding 1-10 fields to existing DocType | Survives upgrades, no code | Limited logic, UI clutter |
| Custom DocType | New business entity not in ERPNext | Full control, clean design | No built-in ERPNext logic |
| Controller Override | Modifying existing ERPNext behavior | Full Python access | Fragile on upgrades |
| Server Script | Simple validation/automation | No custom app needed | Sandbox limitations |
| Client Script | UI customization | No custom app needed | JS only, no server logic |
Extension Decision Rules
- ALWAYS prefer Custom Fields for < 10 additional fields
- ALWAYS prefer Server Script for simple validations
- NEVER override ERPNext controllers unless absolutely necessary
- ALWAYS use
(v16) overextend_doctype_class
for overridesdoc_events - NEVER modify ERPNext source files directly — ALWAYS use hooks or extensions
Common Architecture Mistakes
| Mistake | Why It Fails | Correct Approach |
|---|---|---|
| Circular app dependencies | Install/update breaks | Restructure dependency tree |
| One mega-app with 50+ DocTypes | Unmaintainable, slow tests | Split by domain into 3-5 apps |
| Duplicating ERPNext DocTypes | Data inconsistency, double maintenance | Extend with Custom Fields + hooks |
No declaration | Silent failures on fresh install | ALWAYS declare all dependencies |
| Shared database tables between apps | Tight coupling, migration conflicts | Use Link fields and API calls |
| Modifying ERPNext source files | Lost on every upgrade | Use hooks, Custom Fields, extensions |
| No module organization within app | Files scattered, hard to navigate | Group DocTypes into modules |
| Hardcoded site/company names | Breaks on multi-site/multi-company | Use and filters |
Agent Output Format
ALWAYS produce architecture output in this format:
## Architecture Design ### Requirements Summary | # | Requirement | DocTypes | Mechanism | |---|------------|----------|-----------| ### App Structure [Diagram showing apps and dependencies] ### App Inventory | App | Module(s) | DocTypes | Dependencies | |-----|-----------|----------|-------------| ### Data Model | DocType | App | Key Fields | Relationships | |---------|-----|------------|---------------| ### Cross-App Communication | Source App | Target App | Mechanism | Trigger | |-----------|-----------|-----------|---------| ### ERPNext Extensions | Extension Type | Target DocType | Purpose | |---------------|---------------|---------| ### Implementation Roadmap | Phase | App(s) | Deliverables | Dependencies | |-------|--------|-------------|-------------| ### Risk Assessment | Risk | Mitigation | |------|-----------| ### Referenced Skills - `frappe-syntax-customapp`: App structure - `frappe-syntax-hooks`: Hook configuration - `frappe-syntax-doctypes`: DocType definition - `frappe-impl-customapp`: App development workflow
See references/decision-tree.md for complete decision frameworks. See references/examples.md for architecture design examples.