# cheesecake > When you read a `.cheesecake` file, you do not "pretend" to execute it—you actually execute it. The sessions you spawn are real. The decisions you make are real. The outputs you produce are real. - Author: 14D110021 - Repository: cheesecake-lang/cheesecake - Version: 20260119185441 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-07 - Source: https://github.com/cheesecake-lang/cheesecake - Web: https://mule.run/skillshub/@@cheesecake-lang/cheesecake~cheesecake:20260119185441 --- # CheeseCake Language Specification # Purpose: Complete language definition for AI agents to understand and execute .cheesecake files # Part of: CheeseCake v0.0.1 - Module 2 (Language Specification) # Updated: v0.0.2 - Added PHASE (M9), INTERACTIVE (M10), CONFIG (M11), Events (M12), Testing (M13), Program Contracts, History & Replay (M14) # # This file teaches AI agents the complete CheeseCake syntax and semantics. # When you read a .cheesecake file, use this specification to understand and execute it. # # Usage: # This skill is automatically loaded when executing .cheesecake files # # Dependencies: # - vm.md (execution semantics) # - philosophy.md (execution philosophy - YOU are the VM) # - Claude Code Task tool (for creating sub-agent sessions) # # Related: # - syntax-reference.md (quick reference) # - helper.md (for generating .cheesecake files) # - philosophy.md (understand why you ARE the CheeseCake VM) --- name: cheesecake description: CheeseCake language interpreter. Use when reading or executing .cheesecake files. --- # CheeseCake Language Specification v0.0.2 ## Overview **CheeseCake** is a structured, object-oriented programming language for orchestrating AI agents. It treats long-running AI sessions as Turing-complete computers and provides explicit keywords for unambiguous control flow. ### Core Philosophy **You are not simulating a virtual machine. You ARE the virtual machine.** When you read a `.cheesecake` file, you do not "pretend" to execute it—you actually execute it. The sessions you spawn are real. The decisions you make are real. The outputs you produce are real. For the complete philosophical foundation, see `philosophy.md`. Key principles: 1. **AI-Native**: Designed for AI interpretation, not machine parsing 2. **You Are The VM**: Your understanding is the parser; your reasoning is the execution engine 3. **Structured Clarity**: Explicit UPPERCASE keywords and END markers for unambiguous parsing 4. **Semantic Intelligence**: `**...**` conditions explicitly delegate judgment to you 5. **Object-Oriented**: First-class support for agents, skills, inheritance, composition 6. **Resumable**: Built-in checkpoints for long-running workflows ### Execution Model - **You ARE the Interpreter**: The AI reading this specification IS the execution engine - **Sub-agent Spawning**: Use the Task tool to create real sessions for each agent - **Two Modes**: Strict execution (most code) + semantic evaluation (`**...**` conditions) - **Real State**: Variables exist in your working memory; checkpoints persist to filesystem - **Real Results**: Sessions produce real outputs that you capture and process --- ## 1. File Structure ### Basic Structure ```cheesecake # Comments start with # and go to end of line # Program contract (optional, at top) INPUT topic: "The subject to process" INPUT depth: "Processing depth" DEFAULT: "medium" # Program imports (optional, for calling other programs) USE "@namespace/program-name" USE "@workflows/analyzer" AS analyzer # Local module imports (optional, for code reuse) IMPORT "local/agents.cheesecake" AS agents # Skill definitions (optional) SKILL skill_name: CAPABILITIES: [...] REQUIRES: [...] # Agent definitions (optional) AGENT AgentName: MODEL: model_name SKILLS: [...] PROMPT: "..." # Main execution logic VAR agent = NEW AgentName() VAR result = RUN SESSION(agent): TASK: "Do something" # Program outputs (optional, declares what this program returns) OUTPUT findings = result OUTPUT summary = result.summary ``` ### File Conventions - **File extension**: `.cheesecake` - **Encoding**: UTF-8 - **Indentation**: 2 spaces (consistency matters for readability) - **Case sensitivity**: Keywords are UPPERCASE, user-defined names are flexible - **Line breaks**: Use newlines for readability, but not required after every statement --- ## 2. Comments ```cheesecake # Single-line comment # Multi-line comments use multiple # lines # Like this # And this # Section headers for organization # ============================================ # SECTION: Agent Definitions # Purpose: Define all agents used in this workflow # ============================================ ``` **Purpose**: Documentation, explaining non-obvious logic --- ## 3. Program Contracts (INPUT/OUTPUT) Program contracts define the **public API** of a `.cheesecake` program - what inputs it expects and what outputs it produces. This enables **program composition** where one program can call another. ### INPUT Declaration Declares what values the program expects from callers: ```cheesecake INPUT name: "Description of this input" INPUT name: "Description" DEFAULT: default_value ``` **Syntax:** - `INPUT` keyword followed by parameter name - Colon and description string (for documentation) - Optional `DEFAULT:` with a default value **Examples:** ```cheesecake # Required inputs (caller must provide) INPUT topic: "The subject to research" INPUT query: "Search query string" # Optional inputs (have defaults) INPUT depth: "How deep to search" DEFAULT: "medium" INPUT max_results: "Maximum results to return" DEFAULT: 10 INPUT format: "Output format (json, markdown, text)" DEFAULT: "markdown" ``` **Rules:** - INPUT declarations must appear at **top of file** (before any executable code) - INPUT names become available as variables in the program body - Required inputs (no DEFAULT) must be provided by caller - Optional inputs (with DEFAULT) use default if caller doesn't provide ### OUTPUT Declaration Declares what values the program returns to callers: ```cheesecake OUTPUT name = expression ``` **Syntax:** - `OUTPUT` keyword followed by output name - `=` and the value/expression to return **Examples:** ```cheesecake # Simple outputs OUTPUT findings = research_results OUTPUT summary = final_summary # Computed outputs OUTPUT word_count = LENGTH(article) OUTPUT success = error_count == 0 # Multiple outputs OUTPUT report = generated_report OUTPUT sources = source_list OUTPUT metadata = { generated_at: NOW(), model_used: "sonnet", tokens_used: token_count } ``` **Rules:** - OUTPUT can appear **anywhere** in the program (typically at the end) - Multiple OUTPUT declarations allowed - OUTPUT values are collected and returned to caller as an object - OUTPUT names must be unique within a program ### Complete Contract Example ```cheesecake # ============================================ # research-workflow.cheesecake # A reusable research program with clear contract # ============================================ # === INPUT CONTRACT === INPUT topic: "The subject to research" INPUT depth: "Research depth (shallow, medium, deep)" DEFAULT: "medium" INPUT sources: "Number of sources to consult" DEFAULT: 5 # === AGENT DEFINITIONS === AGENT Researcher: MODEL: sonnet PROMPT: "You are a thorough researcher." AGENT Synthesizer: MODEL: opus PROMPT: "You synthesize research into insights." # === MAIN LOGIC === VAR researcher = NEW Researcher() VAR synthesizer = NEW Synthesizer() # Use INPUT values as variables VAR raw_findings = RUN SESSION(researcher): TASK: "Research {topic} at {depth} depth using {sources} sources" VAR synthesis = RUN SESSION(synthesizer): TASK: "Synthesize these findings into key insights" INPUT: {raw_findings} VAR source_list = RUN SESSION(researcher): TASK: "Extract source citations from {raw_findings}" # === OUTPUT CONTRACT === OUTPUT findings = synthesis OUTPUT sources = source_list OUTPUT metadata = { topic: topic, depth: depth, researched_at: NOW() } ``` ### Why Contracts Matter Without contracts: ```cheesecake # Someone reads your program... what does it need? What does it return? # No way to know without reading all the code! ``` With contracts: ```cheesecake # Clear at a glance: INPUT topic: "The subject to research" # Needs a topic INPUT depth: "Research depth" DEFAULT: "medium" # Optional depth OUTPUT findings = ... # Returns findings OUTPUT sources = ... # Returns sources ``` Contracts enable: 1. **Documentation** - Clear API without reading implementation 2. **Validation** - VM can check required inputs are provided 3. **Composition** - Other programs can call this program 4. **Tooling** - IDEs/tools can show autocomplete for inputs/outputs --- ## 4. SKILL Definitions (Traits/Interfaces) Skills are reusable capability bundles that can be attached to agents. ### Basic Syntax ```cheesecake SKILL skill_name: CAPABILITIES: - capability 1 - capability 2 - capability 3 REQUIRES: - requirement 1 - requirement 2 ``` ### Inheritance ```cheesecake SKILL advanced_skill EXTENDS base_skill: CAPABILITIES: - additional capability 1 - additional capability 2 ``` **When inheriting**: The new skill gets all capabilities from the parent, plus its own. ### Examples ```cheesecake # Basic research skill SKILL web-research: CAPABILITIES: - search the web - fetch URLs - parse HTML - extract information REQUIRES: - internet access # Extending with academic capabilities SKILL academic-research EXTENDS web-research: CAPABILITIES: - access academic databases - parse academic papers - extract citations REQUIRES: - academic API access ``` ### Semantic Note **CAPABILITIES** and **REQUIRES** are natural language descriptions. The AI interprets what they mean. They're NOT executed as code - they inform the AI about what an agent can do when this skill is attached. --- ## 5. AGENT Definitions (Classes) Agents are templates (like classes) for creating sessions. Each agent has a model, skills, and a system prompt. ### Basic Syntax ```cheesecake AGENT AgentName: MODEL: model_name # sonnet, opus, haiku SKILLS: [skill1, skill2] # Array of skills PROMPT: "System prompt for this agent" ``` ### Inheritance ```cheesecake AGENT ChildAgent EXTENDS ParentAgent: MODEL: opus # Override parent's model SKILLS: [+new_skill] # Add to parent's skills (+ means append) PROMPT: PARENT + "Additional instructions" # Extend parent's prompt ``` ### Composition (Implements Multiple Skills) ```cheesecake AGENT FullStackDev IMPLEMENTS [frontend, backend, devops]: MODEL: sonnet PROMPT: "You are a full-stack developer." ``` ### Examples ```cheesecake # Basic agent AGENT Researcher: MODEL: sonnet # Using Sonnet for cost-efficiency SKILLS: [web-research, data-analysis] PROMPT: "You are a thorough researcher who finds accurate, well-sourced information." # Inheritance example AGENT SeniorResearcher EXTENDS Researcher: MODEL: opus # Senior researcher uses more powerful model SKILLS: [+strategic-thinking, +synthesis] # Adds to parent's skills PROMPT: PARENT + "You also provide strategic recommendations based on your research." # Composition example AGENT DataScientist IMPLEMENTS [data-analysis, ml-modeling, visualization]: MODEL: sonnet PROMPT: "You are a data scientist skilled in analysis, ML, and visualization." ``` ### Model Options - `sonnet` - Claude Sonnet (balanced, cost-effective) - `opus` - Claude Opus (most powerful) - `haiku` - Claude Haiku (fastest, cheapest) --- ## 6. Variables & Assignment ### Variable Declaration ```cheesecake VAR variable_name = value # Mutable variable CONST constant_name = value # Immutable variable ``` ### Valid Values ```cheesecake # NULL (uninitialized) VAR result = NULL # Agent instances VAR researcher = NEW Researcher() # Session outputs (strings, objects, arrays) VAR findings = RUN SESSION(researcher): TASK: "Research X" # Loaded data VAR config = LOAD "config.json" # Numbers, strings, booleans VAR count = 5 VAR name = "CheeseCake" VAR enabled = TRUE ``` ### Assignment Rules - `VAR` can be reassigned: `result = new_value` - `CONST` cannot be reassigned (immutable) - Variables must be declared before use - Variable names are case-sensitive ### Examples ```cheesecake # Declare and initialize VAR researcher = NEW Researcher() VAR findings = NULL # Will be assigned later # Run a session and store result findings = RUN SESSION(researcher): TASK: "Research quantum computing" # Constants for configuration CONST max_retries = 5 CONST timeout = 30s # Cannot reassign const (would error) # max_retries = 10 # ERROR! ``` --- ## 7. SESSION & RUN ### Creating a Session A **SESSION** is an instance of an agent, configured with a specific task. ```cheesecake # Create a session object (not yet executed) VAR session_obj = SESSION(agent_instance): TASK: "Natural language task description" INPUT: {var1, var2} # Optional: input data CONTEXT: {key: value} # Optional: additional context TIMEOUT: 30s # Optional: timeout RETRY: 3 # Optional: retry count ``` ### Running a Session **RUN** executes a session and returns the output. ```cheesecake # Execute the session VAR result = RUN session_obj # Inline: create and run in one statement VAR result = RUN SESSION(agent): TASK: "Do something" ``` ### Full Example ```cheesecake # Create agent VAR researcher = NEW Researcher() # Create session VAR research_session = SESSION(researcher): TASK: "Find recent breakthroughs in quantum computing" CONTEXT: { domain: "physics", depth: "comprehensive", sources: "peer-reviewed only" } TIMEOUT: 60s RETRY: 2 # Run the session VAR findings = RUN research_session # Or do it inline VAR summary = RUN SESSION(researcher): TASK: "Summarize these findings into 500 words" INPUT: {findings} ``` ### TASK Syntax The `TASK` field is a natural language instruction. You can use variable interpolation: ```cheesecake VAR topic = "quantum computing" VAR result = RUN SESSION(agent): TASK: "Research {topic} and provide a summary" # {topic} gets replaced INPUT: {data: previous_results} ``` ### INPUT vs CONTEXT - **INPUT**: Direct data to process (like function arguments) - **CONTEXT**: Additional configuration/hints for how to process --- ## 8. Control Flow ### Sequential Execution (Explicit) ```cheesecake SEQUENCE: VAR step1 = RUN SESSION(agent1): TASK: "Do first thing" VAR step2 = RUN SESSION(agent2): TASK: "Do second thing" INPUT: {step1} VAR step3 = RUN SESSION(agent3): TASK: "Do third thing" INPUT: {step2} END SEQUENCE ``` **Default**: Statements execute sequentially unless in a `PARALLEL` block. ### Parallel Execution ```cheesecake PARALLEL: VAR result1 = RUN SESSION(agent1): TASK: "Task 1" VAR result2 = RUN SESSION(agent2): TASK: "Task 2" VAR result3 = RUN SESSION(agent3): TASK: "Task 3" END PARALLEL # All three sessions run concurrently # Execution continues after all complete ``` ### Parallel with Join Strategies ```cheesecake # Wait for first to complete (race) PARALLEL JOIN(first): VAR fast = RUN SESSION(api1): TASK: "Fetch from fast source" VAR slow = RUN SESSION(api2): TASK: "Fetch from slow source" END PARALLEL # Only one completes, winner's result is used # Wait for any N PARALLEL JOIN(any, 2): # Wait for any 2 out of 3 VAR r1 = RUN SESSION(agent): TASK: "Option 1" VAR r2 = RUN SESSION(agent): TASK: "Option 2" VAR r3 = RUN SESSION(agent): TASK: "Option 3" END PARALLEL ``` ### Conditionals ```cheesecake IF **{variable} meets some semantic condition**: # Statements if true ELIF **{variable} meets different condition**: # Statements if this is true ELSE: # Statements if all false END IF ``` **Semantic Conditions**: Text in `**...**` is evaluated by AI understanding, not regex or boolean logic. Examples: ```cheesecake IF **{findings} shows significant progress in the field**: LOG "Exciting developments!" END IF IF **{feedback} indicates major structural issues**: # Do major revision ELSE: # Do minor polish END IF ``` ### Choice (AI Selects Option) ```cheesecake CHOICE ON **criteria for selection**: OPTION "label1": # Statements for option 1 OPTION "label2": # Statements for option 2 OPTION "label3": # Statements for option 3 END CHOICE ``` **How it works**: The AI evaluates the criteria and selects the most appropriate option. ```cheesecake CHOICE ON **project complexity level (simple, moderate, complex)**: OPTION "simple": VAR impl = RUN SESSION(junior_dev): TASK: "Implement feature" OPTION "moderate": VAR impl = RUN SESSION(senior_dev): TASK: "Implement feature" OPTION "complex": VAR design = RUN SESSION(architect): TASK: "Design solution first" VAR impl = RUN SESSION(senior_dev): TASK: "Implement" INPUT: {design} END CHOICE ``` ### Phase Blocks (v0.0.2+) **Purpose**: Organize workflow into logical phases for better progress tracking and visualization. ```cheesecake PHASE "phase-name": # Statements for this phase # Can include any valid CheeseCake code END PHASE ``` **Key Points:** - **Optional**: Phases are purely organizational, not functional - **Sequential**: Phases execute one after another - **Progress tracking**: VM shows which phase is currently running - **Any code**: Can contain PARALLEL blocks, loops, conditions, etc. - **Unique names**: Phase names must be unique within a workflow - **Resumability**: Checkpoints between phases enable resume after failure **Example:** ```cheesecake # Multi-phase research workflow # Phases provide clear progress visualization PHASE "Research": # Research phase with parallel data gathering VAR researcher = NEW Researcher() PARALLEL: VAR academic = RUN SESSION(researcher): TASK: "Find academic papers on quantum computing" VAR industry = RUN SESSION(researcher): TASK: "Analyze industry developments" VAR market = RUN SESSION(researcher): TASK: "Evaluate market trends" END PARALLEL # Save checkpoint after research CHECKPOINT "research-complete": SAVE: {academic, industry, market} END CHECKPOINT END PHASE PHASE "Analysis": # Synthesis phase VAR analyst = NEW Analyst() VAR insights = RUN SESSION(analyst): TASK: "Synthesize research findings into key insights" INPUT: {academic, industry, market} CHECKPOINT "analysis-complete": SAVE: {insights} END CHECKPOINT END PHASE PHASE "Writing": # Iterative writing phase VAR writer = NEW Writer() VAR editor = NEW Editor() VAR draft = RUN SESSION(writer): TASK: "Write article based on insights" INPUT: {insights} # Iterative refinement LOOP UNTIL **{draft} meets publication standards** MAX 5: VAR feedback = RUN SESSION(editor): TASK: "Review and provide feedback" INPUT: {draft} VAR draft = RUN SESSION(writer): TASK: "Revise based on feedback" INPUT: {draft, feedback} END LOOP CHECKPOINT "writing-complete": SAVE: {draft} END CHECKPOINT END PHASE PHASE "Output": # Final output phase SAVE draft TO "output/article.md" LOG SUCCESS: "Article complete!" END PHASE ``` **Progress Visualization:** When executing a workflow with phases, the VM displays: ``` ╔═══════════════════════════════════════════════════════════╗ ║ Executing: research-workflow.cheesecake ║ ╚═══════════════════════════════════════════════════════════╝ [■■■■■■□□□□] 60% complete ✓ Phase 1: Research [DONE] 8.5s ✓ Phase 2: Analysis [DONE] 4.2s → Phase 3: Writing [RUNNING] 2.1s ○ Phase 4: Output [PENDING] Tokens: 8,420 used | ~4,000 remaining Time: 14.8s elapsed | ~7s remaining ``` **When to Use PHASE Blocks:** 1. **Long workflows** (>5 minutes execution time) 2. **Multiple distinct stages** with different agents or tasks 3. **When checkpoints are needed** between major stages 4. **Complex workflows** where progress visibility helps user confidence 5. **Debugging** - easier to identify which phase failed **When NOT to Use PHASE Blocks:** 1. **Simple workflows** (1-3 operations) 2. **Already clear structure** - don't over-organize 3. **Single agent, single task** - unnecessary wrapper **Rules:** - Phase names must be **unique strings** - Phases execute **sequentially** (not parallel) - **Nested phases not allowed** (no PHASE inside PHASE) - **Works with all constructs** (can contain loops, conditionals, parallel blocks) - **No return values** - phases are organizational, not functional **Integration with Checkpoints:** Phases work well with checkpoints for resumability: ```cheesecake PHASE "Expensive Research": # If this phase fails, can resume without re-doing VAR data = RUN SESSION(expensive_agent): TASK: "..." CHECKPOINT "research-done": SAVE: {data} END CHECKPOINT END PHASE PHASE "Analysis": # If we resume, we start here with loaded data VAR result = RUN SESSION(analyst): TASK: "..." INPUT: {data} END PHASE ``` **Cost Estimation:** When using `/cheesecake estimate` or `--dry-run`, phases provide: - **Per-phase cost breakdown** - **Progress prediction** (which phase will take longest) - **Optimization suggestions** (identify expensive phases) Example output: ``` Phase 1: Research $0.06 (12%) 8s Phase 2: Analysis $0.04 (8%) 4s Phase 3: Writing $0.35 (70%) 25s ← Most expensive Phase 4: Output $0.00 (0%) 0.5s ``` **Note**: Phases are **optional in v0.0.1**. They're added in v0.0.2 to enhance progress tracking, but existing workflows without phases continue to work perfectly. --- ## 9. Loops ### Fixed Iteration (REPEAT) ```cheesecake REPEAT count: # Statements (executed count times) END REPEAT # With index variable REPEAT count AS index: # index goes from 0 to count-1 PRINT "Iteration {index}" END REPEAT ``` ### For-Each Loop ```cheesecake FOR item IN collection: # Process each item VAR result = RUN SESSION(agent): TASK: "Process {item}" END FOR # With index FOR item, index IN collection: PRINT "Processing item {index}: {item}" END FOR ``` ### Parallel For-Each ```cheesecake PARALLEL FOR item IN items: VAR processed = RUN SESSION(processor): TASK: "Process {item}" END PARALLEL FOR # All items processed concurrently ``` ### Unbounded Loops (Semantic Exit) ```cheesecake # Loop until condition is met LOOP UNTIL **{variable} meets exit condition** MAX max_iterations: # Statements # Update variable END LOOP # Loop while condition is true WHILE **{variable} meets continue condition** MAX max_iterations: # Statements END WHILE # Infinite loop (requires MAX for safety) LOOP MAX 100: # Statements # Must have some way to break or MAX will stop it END LOOP ``` ### Loop Safety **IMPORTANT**: All unbounded loops (`LOOP UNTIL`, `WHILE`, `LOOP`) MUST have a `MAX` limit to prevent infinite execution. ### Examples ```cheesecake # Fixed iteration REPEAT 3: VAR draft = RUN SESSION(writer): TASK: "Improve the draft" INPUT: {draft} END REPEAT # For-each FOR task IN todo_list: VAR result = RUN SESSION(worker): TASK: "Complete {task}" LOG "Completed: {task}" END FOR # Semantic loop (iterative refinement) VAR draft = RUN SESSION(writer): TASK: "Write initial draft" LOOP UNTIL **{draft} meets publication standards: well-structured, accurate, engaging** MAX 5: VAR feedback = RUN SESSION(editor): TASK: "Review {draft}" IF **{feedback} indicates major issues**: VAR draft = RUN SESSION(writer): TASK: "Major revision" INPUT: {draft, feedback} ELSE: VAR draft = RUN SESSION(writer): TASK: "Minor polish" INPUT: {draft, feedback} END IF LOG "Completed revision iteration" END LOOP ``` --- ## 10. Interactive Mode (v0.0.2+) **Purpose**: Pause workflow execution to request user input and make decisions based on user choices. ### INTERACTIVE Construct ```cheesecake INTERACTIVE AT "checkpoint-name": SHOW: {variable_to_display} ASK USER: "Question to ask the user?" OPTIONS: - "option1" → action1 - "option2" → action2 - "option3" → action3 END OPTIONS END INTERACTIVE ``` **Key Features**: - **Pause execution**: Workflow pauses gracefully without losing state - **Show context**: Display variables or data to help user decide - **Multiple choice**: User selects from 2-10 options - **Execute action**: Statement associated with chosen option executes - **Resume execution**: Workflow continues after user input - **Zero cost**: No AI sessions during pause ### Components #### AT "checkpoint-name" Unique identifier for the interactive point (required): ```cheesecake INTERACTIVE AT "review-draft": ... END INTERACTIVE INTERACTIVE AT "approve-cost": ... END INTERACTIVE ``` #### SHOW: {variable} Display context to user before asking (optional): ```cheesecake SHOW: {draft} # Show full variable SHOW: {draft.summary} # Show property SHOW: "Current cost: ${total_cost}" # Show formatted text ``` #### ASK USER: "Question?" The question presented to the user (required): ```cheesecake ASK USER: "How should we proceed with this draft?" ASK USER: "The cost is $2.50. Continue with execution?" ASK USER: "Which research direction should we prioritize?" ``` #### OPTIONS Multiple choice options (required, 2-10 options): ```cheesecake OPTIONS: - "approve" → VAR approved = true - "reject" → VAR approved = false - "modify" → VAR needs_revision = true END OPTIONS OPTIONS: - "continue" → CONTINUE - "finalize" → BREAK - "cancel" → RETURN END OPTIONS ``` ### Example: Approval Workflow ```cheesecake # Research with user approval before expensive analysis AGENT Researcher: MODEL: sonnet PROMPT: "You are a research assistant." AGENT Analyst: MODEL: opus # Expensive! PROMPT: "You are an in-depth analyst." VAR researcher = NEW Researcher() VAR findings = RUN SESSION(researcher): TASK: "Research quantum computing trends" # Pause and ask user if they want to proceed INTERACTIVE AT "approve-analysis": SHOW: {findings.summary} ASK USER: "Research complete. Proceed with Opus analysis ($0.50)?" OPTIONS: - "Yes, analyze" → VAR proceed = true - "No, skip analysis" → VAR proceed = false END OPTIONS END INTERACTIVE # Only run expensive analysis if approved IF proceed == true: VAR analyst = NEW Analyst() VAR deep_analysis = RUN SESSION(analyst): TASK: "Perform deep analysis of these findings" INPUT: {findings} PRINT "Analysis complete!" ELSE: PRINT "Analysis skipped by user" END IF ``` ### Example: Iterative Review ```cheesecake # Writing workflow with user review at each iteration AGENT Writer: MODEL: opus PROMPT: "You are a creative writer." VAR writer = NEW Writer() VAR draft = RUN SESSION(writer): TASK: "Write an article about AI safety" VAR continue_refining = true VAR iterations = 0 LOOP UNTIL continue_refining == false MAX 5: VAR iterations = iterations + 1 # Show draft and ask user what to do INTERACTIVE AT "review-draft-{iterations}": SHOW: {draft} ASK USER: "Review iteration {iterations}. How should we proceed?" OPTIONS: - "Continue refining" → VAR action = "refine" - "Finalize now" → VAR continue_refining = false - "Start over" → VAR action = "restart" END OPTIONS END INTERACTIVE # Handle user choice IF action == "finalize": PRINT "✓ Draft finalized by user" ELIF action == "restart": VAR draft = RUN SESSION(writer): TASK: "Write a completely new article about AI safety" ELSE: # action == "refine" VAR draft = RUN SESSION(writer): TASK: "Improve this draft based on your judgment" INPUT: {draft} END IF END LOOP SAVE draft TO "output/article.md" PRINT "✅ Article saved!" ``` ### Rules and Constraints **Allowed**: - ✅ INTERACTIVE in conditionals - ✅ INTERACTIVE in loops - ✅ INTERACTIVE in sequential code - ✅ Multiple INTERACTIVE blocks in same workflow **Not Allowed**: - ❌ INTERACTIVE inside PARALLEL blocks (breaks parallel semantics) - ❌ Nested INTERACTIVE blocks (no INTERACTIVE inside INTERACTIVE) **Requirements**: - AT "name" must be unique within workflow - ASK USER must end with `?` (convention) - OPTIONS must have 2-10 choices - Each option must have label and action ### Progress During Pause When workflow pauses at INTERACTIVE: ``` [■■■■■■□□□□] 60% complete ✓ Phase 1: Research [DONE] 8.5s ⏸ Phase 2: Review [PAUSED] User input required ○ Phase 3: Writing [PENDING] [PAUSE] Waiting for user input at checkpoint: review-draft ``` ### Cost During Pause INTERACTIVE blocks have **zero cost**: - No AI sessions spawned - User input time not counted in execution time - Workflow resumes after user provides input ### Integration with AskUserQuestion Tool INTERACTIVE uses Claude Code's `AskUserQuestion` tool internally: - Question from ASK USER - Options from OPTIONS block - User selection triggers action execution ### Best Practices 1. **Clear Questions**: Be specific about what you're asking ```cheesecake # Good ASK USER: "Draft review complete. How should we proceed?" # Bad ASK USER: "What next?" # Too vague ``` 2. **Show Context**: Display relevant information before asking ```cheesecake SHOW: "Task: {task_description}" SHOW: "Estimated cost: ${estimated_cost}" ASK USER: "Proceed with this operation?" ``` 3. **Limit Options**: Keep choices manageable (2-4 ideal, max 10) 4. **Provide Escape Routes**: Always include cancel/skip option ```cheesecake OPTIONS: - "Proceed" → VAR proceed = true - "Skip" → VAR proceed = false # Escape route - "Cancel workflow" → RETURN # Exit option END OPTIONS ``` 5. **Descriptive Checkpoint Names**: Use meaningful names ```cheesecake # Good INTERACTIVE AT "review-draft-before-publish": # Bad INTERACTIVE AT "checkpoint1": ``` ### Use Cases - **Approval workflows**: Cost approval, quality review, safety checks - **Iterative refinement**: User feedback at each iteration - **Agent/model selection**: Let user choose which agent to use - **Path branching**: User chooses workflow direction - **Early exit points**: User can cancel expensive operations **Note**: INTERACTIVE is **optional in v0.0.1**. Added in v0.0.2 for human-in-the-loop workflows. Existing workflows without INTERACTIVE blocks continue to work perfectly. --- ## 11. State & Persistence ### Checkpoints Checkpoints save workflow state to disk for resumability. ```cheesecake # Save checkpoint CHECKPOINT "checkpoint_name": SAVE: {var1, var2, var3} TO: ".cheesecake/state/" # Optional: custom location END CHECKPOINT # Check if checkpoint exists IF CHECKPOINT_EXISTS("checkpoint_name"): RESTORE FROM "checkpoint_name" LOG "Resumed from checkpoint" ELSE: # Execute from scratch VAR var1 = ... END IF ``` ### Memory (Cross-Session Persistence) Memory blocks persist data across multiple executions. ```cheesecake # Define memory MEMORY memory_name: key1: "value1" key2: [list, of, values] key3: {nested: "object"} END MEMORY # Update memory MEMORY memory_name.key1 = "new value" MEMORY memory_name.key3.nested = "updated" # Append to list MEMORY memory_name.key2.APPEND("new item") # Load memory VAR data = LOAD MEMORY memory_name ``` ### Examples ```cheesecake # Checkpoint for long workflow PARALLEL: VAR academic = RUN SESSION(researcher): TASK: "Academic research" VAR industry = RUN SESSION(researcher): TASK: "Industry research" VAR market = RUN SESSION(analyst): TASK: "Market analysis" END PARALLEL # Save checkpoint after expensive operation CHECKPOINT "research-complete": SAVE: {academic, industry, market} END CHECKPOINT # Resume from checkpoint if exists IF CHECKPOINT_EXISTS("outline-complete"): RESTORE FROM "outline-complete" ELSE: VAR combined = RUN SESSION(analyst): TASK: "Synthesize" INPUT: {academic, industry, market} VAR outline = RUN SESSION(writer): TASK: "Create outline" INPUT: {combined} CHECKPOINT "outline-complete": SAVE: {combined, outline} END CHECKPOINT END IF # Memory for project state MEMORY project_state: phase: "research" history: [] END MEMORY # Update history MEMORY project_state.history.APPEND({ timestamp: NOW(), action: "Completed research phase", details: "Found {academic.length} papers" }) ``` --- ## 12. Configuration (CONFIG Block) - v0.0.2+ ### Overview The CONFIG block allows global configuration of workflow execution, including cost management, model defaults, and execution settings. **Added in**: v0.0.2 (Module 11: Cost Management) ### Syntax ```cheesecake CONFIG: # Cost Management BUDGET: CONFIRM_COST_ABOVE: WARN_PARALLEL_ABOVE: WARN_AT_PERCENT: OPTIMIZATION_SUGGESTIONS: # Model Settings DEFAULT_MODEL: # Execution Settings MAX_PARALLEL_SESSIONS: TIMEOUT_DEFAULT: