ALPS Profile Assistant
Generate, validate, and improve ALPS profiles for RESTful API design.
Ideal ALPS Profile
Goal: An ALPS that someone unfamiliar with the app can read and understand.
What Makes a Good ALPS
States = What the user sees
ProductList - viewing a list of products
ProductDetail - viewing one product
Cart - viewing cart contents
Transitions = What the user does
goProductDetail - select a product
doAddToCart - add to cart
Self-documenting
title explains the purpose
doc describes behavior and side effects
- No need to read code to understand
No unreachable states
- Every state has an entry point
- Orphan states indicate design mistakes
Necessary and sufficient
- No over-abstraction
- Describes semantics, not implementation
- No HTTP methods or URLs
What to Avoid
- Mechanical CRUD listings without meaning
- Implementation details leaking in
- States without transitions (can't draw a diagram)
- Excessive documentation nobody reads
How to Use
This skill responds to natural language requests:
Generate ALPS from Description (nl2alps)
- "Create an ALPS profile for a blog application"
- "Generate ALPS for an e-commerce cart system"
- "Design an ALPS profile for user authentication"
Validate Existing Profile
- "Validate this ALPS profile" (with file path or content)
- "Check my ALPS file for issues"
- "Review the ALPS profile at docs/api.json"
Get Improvement Suggestions
- "Improve this ALPS profile"
- "Suggest enhancements for my ALPS"
- "How can I make this ALPS better?"
ALPS Structure Reference
Three Layers of ALPS
Ontology - Semantic descriptors (data elements)
- Atomic data fields with
type="semantic" (default)
- Should have
id, title, and optionally doc and def (schema.org link)
Taxonomy - State descriptors (screens/pages)
- Composite descriptors containing semantic fields and transitions
- Represents application states (e.g., HomePage, ProductDetail, Cart)
Choreography - Transition descriptors (actions)
type="safe" - Read operations (GET)
type="unsafe" - Create operations (POST) - not idempotent
type="idempotent" - Update/Delete operations (PUT/DELETE)
- Must have
rt (return type) pointing to target state
Naming Conventions
| Type |
Prefix |
Example |
| Safe transition |
go |
goToHome, goProductList, goSearchProducts |
| Unsafe transition |
do |
doCreateUser, doAddToCart, doLogin |
| Idempotent transition |
do |
doUpdateUser, doDeleteItem, doRemoveFromCart |
| State/Page |
PascalCase |
HomePage, ProductDetail, ShoppingCart |
| Semantic field |
camelCase |
userId, productName, createdAt |
Safe Transition Naming Rule
IMPORTANT: Safe transitions (go*) MUST include the target state name in their id.
rt="#ProductList" → id must be goProductList (or goToProductList)
rt="#UserProfile" → id must be goUserProfile (or goToUserProfile)
Invalid examples:
goStart with rt="#ProductList" - Wrong! Should be goProductList
goNext with rt="#Checkout" - Wrong! Should be goCheckout
This rule ensures consistency and makes the diagram self-documenting. When a transition has no source state (entry point), it will be displayed as originating from UnknownState in the diagram.
Determining idempotent: PUT vs DELETE
Context clues for AI inference:
PUT (Update) indicators:
update, edit, modify, change, set, replace
- Example:
doUpdateProfile, doEditComment, doSetQuantity
DELETE indicators:
delete, remove, cancel, clear, destroy
- Example:
doDeleteUser, doRemoveFromCart, doCancelOrder
Generation Guidelines
When Creating ALPS from Natural Language
Identify Entities (Ontology)
- Extract nouns: user, product, order, cart, etc.
- Define atomic fields for each entity
Identify States (Taxonomy)
- Map user journey: login -> home -> browse -> cart -> checkout
- Each state contains relevant fields and available transitions
Identify Transitions (Choreography)
- Safe: navigation, viewing, searching
- Unsafe: creating new resources
- Idempotent: updating or deleting resources
Add Documentation
- Every descriptor should have a meaningful
title
- Complex descriptors should have
doc explaining behavior
- Link to schema.org definitions where applicable (
def)
Add Tags for Organization
- Functional area tags: Group by feature domain (e.g.,
search, product, cart, checkout, order, account, review)
- Flow tags: Group by user journey with
flow- prefix (e.g., flow-purchase, flow-register, flow-return)
- States and transitions should have both types where applicable
- Example: A cart-related transition might have
"tag": ["cart", "flow-purchase"]
Add Semantic Descriptors to Transitions
- Every transition (go/do) should specify its required input parameters as nested descriptors
- These define what data is needed to perform the action
- Example:
{"id": "goProductDetail", "type": "safe", "rt": "#ProductDetail", "tag": ["product"], "descriptor": [
{"href": "#productId"}
]},
{"id": "doAddToCart", "type": "unsafe", "rt": "#Cart", "tag": ["cart", "flow-purchase"], "descriptor": [
{"href": "#productId"},
{"href": "#quantity"},
{"href": "#selectedVariant"}
]}
MANDATORY: Validate After Generation
- After generating ALPS JSON, save it to a temporary file
- Run
asd --validate <file> to validate (outputs JSON per validation-result.json schema)
- Parse the JSON result and report issues to the user
- If errors exist, fix them before presenting the final output
Output Format
Generate JSON format by default. Use XML only if explicitly requested.
{
"$schema": "https://alps-io.github.io/schemas/alps.json",
"alps": {
"title": "Application Title",
"doc": {"value": "Description of the application"},
"descriptor": [
// Ontology: semantic fields
{"id": "fieldName", "title": "Human Title", "doc": {"value": "Description"}},
// Taxonomy: states
{"id": "StateName", "title": "State Title", "descriptor": [
{"href": "#fieldName"},
{"href": "#transitionName"}
]},
// Choreography: transitions
{"id": "goToState", "type": "safe", "rt": "#TargetState", "title": "Navigate to State"},
{"id": "doAction", "type": "unsafe", "rt": "#ResultState", "title": "Perform Action",
"descriptor": [{"href": "#requiredField"}]}
]
}
}
Validation
Use asd --validate <file> to validate ALPS profiles. Output conforms to the validation-result.json schema.
Error Codes (E)
- E001: Missing id or href
- E002: Missing rt on transition
- E003: Invalid type
- E004: Broken reference
- E005: Duplicate id
- E006: Invalid href
- E007: Invalid rt format
- E008: Missing alps property in document
- E009: Descriptor must be an array
- E010: Invalid XML character in descriptor title
Warning Codes (W)
- W001: Missing title
- W002: Safe transition naming (should start with 'go')
- W003: Unsafe/idempotent naming (should start with 'do')
- W004: Orphan descriptor
- W005: Safe transition id does not match rt target (e.g.,
goStart with rt="#ProductList" should be goProductList)
Suggestion Codes (S)
- S001: Missing doc on transition
- S002: Missing ALPS title
- S003: Missing ALPS doc
Example: Blog Application
Input: "Create an ALPS for a simple blog with posts and comments"
Output:
{
"$schema": "https://alps-io.github.io/schemas/alps.json",
"alps": {
"title": "Simple Blog",
"doc": {"value": "ALPS profile for a blog application with posts and comments"},
"descriptor": [
{"id": "postId", "title": "Post ID", "def": "https://schema.org/identifier"},
{"id": "title", "title": "Post Title", "def": "https://schema.org/headline"},
{"id": "body", "title": "Post Body", "def": "https://schema.org/articleBody"},
{"id": "authorName", "title": "Author Name", "def": "https://schema.org/author"},
{"id": "createdAt", "title": "Created Date", "def": "https://schema.org/dateCreated"},
{"id": "commentId", "title": "Comment ID"},
{"id": "commentBody", "title": "Comment Text"},
{"id": "Home", "title": "Home Page", "descriptor": [
{"href": "#goPostList"}
]},
{"id": "PostList", "title": "Post List", "descriptor": [
{"href": "#postId"},
{"href": "#title"},
{"href": "#authorName"},
{"href": "#goPostDetail"},
{"href": "#goHome"}
]},
{"id": "PostDetail", "title": "Post Detail", "descriptor": [
{"href": "#postId"},
{"href": "#title"},
{"href": "#body"},
{"href": "#authorName"},
{"href": "#createdAt"},
{"href": "#Comment"},
{"href": "#goPostList"},
{"href": "#doCreateComment"}
]},
{"id": "Comment", "title": "Comment", "descriptor": [
{"href": "#commentId"},
{"href": "#commentBody"},
{"href": "#authorName"},
{"href": "#createdAt"},
{"href": "#doDeleteComment"}
]},
{"id": "goHome", "type": "safe", "rt": "#Home", "title": "Go to Home"},
{"id": "goPostList", "type": "safe", "rt": "#PostList", "title": "View Post List"},
{"id": "goPostDetail", "type": "safe", "rt": "#PostDetail", "title": "View Post Detail",
"descriptor": [{"href": "#postId"}]},
{"id": "doCreatePost", "type": "unsafe", "rt": "#PostDetail", "title": "Create Post",
"descriptor": [{"href": "#title"}, {"href": "#body"}]},
{"id": "doUpdatePost", "type": "idempotent", "rt": "#PostDetail", "title": "Update Post",
"descriptor": [{"href": "#postId"}, {"href": "#title"}, {"href": "#body"}]},
{"id": "doDeletePost", "type": "idempotent", "rt": "#PostList", "title": "Delete Post",
"descriptor": [{"href": "#postId"}]},
{"id": "doCreateComment", "type": "unsafe", "rt": "#PostDetail", "title": "Add Comment",
"descriptor": [{"href": "#postId"}, {"href": "#commentBody"}]},
{"id": "doDeleteComment", "type": "idempotent", "rt": "#PostDetail", "title": "Delete Comment",
"descriptor": [{"href": "#commentId"}]}
]
}
}
Integration with app-state-diagram
Generated ALPS profiles can be visualized using app-state-diagram:
# Generate HTML diagram
asd profile.json
# Generate with watch mode
asd --watch profile.json
# Generate markdown documentation
asd --mode=markdown profile.json
Tips for Better ALPS
- Start with user journeys - Map the happy path first, then add alternatives
- Be consistent - Use the same naming pattern throughout
- Document transitions - Explain what each action does and when it's available
- Use schema.org - Link to standard definitions for interoperability
- Think about errors - Add error states and recovery transitions
- Consider pagination - List states should support pagination
- Tag descriptors - Use
tag attribute to group related descriptors
References
1---2name: alps-33description: Create, validate, and improve ALPS profiles. Generate from natural language (nl2alps), validate existing profiles, and get improvement suggestions.4---56# ALPS Profile Assistant78Generate, validate, and improve ALPS profiles for RESTful API design.910## Ideal ALPS Profile1112**Goal: An ALPS that someone unfamiliar with the app can read and understand.**1314### What Makes a Good ALPS15161. **States = What the user sees**17 - `ProductList` - viewing a list of products18 - `ProductDetail` - viewing one product19 - `Cart` - viewing cart contents20212. **Transitions = What the user does**22 - `goProductDetail` - select a product23 - `doAddToCart` - add to cart24253. **Self-documenting**26 - `title` explains the purpose27 - `doc` describes behavior and side effects28 - No need to read code to understand29304. **No unreachable states**31 - Every state has an entry point32 - Orphan states indicate design mistakes33345. **Necessary and sufficient**35 - No over-abstraction36 - Describes semantics, not implementation37 - No HTTP methods or URLs3839### What to Avoid4041- Mechanical CRUD listings without meaning42- Implementation details leaking in43- States without transitions (can't draw a diagram)44- Excessive documentation nobody reads4546## How to Use4748This skill responds to natural language requests:4950### Generate ALPS from Description (nl2alps)51- "Create an ALPS profile for a blog application"52- "Generate ALPS for an e-commerce cart system"53- "Design an ALPS profile for user authentication"5455### Validate Existing Profile56- "Validate this ALPS profile" (with file path or content)57- "Check my ALPS file for issues"58- "Review the ALPS profile at docs/api.json"5960### Get Improvement Suggestions61- "Improve this ALPS profile"62- "Suggest enhancements for my ALPS"63- "How can I make this ALPS better?"6465## ALPS Structure Reference6667### Three Layers of ALPS68691. **Ontology** - Semantic descriptors (data elements)70 - Atomic data fields with `type="semantic"` (default)71 - Should have `id`, `title`, and optionally `doc` and `def` (schema.org link)72732. **Taxonomy** - State descriptors (screens/pages)74 - Composite descriptors containing semantic fields and transitions75 - Represents application states (e.g., HomePage, ProductDetail, Cart)76773. **Choreography** - Transition descriptors (actions)78 - `type="safe"` - Read operations (GET)79 - `type="unsafe"` - Create operations (POST) - not idempotent80 - `type="idempotent"` - Update/Delete operations (PUT/DELETE)81 - Must have `rt` (return type) pointing to target state8283### Naming Conventions8485| Type | Prefix | Example |86|------|--------|---------|87| Safe transition | `go` | `goToHome`, `goProductList`, `goSearchProducts` |88| Unsafe transition | `do` | `doCreateUser`, `doAddToCart`, `doLogin` |89| Idempotent transition | `do` | `doUpdateUser`, `doDeleteItem`, `doRemoveFromCart` |90| State/Page | PascalCase | `HomePage`, `ProductDetail`, `ShoppingCart` |91| Semantic field | camelCase | `userId`, `productName`, `createdAt` |9293### Safe Transition Naming Rule9495**IMPORTANT**: Safe transitions (`go*`) MUST include the target state name in their id.9697- `rt="#ProductList"` → id must be `goProductList` (or `goToProductList`)98- `rt="#UserProfile"` → id must be `goUserProfile` (or `goToUserProfile`)99100**Invalid examples:**101- `goStart` with `rt="#ProductList"` - Wrong! Should be `goProductList`102- `goNext` with `rt="#Checkout"` - Wrong! Should be `goCheckout`103104This rule ensures consistency and makes the diagram self-documenting. When a transition has no source state (entry point), it will be displayed as originating from `UnknownState` in the diagram.105106### Determining idempotent: PUT vs DELETE107108Context clues for AI inference:109110**PUT (Update) indicators:**111- `update`, `edit`, `modify`, `change`, `set`, `replace`112- Example: `doUpdateProfile`, `doEditComment`, `doSetQuantity`113114**DELETE indicators:**115- `delete`, `remove`, `cancel`, `clear`, `destroy`116- Example: `doDeleteUser`, `doRemoveFromCart`, `doCancelOrder`117118## Generation Guidelines119120### When Creating ALPS from Natural Language1211221. **Identify Entities** (Ontology)123 - Extract nouns: user, product, order, cart, etc.124 - Define atomic fields for each entity1251262. **Identify States** (Taxonomy)127 - Map user journey: login -> home -> browse -> cart -> checkout128 - Each state contains relevant fields and available transitions1291303. **Identify Transitions** (Choreography)131 - Safe: navigation, viewing, searching132 - Unsafe: creating new resources133 - Idempotent: updating or deleting resources1341354. **Add Documentation**136 - Every descriptor should have a meaningful `title`137 - Complex descriptors should have `doc` explaining behavior138 - Link to schema.org definitions where applicable (`def`)1391405. **Add Tags for Organization**141 - **Functional area tags**: Group by feature domain (e.g., `search`, `product`, `cart`, `checkout`, `order`, `account`, `review`)142 - **Flow tags**: Group by user journey with `flow-` prefix (e.g., `flow-purchase`, `flow-register`, `flow-return`)143 - States and transitions should have both types where applicable144 - Example: A cart-related transition might have `"tag": ["cart", "flow-purchase"]`1451466. **Add Semantic Descriptors to Transitions**147 - Every transition (go/do) should specify its required input parameters as nested descriptors148 - These define what data is needed to perform the action149 - Example:150 ```json151 {"id": "goProductDetail", "type": "safe", "rt": "#ProductDetail", "tag": ["product"], "descriptor": [152 {"href": "#productId"}153 ]},154 {"id": "doAddToCart", "type": "unsafe", "rt": "#Cart", "tag": ["cart", "flow-purchase"], "descriptor": [155 {"href": "#productId"},156 {"href": "#quantity"},157 {"href": "#selectedVariant"}158 ]}159 ```1601617. **MANDATORY: Validate After Generation**162 - After generating ALPS JSON, save it to a temporary file163 - Run `asd --validate <file>` to validate (outputs JSON per validation-result.json schema)164 - Parse the JSON result and report issues to the user165 - If errors exist, fix them before presenting the final output166167### Output Format168169Generate JSON format by default. Use XML only if explicitly requested.170171```json172{173 "$schema": "https://alps-io.github.io/schemas/alps.json",174 "alps": {175 "title": "Application Title",176 "doc": {"value": "Description of the application"},177 "descriptor": [178 // Ontology: semantic fields179 {"id": "fieldName", "title": "Human Title", "doc": {"value": "Description"}},180181 // Taxonomy: states182 {"id": "StateName", "title": "State Title", "descriptor": [183 {"href": "#fieldName"},184 {"href": "#transitionName"}185 ]},186187 // Choreography: transitions188 {"id": "goToState", "type": "safe", "rt": "#TargetState", "title": "Navigate to State"},189 {"id": "doAction", "type": "unsafe", "rt": "#ResultState", "title": "Perform Action",190 "descriptor": [{"href": "#requiredField"}]}191 ]192 }193}194```195196## Validation197198Use `asd --validate <file>` to validate ALPS profiles. Output conforms to the [validation-result.json schema](https://alps-asd.github.io/app-state-diagram/schemas/validation-result.json).199200### Error Codes (E)201- E001: Missing id or href202- E002: Missing rt on transition203- E003: Invalid type204- E004: Broken reference205- E005: Duplicate id206- E006: Invalid href207- E007: Invalid rt format208- E008: Missing alps property in document209- E009: Descriptor must be an array210- E010: Invalid XML character in descriptor title211212### Warning Codes (W)213- W001: Missing title214- W002: Safe transition naming (should start with 'go')215- W003: Unsafe/idempotent naming (should start with 'do')216- W004: Orphan descriptor217- W005: Safe transition id does not match rt target (e.g., `goStart` with `rt="#ProductList"` should be `goProductList`)218219### Suggestion Codes (S)220- S001: Missing doc on transition221- S002: Missing ALPS title222- S003: Missing ALPS doc223224## Example: Blog Application225226Input: "Create an ALPS for a simple blog with posts and comments"227228Output:229```json230{231 "$schema": "https://alps-io.github.io/schemas/alps.json",232 "alps": {233 "title": "Simple Blog",234 "doc": {"value": "ALPS profile for a blog application with posts and comments"},235 "descriptor": [236 {"id": "postId", "title": "Post ID", "def": "https://schema.org/identifier"},237 {"id": "title", "title": "Post Title", "def": "https://schema.org/headline"},238 {"id": "body", "title": "Post Body", "def": "https://schema.org/articleBody"},239 {"id": "authorName", "title": "Author Name", "def": "https://schema.org/author"},240 {"id": "createdAt", "title": "Created Date", "def": "https://schema.org/dateCreated"},241 {"id": "commentId", "title": "Comment ID"},242 {"id": "commentBody", "title": "Comment Text"},243244 {"id": "Home", "title": "Home Page", "descriptor": [245 {"href": "#goPostList"}246 ]},247 {"id": "PostList", "title": "Post List", "descriptor": [248 {"href": "#postId"},249 {"href": "#title"},250 {"href": "#authorName"},251 {"href": "#goPostDetail"},252 {"href": "#goHome"}253 ]},254 {"id": "PostDetail", "title": "Post Detail", "descriptor": [255 {"href": "#postId"},256 {"href": "#title"},257 {"href": "#body"},258 {"href": "#authorName"},259 {"href": "#createdAt"},260 {"href": "#Comment"},261 {"href": "#goPostList"},262 {"href": "#doCreateComment"}263 ]},264 {"id": "Comment", "title": "Comment", "descriptor": [265 {"href": "#commentId"},266 {"href": "#commentBody"},267 {"href": "#authorName"},268 {"href": "#createdAt"},269 {"href": "#doDeleteComment"}270 ]},271272 {"id": "goHome", "type": "safe", "rt": "#Home", "title": "Go to Home"},273 {"id": "goPostList", "type": "safe", "rt": "#PostList", "title": "View Post List"},274 {"id": "goPostDetail", "type": "safe", "rt": "#PostDetail", "title": "View Post Detail",275 "descriptor": [{"href": "#postId"}]},276 {"id": "doCreatePost", "type": "unsafe", "rt": "#PostDetail", "title": "Create Post",277 "descriptor": [{"href": "#title"}, {"href": "#body"}]},278 {"id": "doUpdatePost", "type": "idempotent", "rt": "#PostDetail", "title": "Update Post",279 "descriptor": [{"href": "#postId"}, {"href": "#title"}, {"href": "#body"}]},280 {"id": "doDeletePost", "type": "idempotent", "rt": "#PostList", "title": "Delete Post",281 "descriptor": [{"href": "#postId"}]},282 {"id": "doCreateComment", "type": "unsafe", "rt": "#PostDetail", "title": "Add Comment",283 "descriptor": [{"href": "#postId"}, {"href": "#commentBody"}]},284 {"id": "doDeleteComment", "type": "idempotent", "rt": "#PostDetail", "title": "Delete Comment",285 "descriptor": [{"href": "#commentId"}]}286 ]287 }288}289```290291## Integration with app-state-diagram292293Generated ALPS profiles can be visualized using app-state-diagram:294295```bash296# Generate HTML diagram297asd profile.json298299# Generate with watch mode300asd --watch profile.json301302# Generate markdown documentation303asd --mode=markdown profile.json304```305306## Tips for Better ALPS3073081. **Start with user journeys** - Map the happy path first, then add alternatives3092. **Be consistent** - Use the same naming pattern throughout3103. **Document transitions** - Explain what each action does and when it's available3114. **Use schema.org** - Link to standard definitions for interoperability3125. **Think about errors** - Add error states and recovery transitions3136. **Consider pagination** - List states should support pagination3147. **Tag descriptors** - Use `tag` attribute to group related descriptors315316## References317318- [ALPS Specification](http://alps.io/spec/)319- [Schema.org](https://schema.org/)320- [app-state-diagram](https://github.com/alps-asd/app-state-diagram)