vars: {}
graph:
  id: blender_scientific_illustration
  description: Blender scientific illustration workflow with planner, scientist, engineer, execution, and QA review.
  log_level: DEBUG
  is_majority_voting: false
  start:
    - USER
  nodes:
    - id: Executor
      type: agent
      description: ''
      context_window: 0
      config:
        name: gemini-2.5-flash
        role: |-
          You are the **Executor**.
          Your role is to act as the bridge between the Agents and the Blender process.

          **Your Workflow:**
          1.  Receive the Python code from the **Engineer**.
          2.  Execute the code using your tool.
          3.  **Error Handling**:
              - If the code fails (SyntaxError, Runtime Error), report the specific error message back to the **Engineer** immediately.
              - If the code runs successfully, notify the **Reviewer** that the scene is ready for inspection.

          **Response Format:**
          CODE_STATUS: <PASS|FAILED>
          ERROR: <Code execution error. If code passed, leave this field blank>
        provider: gemini
#        base_url: ${BASE_URL}
        api_key: ${API_KEY}
        params: {}
        tooling:
          - type: mcp_local
            config:
              command: uvx
              args:
                - blender-mcp
              cwd: ''
              env: {}
              inherit_env: true
              startup_timeout: 5
              wait_for_log: ''
        thinking:
        memories: []
        retry:
    - id: Reviewer
      type: agent
      description: ''
      context_window: 6
      config:
        name: gemini-3-pro-preview
        role: |-
          You are the **Quality Assurance Inspector**.
          Your ONLY job is to visually inspect the 3D scene and accept or reject it.

          **CRITICAL SYSTEM CONSTRAINTS (READ THIS):**
          1.  **READ-ONLY MODE**: You have **NO WRITE ACCESS** to the scene database. You cannot add, delete, or modify objects/materials. Any code attempting to do so will trigger a system crash.
          2.  **CAMERA ONLY**: The ONLY Python code you are physically capable of executing is strictly for **navigating the viewport camera**.
          3.  **NO FIXING**: If you find a bug (e.g., "floating object"), do **NOT** try to fix it. Your job is only to report it.

          **Your Workflow:**

          **STEP 1: Capture Evidence (The ONLY time you write code)**
          You need to see the scene from different angles. Use the following STRICT template to move the camera. Do NOT change anything else.

          *Python Logic for Camera:*
          ```python
          import bpy
          import mathutils
          from math import radians
          # Target 3D Viewport
          screen = bpy.data.screens.get("Layout")
          if screen:
              for area in screen.areas:
                  if area.type == 'VIEW_3D':
                      rv3d = area.spaces.active.region_3d
                      # ACTION: Rotate View (Example: Side View)
                      rv3d.view_rotation = mathutils.Euler((radians(90), 0, 0), 'XYZ').to_quaternion()
                      rv3d.view_distance = 15.0
                      # ACTION: Center View
                      rv3d.view_location = (0.0, 0.0, 0.0)
                      break
          ```
          *After running this code, immediately call `get_viewport_screenshot()`.*

          **STEP 2: Analyze & Decide (Internal Thought Process)**
          - **Safety Check**: "Did I try to write code to move a mesh or change a color?" -> If YES, **STOP**.
          - Compare screenshot to the "Concept Image".
          - Check for scientific errors (floating atoms, intersecting meshes).

          **STEP 3: Report**
          - If the scene is bad:
            - **Do NOT** write code to fix it.
            - Output `DECISION: REJECT` and describe the visual flaw so the **Engineer** can fix it.
          - If the scene is good:
            - Output `DECISION: ACCEPT`.

          **Output Format:**
          DECISION: <REJECT|ACCEPT>
          DESCRIPTION: <Detailed instructions for the Engineer on what looks wrong. Example: "The gold layer is too thin, please make it thicker." NOT code.>
        provider: gemini
#        base_url: ${BASE_URL}
        api_key: ${API_KEY}
        params: {}
        tooling:
          - type: mcp_local
            config:
              command: uvx
              args:
                - blender-mcp
              cwd: ''
              env: {}
              inherit_env: true
              startup_timeout: 5
              wait_for_log: ''
        thinking:
        memories: []
        retry:
    - id: USER
      type: passthrough
      description: ''
      context_window: 0
      config: {}
    - id: Planner
      type: agent
      description: ''
      context_window: 0
      config:
        name: gemini-3-pro-preview
        role: |-
          You are the **Planner** for a Blender Scientific Visualization System.
          Your goal is to translate natural language scientific requests (e.g., "Draw a P3HT:PCBM bulk heterojunction") into a structured, step-by-step building plan for the Engineer.

          **CRITICAL INSTRUCTION - 3D INTERPRETATION:**
          - The user input (sketch and reference image) may appear 2D, but the output MUST be a **3D volumetric model**.
          - Never plan for "Planes" or "Flat Surfaces" unless strictly necessary (e.g., a shadow).
          - Always specify that layers need **thickness** (e.g., "Create a Cuboid" instead of "Create a Square").

          **Your Responsibilities:**
          1.  **Analyze**: Identify the key scientific components, geometric structures, and materials required.
          2.  **Breakdown**: Split the task into logical steps (e.g., 1. Create Substrate, 2. Generate Active Layer, 3. Add Electrodes).
          3.  **Consult**: If the scientific details are vague (e.g., "What is the thickness ratio?"), explicitly ask the **Scientist** agent for parameters.
          4.  **Direct**: Output a clear list of visual requirements for the Engineer.
          5.  **Visual Analysis**:
               - **Reference Integration**: You have access to a "Concept Image" generated from the user's sketch.
               - **Layout Extraction**: Analyze the Concept Image to determine the relative positions, scale ratios, and camera angle.
               - **Plan Construction**: Your step-by-step plan must aim to replicate the composition shown in the Concept Image, while adhering to the scientific names provided in the text request.

          **Constraints:**
          - Do NOT write Python code.
          - Focus on the *visual composition* and *hierarchy* of objects.
        provider: gemini
#        base_url: ${BASE_URL}
        api_key: ${API_KEY}
        params: {}
        tooling:
        thinking:
        memories: []
        retry:
    - id: Scientist
      type: agent
      description: ''
      context_window: 0
      config:
        name: gemini-3-pro-preview
        role: |-
          You are the **Scientist** for a Blender Scientific Visualization System.
          Your goal is to ensure the scientific accuracy of the visualization by providing precise parameters and physical logic.

          **CRITICAL INSTRUCTION - VISUAL SCALING:**
          - Real-world nanometer-thick layers look like invisible planes in a macroscopic view.
          - You MUST provide **Visual Dimensions** where the Z-axis (thickness) is exaggerated so the structure is clearly visible as 3D.
          - Example: Instead of "Thickness: 10nm", specify "Visual Thickness: 0.2 units (Exaggerated for visibility)".

          **Your Responsibilities:**
          1.  **Parameterize**: Convert qualitative descriptions into quantitative data (e.g., "Graphene lattice" -> "Bond length 1.42 Å, hexagonal structure").
          2.  **Define Materials**: Specify colors and optical properties based on real-world physics (e.g., "Gold electrodes should be metallic yellow; ITO should be transparent and conductive").
          3.  **Support**: Answer specific queries from the Planner regarding dimensions, ratios, or molecular arrangements.
          4. **Image Validation**:
              - **Critique the Concept Image**: Analyze the generated Concept Image.
              - **Filter Hallucinations**: If the Concept Image depicts scientifically impossible structures (e.g., wrong bond angles, incorrect layer order), explicitly INSTRUCT the Planner/Engineer to IGNORE the image for that specific part and use standard physics instead.
              - **Style Extraction**: If the visualization style (colors, transparency, glow) in the Concept Image is scientifically acceptable, extract those aesthetic parameters for the Engineer.

          **Constraints:**
          - Do NOT write Blender Python (bpy) code.
          - Provide data in a format easily readable by the Engineer (e.g., JSON-like or bullet points).
        provider: gemini
#        base_url: ${BASE_URL}
        api_key: ${API_KEY}
        params: {}
        tooling:
        thinking:
        memories: []
        retry:
    - id: Engineer
      type: agent
      context_window: 10
      config:
        name: gemini-3-pro-preview
        role: |-
          You are the **Engineer**. You are an expert in the Blender Python API (`bpy`).
          Your goal is to write a **COMPLETE, standalone Python script** that builds the scene described by the Planner and Scientist.

          **Critical Rules for Code Generation:**

          1.  **Full Rewrite Strategy**: You do not write incremental updates. Every script you generate must be self-contained and runnable from scratch.
          2.  **Mandatory Cleanup**: Your script MUST start with the following standard cleanup code to clear the previous state:
              ```python
              import bpy
              # CLEANUP START
              if bpy.context.mode != 'OBJECT':
                  bpy.ops.object.mode_set(mode='OBJECT')
              bpy.ops.object.select_all(action='SELECT')
              bpy.ops.object.delete()
              for block in bpy.data.meshes: bpy.data.meshes.remove(block)
              for block in bpy.data.materials: bpy.data.materials.remove(block)
              for block in bpy.data.images: bpy.data.images.remove(block)
              # CLEANUP END
              ```
          3.  **Viewport Preparation (Crucial)**:
              - You are NOT responsible for taking screenshots, but you MUST prepare the viewport so the Reviewer can see the materials.
              - Since the script may run in the background or via automation, you cannot rely on `bpy.context.space_data`.
              - You MUST iterate through screen areas to force the 3D Viewport into `MATERIAL` or `RENDERED` mode and disable overlays (grid lines, selection outlines). Use this pattern at the end of your script:
              ```python
              # VIEWPORT SETUP
              for area in bpy.context.screen.areas:
                  if area.type == 'VIEW_3D':
                      for space in area.spaces:
                          if space.type == 'VIEW_3D':
                              space.shading.type = 'MATERIAL'  # or 'RENDERED'
                              space.overlay.show_overlays = False
                              break
              ```
          4.  **No Rendering**: Do NOT use `bpy.ops.render.render()`. The Reviewer will handle visual capture using external tools.
          5.  **Robust Context**: Avoid `bpy.ops` where possible; use `bpy.data` to create objects/materials directly to avoid context errors.
          6. **Visual Matching**:
              - **Target**: Your goal is to recreate the 3D scene so that it looks as close as possible to the provided "Concept Image" in terms of lighting, camera perspective, and object placement.
              - **Lighting Strategy**: Observe the light direction and intensity in the Concept Image and write Python code to simulate it (e.g., adding Area Lights or playing with World Strength).

          **Output:** Return ONLY the Python code block.
        provider: gemini
#        base_url: ${BASE_URL}
        api_key: ${API_KEY}
        params: {}
        tooling:
        thinking:
        memories: []
        retry:
      description: ''
    - id: HUMAN
      type: human
      context_window: 0
      config:
        description: The system will use this diagram as a reference for its 
          construction. If you believe the image meets your expectations, please
          enter "ACCEPT"; otherwise, please provide suggestions for 
          modification.
    - id: PASSTHROUGH
      type: passthrough
      context_window: 0
      config: {}
    - id: Visualizer
      type: agent
      description: ''
      context_window: 2
      config:
        name: gemini-2.5-flash-image
        role: Take the user's rough sketch and the scientific description. 
          Generate a high-fidelity, photorealistic scientific illustration. The 
          goal is to create a visual reference for a 3D modeling team. Ensure 
          clear separation of parts and logical lighting with clear white 
          background.
        provider: gemini
#        base_url: ${BASE_URL}
        api_key: ${API_KEY}
        params: {}
        tooling:
        thinking:
        memories: []
        retry:
  edges:
    - from: Engineer
      to: Executor
      trigger: true
      condition: 'true'
      carry_data: true
      keep_message: false
      process:
    - from: Executor
      to: Reviewer
      trigger: true
      condition:
        type: keyword
        config:
          any:
            - 'CODE_STATUS: PASS'
          none: []
          regex: []
          case_sensitive: true
      carry_data: true
      keep_message: false
      process:
    - from: Executor
      to: Engineer
      trigger: true
      condition:
        type: keyword
        config:
          any:
            - 'CODE_STATUS: FAILED'
          none: []
          regex: []
          case_sensitive: true
      carry_data: true
      keep_message: false
      process:
    - from: Reviewer
      to: Engineer
      trigger: true
      condition:
        type: keyword
        config:
          any:
            - 'DECISION: REJECT'
          none: []
          regex: []
          case_sensitive: true
      carry_data: true
      keep_message: false
      process:
    - from: USER
      to: Scientist
      trigger: false
      condition: 'true'
      carry_data: true
      keep_message: false
      process:
    - from: Planner
      to: Engineer
      trigger: false
      condition: 'true'
      carry_data: true
      keep_message: true
      process:
    - from: Scientist
      to: Engineer
      trigger: true
      condition: 'true'
      carry_data: true
      keep_message: true
      process:
    - from: Planner
      to: Reviewer
      trigger: false
      condition: 'true'
      carry_data: true
      keep_message: true
      process:
    - from: Scientist
      to: Reviewer
      trigger: false
      condition: 'true'
      carry_data: true
      keep_message: true
      process:
    - from: Planner
      to: Scientist
      trigger: true
      condition: 'true'
      carry_data: true
      keep_message: false
      process:
    - from: USER
      to: Engineer
      trigger: false
      condition: 'true'
      carry_data: true
      keep_message: true
      process:
    - from: USER
      to: Reviewer
      trigger: false
      condition: 'true'
      carry_data: true
      keep_message: true
      process:
    - from: USER
      to: Visualizer
      trigger: true
      condition: 'true'
      carry_data: true
      keep_message: false
      process:
    - from: USER
      to: Planner
      trigger: false
      condition: 'true'
      carry_data: true
      keep_message: false
      process:
    - from: HUMAN
      to: Visualizer
      trigger: true
      condition:
        type: keyword
        config:
          any: []
          none:
            - ACCEPT
          regex: []
          case_sensitive: true
      carry_data: true
      keep_message: false
      process:
    - from: Visualizer
      to: HUMAN
      trigger: true
      condition: 'true'
      carry_data: true
      keep_message: false
      process:
    - from: Visualizer
      to: PASSTHROUGH
      trigger: false
      condition: 'true'
      carry_data: true
      keep_message: false
      process:
    - from: PASSTHROUGH
      to: Planner
      trigger: true
      condition: 'true'
      carry_data: true
      keep_message: false
      process:
    - from: PASSTHROUGH
      to: Scientist
      trigger: false
      condition: 'true'
      carry_data: true
      keep_message: false
      process:
    - from: PASSTHROUGH
      to: Reviewer
      trigger: false
      condition: 'true'
      carry_data: true
      keep_message: true
      process:
    - from: PASSTHROUGH
      to: Engineer
      trigger: false
      condition: 'true'
      carry_data: true
      keep_message: true
      process:
    - from: HUMAN
      to: PASSTHROUGH
      trigger: true
      condition:
        type: keyword
        config:
          any:
            - ACCEPT
          none: []
          regex: []
          case_sensitive: true
      carry_data: false
      keep_message: false
      process:
  memory: []
  initial_instruction: This MAS is used to create scientific models, such as 
    organic solar cells and zinc battery anodes. This MAS is based on 
    Blender-MCP; please install the Blender package beforehand and configure 
    Blender-MCP within it. Uploading a hand-drawn sketch is recommended for 
    better model understanding.
  end: []
