# Decision Tree Format Specification ## Overview Decision trees are structured YAML documents that guide users through a series of questions to reach a recommendation. They are rendered as interactive SVG diagrams with boxes, connecting lines, and Yes/No branch labels. ## Basic Structure ```yaml ```decision-tree {id="documents-tree"} id: documents-tree scope: documents rootQuestion: root questions: root: text: "Your question here?" whyAsk: "Explanation of why this question matters" answers: yes: value: "Yes" outcome: label: "Recommendation" id: outcomeId no: value: "No" nextQuestion: nextQuestionId nextQuestionId: text: "Follow-up question?" whyAsk: "Why this matters" answers: yes: value: "Yes" outcome: label: "Recommendation" id: outcomeId no: value: "No" outcome: label: "Alternative recommendation" id: altOutcomeId ``` ``` ## Fields ### Top-level - **`id`** (required): Unique identifier for this decision tree (e.g., `documents-tree`, `collections-tree`). Used for discovery and referencing by AI agents. - **`scope`** (required): Category or domain this tree applies to (e.g., `documents`, `collections`, `sequences`). Helps AI agents understand the tree's purpose and applicability. - **`rootQuestion`** (required): The ID of the starting question - **`questions`** (required): Object containing all questions, keyed by ID - **`indentWidth`** (optional): Horizontal spacing in pixels between parent and child nodes. Default: 40. Use smaller values (e.g., 20-30) for deeply nested trees to reduce overall width. This is a rendering preference and does not affect the semantic metadata. ### Question Object - **`text`** (required): The question text. Can span multiple lines using YAML's `|` literal block syntax - **`whyAsk`** (required): Explanation of why this question matters. Helps AI agents understand the decision logic - **`answers`** (required): Object with answer keys (can be `yes`/`no` for binary trees, or arbitrary keys for multiway branching) ### Answer Object Each answer contains: - **`value`** (required): Display text (e.g., "Yes", "No", "Python", "JavaScript", etc.) - **`outcome`** (optional): Terminal recommendation - `label`: Text to display (e.g., "Use JSON") - `id`: Unique identifier for this outcome - **`nextQuestion`** (optional): ID of the next question to ask **Note**: Each answer must have either `outcome` or `nextQuestion`, not both. ### Multiway Branching Instead of limiting answers to `yes` and `no`, you can use arbitrary answer keys for multiway branching: ```yaml languageQuestion: text: What is your primary programming language? whyAsk: Different languages have different client libraries answers: python: value: Python nextQuestion: pythonUseCase javascript: value: JavaScript nextQuestion: javascriptOMQuestion java: value: Java nextQuestion: javaQuestion other: value: Other nextQuestion: otherLanguageQuestion ``` **Benefits**: - Reduces tree depth by allowing multiple branches from a single question - More natural for questions with 3+ distinct options - Cleaner than binary yes/no chains - Answers are stacked vertically in the diagram ### Outcome Object - **`label`** (required): The recommendation text - **`id`** (required): Unique identifier (e.g., `jsonOutcome`, `hashOutcome`) - **`sentiment`** (optional): Indicates the nature of the outcome for visual styling - `"positive"`: Renders with green styling (e.g., "Use this option") - `"negative"`: Renders with red styling (e.g., "Don't use this option") - `"indeterminate"`: Renders with yellow/amber styling (e.g., "Further analysis needed") - Omitted: Defaults to red (neutral/warning styling) **Note**: The `sentiment` field is particularly useful for **suitability trees** (where outcomes are binary: suitable vs. unsuitable) as opposed to **selection trees** (where all outcomes are valid options). See [Tree Types](#tree-types) below. ## Tree Types Decision trees can serve different purposes, which affects how you structure outcomes: ### Selection Trees All paths lead to valid recommendations. Users choose between options. - **Example**: "Which data type should I use?" → JSON, Hash, or String (all valid) - **Outcome styling**: Typically all neutral (no sentiment field needed) - **Use case**: Helping users choose among alternatives ### Suitability Trees Paths lead to binary outcomes: suitable or unsuitable for the use case. - **Example**: "Should I use RDI?" → Yes (good fit) or No (various reasons why not) - **Outcome styling**: Use `sentiment: "positive"` for suitable outcomes and `sentiment: "negative"` for unsuitable ones - **Use case**: Determining if a technology/approach is appropriate - **Benefit**: Visual distinction (green vs. red) helps users quickly understand if something is recommended ## Multi-line Text Use YAML's literal block syntax (`|`) for multi-line text: ```yaml text: | Do you need nested data structures (fields and arrays) or geospatial index/query with Redis query engine? whyAsk: | JSON is the only document type that supports deeply nested structures and integrates with the query engine for those structures ``` ## Code Block Attributes The code block fence supports the following attributes: - **`id`** (optional): Unique identifier for the tree. Should match the `id` field in the YAML. Used by Hugo to pass metadata to the render hook. Example: ```markdown ```decision-tree {id="documents-tree"} id: documents-tree scope: documents # ... ``` ``` ## Best Practices 1. **Use descriptive IDs**: `root`, `hashQuestion`, `jsonOutcome` are clearer than `q1`, `q2` 2. **Keep questions concise**: Aim for 1-2 lines when possible 3. **Explain the rationale**: The `whyAsk` field helps users and AI agents understand the decision logic 4. **Reuse outcomes**: Multiple paths can lead to the same outcome (same `id`) 5. **Consistent naming**: Use camelCase for IDs, end question IDs with "Question" 6. **Match fence and YAML IDs**: The `id` in the code block fence should match the `id` field in the YAML for consistency 7. **Use meaningful scopes**: Choose scope values that clearly indicate the tree's domain (e.g., `documents`, `collections`, `sequences`) 8. **Add sentiment for suitability trees**: If your tree determines whether something is suitable (not just choosing between options), use `sentiment: "positive"` and `sentiment: "negative"` to provide visual feedback 9. **Be consistent with sentiment**: In a suitability tree, ensure all positive outcomes have `sentiment: "positive"` and all negative outcomes have `sentiment: "negative"` for clarity 10. **Control answer order**: The order of answers in the YAML controls the visual layout. For early rejection patterns, put negative outcomes first so they appear at the top of the diagram 11. **Adjust indent width for deeply nested trees**: If your tree has many levels and becomes too wide, use `indentWidth="25"` (or lower) in the code block fence to reduce horizontal spacing between parent and child nodes 12. **Use multiway branching for 3+ options**: Instead of chaining binary yes/no questions, use multiway branching with descriptive answer keys (e.g., `python`, `javascript`, `java`) to reduce tree depth and improve readability 13. **Keep answer values short**: Answer labels appear on connecting lines, so keep them concise (1-3 words) to fit neatly in the diagram ## Example: Redis Data Type Selection See `content/develop/data-types/compare-data-types.md` for a complete example. ## Rendering Decision trees are rendered as: - **SVG diagram** for humans (with boxes, lines, and labels) - **Normalized JSON** embedded for AI agents (accessible via `.html.md` URLs) - **Raw YAML** preserved in `
` element for accessibility ## AI Agent Compatibility The format is designed to be easily parseable by AI agents: ### Metadata Embedding - **Server-side JSON**: Each tree is embedded with metadata as `