================================================================================
EXPLORER 0
================================================================================

--- INPUT PROMPT ---

You are an environment design expert helping to build realistic tool ecosystems for AI agents.

We are building an environment for an AI agent that will assist a user with tasks in a specific domain. You need to propose a COMPONENT (a specific service or system) and then propose tools for that component.

<environment>
A cryogenic materials testing facility measuring critical temperatures and magnetic levitation
</environment>

<user>
A physicist developing room-temperature superconductors
</user>

<existing_components>

Component: Quantum Design MultiVu (multivu)
  - multivu_list_measurements: Lists MultiVu measurements currently known to the system. Returns all fields for all measurements that match optional filters. If no filters are provided, it returns every measurement record, regardless of user ownership. Status may include queued, running, completed, or aborted; mode may include resistivity, magnetization, or levitation_height. This call does not modify any records and is safe to use for broad overviews.
    Parameters:
      - status (string) (optional): Optional status filter (e.g., queued, running, completed, aborted).
      - mode (string) (optional): Optional mode filter (e.g., resistivity, magnetization, levitation_height).
  - multivu_get_measurement_data: Retrieves a single measurement by ID, including configuration and full data content. Useful for fetching raw curves (e.g., resistivity vs. temperature, levitation height vs. temperature) for analysis. If the measurement is still running or queued, the current data buffer is returned as-is; no lock is taken and the data may be incomplete. Returns an error if the ID does not correspond to any known measurement.
    Parameters:
      - measurement_id (string) (required): The unique identifier of the measurement to retrieve.
  - multivu_submit_temperature_sweep: Submits a new temperature sweep measurement to MultiVu with specified bounds and field. Creates a measurement record and queues it immediately; the configuration text summarizes the sweep range, magnetic field, mode, and step size. Mode accepts resistivity, magnetization, or levitation_height; values outside instrument limits are clamped to safe ranges and reflected in the returned configuration. If start and end temperatures are identical, or step_size is non-positive, the submission is rejected. Returns the full created measurement with status queued and empty or initial data content.
    Parameters:
      - sample_id (string) (required): Associated sample identifier to link the run with a specific material.
      - start_temp (number) (required): Starting temperature in Kelvin.
      - end_temp (number) (required): Ending temperature in Kelvin.
      - field_tesla (number) (required): Applied magnetic field in Tesla (will be clamped to magnet limits if needed).
      - mode (string) (required): Measurement mode: resistivity, magnetization, or levitation_height.
      - step_size (number) (required): Temperature step size in Kelvin for the sweep (must be > 0).
      - excitation_current_ma (number) (optional): Optional excitation current in mA (used for resistivity mode only).
  - multivu_update_sequence_steps: Replaces the step content of an existing MultiVu sequence. Use this to revise command order, setpoints, dwell times, or field ramps prior to execution. The provided steps string completely overwrites the existing steps; partial edits are not supported by this call. Returns the updated sequence with all fields so you can verify the changes. If the sequence_id does not exist, the operation fails without creating a new sequence.
    Parameters:
      - sequence_id (string) (required): Identifier of the sequence to update.
      - steps (string) (required): Full replacement step content in MultiVu sequence format.
  - multivu_abort_measurement: Attempts to abort a running or queued MultiVu measurement by ID. If the measurement is already completed or previously aborted, no changes are made and the final status is returned. Hardware will be brought to a safe state per MultiVu's built-in interlocks. Returns the measurement with updated status (typically aborted) and any data collected up to the abort point.
    Parameters:
      - measurement_id (string) (required): The unique identifier of the measurement to abort.
      - reason (string) (optional): Optional human-readable reason for aborting, appended to configuration text.
  - multivu_analyze_tc_and_update_sample_notes: Reads a measurement's data to estimate a critical temperature (Tc) and appends the result to the associated sample notes. For resistivity, the method resistivity_drop estimates Tc from a chosen onset/offset criterion; for levitation_height, levitation_onset estimates Tc at the first nonzero stable height. If data are insufficient (e.g., too few points or flat/noisy signal), the call returns a diagnostic and does not modify notes. On success, returns the full updated sample and the original measurement; the sample notes gain a new entry summarizing Tc, mode, and method used. This operation both reads measurement content and writes to sample notes.
    Parameters:
      - measurement_id (string) (required): Measurement whose data will be analyzed for Tc.
      - sample_id (string) (required): Sample to annotate with Tc results.
      - method (string) (required): Tc estimation method: resistivity_drop or levitation_onset.
      - smoothing (boolean) (optional): Optional: apply light smoothing to reduce noise before detection.
      - annotate_prefix (string) (optional): Optional prefix to include in the sample notes before the Tc summary.

Component: Keithley KickStart Instrument Control Software (kickstart)
  - kickstart_list_sessions: Lists all KickStart sessions with their status and configuration text. Optional filters allow narrowing by status (e.g., running, queued, stopped) or type (e.g., time_trace, iv_sweep). Returns all matching sessions across the system without user-based filtering. Useful for getting a live overview of what measurements are configured or in progress.
    Parameters:
      - status (string) (optional): Optional status filter (e.g., running, queued, stopped).
      - type (string) (optional): Optional session type filter (e.g., time_trace, iv_sweep, resistance_logging).
  - kickstart_start_time_trace: Creates and starts a time-trace measurement session on a specified Keithley instrument. The session will source a constant value (current or voltage) and record the chosen measurement function at a fixed interval for a set duration. Values beyond instrument limits are clamped to safe ranges and reflected in the returned configuration text. If the instrument is busy, the session is queued and will begin automatically when available. Returns the full created session record with status (running or queued) and the effective configuration.
    Parameters:
      - instrument_id (string) (required): Identifier of the connected Keithley instrument to use.
      - measure_function (string) (required): What to measure: resistance, voltage, or current.
      - source_mode (string) (required): Source mode: current or voltage.
      - source_value (number) (required): Setpoint value to source in the chosen mode.
      - interval_s (number) (required): Sampling interval in seconds between measurements.
      - duration_s (number) (required): Total duration of the time trace in seconds (must be > 0).
      - session_label (string) (optional): Optional human-readable label to include in the session configuration text.
  - kickstart_fetch_dataset: Retrieves a specific dataset by dataset ID and returns the full CSV data content. If acquisition is still in progress, the current buffer is returned without locking and may be incomplete. Useful for pulling resistance vs. time or IV data for external analysis. Returns all dataset fields including data_csv, which contains the readable data table.
    Parameters:
      - dataset_id (string) (required): The unique identifier of the dataset to retrieve.
  - kickstart_update_source_limit: Updates the compliance/limit setting on a specified instrument in KickStart. The limit applies to the active source mode (e.g., compliance voltage when sourcing current, or compliance current when sourcing voltage). Values are clamped to the instrument's safe range; the returned instrument record reflects the effective limit. This call does not alter running sessions' setpoints but updates the instrument's protection behavior immediately.
    Parameters:
      - instrument_id (string) (required): Identifier of the instrument to update.
      - limit_value (number) (required): New limit/compliance value for the active source mode.
  - kickstart_stop_session_and_export: Stops a running or queued session and exports its most recent dataset as CSV, returning both the final session and dataset records. If the session is already stopped, it re-exports the last dataset. Ensures a graceful stop so the last partially collected interval is included. If no data were collected, an empty dataset is returned with a descriptive name. Returns full fields for the session and the dataset (including data_csv).
    Parameters:
      - session_id (string) (required): The session to stop and export.
      - export_name (string) (optional): Optional name to assign to the exported dataset.
</existing_components>

<task>
1. Identify a REAL component/service that would exist in this environment
   - Must be an actual service, software, or system (e.g., "Microsoft Excel", "Gmail", "Salesforce CRM", "PostgreSQL Database", "Slack")
   - NOT generic categories like "email system" - use specific real services
   - Must be plausible for this specific environment and user role
   - Should NOT duplicate existing components

   STRONGLY PREFER DOMAIN-SPECIFIC COMPONENTS:
   - Prioritize specialized software/services relevant to this specific environment and user role
   - Generic system tools (Terminal, Bash, Text Editor, File System) should only be proposed occasionally when truly essential
   - Think: What specialized tools would this specific user actually use day-to-day?
   - Examples: Instead of "Text Editor", propose "LaTeX Editor" for a researcher, "Code Editor with Linter" for a developer, "Markdown Editor" for documentation

2. Propose 3-6 tools for this component
   - You may choose any number within this range based on what makes sense for the component
   - Each tool should do ONE specific thing (Single Responsibility Principle)
   - Tools should be diverse and cover different operations for this component
   - Avoid "mega-tools" that try to do everything at once
   - Consider what the user might ask the AI agent to do with this component

   ENSURE VARIETY IN READ/WRITE OPERATIONS:
   - Include a MIX of read-only, write-only, and read-write tools
   - Read tools: Query/retrieve data without modification (e.g., list_emails, get_job_status, search_records)
   - Write tools: Create/modify/delete data (e.g., send_email, cancel_job, update_record, delete_file)
   - Read-write tools: Operations that both retrieve and modify (e.g., archive_and_summarize, process_and_update)
   - Realistic components have BOTH read and write capabilities - don't create read-only or write-only components

3. Format requirements:
   - Tool names MUST follow Python method naming (lowercase_with_underscores)
   - Tool names should indicate which component they interact with
   - Naming can be diverse: "read_excel_cell", "send_gmail", "query_salesforce_leads", "postgres_execute_query", "create_slack_channel"
   - Each tool should have clear, specific parameters (not 10+ parameters)

   DESCRIPTION STYLE: BRIEF
   - If BRIEF: Write short 1-2 sentence descriptions for all tools (e.g., "Sends an email to specified recipient.")
   - If DETAILED: Write comprehensive 3-6 sentence descriptions with behavior details, constraints, edge cases, return values
     Example: "Cancels a running SLURM job by job ID. If the job is already completed or cancelled, returns an error. Requires the job to be owned by the current user or admin privileges. Returns cancellation confirmation and final job status."
</task>

<response_format>
Respond with a JSON object in this exact format:
{
  "component_name": "Specific Real Service Name (e.g., Microsoft Excel, Gmail, Salesforce CRM)",
  "component_id": "lowercase_identifier (e.g., excel, gmail, salesforce)",
  "resources": {
    "resource_type": {
      "description": "What this resource represents",
      "fields": ["field1", "field2", "field3"]
    }
  },
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "tool_name_indicating_component",
        "description": "Clear description of what this tool does.",
        "operation_type": "read|write|read-write",
        "parameters": {
          "type": "object",
          "properties": {
            "param_name": {
              "type": "string",
              "description": "Parameter description."
            },
            "tags": {
              "type": "array",
              "items": {"type": "string"},
              "description": "List of tags (for array parameters, MUST include 'items' field)"
            }
          },
          "required": ["param_name"]
        }
      }
    }
  ]
}

IMPORTANT:
- Component must be a REAL service/software that would be used in this environment
- Tool names must be lowercase_with_underscores
- Tool names should make it clear which component they're for (naming convention can vary)
- Each tool should be focused and specific, not a mega-tool
- Each tool MUST specify operation_type: "read", "write", or "read-write"
  * "read" = retrieves/queries data without modification
  * "write" = creates/modifies/deletes data
  * "read-write" = both retrieves and modifies in a single operation
- ARRAY PARAMETERS: If a parameter has "type": "array", you MUST include an "items" field specifying the array element type
  * Example: {"type": "array", "items": {"type": "string"}}
  * Valid item types: "string", "number", "boolean", or object schemas

RESOURCES - Keep them SIMPLE:
- Define what data/entities this component manages (e.g., for SLURM: jobs, queue; for Gmail: emails, folders)
- Use 2-5 fields per resource (MAXIMUM 5 fields, only if absolutely necessary)
- Only include ESSENTIAL fields that tools actually need to read/modify
- DO NOT include: authentication details, permissions, access levels, audit logs, metadata timestamps
- DO NOT include any date or time fields (no created_at, updated_at, timestamp, submit_time, date fields). This is critical for evaluation purposes.
- Good example: job: [job_id, status, user, partition, priority]
- Bad example: job with 20+ fields including detailed permissions, logging, authentication, etc.

CRITICAL - RESOURCES MUST CONTAIN ACTUAL READABLE CONTENT:
- Resources MUST contain a field with ACTUAL READABLE CONTENT, not just references
- Path/URL fields are allowed as OPTIONAL METADATA, but only if a content field is also present
- Good: document: [doc_id, title, content, author] where "content" is the actual text
- Good: document: [doc_id, title, file_path, content, author] where both path AND content exist
- Bad: document: [doc_id, title, file_path, author] where "file_path" is the only data (no actual content)
- Good: email: [email_id, subject, body, sender] where "body" is the actual email text
- Bad: email: [email_id, subject, attachment_url, sender] where URL is the only data (no actual content)
- Good: dataset: [dataset_id, name, data, owner] where "data" is actual data content
- Bad: dataset: [dataset_id, name, root_path, owner] where "root_path" is the only data (no actual content)
- If representing file systems or data collections, define resources as the ACTUAL FILES/ITEMS with content

TOOLS - Return FULL data by default:
- Tools should return ALL fields for ALL matching resources (e.g., list_jobs returns jobs from ALL users, not just current user)
- DO NOT implement access controls or filtering in tool descriptions
- The agent should have full read access to all resource data
- Example: "list_slurm_jobs" should return all jobs in the queue, not just the user's jobs
- Example: "search_emails" should return all matching emails, not filtered by sender/recipient

Only respond with the JSON object, nothing else.
</response_format>

--- OUTPUT ---

{
  "component_name": "Lake Shore MeasureLINK",
  "component_id": "measurelink",
  "resources": {
    "recipe": {
      "description": "Experiment recipes that automate instrument control and logging within MeasureLINK.",
      "fields": ["recipe_id", "name", "steps", "notes"]
    },
    "run": {
      "description": "Executed or active runs started from recipes, including current status and textual log.",
      "fields": ["run_id", "recipe_id", "status", "log"]
    },
    "dataset": {
      "description": "Measurement datasets generated by runs; raw tabular content is stored as CSV text.",
      "fields": ["dataset_id", "name", "data_csv", "run_id"]
    }
  },
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "measurelink_list_recipes",
        "description": "Lists all MeasureLINK recipes, returning full fields including steps and notes. Optional name filter performs a substring match.",
        "operation_type": "read",
        "parameters": {
          "type": "object",
          "properties": {
            "name_contains": {
              "type": "string",
              "description": "Optional substring to filter recipe names."
            }
          },
          "required": []
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "measurelink_start_recipe_run",
        "description": "Starts a new run from a specified recipe. Returns the created run with initial status and log entry including the note if provided.",
        "operation_type": "write",
        "parameters": {
          "type": "object",
          "properties": {
            "recipe_id": {
              "type": "string",
              "description": "Identifier of the recipe to run."
            },
            "run_note": {
              "type": "string",
              "description": "Optional note to append to the run log at start."
            }
          },
          "required": ["recipe_id"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "measurelink_get_run",
        "description": "Retrieves a single run by ID, including full status and complete log content.",
        "operation_type": "read",
        "parameters": {
          "type": "object",
          "properties": {
            "run_id": {
              "type": "string",
              "description": "The run identifier to retrieve."
            }
          },
          "required": ["run_id"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "measurelink_abort_run",
        "description": "Attempts to abort a running or queued run. Returns the run with updated status and a log entry including the reason if provided.",
        "operation_type": "write",
        "parameters": {
          "type": "object",
          "properties": {
            "run_id": {
              "type": "string",
              "description": "The run identifier to abort."
            },
            "reason": {
              "type": "string",
              "description": "Optional human-readable reason to append to the run log."
            }
          },
          "required": ["run_id"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "measurelink_fetch_dataset",
        "description": "Retrieves a dataset by ID and returns all fields including the full data_csv content. If acquisition is ongoing, returns the current buffer.",
        "operation_type": "read",
        "parameters": {
          "type": "object",
          "properties": {
            "dataset_id": {
              "type": "string",
              "description": "The dataset identifier to retrieve."
            }
          },
          "required": ["dataset_id"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "measurelink_analyze_dataset_and_append_note",
        "description": "Estimates Tc from a dataset (resistivity_drop or levitation_onset) and appends a summary note to the associated run log. Returns the updated run and the dataset.",
        "operation_type": "read-write",
        "parameters": {
          "type": "object",
          "properties": {
            "dataset_id": {
              "type": "string",
              "description": "Dataset to analyze for Tc."
            },
            "run_id": {
              "type": "string",
              "description": "Run whose log will be annotated with the Tc summary."
            },
            "method": {
              "type": "string",
              "description": "Tc estimation method: 'resistivity_drop' or 'levitation_onset'."
            },
            "smoothing": {
              "type": "boolean",
              "description": "Apply light smoothing to reduce noise before detection."
            },
            "note_prefix": {
              "type": "string",
              "description": "Optional prefix to include before the Tc summary in the run log."
            }
          },
          "required": ["dataset_id", "run_id", "method"]
        }
      }
    }
  ]
}

================================================================================
EXPLORER 1
================================================================================

--- INPUT PROMPT ---

You are an environment design expert helping to build realistic tool ecosystems for AI agents.

We are building an environment for an AI agent that will assist a user with tasks in a specific domain. You need to propose a COMPONENT (a specific service or system) and then propose tools for that component.

<environment>
A cryogenic materials testing facility measuring critical temperatures and magnetic levitation
</environment>

<user>
A physicist developing room-temperature superconductors
</user>

<existing_components>

Component: Quantum Design MultiVu (multivu)
  - multivu_list_measurements: Lists MultiVu measurements currently known to the system. Returns all fields for all measurements that match optional filters. If no filters are provided, it returns every measurement record, regardless of user ownership. Status may include queued, running, completed, or aborted; mode may include resistivity, magnetization, or levitation_height. This call does not modify any records and is safe to use for broad overviews.
    Parameters:
      - status (string) (optional): Optional status filter (e.g., queued, running, completed, aborted).
      - mode (string) (optional): Optional mode filter (e.g., resistivity, magnetization, levitation_height).
  - multivu_get_measurement_data: Retrieves a single measurement by ID, including configuration and full data content. Useful for fetching raw curves (e.g., resistivity vs. temperature, levitation height vs. temperature) for analysis. If the measurement is still running or queued, the current data buffer is returned as-is; no lock is taken and the data may be incomplete. Returns an error if the ID does not correspond to any known measurement.
    Parameters:
      - measurement_id (string) (required): The unique identifier of the measurement to retrieve.
  - multivu_submit_temperature_sweep: Submits a new temperature sweep measurement to MultiVu with specified bounds and field. Creates a measurement record and queues it immediately; the configuration text summarizes the sweep range, magnetic field, mode, and step size. Mode accepts resistivity, magnetization, or levitation_height; values outside instrument limits are clamped to safe ranges and reflected in the returned configuration. If start and end temperatures are identical, or step_size is non-positive, the submission is rejected. Returns the full created measurement with status queued and empty or initial data content.
    Parameters:
      - sample_id (string) (required): Associated sample identifier to link the run with a specific material.
      - start_temp (number) (required): Starting temperature in Kelvin.
      - end_temp (number) (required): Ending temperature in Kelvin.
      - field_tesla (number) (required): Applied magnetic field in Tesla (will be clamped to magnet limits if needed).
      - mode (string) (required): Measurement mode: resistivity, magnetization, or levitation_height.
      - step_size (number) (required): Temperature step size in Kelvin for the sweep (must be > 0).
      - excitation_current_ma (number) (optional): Optional excitation current in mA (used for resistivity mode only).
  - multivu_update_sequence_steps: Replaces the step content of an existing MultiVu sequence. Use this to revise command order, setpoints, dwell times, or field ramps prior to execution. The provided steps string completely overwrites the existing steps; partial edits are not supported by this call. Returns the updated sequence with all fields so you can verify the changes. If the sequence_id does not exist, the operation fails without creating a new sequence.
    Parameters:
      - sequence_id (string) (required): Identifier of the sequence to update.
      - steps (string) (required): Full replacement step content in MultiVu sequence format.
  - multivu_abort_measurement: Attempts to abort a running or queued MultiVu measurement by ID. If the measurement is already completed or previously aborted, no changes are made and the final status is returned. Hardware will be brought to a safe state per MultiVu's built-in interlocks. Returns the measurement with updated status (typically aborted) and any data collected up to the abort point.
    Parameters:
      - measurement_id (string) (required): The unique identifier of the measurement to abort.
      - reason (string) (optional): Optional human-readable reason for aborting, appended to configuration text.
  - multivu_analyze_tc_and_update_sample_notes: Reads a measurement's data to estimate a critical temperature (Tc) and appends the result to the associated sample notes. For resistivity, the method resistivity_drop estimates Tc from a chosen onset/offset criterion; for levitation_height, levitation_onset estimates Tc at the first nonzero stable height. If data are insufficient (e.g., too few points or flat/noisy signal), the call returns a diagnostic and does not modify notes. On success, returns the full updated sample and the original measurement; the sample notes gain a new entry summarizing Tc, mode, and method used. This operation both reads measurement content and writes to sample notes.
    Parameters:
      - measurement_id (string) (required): Measurement whose data will be analyzed for Tc.
      - sample_id (string) (required): Sample to annotate with Tc results.
      - method (string) (required): Tc estimation method: resistivity_drop or levitation_onset.
      - smoothing (boolean) (optional): Optional: apply light smoothing to reduce noise before detection.
      - annotate_prefix (string) (optional): Optional prefix to include in the sample notes before the Tc summary.

Component: Keithley KickStart Instrument Control Software (kickstart)
  - kickstart_list_sessions: Lists all KickStart sessions with their status and configuration text. Optional filters allow narrowing by status (e.g., running, queued, stopped) or type (e.g., time_trace, iv_sweep). Returns all matching sessions across the system without user-based filtering. Useful for getting a live overview of what measurements are configured or in progress.
    Parameters:
      - status (string) (optional): Optional status filter (e.g., running, queued, stopped).
      - type (string) (optional): Optional session type filter (e.g., time_trace, iv_sweep, resistance_logging).
  - kickstart_start_time_trace: Creates and starts a time-trace measurement session on a specified Keithley instrument. The session will source a constant value (current or voltage) and record the chosen measurement function at a fixed interval for a set duration. Values beyond instrument limits are clamped to safe ranges and reflected in the returned configuration text. If the instrument is busy, the session is queued and will begin automatically when available. Returns the full created session record with status (running or queued) and the effective configuration.
    Parameters:
      - instrument_id (string) (required): Identifier of the connected Keithley instrument to use.
      - measure_function (string) (required): What to measure: resistance, voltage, or current.
      - source_mode (string) (required): Source mode: current or voltage.
      - source_value (number) (required): Setpoint value to source in the chosen mode.
      - interval_s (number) (required): Sampling interval in seconds between measurements.
      - duration_s (number) (required): Total duration of the time trace in seconds (must be > 0).
      - session_label (string) (optional): Optional human-readable label to include in the session configuration text.
  - kickstart_fetch_dataset: Retrieves a specific dataset by dataset ID and returns the full CSV data content. If acquisition is still in progress, the current buffer is returned without locking and may be incomplete. Useful for pulling resistance vs. time or IV data for external analysis. Returns all dataset fields including data_csv, which contains the readable data table.
    Parameters:
      - dataset_id (string) (required): The unique identifier of the dataset to retrieve.
  - kickstart_update_source_limit: Updates the compliance/limit setting on a specified instrument in KickStart. The limit applies to the active source mode (e.g., compliance voltage when sourcing current, or compliance current when sourcing voltage). Values are clamped to the instrument's safe range; the returned instrument record reflects the effective limit. This call does not alter running sessions' setpoints but updates the instrument's protection behavior immediately.
    Parameters:
      - instrument_id (string) (required): Identifier of the instrument to update.
      - limit_value (number) (required): New limit/compliance value for the active source mode.
  - kickstart_stop_session_and_export: Stops a running or queued session and exports its most recent dataset as CSV, returning both the final session and dataset records. If the session is already stopped, it re-exports the last dataset. Ensures a graceful stop so the last partially collected interval is included. If no data were collected, an empty dataset is returned with a descriptive name. Returns full fields for the session and the dataset (including data_csv).
    Parameters:
      - session_id (string) (required): The session to stop and export.
      - export_name (string) (optional): Optional name to assign to the exported dataset.
</existing_components>

<task>
1. Identify a REAL component/service that would exist in this environment
   - Must be an actual service, software, or system (e.g., "Microsoft Excel", "Gmail", "Salesforce CRM", "PostgreSQL Database", "Slack")
   - NOT generic categories like "email system" - use specific real services
   - Must be plausible for this specific environment and user role
   - Should NOT duplicate existing components

   STRONGLY PREFER DOMAIN-SPECIFIC COMPONENTS:
   - Prioritize specialized software/services relevant to this specific environment and user role
   - Generic system tools (Terminal, Bash, Text Editor, File System) should only be proposed occasionally when truly essential
   - Think: What specialized tools would this specific user actually use day-to-day?
   - Examples: Instead of "Text Editor", propose "LaTeX Editor" for a researcher, "Code Editor with Linter" for a developer, "Markdown Editor" for documentation

2. Propose 3-6 tools for this component
   - You may choose any number within this range based on what makes sense for the component
   - Each tool should do ONE specific thing (Single Responsibility Principle)
   - Tools should be diverse and cover different operations for this component
   - Avoid "mega-tools" that try to do everything at once
   - Consider what the user might ask the AI agent to do with this component

   ENSURE VARIETY IN READ/WRITE OPERATIONS:
   - Include a MIX of read-only, write-only, and read-write tools
   - Read tools: Query/retrieve data without modification (e.g., list_emails, get_job_status, search_records)
   - Write tools: Create/modify/delete data (e.g., send_email, cancel_job, update_record, delete_file)
   - Read-write tools: Operations that both retrieve and modify (e.g., archive_and_summarize, process_and_update)
   - Realistic components have BOTH read and write capabilities - don't create read-only or write-only components

3. Format requirements:
   - Tool names MUST follow Python method naming (lowercase_with_underscores)
   - Tool names should indicate which component they interact with
   - Naming can be diverse: "read_excel_cell", "send_gmail", "query_salesforce_leads", "postgres_execute_query", "create_slack_channel"
   - Each tool should have clear, specific parameters (not 10+ parameters)

   DESCRIPTION STYLE: BRIEF
   - If BRIEF: Write short 1-2 sentence descriptions for all tools (e.g., "Sends an email to specified recipient.")
   - If DETAILED: Write comprehensive 3-6 sentence descriptions with behavior details, constraints, edge cases, return values
     Example: "Cancels a running SLURM job by job ID. If the job is already completed or cancelled, returns an error. Requires the job to be owned by the current user or admin privileges. Returns cancellation confirmation and final job status."
</task>

<response_format>
Respond with a JSON object in this exact format:
{
  "component_name": "Specific Real Service Name (e.g., Microsoft Excel, Gmail, Salesforce CRM)",
  "component_id": "lowercase_identifier (e.g., excel, gmail, salesforce)",
  "resources": {
    "resource_type": {
      "description": "What this resource represents",
      "fields": ["field1", "field2", "field3"]
    }
  },
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "tool_name_indicating_component",
        "description": "Clear description of what this tool does.",
        "operation_type": "read|write|read-write",
        "parameters": {
          "type": "object",
          "properties": {
            "param_name": {
              "type": "string",
              "description": "Parameter description."
            },
            "tags": {
              "type": "array",
              "items": {"type": "string"},
              "description": "List of tags (for array parameters, MUST include 'items' field)"
            }
          },
          "required": ["param_name"]
        }
      }
    }
  ]
}

IMPORTANT:
- Component must be a REAL service/software that would be used in this environment
- Tool names must be lowercase_with_underscores
- Tool names should make it clear which component they're for (naming convention can vary)
- Each tool should be focused and specific, not a mega-tool
- Each tool MUST specify operation_type: "read", "write", or "read-write"
  * "read" = retrieves/queries data without modification
  * "write" = creates/modifies/deletes data
  * "read-write" = both retrieves and modifies in a single operation
- ARRAY PARAMETERS: If a parameter has "type": "array", you MUST include an "items" field specifying the array element type
  * Example: {"type": "array", "items": {"type": "string"}}
  * Valid item types: "string", "number", "boolean", or object schemas

RESOURCES - Keep them SIMPLE:
- Define what data/entities this component manages (e.g., for SLURM: jobs, queue; for Gmail: emails, folders)
- Use 2-5 fields per resource (MAXIMUM 5 fields, only if absolutely necessary)
- Only include ESSENTIAL fields that tools actually need to read/modify
- DO NOT include: authentication details, permissions, access levels, audit logs, metadata timestamps
- DO NOT include any date or time fields (no created_at, updated_at, timestamp, submit_time, date fields). This is critical for evaluation purposes.
- Good example: job: [job_id, status, user, partition, priority]
- Bad example: job with 20+ fields including detailed permissions, logging, authentication, etc.

CRITICAL - RESOURCES MUST CONTAIN ACTUAL READABLE CONTENT:
- Resources MUST contain a field with ACTUAL READABLE CONTENT, not just references
- Path/URL fields are allowed as OPTIONAL METADATA, but only if a content field is also present
- Good: document: [doc_id, title, content, author] where "content" is the actual text
- Good: document: [doc_id, title, file_path, content, author] where both path AND content exist
- Bad: document: [doc_id, title, file_path, author] where "file_path" is the only data (no actual content)
- Good: email: [email_id, subject, body, sender] where "body" is the actual email text
- Bad: email: [email_id, subject, attachment_url, sender] where URL is the only data (no actual content)
- Good: dataset: [dataset_id, name, data, owner] where "data" is actual data content
- Bad: dataset: [dataset_id, name, root_path, owner] where "root_path" is the only data (no actual content)
- If representing file systems or data collections, define resources as the ACTUAL FILES/ITEMS with content

TOOLS - Return FULL data by default:
- Tools should return ALL fields for ALL matching resources (e.g., list_jobs returns jobs from ALL users, not just current user)
- DO NOT implement access controls or filtering in tool descriptions
- The agent should have full read access to all resource data
- Example: "list_slurm_jobs" should return all jobs in the queue, not just the user's jobs
- Example: "search_emails" should return all matching emails, not filtered by sender/recipient

Only respond with the JSON object, nothing else.
</response_format>

--- OUTPUT ---

{
  "component_name": "Lake Shore MeasureLINK",
  "component_id": "measurelink",
  "resources": {
    "instrument": {
      "description": "Connected Lake Shore instruments available to MeasureLINK (e.g., Model 336/372 temperature controllers).",
      "fields": ["instrument_id", "model", "role", "status"]
    },
    "ramp": {
      "description": "A temperature ramp sequence running on a controller.",
      "fields": ["ramp_id", "instrument_id", "status", "profile_text"]
    },
    "log_session": {
      "description": "An active or configured sensor logging session managed by MeasureLINK.",
      "fields": ["session_id", "instrument_id", "status", "config_text"]
    },
    "dataset": {
      "description": "An exported data set from MeasureLINK containing logged readings.",
      "fields": ["dataset_id", "name", "data_csv", "source_instrument"]
    }
  },
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "measurelink_list_instruments",
        "description": "Lists all connected Lake Shore instruments with their status and role.",
        "operation_type": "read",
        "parameters": {
          "type": "object",
          "properties": {
            "status": {
              "type": "string",
              "description": "Optional status filter (e.g., online, offline, busy)."
            },
            "role": {
              "type": "string",
              "description": "Optional role filter (e.g., temperature_controller, sensor_monitor)."
            }
          },
          "required": []
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "measurelink_start_temperature_ramp",
        "description": "Starts a temperature ramp on a specified controller with a setpoint and rate.",
        "operation_type": "write",
        "parameters": {
          "type": "object",
          "properties": {
            "instrument_id": {
              "type": "string",
              "description": "Identifier of the Lake Shore controller to use."
            },
            "target_k": {
              "type": "number",
              "description": "Target temperature in Kelvin."
            },
            "rate_k_per_min": {
              "type": "number",
              "description": "Ramp rate in Kelvin per minute."
            },
            "control_loop": {
              "type": "string",
              "description": "Control loop to use (e.g., A or B)."
            }
          },
          "required": ["instrument_id", "target_k", "rate_k_per_min", "control_loop"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "measurelink_update_heater_range",
        "description": "Sets the heater output range for a controller loop to manage power safely.",
        "operation_type": "write",
        "parameters": {
          "type": "object",
          "properties": {
            "instrument_id": {
              "type": "string",
              "description": "Identifier of the controller."
            },
            "control_loop": {
              "type": "string",
              "description": "Control loop to configure (e.g., A or B)."
            },
            "range_value": {
              "type": "string",
              "description": "Heater range setting (e.g., Off, Low, Med, High, or numeric code)."
            }
          },
          "required": ["instrument_id", "control_loop", "range_value"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "measurelink_start_logging_session",
        "description": "Creates and starts a sensor logging session at a fixed interval on selected channels.",
        "operation_type": "write",
        "parameters": {
          "type": "object",
          "properties": {
            "instrument_id": {
              "type": "string",
              "description": "Identifier of the instrument hosting the channels."
            },
            "channels": {
              "type": "array",
              "items": {"type": "string"},
              "description": "List of channel identifiers to log (e.g., A, B, C, or sensor names)."
            },
            "interval_s": {
              "type": "number",
              "description": "Sampling interval in seconds."
            },
            "session_label": {
              "type": "string",
              "description": "Optional human-readable label for the session."
            }
          },
          "required": ["instrument_id", "channels", "interval_s"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "measurelink_stop_logging_and_export",
        "description": "Stops a logging session and exports its data as a dataset CSV, returning both session and dataset info.",
        "operation_type": "read-write",
        "parameters": {
          "type": "object",
          "properties": {
            "session_id": {
              "type": "string",
              "description": "Identifier of the logging session to stop."
            },
            "export_name": {
              "type": "string",
              "description": "Optional name for the exported dataset."
            }
          },
          "required": ["session_id"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "measurelink_get_dataset",
        "description": "Retrieves a dataset by ID, returning the full CSV content and metadata.",
        "operation_type": "read",
        "parameters": {
          "type": "object",
          "properties": {
            "dataset_id": {
              "type": "string",
              "description": "Unique identifier of the dataset to retrieve."
            }
          },
          "required": ["dataset_id"]
        }
      }
    }
  ]
}

================================================================================
EXPLORER 2
================================================================================

--- INPUT PROMPT ---

You are an environment design expert helping to build realistic tool ecosystems for AI agents.

We are building an environment for an AI agent that will assist a user with tasks in a specific domain. You need to propose a COMPONENT (a specific service or system) and then propose tools for that component.

<environment>
A cryogenic materials testing facility measuring critical temperatures and magnetic levitation
</environment>

<user>
A physicist developing room-temperature superconductors
</user>

<existing_components>

Component: Quantum Design MultiVu (multivu)
  - multivu_list_measurements: Lists MultiVu measurements currently known to the system. Returns all fields for all measurements that match optional filters. If no filters are provided, it returns every measurement record, regardless of user ownership. Status may include queued, running, completed, or aborted; mode may include resistivity, magnetization, or levitation_height. This call does not modify any records and is safe to use for broad overviews.
    Parameters:
      - status (string) (optional): Optional status filter (e.g., queued, running, completed, aborted).
      - mode (string) (optional): Optional mode filter (e.g., resistivity, magnetization, levitation_height).
  - multivu_get_measurement_data: Retrieves a single measurement by ID, including configuration and full data content. Useful for fetching raw curves (e.g., resistivity vs. temperature, levitation height vs. temperature) for analysis. If the measurement is still running or queued, the current data buffer is returned as-is; no lock is taken and the data may be incomplete. Returns an error if the ID does not correspond to any known measurement.
    Parameters:
      - measurement_id (string) (required): The unique identifier of the measurement to retrieve.
  - multivu_submit_temperature_sweep: Submits a new temperature sweep measurement to MultiVu with specified bounds and field. Creates a measurement record and queues it immediately; the configuration text summarizes the sweep range, magnetic field, mode, and step size. Mode accepts resistivity, magnetization, or levitation_height; values outside instrument limits are clamped to safe ranges and reflected in the returned configuration. If start and end temperatures are identical, or step_size is non-positive, the submission is rejected. Returns the full created measurement with status queued and empty or initial data content.
    Parameters:
      - sample_id (string) (required): Associated sample identifier to link the run with a specific material.
      - start_temp (number) (required): Starting temperature in Kelvin.
      - end_temp (number) (required): Ending temperature in Kelvin.
      - field_tesla (number) (required): Applied magnetic field in Tesla (will be clamped to magnet limits if needed).
      - mode (string) (required): Measurement mode: resistivity, magnetization, or levitation_height.
      - step_size (number) (required): Temperature step size in Kelvin for the sweep (must be > 0).
      - excitation_current_ma (number) (optional): Optional excitation current in mA (used for resistivity mode only).
  - multivu_update_sequence_steps: Replaces the step content of an existing MultiVu sequence. Use this to revise command order, setpoints, dwell times, or field ramps prior to execution. The provided steps string completely overwrites the existing steps; partial edits are not supported by this call. Returns the updated sequence with all fields so you can verify the changes. If the sequence_id does not exist, the operation fails without creating a new sequence.
    Parameters:
      - sequence_id (string) (required): Identifier of the sequence to update.
      - steps (string) (required): Full replacement step content in MultiVu sequence format.
  - multivu_abort_measurement: Attempts to abort a running or queued MultiVu measurement by ID. If the measurement is already completed or previously aborted, no changes are made and the final status is returned. Hardware will be brought to a safe state per MultiVu's built-in interlocks. Returns the measurement with updated status (typically aborted) and any data collected up to the abort point.
    Parameters:
      - measurement_id (string) (required): The unique identifier of the measurement to abort.
      - reason (string) (optional): Optional human-readable reason for aborting, appended to configuration text.
  - multivu_analyze_tc_and_update_sample_notes: Reads a measurement's data to estimate a critical temperature (Tc) and appends the result to the associated sample notes. For resistivity, the method resistivity_drop estimates Tc from a chosen onset/offset criterion; for levitation_height, levitation_onset estimates Tc at the first nonzero stable height. If data are insufficient (e.g., too few points or flat/noisy signal), the call returns a diagnostic and does not modify notes. On success, returns the full updated sample and the original measurement; the sample notes gain a new entry summarizing Tc, mode, and method used. This operation both reads measurement content and writes to sample notes.
    Parameters:
      - measurement_id (string) (required): Measurement whose data will be analyzed for Tc.
      - sample_id (string) (required): Sample to annotate with Tc results.
      - method (string) (required): Tc estimation method: resistivity_drop or levitation_onset.
      - smoothing (boolean) (optional): Optional: apply light smoothing to reduce noise before detection.
      - annotate_prefix (string) (optional): Optional prefix to include in the sample notes before the Tc summary.

Component: Keithley KickStart Instrument Control Software (kickstart)
  - kickstart_list_sessions: Lists all KickStart sessions with their status and configuration text. Optional filters allow narrowing by status (e.g., running, queued, stopped) or type (e.g., time_trace, iv_sweep). Returns all matching sessions across the system without user-based filtering. Useful for getting a live overview of what measurements are configured or in progress.
    Parameters:
      - status (string) (optional): Optional status filter (e.g., running, queued, stopped).
      - type (string) (optional): Optional session type filter (e.g., time_trace, iv_sweep, resistance_logging).
  - kickstart_start_time_trace: Creates and starts a time-trace measurement session on a specified Keithley instrument. The session will source a constant value (current or voltage) and record the chosen measurement function at a fixed interval for a set duration. Values beyond instrument limits are clamped to safe ranges and reflected in the returned configuration text. If the instrument is busy, the session is queued and will begin automatically when available. Returns the full created session record with status (running or queued) and the effective configuration.
    Parameters:
      - instrument_id (string) (required): Identifier of the connected Keithley instrument to use.
      - measure_function (string) (required): What to measure: resistance, voltage, or current.
      - source_mode (string) (required): Source mode: current or voltage.
      - source_value (number) (required): Setpoint value to source in the chosen mode.
      - interval_s (number) (required): Sampling interval in seconds between measurements.
      - duration_s (number) (required): Total duration of the time trace in seconds (must be > 0).
      - session_label (string) (optional): Optional human-readable label to include in the session configuration text.
  - kickstart_fetch_dataset: Retrieves a specific dataset by dataset ID and returns the full CSV data content. If acquisition is still in progress, the current buffer is returned without locking and may be incomplete. Useful for pulling resistance vs. time or IV data for external analysis. Returns all dataset fields including data_csv, which contains the readable data table.
    Parameters:
      - dataset_id (string) (required): The unique identifier of the dataset to retrieve.
  - kickstart_update_source_limit: Updates the compliance/limit setting on a specified instrument in KickStart. The limit applies to the active source mode (e.g., compliance voltage when sourcing current, or compliance current when sourcing voltage). Values are clamped to the instrument's safe range; the returned instrument record reflects the effective limit. This call does not alter running sessions' setpoints but updates the instrument's protection behavior immediately.
    Parameters:
      - instrument_id (string) (required): Identifier of the instrument to update.
      - limit_value (number) (required): New limit/compliance value for the active source mode.
  - kickstart_stop_session_and_export: Stops a running or queued session and exports its most recent dataset as CSV, returning both the final session and dataset records. If the session is already stopped, it re-exports the last dataset. Ensures a graceful stop so the last partially collected interval is included. If no data were collected, an empty dataset is returned with a descriptive name. Returns full fields for the session and the dataset (including data_csv).
    Parameters:
      - session_id (string) (required): The session to stop and export.
      - export_name (string) (optional): Optional name to assign to the exported dataset.
</existing_components>

<task>
1. Identify a REAL component/service that would exist in this environment
   - Must be an actual service, software, or system (e.g., "Microsoft Excel", "Gmail", "Salesforce CRM", "PostgreSQL Database", "Slack")
   - NOT generic categories like "email system" - use specific real services
   - Must be plausible for this specific environment and user role
   - Should NOT duplicate existing components

   STRONGLY PREFER DOMAIN-SPECIFIC COMPONENTS:
   - Prioritize specialized software/services relevant to this specific environment and user role
   - Generic system tools (Terminal, Bash, Text Editor, File System) should only be proposed occasionally when truly essential
   - Think: What specialized tools would this specific user actually use day-to-day?
   - Examples: Instead of "Text Editor", propose "LaTeX Editor" for a researcher, "Code Editor with Linter" for a developer, "Markdown Editor" for documentation

2. Propose 3-6 tools for this component
   - You may choose any number within this range based on what makes sense for the component
   - Each tool should do ONE specific thing (Single Responsibility Principle)
   - Tools should be diverse and cover different operations for this component
   - Avoid "mega-tools" that try to do everything at once
   - Consider what the user might ask the AI agent to do with this component

   ENSURE VARIETY IN READ/WRITE OPERATIONS:
   - Include a MIX of read-only, write-only, and read-write tools
   - Read tools: Query/retrieve data without modification (e.g., list_emails, get_job_status, search_records)
   - Write tools: Create/modify/delete data (e.g., send_email, cancel_job, update_record, delete_file)
   - Read-write tools: Operations that both retrieve and modify (e.g., archive_and_summarize, process_and_update)
   - Realistic components have BOTH read and write capabilities - don't create read-only or write-only components

3. Format requirements:
   - Tool names MUST follow Python method naming (lowercase_with_underscores)
   - Tool names should indicate which component they interact with
   - Naming can be diverse: "read_excel_cell", "send_gmail", "query_salesforce_leads", "postgres_execute_query", "create_slack_channel"
   - Each tool should have clear, specific parameters (not 10+ parameters)

   DESCRIPTION STYLE: BRIEF
   - If BRIEF: Write short 1-2 sentence descriptions for all tools (e.g., "Sends an email to specified recipient.")
   - If DETAILED: Write comprehensive 3-6 sentence descriptions with behavior details, constraints, edge cases, return values
     Example: "Cancels a running SLURM job by job ID. If the job is already completed or cancelled, returns an error. Requires the job to be owned by the current user or admin privileges. Returns cancellation confirmation and final job status."
</task>

<response_format>
Respond with a JSON object in this exact format:
{
  "component_name": "Specific Real Service Name (e.g., Microsoft Excel, Gmail, Salesforce CRM)",
  "component_id": "lowercase_identifier (e.g., excel, gmail, salesforce)",
  "resources": {
    "resource_type": {
      "description": "What this resource represents",
      "fields": ["field1", "field2", "field3"]
    }
  },
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "tool_name_indicating_component",
        "description": "Clear description of what this tool does.",
        "operation_type": "read|write|read-write",
        "parameters": {
          "type": "object",
          "properties": {
            "param_name": {
              "type": "string",
              "description": "Parameter description."
            },
            "tags": {
              "type": "array",
              "items": {"type": "string"},
              "description": "List of tags (for array parameters, MUST include 'items' field)"
            }
          },
          "required": ["param_name"]
        }
      }
    }
  ]
}

IMPORTANT:
- Component must be a REAL service/software that would be used in this environment
- Tool names must be lowercase_with_underscores
- Tool names should make it clear which component they're for (naming convention can vary)
- Each tool should be focused and specific, not a mega-tool
- Each tool MUST specify operation_type: "read", "write", or "read-write"
  * "read" = retrieves/queries data without modification
  * "write" = creates/modifies/deletes data
  * "read-write" = both retrieves and modifies in a single operation
- ARRAY PARAMETERS: If a parameter has "type": "array", you MUST include an "items" field specifying the array element type
  * Example: {"type": "array", "items": {"type": "string"}}
  * Valid item types: "string", "number", "boolean", or object schemas

RESOURCES - Keep them SIMPLE:
- Define what data/entities this component manages (e.g., for SLURM: jobs, queue; for Gmail: emails, folders)
- Use 2-5 fields per resource (MAXIMUM 5 fields, only if absolutely necessary)
- Only include ESSENTIAL fields that tools actually need to read/modify
- DO NOT include: authentication details, permissions, access levels, audit logs, metadata timestamps
- DO NOT include any date or time fields (no created_at, updated_at, timestamp, submit_time, date fields). This is critical for evaluation purposes.
- Good example: job: [job_id, status, user, partition, priority]
- Bad example: job with 20+ fields including detailed permissions, logging, authentication, etc.

CRITICAL - RESOURCES MUST CONTAIN ACTUAL READABLE CONTENT:
- Resources MUST contain a field with ACTUAL READABLE CONTENT, not just references
- Path/URL fields are allowed as OPTIONAL METADATA, but only if a content field is also present
- Good: document: [doc_id, title, content, author] where "content" is the actual text
- Good: document: [doc_id, title, file_path, content, author] where both path AND content exist
- Bad: document: [doc_id, title, file_path, author] where "file_path" is the only data (no actual content)
- Good: email: [email_id, subject, body, sender] where "body" is the actual email text
- Bad: email: [email_id, subject, attachment_url, sender] where URL is the only data (no actual content)
- Good: dataset: [dataset_id, name, data, owner] where "data" is actual data content
- Bad: dataset: [dataset_id, name, root_path, owner] where "root_path" is the only data (no actual content)
- If representing file systems or data collections, define resources as the ACTUAL FILES/ITEMS with content

TOOLS - Return FULL data by default:
- Tools should return ALL fields for ALL matching resources (e.g., list_jobs returns jobs from ALL users, not just current user)
- DO NOT implement access controls or filtering in tool descriptions
- The agent should have full read access to all resource data
- Example: "list_slurm_jobs" should return all jobs in the queue, not just the user's jobs
- Example: "search_emails" should return all matching emails, not filtered by sender/recipient

Only respond with the JSON object, nothing else.
</response_format>

--- OUTPUT ---

{
  "component_name": "Lake Shore MeasureLINK",
  "component_id": "measurelink",
  "resources": {
    "task": {
      "description": "Automation tasks/workflows configured in MeasureLINK (e.g., temperature sweeps, sensor logging).",
      "fields": ["task_id", "status", "type", "steps_text"]
    },
    "dataset": {
      "description": "Measured data exported or generated by tasks.",
      "fields": ["dataset_id", "name", "data_csv", "source_task_id", "analysis_text"]
    },
    "controller": {
      "description": "Lake Shore controllers managed by MeasureLINK (e.g., temperature controllers), including current setpoint.",
      "fields": ["controller_id", "name", "config_text", "setpoint"]
    }
  },
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "measurelink_list_tasks",
        "description": "Lists all MeasureLINK tasks with optional status and type filters; returns full records for every matching task.",
        "operation_type": "read",
        "parameters": {
          "type": "object",
          "properties": {
            "status": {
              "type": "string",
              "description": "Optional task status filter (e.g., queued, running, completed, aborted)."
            },
            "type": {
              "type": "string",
              "description": "Optional task type filter (e.g., temp_sweep, sensor_log)."
            }
          },
          "required": []
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "measurelink_start_temperature_sweep",
        "description": "Creates and starts a temperature sweep task on a specified controller, logging selected channels; returns the created task.",
        "operation_type": "write",
        "parameters": {
          "type": "object",
          "properties": {
            "controller_id": {
              "type": "string",
              "description": "Target controller to command (e.g., Model 336/372)."
            },
            "start_temp": {
              "type": "number",
              "description": "Starting temperature in Kelvin."
            },
            "end_temp": {
              "type": "number",
              "description": "Ending temperature in Kelvin."
            },
            "ramp_rate_k_per_min": {
              "type": "number",
              "description": "Ramp rate in K/min for the sweep."
            },
            "dwell_s": {
              "type": "number",
              "description": "Dwell time in seconds at each step (0 for continuous ramp)."
            },
            "channels": {
              "type": "array",
              "items": { "type": "string" },
              "description": "Sensor or measurement channels to log (e.g., 'CH1_T', 'CH2_R')."
            },
            "step_k": {
              "type": "number",
              "description": "Optional step size in Kelvin; if omitted, a continuous ramp is used."
            }
          },
          "required": ["controller_id", "start_temp", "end_temp", "ramp_rate_k_per_min", "dwell_s", "channels"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "measurelink_fetch_dataset",
        "description": "Retrieves the full dataset by ID, including the complete CSV content and any analysis text.",
        "operation_type": "read",
        "parameters": {
          "type": "object",
          "properties": {
            "dataset_id": {
              "type": "string",
              "description": "Unique identifier of the dataset to fetch."
            }
          },
          "required": ["dataset_id"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "measurelink_update_controller_setpoint",
        "description": "Updates a controller's temperature setpoint; returns the updated controller record.",
        "operation_type": "write",
        "parameters": {
          "type": "object",
          "properties": {
            "controller_id": {
              "type": "string",
              "description": "Controller to update."
            },
            "setpoint_k": {
              "type": "number",
              "description": "New setpoint in Kelvin."
            }
          },
          "required": ["controller_id", "setpoint_k"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "measurelink_stop_task_and_export",
        "description": "Stops a running or queued task and exports its most recent dataset; returns the final task and dataset.",
        "operation_type": "read-write",
        "parameters": {
          "type": "object",
          "properties": {
            "task_id": {
              "type": "string",
              "description": "Task to stop and export."
            },
            "export_name": {
              "type": "string",
              "description": "Optional name to assign to the exported dataset."
            }
          },
          "required": ["task_id"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "measurelink_analyze_tc_and_update_dataset",
        "description": "Analyzes a dataset to estimate Tc (e.g., resistivity drop) and appends a summary to analysis_text; returns the updated dataset.",
        "operation_type": "read-write",
        "parameters": {
          "type": "object",
          "properties": {
            "dataset_id": {
              "type": "string",
              "description": "Dataset to analyze for Tc."
            },
            "method": {
              "type": "string",
              "description": "Tc estimation method (e.g., resistance_drop)."
            },
            "smoothing": {
              "type": "boolean",
              "description": "Apply light smoothing before detection."
            },
            "annotate_prefix": {
              "type": "string",
              "description": "Optional prefix text to include before the Tc summary."
            }
          },
          "required": ["dataset_id", "method"]
        }
      }
    }
  ]
}

