Browser-readable recovery surface

FlyLab agent guide

This HTML page mirrors FlyLab's static agent documentation because some in-app browsers block top-level navigation to JSON resources. It does not create a fallback transport or make Site Tools callable.

Keep the live laboratory open in its original tab. FlyLab's revision and artifacts belong to that page session; this static guide does not retain them.

Return to the live laboratory

Compatibility check

  1. Use the latest ChatGPT desktop app's built-in browser with GPT-5.6 Sol or Terra, or Chrome 149+ with WebMCP testing enabled.
  2. In ChatGPT, turn on Enable site tools under Settings → Browser → Permissions.
  3. Do not use GPT-5.6 Luna; Site Tools are also unavailable in Enterprise and Edu workspaces, and access can remain rollout-dependent.
  4. Open the laboratory in a browser that exposes document.modelContext.registerTool.
  5. Use the laboratory's visible Runtime diagnostic to distinguish an absent API from a rejected registration.
  6. When tools are available, call inspect_flylab_state first and after every interruption or visible edit.
  7. Protocol authorization remains a visible operator action and is intentionally not a Site Tool.

The page can detect its own API and registration results, but it cannot detect the selected model, account eligibility, workspace policy, Site Tools setting, or rollout. See the official Site Tools guidance.

The raw machine endpoints remain /flylab-agent-manifest.json and /flylab-tool-contracts.json. Portable v3 exports are documented by the deployed evidence-export JSON Schema. The current page-session state is embedded only on the open laboratory page at #flylab-agent-handoff and is also exposed there in a visible, selectable recovery packet.

Declared Site Tools

  1. inspect_flylab_stateRead the current shared FlyLab page state before starting or resuming work. Returns the state revision, artifact IDs, exact next valid action, blockers, the visible non-WebMCP review gate, and the complete tool pipeline. It does not modify the page.
  2. find_fly_circuitsSearch FlyLab's curated adult Drosophila evidence and embodied motor-map index by behavior, body part, circuit, or neuron name. Use before drafting a hypothesis. Returns stable circuit IDs, typed brain-to-body paths, citations, model-readiness boundaries, and explicit evidence labels; it does not run a simulation.
  3. draft_fly_hypothesisCreate a visible, editable and falsifiable hypothesis from a selected circuit and discovered evidence. At least one cited role=hypothesis_support record must have kind=perturbation_effect matching the requested perturbation and behavior; structural, inventory, and motor-context records are supplemental only. Returns an agent_hypothesized record and does not run a simulation.
  4. design_stimulation_trialCreate and display a controlled adult-fly perturbation protocol for a saved hypothesis. Returns baseline, sham and perturbation conditions, visible effective-drive derivations, timing, seeds and model assumptions; operator approval is still required before execution.
  5. run_fly_simulationExecute one approved, bounded FlyLab experiment and make exact seeded runs replayable in the shared arena. The caller must echo the approved_protocol_hash from the visible operator gate; any protocol or seed-manifest change revokes authorization. Returns effective-drive derivations, state/event timelines, complete per-run trajectories, model/controller identities, legacy lineage hash, and SHA-256 content hash with field-level attribution.
  6. analyze_fly_behaviorCompute and save the selected motor map's complete five-metric panel from summaries derived from each run's authoritative state trajectory. The required metric IDs are returned on the circuit motor map and simulation batch. The shared arena can replay the exact selected seeded run; a legacy condition illustration remains compatibility-only and excluded from analysis. Outputs are not wet-lab evidence.
  7. compare_fly_trialsRank conditions from one or more saved analyses against a behavioral objective and create one bounded next-experiment proposal. It never executes the proposal automatically.
  8. save_fly_evidenceCommit a complete FlyLab hypothesis, experiment, runs, analyses, comparison, citations, model versions and seeds to the visible browser-local evidence ledger. Verifies the simulation content hash and returns stable bundle metadata, the exact portable evidence-export envelope, its manifest hash, media type, and published JSON Schema URL.
Agent manifest
{
  "schema_version": "flylab.agent-manifest.v3",
  "name": "FlyLab",
  "description": "Agent-first WebMCP virtual Drosophila neuroethology lab with a visible operator audit surface.",
  "site": "https://flylab-neuroethology.d-lougen.chatgpt.site/",
  "source": "https://github.com/DJLougen/flylab",
  "transport": {
    "api": "WebMCP document.modelContext.registerTool",
    "scope": "current_open_page",
    "state_contract": "flylab.agent-context.v3",
    "result_contract": "flylab.tool-result.v3",
    "provenance_manifest_contract": "flylab.provenance-manifest.v1",
    "required_first_call": "inspect_flylab_state",
    "tool_contract_document": "/flylab-tool-contracts.json"
  },
  "discovery": {
    "html_link_rel": "alternate",
    "webmcp_standard_discovery": false,
    "catalog_kind": "FlyLab-specific read-only documentation",
    "browser_documentation_url": "/agent",
    "manifest_url": "/flylab-agent-manifest.json",
    "contract_url": "/flylab-tool-contracts.json",
    "evidence_export_schema_url": "/schemas/flylab-evidence-export-v3.schema.json",
    "evidence_export_media_type": "application/vnd.flylab.evidence+json",
    "inline_state_selector": "#flylab-agent-context",
    "inline_runtime_selector": "#flylab-agent-runtime",
    "inline_handoff_selector": "#flylab-agent-handoff",
    "control_plane_selector": "[aria-label=\"WebMCP agent control plane\"]",
    "capability_diagnostic_path": "#flylab-agent-runtime / capability_diagnostic",
    "unsupported_browser_behavior": "The visible /agent guide and same-page Runtime diagnostic remain browser-readable; raw JSON contracts and inline state remain machine-readable. This does not polyfill WebMCP or make tools callable; execution requires a browser and workspace where document.modelContext is available."
  },
  "workflow": [
    "inspect_flylab_state",
    "find_fly_circuits",
    "draft_fly_hypothesis",
    "design_stimulation_trial",
    "visible_operator_approval",
    "run_fly_simulation",
    "analyze_fly_behavior",
    "compare_fly_trials",
    "save_fly_evidence"
  ],
  "tools": [
    {
      "name": "inspect_flylab_state",
      "effect": "read_only",
      "purpose": "Recover the exact shared revision, artifact IDs, blocker, and next valid action."
    },
    {
      "name": "find_fly_circuits",
      "effect": "writes_shared_selection",
      "purpose": "Search source-backed adult circuits by neuron, behavior, or body part and return their typed motor maps."
    },
    {
      "name": "draft_fly_hypothesis",
      "effect": "writes_hypothesis",
      "purpose": "Create a falsifiable agent_hypothesized claim from eligible evidence."
    },
    {
      "name": "design_stimulation_trial",
      "effect": "writes_protocol",
      "purpose": "Create controlled conditions, timing, seeds, and model assumptions."
    },
    {
      "name": "run_fly_simulation",
      "effect": "writes_simulation_batch",
      "purpose": "Run only the exact protocol hash and seed manifest committed by visible operator approval; return state-coherent seeded traces and content integrity."
    },
    {
      "name": "analyze_fly_behavior",
      "effect": "writes_analysis",
      "purpose": "Compute the selected motor map's complete five-metric panel from authoritative per-run state trajectories."
    },
    {
      "name": "compare_fly_trials",
      "effect": "writes_comparison_and_proposal",
      "purpose": "Rank conditions and propose, but never execute, one bounded follow-up."
    },
    {
      "name": "save_fly_evidence",
      "effect": "writes_evidence_bundle",
      "purpose": "Commit the exact source-to-result lineage and portable JSON envelope."
    }
  ],
  "output_contracts": {
    "inspect_flylab_state": {
      "required_data_fields": [
        "page_session_id",
        "agent_context"
      ],
      "produced_artifacts": [],
      "scientific_paths": [
        "/agent_context/artifact_manifest"
      ],
      "operational_paths": [
        "/page_session_id",
        "/agent_context/state",
        "/agent_context/next_action",
        "/agent_context/human_gate",
        "/agent_context/pipeline"
      ]
    },
    "find_fly_circuits": {
      "required_data_fields": [
        "discovery_decision",
        "candidate_circuit_records",
        "candidate_circuits",
        "selection_status",
        "disambiguation",
        "circuits",
        "evidence",
        "connectome_records",
        "dataset_versions",
        "embodiment_coverage",
        "selected_circuit_id",
        "candidate_match_count",
        "hypothesis_eligible_evidence_ids",
        "causal_evidence_ids_by_perturbation",
        "evidence_role_policy",
        "coverage_warning",
        "next_action"
      ],
      "produced_artifacts": [
        "discovery_decision",
        "circuit_selection",
        "evidence_record",
        "connectome_record",
        "embodied_motor_map"
      ],
      "scientific_paths": [
        "/discovery_decision",
        "/candidate_circuit_records",
        "/circuits",
        "/evidence",
        "/connectome_records",
        "/dataset_versions",
        "/embodiment_coverage"
      ],
      "operational_paths": [
        "/discovery_decision/missionGoal",
        "/discovery_decision/search",
        "/candidate_circuits",
        "/selection_status",
        "/disambiguation",
        "/selected_circuit_id",
        "/candidate_match_count",
        "/hypothesis_eligible_evidence_ids",
        "/causal_evidence_ids_by_perturbation",
        "/evidence_role_policy",
        "/coverage_warning",
        "/next_action"
      ]
    },
    "draft_fly_hypothesis": {
      "required_data_fields": [
        "hypothesis",
        "next_action"
      ],
      "produced_artifacts": [
        "hypothesis"
      ],
      "scientific_paths": [
        "/hypothesis"
      ],
      "operational_paths": [
        "/next_action"
      ]
    },
    "design_stimulation_trial": {
      "required_data_fields": [
        "experiment",
        "approval_required",
        "agent_status",
        "blocked_by",
        "agent_actionable",
        "human_gate",
        "next_action"
      ],
      "produced_artifacts": [
        "experiment",
        "trial_condition",
        "embodied_motor_map"
      ],
      "scientific_paths": [
        "/experiment",
        "/experiment/motorMap",
        "/experiment/model",
        "/experiment/model/controllerMapping"
      ],
      "operational_paths": [
        "/experiment/approved",
        "/approval_required",
        "/agent_status",
        "/blocked_by",
        "/agent_actionable",
        "/human_gate",
        "/next_action"
      ]
    },
    "run_fly_simulation": {
      "required_data_fields": [
        "id",
        "experimentId",
        "targetCircuitId",
        "behavior",
        "motorMap",
        "status",
        "conditionRuns",
        "runHash",
        "runHashScope",
        "runHashSerialization",
        "runContentHash",
        "runContentHashScope",
        "runContentHashSerialization",
        "protocol",
        "approval",
        "model",
        "provenance",
        "boundary",
        "next_action"
      ],
      "produced_artifacts": [
        "simulation_batch",
        "simulation_run",
        "per_run_trajectory",
        "illustrative_trajectory",
        "experiment_approval",
        "embodied_motor_map"
      ],
      "scientific_paths": [
        "",
        "/motorMap",
        "/conditionRuns",
        "/protocol",
        "/approval/protocol",
        "/approval/seed_manifest",
        "/model",
        "/model/controllerMapping",
        "/boundary"
      ],
      "operational_paths": [
        "/status",
        "/approval/approved_at",
        "/approval/protocol_hash",
        "/approval/seed_manifest_hash",
        "/next_action"
      ]
    },
    "analyze_fly_behavior": {
      "required_data_fields": [
        "analysis",
        "metric_definitions",
        "response_initiation_summary_definition",
        "response_observation_summary_definition",
        "per_run_results",
        "unit_boundary",
        "next_action"
      ],
      "produced_artifacts": [
        "behavior_analysis",
        "simulation_run_summary"
      ],
      "scientific_paths": [
        "/analysis",
        "/metric_definitions",
        "/response_initiation_summary_definition",
        "/response_observation_summary_definition",
        "/per_run_results",
        "/unit_boundary"
      ],
      "operational_paths": [
        "/next_action"
      ]
    },
    "compare_fly_trials": {
      "required_data_fields": [
        "comparison",
        "execution_authorized",
        "next_action"
      ],
      "produced_artifacts": [
        "trial_comparison",
        "follow_up_proposal"
      ],
      "scientific_paths": [
        "/comparison",
        "/comparison/proposal"
      ],
      "operational_paths": [
        "/execution_authorized",
        "/next_action"
      ]
    },
    "save_fly_evidence": {
      "required_data_fields": [
        "bundle",
        "evidence_export",
        "export_media_type",
        "export_schema_url",
        "export_filename",
        "local_reference",
        "storage_scope",
        "next_action"
      ],
      "produced_artifacts": [
        "evidence_bundle",
        "portable_evidence_export"
      ],
      "scientific_paths": [
        "/bundle",
        "/evidence_export"
      ],
      "operational_paths": [
        "/export_media_type",
        "/export_schema_url",
        "/export_filename",
        "/local_reference",
        "/storage_scope",
        "/next_action"
      ]
    }
  },
  "operator_gate": {
    "name": "visible_operator_approval",
    "webmcp_tool": false,
    "blocks": "run_fly_simulation",
    "scope": "webmcp_site_tools",
    "boundary": "Approval is absent from the WebMCP tool surface and requires visible UI interaction. It is not identity-authenticated against general browser automation."
  },
  "recovery": {
    "rule": "Call inspect_flylab_state after interruption, edit, cancellation, stale-state failure, or navigation.",
    "mutation_guard": "Every mutation requires the inspected page_session_id and expected_state_revision. Simulation also requires the exact approved_protocol_hash. Simulation and evidence save require a caller operation_id; identical retries replay without another mutation."
  },
  "hypothesis_evidence_gate": {
    "required_role": "hypothesis_support",
    "required_support_kind": "perturbation_effect",
    "must_match": [
      "perturbation",
      "predicted_behavior"
    ],
    "supplemental_only": [
      "structural_path",
      "specimen_inventory",
      "motor_context"
    ],
    "excluded": [
      "model_context",
      "catalog_context"
    ]
  },
  "provenance": {
    "schema_version": "flylab.provenance-manifest.v1",
    "summary_field": "provenance",
    "summary_semantics": "Union summary only; use provenance_manifest for field-level attribution.",
    "manifest_field": "provenance_manifest",
    "path_scope": "RFC 6901 JSON Pointer paths relative to structuredContent.data; the empty path addresses the data root.",
    "inheritance": "Each manifest entry labels its complete scientific subtree unless a more specific nested entry overrides it.",
    "operational_boundary": "Paths in operational_paths are workflow or storage metadata, not scientific evidence, and do not inherit a scientific label.",
    "untrusted_annotation_boundary": "Caller-supplied goals, titles, and notes are untrusted administrative annotations, excluded from scientific provenance counts.",
    "definitions": {
      "measured": "An empirical result reported under the cited study conditions; it is not automatically universal or reproduced by FlyLab.",
      "derived": "A deterministic filter, aggregation, or calculation from pinned source records; it is not a new wet-lab measurement.",
      "connectome_inferred": "An anatomical inference from EM reconstruction or annotations; it does not establish activity, physiological efficacy, or behavior.",
      "simulation_predicted": "An output conditional on the stated model, controller mapping, parameters, and seed; it is not biological validation.",
      "agent_hypothesized": "An untested proposal authored by an agent that must remain distinct from source evidence and simulation output."
    }
  },
  "provenance_labels": [
    "measured",
    "derived",
    "connectome_inferred",
    "simulation_predicted",
    "agent_hypothesized"
  ],
  "scientific_scope": {
    "release_slice": "adult MDN leg-retreat and adult giant-fiber bilateral short-mode escape motor maps",
    "model_version": "0.3.0",
    "controller": "state-coherent-mapped-circuit-adapter.v2",
    "environment": "stateful-open-field-model-scale.v3",
    "metric_method": "flylab.behavior-metrics.v5",
    "calibration_status": "literature_constrained_event_order_unfitted_amplitudes",
    "boundary": "GF event order and approximate intervals are literature-constrained; probabilities, amplitudes, controller gains, recovery, and MDN dynamics remain hand-authored and unfitted. The model does not execute connectome neurons, neural dynamics, synapses, muscles, aerodynamics, FlyGym, or wet-lab experiments and is not biological validation."
  },
  "license": "Apache-2.0"
}
Exact tool contracts
{
  "schema_version": "flylab.webmcp-contracts.v3",
  "name": "FlyLab WebMCP contracts",
  "site": "https://flylab-neuroethology.d-lougen.chatgpt.site/",
  "transport": {
    "api": "document.modelContext.registerTool",
    "required_first_call": "inspect_flylab_state",
    "scope": "current_open_page",
    "context_contract": "flylab.agent-context.v3",
    "result_contract": "flylab.tool-result.v3",
    "provenance_manifest_contract": "flylab.provenance-manifest.v1",
    "execution_note": "This document describes the live site tools but is not a fallback transport. Tool calls require a browser and workspace where WebMCP site tools are available."
  },
  "discovery": {
    "webmcp_standard_discovery": false,
    "catalog_kind": "FlyLab-specific read-only documentation",
    "browser_documentation_url": "/agent",
    "manifest_url": "/flylab-agent-manifest.json",
    "contract_url": "/flylab-tool-contracts.json",
    "evidence_export_schema_url": "https://flylab-neuroethology.d-lougen.chatgpt.site/schemas/flylab-evidence-export-v3.schema.json",
    "evidence_export_media_type": "application/vnd.flylab.evidence+json",
    "inline_state_selector": "#flylab-agent-context",
    "inline_runtime_selector": "#flylab-agent-runtime",
    "inline_handoff_selector": "#flylab-agent-handoff",
    "control_plane_selector": "[aria-label=\"WebMCP agent control plane\"]",
    "capability_diagnostic_path": "#flylab-agent-runtime / capability_diagnostic"
  },
  "result_contract": {
    "schema_version": "flylab.tool-result.v3",
    "success_fields": [
      "ok",
      "result_version",
      "tool",
      "summary",
      "page_session_id",
      "previous_state_revision",
      "state_revision",
      "created_artifact_ids",
      "operation_id",
      "idempotent_replay",
      "next_action",
      "verification",
      "provenance",
      "provenance_scope",
      "provenance_manifest",
      "data"
    ],
    "failure_fields": [
      "ok",
      "result_version",
      "tool",
      "page_session_id",
      "state_revision",
      "error",
      "recovery"
    ],
    "failure_error_fields": [
      "code",
      "message",
      "retryable",
      "details"
    ],
    "domain_error_codes": [
      "INVALID_INPUT",
      "NOT_FOUND",
      "EVIDENCE_MISMATCH",
      "UNSUPPORTED_TARGET",
      "INVALID_TIMING",
      "STALE_STATE",
      "APPROVAL_REQUIRED",
      "RUN_LIMIT_EXCEEDED",
      "SIMULATION_UNAVAILABLE",
      "INCOMPLETE_BATCH",
      "METRIC_UNAVAILABLE",
      "INCOMPARABLE_ANALYSES",
      "INCOMPLETE_PROVENANCE"
    ],
    "cancellation": "A cancellation observed before commit rejects with AbortError and publishes no prepared batch or evidence bundle.",
    "recovery": "After any interruption, cancellation, stale-state response, or visible person edit, call inspect_flylab_state before choosing another action."
  },
  "context_contract": {
    "schema_version": "flylab.agent-context.v3",
    "artifact_manifest_field": "artifact_manifest",
    "provenance_policy_field": "provenance_policy",
    "recovery_semantics": "The artifact manifest carries compact, auditable scientific lineage for the current page session; artifact IDs alone are navigation references, not provenance."
  },
  "provenance_contract": {
    "schema_version": "flylab.provenance-manifest.v1",
    "definitions": {
      "measured": "An empirical result reported under the cited study conditions; it is not automatically universal or reproduced by FlyLab.",
      "derived": "A deterministic filter, aggregation, or calculation from pinned source records; it is not a new wet-lab measurement.",
      "connectome_inferred": "An anatomical inference from EM reconstruction or annotations; it does not establish activity, physiological efficacy, or behavior.",
      "simulation_predicted": "An output conditional on the stated model, controller mapping, parameters, and seed; it is not biological validation.",
      "agent_hypothesized": "An untested proposal authored by an agent that must remain distinct from source evidence and simulation output."
    },
    "summary_field": "provenance",
    "summary_semantics": "Union summary only. It lists labels present in the result but does not attribute a label to a specific field.",
    "manifest_field": "provenance_manifest",
    "path_scope": "RFC 6901 JSON Pointer paths relative to structuredContent.data. The empty path addresses the data root.",
    "entry_fields": [
      "path",
      "artifact_id",
      "artifact_type",
      "scope",
      "labels",
      "parent_ids",
      "evidence_ids",
      "source_ids",
      "boundary"
    ],
    "inheritance": "Each manifest entry labels its complete scientific subtree unless a more specific nested entry overrides it.",
    "operational_boundary": "Paths listed in operational_paths contain workflow state, blockers, controls, storage references, or other operational metadata; they are not scientific evidence and do not inherit a scientific label.",
    "untrusted_annotation_boundary": "Caller-supplied goals, titles, and notes are untrusted administrative annotations, never scientific evidence, and are excluded from scientific provenance counts."
  },
  "operator_gate": {
    "name": "visible_operator_approval",
    "webmcp_tool": false,
    "blocks": "run_fly_simulation",
    "boundary": "Approval is a visible page action and is intentionally absent from the WebMCP tool surface. It is not identity-authenticated against general browser automation."
  },
  "tools": [
    {
      "name": "inspect_flylab_state",
      "title": "Inspect FlyLab state",
      "description": "Read the current shared FlyLab page state before starting or resuming work. Returns the state revision, artifact IDs, exact next valid action, blockers, the visible non-WebMCP review gate, and the complete tool pipeline. It does not modify the page.",
      "annotations": {
        "readOnlyHint": true,
        "untrustedContentHint": true
      },
      "input_schema": {
        "type": "object",
        "properties": {},
        "required": [],
        "additionalProperties": false
      },
      "output_contract": {
        "required_data_fields": [
          "page_session_id",
          "agent_context"
        ],
        "produced_artifacts": [],
        "scientific_paths": [
          "/agent_context/artifact_manifest"
        ],
        "operational_paths": [
          "/page_session_id",
          "/agent_context/state",
          "/agent_context/next_action",
          "/agent_context/human_gate",
          "/agent_context/pipeline"
        ]
      }
    },
    {
      "name": "find_fly_circuits",
      "title": "Find fly circuits",
      "description": "Search FlyLab's curated adult Drosophila evidence and embodied motor-map index by behavior, body part, circuit, or neuron name. Use before drafting a hypothesis. Returns stable circuit IDs, typed brain-to-body paths, citations, model-readiness boundaries, and explicit evidence labels; it does not run a simulation.",
      "annotations": {
        "readOnlyHint": false,
        "untrustedContentHint": true
      },
      "input_schema": {
        "type": "object",
        "properties": {
          "page_session_id": {
            "type": "string",
            "minLength": 9,
            "maxLength": 80,
            "description": "Exact page_session_id returned by inspect_flylab_state for this open FlyLab page."
          },
          "expected_state_revision": {
            "type": "integer",
            "minimum": 1,
            "description": "Exact state revision returned by the most recent inspect or successful mutation."
          },
          "query": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1000,
            "description": "Behavior, circuit, neuron type, complete mission prompt, or scientific question to search."
          },
          "behavior": {
            "type": "string",
            "enum": [
              "backward_walking",
              "retreat",
              "forward_walking",
              "turning",
              "short_mode_escape",
              "grooming",
              "any"
            ],
            "default": "any"
          },
          "body_part": {
            "type": "string",
            "enum": [
              "left_foreleg",
              "right_foreleg",
              "left_midleg",
              "right_midleg",
              "left_hindleg",
              "right_hindleg",
              "left_wing",
              "right_wing",
              "any"
            ],
            "default": "any"
          },
          "evidence_labels": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "measured",
                "derived",
                "connectome_inferred",
                "simulation_predicted",
                "agent_hypothesized"
              ]
            },
            "minItems": 1,
            "maxItems": 5,
            "uniqueItems": true
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 20,
            "default": 8,
            "description": "Minimum top-k cutoff. Every candidate tied at the cutoff score is retained, so the returned candidate count may exceed this value."
          }
        },
        "required": [
          "page_session_id",
          "expected_state_revision",
          "query"
        ],
        "additionalProperties": false
      },
      "output_contract": {
        "required_data_fields": [
          "discovery_decision",
          "candidate_circuit_records",
          "candidate_circuits",
          "selection_status",
          "disambiguation",
          "circuits",
          "evidence",
          "connectome_records",
          "dataset_versions",
          "embodiment_coverage",
          "selected_circuit_id",
          "candidate_match_count",
          "hypothesis_eligible_evidence_ids",
          "causal_evidence_ids_by_perturbation",
          "evidence_role_policy",
          "coverage_warning",
          "next_action"
        ],
        "produced_artifacts": [
          "discovery_decision",
          "circuit_selection",
          "evidence_record",
          "connectome_record",
          "embodied_motor_map"
        ],
        "scientific_paths": [
          "/discovery_decision",
          "/candidate_circuit_records",
          "/circuits",
          "/evidence",
          "/connectome_records",
          "/dataset_versions",
          "/embodiment_coverage"
        ],
        "operational_paths": [
          "/discovery_decision/missionGoal",
          "/discovery_decision/search",
          "/candidate_circuits",
          "/selection_status",
          "/disambiguation",
          "/selected_circuit_id",
          "/candidate_match_count",
          "/hypothesis_eligible_evidence_ids",
          "/causal_evidence_ids_by_perturbation",
          "/evidence_role_policy",
          "/coverage_warning",
          "/next_action"
        ]
      }
    },
    {
      "name": "draft_fly_hypothesis",
      "title": "Draft fly hypothesis",
      "description": "Create a visible, editable and falsifiable hypothesis from a selected circuit and discovered evidence. At least one cited role=hypothesis_support record must have kind=perturbation_effect matching the requested perturbation and behavior; structural, inventory, and motor-context records are supplemental only. Returns an agent_hypothesized record and does not run a simulation.",
      "annotations": {
        "readOnlyHint": false,
        "untrustedContentHint": true
      },
      "input_schema": {
        "type": "object",
        "properties": {
          "page_session_id": {
            "type": "string",
            "minLength": 9,
            "maxLength": 80,
            "description": "Exact page_session_id returned by inspect_flylab_state for this open FlyLab page."
          },
          "expected_state_revision": {
            "type": "integer",
            "minimum": 1,
            "description": "Exact state revision returned by the most recent inspect or successful mutation."
          },
          "circuit_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "claim": {
            "type": "string",
            "minLength": 10,
            "maxLength": 500
          },
          "predicted_behavior": {
            "type": "string",
            "enum": [
              "backward_walking",
              "retreat",
              "forward_walking",
              "turning",
              "short_mode_escape",
              "grooming"
            ]
          },
          "perturbation": {
            "type": "string",
            "enum": [
              "activate",
              "silence"
            ]
          },
          "primary_outcome": {
            "type": "string",
            "enum": [
              "backward_distance_mm",
              "signed_speed_mm_s",
              "response_latency_ms",
              "heading_change_deg",
              "stance_stability",
              "short_mode_escape_probability",
              "vertical_displacement_mm",
              "wing_recruitment",
              "leg_recruitment"
            ],
            "description": "Stable simulation metric ID used as the hypothesis primary outcome."
          },
          "expected_direction": {
            "type": "string",
            "enum": [
              "increase",
              "decrease"
            ]
          },
          "controls": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "condition_baseline",
                "condition_sham"
              ]
            },
            "minItems": 2,
            "maxItems": 2,
            "uniqueItems": true,
            "description": "Must include the exact baseline and model-sham condition IDs."
          },
          "evidence_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            },
            "minItems": 1,
            "maxItems": 20,
            "uniqueItems": true,
            "description": "Discovered hypothesis-support IDs. Must include at least one perturbation_effect record matching perturbation and predicted_behavior; structural, inventory, and motor-context IDs may only supplement it."
          },
          "evidence_limitations": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 5,
              "maxLength": 300
            },
            "minItems": 1,
            "maxItems": 10,
            "uniqueItems": true,
            "description": "Explicit limits on what the cited evidence and reduced-order model can establish."
          },
          "falsification_criterion": {
            "type": "string",
            "minLength": 5,
            "maxLength": 300
          }
        },
        "required": [
          "page_session_id",
          "expected_state_revision",
          "circuit_id",
          "claim",
          "predicted_behavior",
          "perturbation",
          "primary_outcome",
          "expected_direction",
          "controls",
          "evidence_ids",
          "evidence_limitations",
          "falsification_criterion"
        ],
        "additionalProperties": false
      },
      "output_contract": {
        "required_data_fields": [
          "hypothesis",
          "next_action"
        ],
        "produced_artifacts": [
          "hypothesis"
        ],
        "scientific_paths": [
          "/hypothesis"
        ],
        "operational_paths": [
          "/next_action"
        ]
      }
    },
    {
      "name": "design_stimulation_trial",
      "title": "Design stimulation trial",
      "description": "Create and display a controlled adult-fly perturbation protocol for a saved hypothesis. Returns baseline, sham and perturbation conditions, visible effective-drive derivations, timing, seeds and model assumptions; operator approval is still required before execution.",
      "annotations": {
        "readOnlyHint": false,
        "untrustedContentHint": false
      },
      "input_schema": {
        "type": "object",
        "properties": {
          "page_session_id": {
            "type": "string",
            "minLength": 9,
            "maxLength": 80,
            "description": "Exact page_session_id returned by inspect_flylab_state for this open FlyLab page."
          },
          "expected_state_revision": {
            "type": "integer",
            "minimum": 1,
            "description": "Exact state revision returned by the most recent inspect or successful mutation."
          },
          "hypothesis_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "target_circuit_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "perturbation": {
            "type": "string",
            "enum": [
              "activate",
              "silence"
            ]
          },
          "laterality": {
            "type": "string",
            "enum": [
              "bilateral",
              "left",
              "right"
            ]
          },
          "activation_level": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "description": "Unitless simulation control; not biological light power."
          },
          "onset_ms": {
            "type": "integer",
            "minimum": 0,
            "maximum": 5000
          },
          "duration_ms": {
            "type": "integer",
            "minimum": 50,
            "maximum": 5000
          },
          "trial_duration_ms": {
            "type": "integer",
            "minimum": 1000,
            "maximum": 10000
          },
          "replicates": {
            "type": "integer",
            "minimum": 1,
            "maximum": 20,
            "default": 5
          },
          "include_baseline": {
            "type": "boolean",
            "const": true,
            "default": true,
            "description": "Required for the controlled FlyLab vertical slice."
          },
          "include_sham_control": {
            "type": "boolean",
            "const": true,
            "default": true,
            "description": "Required for the controlled FlyLab vertical slice."
          },
          "seed": {
            "type": "integer",
            "minimum": 0,
            "maximum": 2147483647
          }
        },
        "required": [
          "page_session_id",
          "expected_state_revision",
          "hypothesis_id",
          "target_circuit_id",
          "perturbation",
          "laterality",
          "activation_level",
          "onset_ms",
          "duration_ms",
          "trial_duration_ms",
          "replicates",
          "include_baseline",
          "include_sham_control",
          "seed"
        ],
        "additionalProperties": false
      },
      "output_contract": {
        "required_data_fields": [
          "experiment",
          "approval_required",
          "agent_status",
          "blocked_by",
          "agent_actionable",
          "human_gate",
          "next_action"
        ],
        "produced_artifacts": [
          "experiment",
          "trial_condition",
          "embodied_motor_map"
        ],
        "scientific_paths": [
          "/experiment",
          "/experiment/motorMap",
          "/experiment/model",
          "/experiment/model/controllerMapping"
        ],
        "operational_paths": [
          "/experiment/approved",
          "/approval_required",
          "/agent_status",
          "/blocked_by",
          "/agent_actionable",
          "/human_gate",
          "/next_action"
        ]
      }
    },
    {
      "name": "run_fly_simulation",
      "title": "Run fly simulation",
      "description": "Execute one approved, bounded FlyLab experiment and make exact seeded runs replayable in the shared arena. The caller must echo the approved_protocol_hash from the visible operator gate; any protocol or seed-manifest change revokes authorization. Returns effective-drive derivations, state/event timelines, complete per-run trajectories, model/controller identities, legacy lineage hash, and SHA-256 content hash with field-level attribution.",
      "annotations": {
        "readOnlyHint": false,
        "untrustedContentHint": false
      },
      "input_schema": {
        "type": "object",
        "properties": {
          "page_session_id": {
            "type": "string",
            "minLength": 9,
            "maxLength": 80,
            "description": "Exact page_session_id returned by inspect_flylab_state for this open FlyLab page."
          },
          "expected_state_revision": {
            "type": "integer",
            "minimum": 1,
            "description": "Exact state revision returned by the most recent inspect or successful mutation."
          },
          "experiment_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "approved_protocol_hash": {
            "type": "string",
            "minLength": 71,
            "maxLength": 71,
            "pattern": "^sha256:[a-f0-9]{64}$",
            "description": "Exact protocol hash returned after visible operator approval and exposed by inspect_flylab_state."
          },
          "operation_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120,
            "description": "Stable caller-generated ID for one logical simulation operation. Retry the same operation with the same ID."
          }
        },
        "required": [
          "page_session_id",
          "expected_state_revision",
          "experiment_id",
          "approved_protocol_hash",
          "operation_id"
        ],
        "additionalProperties": false
      },
      "output_contract": {
        "required_data_fields": [
          "id",
          "experimentId",
          "targetCircuitId",
          "behavior",
          "motorMap",
          "status",
          "conditionRuns",
          "runHash",
          "runHashScope",
          "runHashSerialization",
          "runContentHash",
          "runContentHashScope",
          "runContentHashSerialization",
          "protocol",
          "approval",
          "model",
          "provenance",
          "boundary",
          "next_action"
        ],
        "produced_artifacts": [
          "simulation_batch",
          "simulation_run",
          "per_run_trajectory",
          "illustrative_trajectory",
          "experiment_approval",
          "embodied_motor_map"
        ],
        "scientific_paths": [
          "",
          "/motorMap",
          "/conditionRuns",
          "/protocol",
          "/approval/protocol",
          "/approval/seed_manifest",
          "/model",
          "/model/controllerMapping",
          "/boundary"
        ],
        "operational_paths": [
          "/status",
          "/approval/approved_at",
          "/approval/protocol_hash",
          "/approval/seed_manifest_hash",
          "/next_action"
        ]
      }
    },
    {
      "name": "analyze_fly_behavior",
      "title": "Analyze fly behavior",
      "description": "Compute and save the selected motor map's complete five-metric panel from summaries derived from each run's authoritative state trajectory. The required metric IDs are returned on the circuit motor map and simulation batch. The shared arena can replay the exact selected seeded run; a legacy condition illustration remains compatibility-only and excluded from analysis. Outputs are not wet-lab evidence.",
      "annotations": {
        "readOnlyHint": false,
        "untrustedContentHint": false
      },
      "input_schema": {
        "type": "object",
        "properties": {
          "page_session_id": {
            "type": "string",
            "minLength": 9,
            "maxLength": 80,
            "description": "Exact page_session_id returned by inspect_flylab_state for this open FlyLab page."
          },
          "expected_state_revision": {
            "type": "integer",
            "minimum": 1,
            "description": "Exact state revision returned by the most recent inspect or successful mutation."
          },
          "batch_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "metrics": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "backward_distance_mm",
                "signed_speed_mm_s",
                "response_latency_ms",
                "heading_change_deg",
                "stance_stability",
                "short_mode_escape_probability",
                "vertical_displacement_mm",
                "wing_recruitment",
                "leg_recruitment"
              ]
            },
            "minItems": 5,
            "maxItems": 5,
            "uniqueItems": true,
            "description": "The complete five-metric panel declared by the selected circuit motor map; partial or mixed panels are rejected."
          }
        },
        "required": [
          "page_session_id",
          "expected_state_revision",
          "batch_id",
          "metrics"
        ],
        "additionalProperties": false
      },
      "output_contract": {
        "required_data_fields": [
          "analysis",
          "metric_definitions",
          "response_initiation_summary_definition",
          "response_observation_summary_definition",
          "per_run_results",
          "unit_boundary",
          "next_action"
        ],
        "produced_artifacts": [
          "behavior_analysis",
          "simulation_run_summary"
        ],
        "scientific_paths": [
          "/analysis",
          "/metric_definitions",
          "/response_initiation_summary_definition",
          "/response_observation_summary_definition",
          "/per_run_results",
          "/unit_boundary"
        ],
        "operational_paths": [
          "/next_action"
        ]
      }
    },
    {
      "name": "compare_fly_trials",
      "title": "Compare fly trials",
      "description": "Rank conditions from one or more saved analyses against a behavioral objective and create one bounded next-experiment proposal. It never executes the proposal automatically.",
      "annotations": {
        "readOnlyHint": false,
        "untrustedContentHint": false
      },
      "input_schema": {
        "type": "object",
        "properties": {
          "page_session_id": {
            "type": "string",
            "minLength": 9,
            "maxLength": 80,
            "description": "Exact page_session_id returned by inspect_flylab_state for this open FlyLab page."
          },
          "expected_state_revision": {
            "type": "integer",
            "minimum": 1,
            "description": "Exact state revision returned by the most recent inspect or successful mutation."
          },
          "analysis_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            },
            "minItems": 1,
            "maxItems": 8,
            "uniqueItems": true
          },
          "objective_metric": {
            "type": "string",
            "enum": [
              "backward_distance_mm",
              "signed_speed_mm_s",
              "response_latency_ms",
              "heading_change_deg",
              "stance_stability",
              "short_mode_escape_probability",
              "vertical_displacement_mm",
              "wing_recruitment",
              "leg_recruitment"
            ]
          },
          "objective": {
            "type": "string",
            "enum": [
              "maximize",
              "minimize"
            ]
          }
        },
        "required": [
          "page_session_id",
          "expected_state_revision",
          "analysis_ids",
          "objective_metric",
          "objective"
        ],
        "additionalProperties": false
      },
      "output_contract": {
        "required_data_fields": [
          "comparison",
          "execution_authorized",
          "next_action"
        ],
        "produced_artifacts": [
          "trial_comparison",
          "follow_up_proposal"
        ],
        "scientific_paths": [
          "/comparison",
          "/comparison/proposal"
        ],
        "operational_paths": [
          "/execution_authorized",
          "/next_action"
        ]
      }
    },
    {
      "name": "save_fly_evidence",
      "title": "Save fly evidence",
      "description": "Commit a complete FlyLab hypothesis, experiment, runs, analyses, comparison, citations, model versions and seeds to the visible browser-local evidence ledger. Verifies the simulation content hash and returns stable bundle metadata, the exact portable evidence-export envelope, its manifest hash, media type, and published JSON Schema URL.",
      "annotations": {
        "readOnlyHint": false,
        "untrustedContentHint": true
      },
      "input_schema": {
        "type": "object",
        "properties": {
          "page_session_id": {
            "type": "string",
            "minLength": 9,
            "maxLength": 80,
            "description": "Exact page_session_id returned by inspect_flylab_state for this open FlyLab page."
          },
          "expected_state_revision": {
            "type": "integer",
            "minimum": 1,
            "description": "Exact state revision returned by the most recent inspect or successful mutation."
          },
          "scope": {
            "type": "string",
            "enum": [
              "experiment",
              "mission"
            ],
            "description": "experiment saves the exact selected lineage; mission additionally preserves the goal, discovery decision, alternatives, exclusions, and coverage gaps."
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120,
            "description": "Optional caller-entered administrative title. Omit it to use FlyLab system metadata; it is never scientific evidence."
          },
          "hypothesis_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "experiment_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "batch_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            },
            "minItems": 1,
            "maxItems": 1,
            "uniqueItems": true
          },
          "analysis_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            },
            "minItems": 1,
            "maxItems": 8,
            "uniqueItems": true
          },
          "comparison_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "note": {
            "type": "string",
            "maxLength": 500
          },
          "operation_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120,
            "description": "Stable caller-generated ID for one logical evidence-save operation. Retry the same operation with the same ID."
          }
        },
        "required": [
          "page_session_id",
          "expected_state_revision",
          "scope",
          "hypothesis_id",
          "experiment_id",
          "batch_ids",
          "analysis_ids",
          "comparison_id",
          "operation_id"
        ],
        "additionalProperties": false
      },
      "output_contract": {
        "required_data_fields": [
          "bundle",
          "evidence_export",
          "export_media_type",
          "export_schema_url",
          "export_filename",
          "local_reference",
          "storage_scope",
          "next_action"
        ],
        "produced_artifacts": [
          "evidence_bundle",
          "portable_evidence_export"
        ],
        "scientific_paths": [
          "/bundle",
          "/evidence_export"
        ],
        "operational_paths": [
          "/export_media_type",
          "/export_schema_url",
          "/export_filename",
          "/local_reference",
          "/storage_scope",
          "/next_action"
        ]
      }
    }
  ]
}