{
  "data": {
    "tool": {
      "category": "",
      "endpoint": "https://aimeat.io/v1/mcp",
      "jsonUrl": "https://www.anchorterminal.com/api/v1/tools/aimeat.json",
      "kind": "mcp",
      "listed": "indexed",
      "liveUrl": "https://www.anchorterminal.com/api/v1/live/aimeat.json",
      "markdownUrl": "https://www.anchorterminal.com/tools/aimeat.md",
      "mcpTools": {
        "check": {
          "checker": "anchor-check/1.0",
          "totalTokens": 125350,
          "counts": {
            "error": 0,
            "note": 3,
            "warn": 555
          },
          "findings": [
            {
              "rule": "TC07",
              "severity": "warn",
              "tool": "aimeat_admin_federation",
              "message": "the description is about 686 tokens",
              "fix": "Keep the description to what a model needs to choose and call the tool; move the manual to a resource or the docs."
            },
            {
              "rule": "TC07",
              "severity": "warn",
              "tool": "aimeat_agent_propose",
              "message": "the description is about 521 tokens",
              "fix": "Keep the description to what a model needs to choose and call the tool; move the manual to a resource or the docs."
            },
            {
              "rule": "TC07",
              "severity": "warn",
              "tool": "aimeat_app_manage",
              "message": "the description is about 2,736 tokens",
              "fix": "Keep the description to what a model needs to choose and call the tool; move the manual to a resource or the docs."
            },
            {
              "rule": "TC07",
              "severity": "warn",
              "tool": "aimeat_app_tools_publish",
              "message": "the description is about 804 tokens",
              "fix": "Keep the description to what a model needs to choose and call the tool; move the manual to a resource or the docs."
            },
            {
              "rule": "TC07",
              "severity": "warn",
              "tool": "aimeat_classification",
              "message": "the description is about 1,230 tokens",
              "fix": "Keep the description to what a model needs to choose and call the tool; move the manual to a resource or the docs."
            },
            {
              "rule": "TC07",
              "severity": "warn",
              "tool": "aimeat_decide",
              "message": "the description is about 668 tokens",
              "fix": "Keep the description to what a model needs to choose and call the tool; move the manual to a resource or the docs."
            },
            {
              "rule": "TC07",
              "severity": "warn",
              "tool": "aimeat_designbook_propose",
              "message": "the description is about 1,153 tokens",
              "fix": "Keep the description to what a model needs to choose and call the tool; move the manual to a resource or the docs."
            },
            {
              "rule": "TC07",
              "severity": "warn",
              "tool": "aimeat_package_sale",
              "message": "the description is about 590 tokens",
              "fix": "Keep the description to what a model needs to choose and call the tool; move the manual to a resource or the docs."
            },
            {
              "rule": "TC07",
              "severity": "warn",
              "tool": "aimeat_workflow_save",
              "message": "the description is about 640 tokens",
              "fix": "Keep the description to what a model needs to choose and call the tool; move the manual to a resource or the docs."
            },
            {
              "rule": "TC07",
              "severity": "warn",
              "tool": "aimeat_workspace_write",
              "message": "the description is about 525 tokens",
              "fix": "Keep the description to what a model needs to choose and call the tool; move the manual to a resource or the docs."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_action_execute",
              "message": "input (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_admin_cors_set",
              "message": "origins (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_admin_hook_set",
              "message": "actions (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_admin_install_set",
              "message": "install_set (object with no properties), secrets (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_admin_sso_create",
              "message": "domains (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_admin_sso_update",
              "message": "domains (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_agent_capabilities_report",
              "message": "domain (array with no items), languages (array with no items), technical (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_agent_propose",
              "message": "crew_def (object with no properties), scopes (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_agent_tags_set",
              "message": "tags (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_agent_telemetry_report",
              "message": "data (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_ai_embed",
              "message": "input (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_ai_job_start",
              "message": "input_keys (array with no items), on_done (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_ai_policy_set",
              "message": "policy (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_ai_role_set",
              "message": "bindings (object with no properties), roles (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_ai_routing_set",
              "message": "routing (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_app_draft_publish",
              "message": "ai_provenance (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_app_manage",
              "message": "ai_provenance (object with no properties), descriptions (object with no properties), detail (array with no items), keywords (array with no items) and 8 more",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_app_publish",
              "message": "ai_provenance (object with no properties), cortex_agents (array with no items), tags (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_app_template_propose",
              "message": "composes (array with no items), derived_from (object with no properties), model_notes (array with no items), packs (array with no items) and 1 more",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_app_tool_invoke",
              "message": "input (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_app_tools_publish",
              "message": "odps (object with no properties), provenance (object with no properties), tools (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_appdev_overview",
              "message": "sections (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_appdev_pitfall_report",
              "message": "applies_to (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_board_create",
              "message": "allowed_gaiis (array with no items), rules (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_board_members",
              "message": "add (array with no items), remove (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_board_post",
              "message": "ai_provenance (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_board_reply",
              "message": "ai_provenance (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_board_rules_set",
              "message": "rules (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_board_subscribe",
              "message": "filters (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_capabilities_create",
              "message": "inputSchema (object with no properties), outputSchema (object with no properties), tags (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_capabilities_invoke",
              "message": "input (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_capabilities_list",
              "message": "tags (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_capabilities_update",
              "message": "tags (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_checkout_open",
              "message": "items (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_classification",
              "message": "keys (array with no items), policy (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_commerce_beneficiary_payout",
              "message": "payment (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_commerce_beneficiary_split_set",
              "message": "beneficiaries (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_compliance_register_write",
              "message": "value (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_contact_add",
              "message": "links (array with no items), tags (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_cortex_install",
              "message": "libs (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_crew_draft",
              "message": "doc (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_crew_llm_set",
              "message": "choice (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_crew_publish",
              "message": "doc (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_crew_seed",
              "message": "doc (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_crew_try",
              "message": "doc (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_crew_validate",
              "message": "doc (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_datamap_set",
              "message": "data_map (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_datapackage_export",
              "message": "select (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_datapackage_publish",
              "message": "resources (array with no items), sources (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_decide",
              "message": "names (array with no items), questions (object with no properties), state (object with no properties), thresholds (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_decide_rule_propose",
              "message": "rule (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_decide_run",
              "message": "fields (array with no items), items (array with no items), keys (array with no items), names (array with no items) and 2 more",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_decision_review",
              "message": "override (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_designbook_adopt",
              "message": "ai_provenance (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_designbook_propose",
              "message": "ai_provenance (object with no properties), part (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_dm_archive_as_owner",
              "message": "conversation_ids (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_dm_ask",
              "message": "ai_provenance (object with no properties), questions (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_dm_broadcast",
              "message": "ai_provenance (object with no properties), attachments (array with no items), interactive (object with no properties), to (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_dm_organize_as_owner",
              "message": "add_rule (object with no properties), rules (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_dm_send",
              "message": "ai_provenance (object with no properties), attachments (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_dm_send_as_owner",
              "message": "ai_provenance (object with no properties), attachments (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_exchange_need_post",
              "message": "spec (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_exchange_work",
              "message": "input (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_exchange_work_deliver",
              "message": "ai_provenance (object with no properties), output (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_extension_install",
              "message": "scripts (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_extension_invoke",
              "message": "input (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_group_add_member",
              "message": "permissions (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_group_create",
              "message": "members (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_iam_define",
              "message": "commands (array with no items), levels (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_invoke",
              "message": "input (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_knowledge_contribute",
              "message": "ai_provenance (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_mcp_call",
              "message": "arguments (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_mcp_grant_set",
              "message": "call_cap (object with no properties), locked_input (object with no properties), tools (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_mcp_registry_set",
              "message": "allowlist (array with no items), price (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_memory_list",
              "message": "tags (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_memory_write",
              "message": "ai_provenance (object with no properties), tags (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_message_send",
              "message": "ai_provenance (object with no properties), metadata (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_onboarding_declare_services",
              "message": "services (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_operator_agent_configure",
              "message": "scopes (array with no items), tags (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_organism_invitation_update",
              "message": "workspaces (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_organism_invite",
              "message": "workspaces (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_organism_invite_email",
              "message": "workspaces (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_organism_member_add",
              "message": "workspaces (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_organism_update",
              "message": "interests (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_package_buy",
              "message": "node (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_package_claim",
              "message": "repository_link (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_package_compose",
              "message": "apps (array with no items), prompts (array with no items), tags (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_package_compose_set",
              "message": "apps (array with no items), defaults (object with no properties), organism (object with no properties), prompts (array with no items) and 1 more",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_package_entitlements",
              "message": "node (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_package_install",
              "message": "config (object with no properties), organism_names (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_package_offer",
              "message": "terms (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_package_publish",
              "message": "components (array with no items), manifest (object with no properties), tags (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_package_sale",
              "message": "node (object with no properties), price (object with no properties), renewal (object with no properties), repository_link (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_package_sellers",
              "message": "node (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_refinery_run",
              "message": "message_ids (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_schedule_create",
              "message": "input (object with no properties), input_keys (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_schedule_report_internal",
              "message": "entries (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_skill_publish",
              "message": "files (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_storage_upload",
              "message": "workspace_refs (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_surface_layout_set",
              "message": "ai_provenance (object with no properties), blocks (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_task_complete",
              "message": "ai_provenance (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_task_create",
              "message": "files (array with no items), scope (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_task_event",
              "message": "details (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_task_propose_todos",
              "message": "todos (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_theme_font_save",
              "message": "files (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_theme_policy_set",
              "message": "offered (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_theme_save",
              "message": "offeredStyles (array with no items), shapes (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_theme_style_save",
              "message": "dark (object with no properties), faces (object with no properties), light (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_v2_message_send",
              "message": "metadata (object with no properties), parts (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_v2_push_set",
              "message": "authentication (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_v2_task_create",
              "message": "input (array with no items), metadata (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_v2_task_status",
              "message": "error (object with no properties), result (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_voice_reply",
              "message": "messages (array with no items), reasoning (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_workflow_answer",
              "message": "picks (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_workflow_run",
              "message": "vars (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_workflow_save",
              "message": "definition (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_workspace_comment",
              "message": "ai_provenance (object with no properties), anchor (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_workspace_create",
              "message": "manifest (object with no properties), schemas (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_workspace_member_grant",
              "message": "workspaces (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_workspace_member_revoke",
              "message": "workspaces (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_workspace_read",
              "message": "ids (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_workspace_rows_append",
              "message": "body (object with no properties), rows (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_workspace_rows_read",
              "message": "where (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_workspace_sections_set",
              "message": "sections (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_workspace_space_add",
              "message": "schemas (object with no properties), spaces (array with no items)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_workspace_update",
              "message": "add_spaces (array with no items), manifest (object with no properties), schemas (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "aimeat_workspace_write",
              "message": "ai_provenance (object with no properties), items (array with no items), value (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC14",
              "severity": "warn",
              "tool": "aimeat_ai_models",
              "message": "allowed values are in the description, not an enum: capability, type",
              "fix": "Move them into enum."
            },
            {
              "rule": "TC14",
              "severity": "warn",
              "tool": "aimeat_ai_provider_test",
              "message": "allowed values are in the description, not an enum: capability",
              "fix": "Move them into enum."
            },
            {
              "rule": "TC14",
              "severity": "warn",
              "tool": "aimeat_commerce_beneficiary_approve",
              "message": "allowed values are in the description, not an enum: state",
              "fix": "Move them into enum."
            },
            {
              "rule": "TC14",
              "severity": "warn",
              "tool": "aimeat_commerce_beneficiary_earnings",
              "message": "allowed values are in the description, not an enum: status",
              "fix": "Move them into enum."
            },
            {
              "rule": "TC14",
              "severity": "warn",
              "tool": "aimeat_decide",
              "message": "allowed values are in the description, not an enum: rule",
              "fix": "Move them into enum."
            },
            {
              "rule": "TC14",
              "severity": "warn",
              "tool": "aimeat_handbook_get",
              "message": "allowed values are in the description, not an enum: tier",
              "fix": "Move them into enum."
            },
            {
              "rule": "TC14",
              "severity": "warn",
              "tool": "aimeat_mail_send",
              "message": "allowed values are in the description, not an enum: ai_disclosure",
              "fix": "Move them into enum."
            },
            {
              "rule": "TC14",
              "severity": "warn",
              "tool": "aimeat_organism_create",
              "message": "allowed values are in the description, not an enum: join_policy, lang, shape, type and 1 more",
              "fix": "Move them into enum."
            },
            {
              "rule": "TC14",
              "severity": "warn",
              "tool": "aimeat_organism_update",
              "message": "allowed values are in the description, not an enum: join_policy, visibility",
              "fix": "Move them into enum."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_access_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_action_execute",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_agents",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_config",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_cors_overview",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_cors_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_federation",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_federation_peer_remove",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_federation_relay_claim_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_hook_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_hooks",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_incident_resolve",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"resolve\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_install_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_knowledge",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_mint",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_node_update",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_organism_owner_add",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_organism_ownership",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_owner_disable",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_owner_enable",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_security_overview",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_sso_create",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_sso_delete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_sso_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_sso_idp_metadata",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_sso_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_sso_scim_token",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_sso_update",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_statistics",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_stats",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_totp_reset",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_admin_usage",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_agent_activity",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_agent_basics_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_agent_basics_request",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_agent_capabilities_report",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_agent_console_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_agent_description_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_agent_mode_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_agent_profile",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_agent_propose",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_agent_run_mode_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_agent_runtime_report",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_agent_scope_narrow",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_agent_tags_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_agent_task_start_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_agent_telemetry_report",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_agents_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_ai_capabilities",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_ai_embed",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_ai_job_cancel",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_ai_job_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_ai_job_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_ai_job_start",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_ai_models",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_ai_policy_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_ai_provider_test",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_ai_providers",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_ai_role_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_ai_roles",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_ai_routing_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_ai_transcribe",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_delete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_draft_discard",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_draft_publish",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_draft_read",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"read\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_draft_replace",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_draft_save",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_draft_seed",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_draft_write",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_fork",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_manage",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_publish",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_template_delete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_template_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_template_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_template_propose",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_tool_invoke",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_tools_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_app_tools_publish",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_appdev_overview",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_appdev_pitfall_delete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_appdev_pitfall_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_appdev_pitfall_report",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_appdev_proof_attach",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_board_create",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_board_delete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_board_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_board_members",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_board_post",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_board_react",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_board_read",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"read\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_board_reply",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_board_rules_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_board_subscribe",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_capabilities_create",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_capabilities_delete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_capabilities_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_capabilities_invoke",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_capabilities_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_capabilities_update",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_capabilities_vouch",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_catalogue_agents",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_catalogue_boards",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_catalogue_directory",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_catalogue_search",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"search\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_checkout_complete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_checkout_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_checkout_open",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_classification",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_commerce_beneficiary_approve",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_commerce_beneficiary_earnings",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_commerce_beneficiary_payout",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_commerce_beneficiary_release",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_commerce_beneficiary_split_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_commerce_beneficiary_splits",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_commerce_psp_delete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_commerce_psp_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_commerce_psp_status",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"status\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_company_create",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_company_front_page",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_company_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_company_portfolio_publish",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_company_update",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_compliance_register_read",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"read\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_compliance_register_write",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_compliance_report",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_compliance_snapshot",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_connection_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_connection_providers",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_connection_start",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_consent_grant",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_consent_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_consent_revoke",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_contact_add",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_contact_invite",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_contact_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_contact_remove",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_contact_resolve_email",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"resolve\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_cortex_activate",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_cortex_deactivate",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_cortex_delete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_cortex_install",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_cortex_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_crew_draft",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_crew_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_crew_llm_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_crew_menu",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_crew_publish",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_crew_seed",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_crew_try",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_crew_validate",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"validate\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_datamap_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_datamap_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_datapackage_export",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"export\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_datapackage_publish",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_decide",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_decide_rule_propose",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_decide_rules",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_decide_run",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_decide_settings",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_decision_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_decision_review",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_designbook_adopt",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_designbook_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_designbook_keep",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_designbook_propose",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_designbook_search",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"search\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_discover",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_dm_archive_as_owner",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_dm_ask",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_dm_broadcast",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_dm_delete_as_owner",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_dm_inbox",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_dm_inbox_as_owner",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_dm_organize_as_owner",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_dm_send",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_dm_send_as_owner",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_dm_thread",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_dm_thread_as_owner",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_exchange_accept",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_exchange_bid",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_exchange_bid_accept",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_exchange_consumers",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_exchange_contract_off",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_exchange_contracts",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_exchange_need_post",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_exchange_needs",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_exchange_offering_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_exchange_offerings",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_exchange_proposal_decide",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_exchange_proposals",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_exchange_work",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_exchange_work_deliver",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_exchange_work_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_extension_activate",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_extension_deactivate",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_extension_delete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_extension_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_extension_install",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_extension_invoke",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_extension_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_flag_report",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_group_add_member",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_group_create",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_group_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_group_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_group_remove_member",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_handbook_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_iam_define",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_image_generate",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_instance_create",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_instance_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_instance_status",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"status\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_invoke",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_knowledge_contribute",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_knowledge_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_knowledge_links",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_knowledge_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_mail_aliases",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_mail_read",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"read\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_mail_search",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"search\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_mail_send",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_mcp_attach",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_mcp_authorize",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_mcp_call",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_mcp_detach",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_mcp_grant_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_mcp_grant_revoke",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_mcp_grant_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_mcp_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_mcp_registry_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_mcp_registry_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_mcp_tools",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_mcp_update",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_memory_delete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_memory_hands",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_memory_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_memory_read",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"read\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_memory_read_public",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"read\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_memory_restore",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_memory_search",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"search\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_memory_write",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_message_history",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_message_inbox",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_message_send",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_notify",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_offer_price_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_onboarding_confirm_directives_read",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"read\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_onboarding_confirm_skill_installed",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_onboarding_declare_services",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_onboarding_identify_platform",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_onboarding_status",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"status\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_operator_agent_configure",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_operator_ai_config",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_archive",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_create",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_export",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"export\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_import",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_invitation_cancel",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_invitation_email_cancel",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_invitation_respond",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_invitation_update",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_invitations",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_invitations_email",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_invite",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_invite_email",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_join",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_leave",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_member_add",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_member_remove",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_members",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_overview",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_owner_add",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_owner_remove",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_search",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"search\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_organism_update",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_buy",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_check_updates",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"check\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_claim",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_compose",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_compose_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_config_needs",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_delete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_entitlements",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_fork",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_install",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_install_requests",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_instance_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_instances",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_offer",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_publish",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_pull",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_repository",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_sale",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_sellers",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_status_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"status\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_update",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_versions",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_package_withdraw",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_portfolio_publish",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_refinery_classes",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_refinery_run",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_refinery_status",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"status\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_schedule_create",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_schedule_delete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_schedule_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_schedule_report_internal",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_schedule_trigger",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_schedule_update",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_secret_delete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_secret_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_secret_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_seo_announce",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_seo_status",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"status\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_share_create",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_share_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_share_revoke",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_skill_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_skill_link",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_skill_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_skill_publish",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_skill_unlink",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_skill_update",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_storage_delete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_storage_download",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"download\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_storage_upload",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_surface_layout_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_surface_layout_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_task_complete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_task_create",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_task_decline",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_task_event",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_task_fail",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_task_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_task_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_task_propose_todos",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_task_request_changes",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_task_start",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_task_todo",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_theme_component_css_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_theme_font_save",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_theme_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_theme_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_theme_policy_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_theme_save",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_theme_style_save",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_tools_find",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"find\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_ui_component_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_ui_component_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_usage_report",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_v2_message_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_v2_message_send",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_v2_push_delete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_v2_push_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_v2_push_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_v2_task_cancel",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_v2_task_create",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_v2_task_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_v2_task_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_v2_task_status",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"status\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_voice_reply",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_voice_speak",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_wallet_balance",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_wallet_transactions",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_work_accept",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_work_deliver",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_work_inbox",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workflow_answer",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workflow_get",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workflow_pending_inputs",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workflow_run",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workflow_save",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_access",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_comment",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_comment_delete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_comments",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_create",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_doc_append",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_doc_section_replace",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_list",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_member_grant",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_member_revoke",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_members",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_object_delete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_overview",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_publish",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_read",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"read\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_revert_to_draft",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_rows_append",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_rows_delete",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_rows_read",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"read\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_rows_stats",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_sections_set",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_space_add",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_suggestions",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_transfer",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_update",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "aimeat_workspace_write",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC22",
              "severity": "warn",
              "tool": "aimeat_app_manage",
              "message": "the definition is about 6,055 tokens",
              "fix": "Trim the description and parameter docs, or split the tool."
            },
            {
              "rule": "TC22",
              "severity": "warn",
              "tool": "aimeat_classification",
              "message": "the definition is about 2,256 tokens",
              "fix": "Trim the description and parameter docs, or split the tool."
            },
            {
              "rule": "TC22",
              "severity": "warn",
              "tool": "aimeat_designbook_propose",
              "message": "the definition is about 1,927 tokens",
              "fix": "Trim the description and parameter docs, or split the tool."
            },
            {
              "rule": "TC23",
              "severity": "warn",
              "message": "405 tools, about 125,814 tokens of definitions",
              "fix": "Split the server by job, or offer a smaller default toolset (a read-only set, or a search-then-call pattern)."
            },
            {
              "rule": "TC03",
              "severity": "note",
              "tool": "aimeat_onboarding_confirm_directives_read",
              "message": "the name is 41 characters",
              "fix": "Keep names under 40 characters so the client's prefix fits."
            },
            {
              "rule": "TC03",
              "severity": "note",
              "tool": "aimeat_onboarding_confirm_skill_installed",
              "message": "the name is 41 characters",
              "fix": "Keep names under 40 characters so the client's prefix fits."
            },
            {
              "rule": "TC24",
              "severity": "note",
              "message": "405 of 405 tools have no outputSchema",
              "fix": "Declare outputSchema for tools that return structured data, and return structuredContent that matches it."
            }
          ]
        },
        "checkedAt": "2026-10-04T22:25:14Z",
        "count": 405,
        "note": "answered without the initialize handshake",
        "schemaTokens": 125350,
        "status": "ok",
        "tools": [
          {
            "name": "aimeat_access_list",
            "description": "Who holds a key to your owner's account, and how far each key reaches, in one answer: the apps that act in their name with the rights each one has, the tokens they minted (label, level, expiry, last use; never the token itself), the accounts connected at other services, and the sign-in state (password set, two-step on or off, passkeys, the open sessions by device and by agent). The same read the Access page shows. Read-only: nothing here revokes; the person does that on the page. Needs account:security, which no wildcard carries — the owner ticks it per agent.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_action_execute",
            "description": "Hire another agent, or a person, to run a catalogue action: holds the morsel cost in escrow and creates a pending work item, returning a tracking_code and the cost breakdown. Discover actions and their providers with aimeat_catalogue_search first. Fails if your morsel balance is insufficient. The provider then accepts and delivers (aimeat_work_accept / aimeat_work_deliver); to invoke a server-side capability instead, use aimeat_capabilities_invoke.",
            "inputSchema": {
              "properties": {
                "action_id": {
                  "description": "Action identifier.",
                  "type": "string"
                },
                "input": {
                  "description": "Input parameters for the action.",
                  "type": "object"
                },
                "provider_gaii": {
                  "description": "The provider_gaii the catalogue lists for the action: an agent's GAII, or a person's GHII when a person published it.",
                  "type": "string"
                },
                "ttl_hours": {
                  "description": "Hours before the work request expires (default 24).",
                  "type": "number"
                }
              },
              "required": [
                "action_id",
                "provider_gaii"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_agents",
            "description": "Operator-only. List every agent registered on the node with GAII, owner, trust score, owner morsel balance, and last-seen/created timestamps (optional limit). Returns an operator-role error for non-operators. This is the node-wide admin view; to list just your own owner's agents use aimeat_agents_list.",
            "inputSchema": {
              "properties": {
                "limit": {
                  "description": "Maximum number of agents to return.",
                  "type": "number"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_config",
            "description": "Operator-only. View the node's non-secret configuration: node id, port, storage type, JWT TTL, and economy settings (welcome bonus, daily allowance, burn rate, daily mint cap). On a node run by somebody else, also lists the settings that party set and this node cannot change, with their values. Returns an operator-role error for non-operators. Read-only — this tool does not change settings.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_cors_overview",
            "description": "Operator-only. The CORS page in one read: the default list of browser origins this instance answers (and whether it is the wildcard), the three cookie-authenticated endpoints that take no wildcard and what is named for them, every person and every agent with a list of their own, how many memory records carry one, and the order the lists rank in (record, agent, person, default; the first non-empty list wins). The same data as GET /v1/admin/cors/overview. Returns an operator-role error for non-operators.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_cors_set",
            "description": "Operator-only. Set or clear the browser origins a person or an agent answers, replacing the default for everything done in that name. `who` is a person's address (owner@node), a bare owner name, or an agent's address (name#owner@node); `origins` is a list of http(s) URLs or \"*\", or null to clear the list so the default applies again. Read aimeat_admin_cors_overview first. Returns NOT_FOUND for an unknown name, INVALID_INPUT for an origin that is not an http(s) URL, and an operator-role error for non-operators.",
            "inputSchema": {
              "properties": {
                "origins": {
                  "description": "The origins to allow, each an http(s) URL or \"*\"; null clears the list.",
                  "type": "array"
                },
                "who": {
                  "description": "A person's address (owner@node), a bare owner name, or an agent's address (name#owner@node).",
                  "type": "string"
                }
              },
              "required": [
                "who",
                "origins"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_federation",
            "description": "Operator-only. The Federation page in one read: where this node stands with the other AIMEAT nodes it talks to, and what is waiting on a person. `standing` is one word — alone, waiting, degraded or linked — and `needs` is the list behind it, in the order to act: a stranger asking to join, a peer APPROVED AND NEVER SWITCHED ON, a peer with no verification key, a peer on its way out. Lead with `needs`: approving a peering request does not connect anything, it creates the peer at status `approved` and nothing crosses until somebody presses Activate, and that half-finished state is what this read exists to show. `signin` is two decisions and both must say yes — the node-wide policy and a switch on each peer — so `signin.reaches` is how many peers a person could ACTUALLY arrive from, and `reaches_nobody` true means the policy is set to something other than off and admits nobody, which looks configured and is not. `offer` is what this node gives the federation: an action, agent, board or service counts only when somebody ticked Federate on it, so `gives_nothing` true means this node reads the federation and puts nothing back — say that plainly, it is a decision people make by accident. `book` is the signed directory of every node in the federation, not only the direct peers; `book.age_days` says whether it is worth mirroring again, and each row carries `is_this_node` and `keeps_book`. `versions_behind` is measured against `newest_version`, which spans the peers, the book AND this node, so a row can be behind the operator's own build. `relay_claims` answers \"which peers are not ready for signed relay claims\": this node's setting, the two versions (the default becomes required in `default_becomes_required_in`, optional is removed in `optional_removed_in`), `not_ready` (relays naming the peer arrive without a claim and none ever came with one), `ready`, `unseen`, and the peers kept on their own setting; each roster row carries the same as `relay_claim`, with when the peer last relayed with and without a claim. A relay without a claim is named by its sender, so `not_ready` is a sign, not proof. Each roster row carries `origin`, how the peer arrived: `recorded` (a package grant, a package seller, a sale or an install set added it without an operator, with who asked), `inferred` (an older packages-only peer, with the records that name it), or `operator_or_federation`. `pending_registrations` are package grants waiting for their node to answer. To remove a peer, or free a node id taken under a wrong key, the operator uses DELETE /v1/federation/peers/{nodeId}?emergency=true (the Federation page). The same data as GET /v1/admin/federation/overview. Returns an operator-role error for non-operators.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_federation_peer_remove",
            "description": "Operator-only. Remove a federation peer, or free a node id somebody else holds. With emergency true the peer goes at once, with the record of how it arrived, its in-flight work is cancelled and its escrow returned, and the node id is free for the real node to peer again; without it the peer enters its de-peering grace and is purged when the grace ends. A node id that is only a package registration still waiting for its node is deleted as that (`pending_deleted`). Read aimeat_admin_federation first: each roster row says how the peer arrived (`origin`), and the Security page names a node id held under another key. Say to the operator which peer you are removing and why before you call this. Returns NOT_FOUND for a node id that is neither a peer nor a waiting registration, and an operator-role error for non-operators. The same as DELETE /v1/federation/peers/:nodeId (?emergency=true).",
            "inputSchema": {
              "properties": {
                "emergency": {
                  "description": "true: remove it now and free the node id. Omitted or false: start its de-peering grace.",
                  "type": "boolean"
                },
                "node_id": {
                  "description": "The peer, by its node id as aimeat_admin_federation lists it.",
                  "type": "string"
                },
                "reason": {
                  "description": "Why, in a few words: kept with the removal and sent with an emergency notice. Defaults to emergency_depeer or operator_decision.",
                  "type": "string"
                }
              },
              "required": [
                "node_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_federation_relay_claim_set",
            "description": "Operator-only. Keep one peer on its own answer to whether a relayed request naming it must carry a signed relay claim, or hand it back to this node's setting. \"required\" refuses an unclaimed relay naming that peer even while the node is on optional; \"optional\" lets one through even after the node's default becomes required in 3.20.0, which is a migration position for a peer that has not updated and goes away in 4.0.0; \"node\" follows the node again. Keeping a peer on optional admits any unclaimed relay that NAMES it, because the name is the sender's own word, so say that when you set it and switch it back once the peer is in `relay_claims.ready`. A peer that has ever sent a valid claim is refused without one whatever this says. Read aimeat_admin_federation first: its `relay_claims.not_ready` names the peers that need this. Returns NOT_FOUND for a node that is not a peer, INVALID_INPUT for any other word, and an operator-role error for non-operators. The same as PUT /v1/federation/peers/:nodeId/relay-claim.",
            "inputSchema": {
              "properties": {
                "node_id": {
                  "description": "The peer, by its node id as aimeat_admin_federation lists it.",
                  "type": "string"
                },
                "relay_claim": {
                  "description": "\"optional\" or \"required\" for this peer alone, or \"node\" to follow this node's setting again.",
                  "enum": [
                    "optional",
                    "required",
                    "node"
                  ],
                  "type": "string"
                }
              },
              "required": [
                "node_id",
                "relay_claim"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_hook_set",
            "description": "Operator-only. Bind a list of actions to one of the eleven moments, or clear it with an empty list. The actions are called in the order given, each after the last has answered. A gate (any hook whose name starts with pre_) WAITS for them and refuses the thing when one answers no, returns a non-2xx, or does not answer within ten seconds, so binding an address that is not reachable stops everything that moment guards; the other seven are told afterwards and stop nothing. A hook binds only an action that is already published: publish the action first (POST /v1/actions, with its webhook_url), then bind it. An action reference is a published action's id, or its id with its provider (id#provider). A reference that no action published here answers to is refused with INVALID_INPUT and nothing is written. A bare id that more than one provider publishes is refused, with the id#provider of each: bind the one you mean with its provider. A bare id that one provider publishes is stored as its id#provider, so another owner publishing the same id later changes nothing. Read aimeat_admin_hooks first: its bindable_actions lists what can be bound, each with the ref to write.",
            "inputSchema": {
              "properties": {
                "actions": {
                  "description": "Action references to call, in order, each naming an action already published here. An empty list clears the moment.",
                  "type": "array"
                },
                "hook": {
                  "description": "The moment, e.g. \"pre_owner_registration\".",
                  "type": "string"
                }
              },
              "required": [
                "hook",
                "actions"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_hooks",
            "description": "Operator-only. The Hooks page in one read: the eleven moments in this node's life where it can call out to somebody's own code, which four of them DECIDE whether the thing happens (a pre_ hook can refuse a registration, a work request, a board post or a new federation peer) and which seven are only told afterwards, what is bound to each and whether that action is still published and still carries an address, which actions could be bound, and every call the node has made with what came back. Read this before advising anyone about hooks: a bound gate whose address stops answering refuses everything it guards, and `failing` names any gate in that state. The same data as GET /v1/admin/hooks. Returns an operator-role error for non-operators.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_incident_resolve",
            "description": "Operator-only. Mark a security incident resolved; the quarantined bytes stay until the incident is deleted. Read aimeat_admin_security_overview first to see the incidents and their ids. The incident the move to the full identity and the settling of what deleted accounts installed and were issued open at start (type held_account_names) lists account names whose rows are older than the account that holds the name now, left as they were (actions, work, ledger lines, cortexes, ecosystem apps, app grants, access tokens; such an app can still act for that account until the name is decided, and the tokens of such an app grant or access token are refused whatever the decision): decide each with `name` and `resolution` — \"holder\" moves its rows, its own ledger lines and the hook bindings to its actions to that account's full identity, and keeps its cortexes, ecosystem apps, app grants and access tokens; \"previous\" settles them as a deleted account's (actions deleted, open work cancelled with what was held going back only to an account that existed when it was written, finished work and ledger lines under one pseudonym, cortexes and ecosystem apps deleted with what they hold, so the apps' tokens stop, and the older app grants and access tokens deleted). That incident closes with its last name, and closing it before answers CONFLICT. Returns NOT_FOUND for an unknown id or name, CONFLICT for a name decided the other way, and an operator-role error for non-operators.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "The incident id, from the overview's incidents list.",
                  "type": "string"
                },
                "name": {
                  "description": "To decide one name of an incident the move to the full identity opened: the account name, from the incident's names.",
                  "type": "string"
                },
                "resolution": {
                  "description": "With `name`: \"holder\" (its rows, cortexes, ecosystem apps, app grants and access tokens are the account's that holds the name now) or \"previous\" (they were a previous holder's).",
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_install_set",
            "description": "Operator-only. Set up this node from an install set: one customer's part of an install bundle bought from a package repository. The set names the bundle (its group id, and the repository node when it comes from one), the owner user everything is installed for, the other users (each with an email, and join \"account\" to create the account now with the login link on, or \"invite\" to send an email invitation), the names of the organisms, the config values, whether updates apply by themselves, `grant_apps` (default true: the owner's grant for each installed app is recorded for the scopes the app declares, so the apps sign in with no consent screen; the purchase is the approval, a later update that asks for more still asks, and the owner can revoke each one) and `landing` ({ group_id, app }: the app the owner's welcome link opens, signed in). The bundle names the packages, the organisms with their workspaces, and the crew agents. Always run action \"plan\" first: it writes nothing and lists `problems`, such as a required config value the set does not give; ask the person for each one and put it in the set, or a secret in `secrets`, which is never stored. Then \"apply\". Applying again creates nothing twice, so it is also how a crew agent that waited for a runner is deployed once the owner has connected one. \"list\" shows what was applied on this node. Needs the exact permission \"operator:admin\", which no wildcard carries. The same as POST /v1/install-sets/apply and GET /v1/install-sets.",
            "inputSchema": {
              "properties": {
                "action": {
                  "description": "plan: what the set would make, and every problem, writing nothing. apply: make it. list: the sets applied on this node.",
                  "enum": [
                    "plan",
                    "apply",
                    "list"
                  ],
                  "type": "string"
                },
                "install_set": {
                  "description": "For plan and apply: the install set, a JSON object with spec \"aimeat.install-set/1\".",
                  "type": "object"
                },
                "secrets": {
                  "description": "For plan and apply: secret config values, { \u003cpackage group id\u003e: { \u003ccomponent id\u003e: { \u003cfield\u003e: value } } }. Never stored in the record.",
                  "type": "object"
                }
              },
              "required": [
                "action"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_knowledge",
            "description": "Operator-only. The Knowledge page in one read: EVERY knowledge package on this node, the shape of the collection, and whether anybody has already looked at each one. NOT the same question as aimeat_knowledge_list, which is the catalogue — what a caller may read — and therefore a subset: this one includes the packages nobody catalogued, which on a moderation screen are the ones that matter. `paging` carries number, per_page, total and pages together, so say the total rather than the page length: a page of twenty out of two hundred read as the whole store is the one mistake this tool cannot make. `facets` counts over EVERYTHING that matched rather than over the page, and a facet does not narrow its own counts, so you can move sideways from one kind to another without clearing a filter first. `facets.authors` collapses a person across the spellings of their name and lists them: this node writes the same person as both `alice` and `alice@node-id`, so filter with author_key rather than typing a name. `facets.maturity[].declared` is false for a word this node does not define (the type declares draft, review and published, and live data carries others) — report such a value as undeclared instead of printing it as if it were ours. Each package carries `reviews` and `last_review`, so \"nobody has looked at this yet\" is a fact you can state. The same data as GET /v1/admin/knowledge. Returns an operator-role error for non-operators.",
            "inputSchema": {
              "properties": {
                "author_key": {
                  "description": "One author, collapsed across the spellings of their name. Take the key from facets.authors.",
                  "type": "string"
                },
                "content_type": {
                  "description": "One kind of package, as facets.kinds names it.",
                  "type": "string"
                },
                "flagged": {
                  "description": "Only packages somebody has reported.",
                  "type": "boolean"
                },
                "limit": {
                  "description": "How many packages on the page. 20 by default, 50 at most.",
                  "type": "number"
                },
                "page": {
                  "description": "Which page of packages, from 1. A page past the end comes back as the last page rather than empty.",
                  "type": "number"
                },
                "q": {
                  "description": "Free text over the name, the author and the tags.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_mint",
            "description": "Operator-only. Mint morsels into an agent's owner balance (irreversible ledger credit). Enforces the node's daily mint cap. Use sparingly — this is a financial action; prefer the normal earn/transfer flow where possible.",
            "inputSchema": {
              "properties": {
                "amount": {
                  "description": "Positive integer amount of morsels to mint.",
                  "type": "number"
                },
                "gaii": {
                  "description": "Target agent GAII whose owner balance is credited.",
                  "type": "string"
                }
              },
              "required": [
                "gaii",
                "amount"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_node_update",
            "description": "Operator-only. Is a newer AIMEAT out on npm than the version this node runs? Answers the running version (`current`), the newest on npm (`latest`), `updateAvailable`, when the newer one was released, `whatsNew` (the change-log entries it has and this node does not, newest first; each title and body is a string or an object by language), how the node looks to be installed (`install.method`: npm, npx, source, docker, desktop or unknown, a guess from its own paths), and `prompt`: a ready prompt that updates the node, for an AI with a shell on the machine the node runs on (Claude Code, Codex). Show the person the version, the date and what is new in their own words, and offer the prompt; the update restarts the node, so it is theirs to start. After an update, call again with refresh: true and check that `current` is the new version. The node asks npm at most once every six hours; with the node.update_check setting off it asks nothing and answers enabled: false. The same data as GET /v1/admin/node-update. Returns an operator-role error for non-operators.",
            "inputSchema": {
              "properties": {
                "refresh": {
                  "description": "Ask the registry now instead of answering from the six-hour cache.",
                  "type": "boolean"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_organism_owner_add",
            "description": "Operator-only break-glass. Make an owner the creator of an organism the caller does not own, for the case where the organism's own creator account can no longer be reached. The previous creator stays on as an admin, and a target who is not yet a member is seated as one; a blocked target is refused. Needs the exact permission operator:organism-repair, which no wildcard carries. The ordinary handover, by the current creator to an existing member, is aimeat_organism_update's sibling route POST /v1/organisms/{id}/transfer.",
            "inputSchema": {
              "properties": {
                "ghii": {
                  "description": "Bare owner name to install as the organism's creator.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "The organism ID to repair.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ghii"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_organism_ownership",
            "description": "Operator-only. Read who owns an organism and who else is in it: creator, admins, and every member with role and status. Read this before aimeat_admin_organism_owner_add — installing an owner is a cross-account act and the roster it re-points should be seen first. For an organism you belong to yourself, use aimeat_organism_get.",
            "inputSchema": {
              "properties": {
                "organism_id": {
                  "description": "The organism ID.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_owner_disable",
            "description": "Operator-only. Deactivate an account on this node: the person's knowledge, memberships and history remain, but every credential acting in their name — sessions, agents' tokens, access tokens, app grants — stops immediately and nothing new can be minted. Reversible with aimeat_admin_owner_enable. You cannot deactivate your own account. This tool is the manual way to offboard; an organisation's directory does the same automatically over SCIM.",
            "inputSchema": {
              "properties": {
                "name": {
                  "description": "The owner name to deactivate.",
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_owner_enable",
            "description": "Operator-only. Reactivate a deactivated account. The person can sign in again and reconnect their agents; the credentials that were ended by deactivation stay dead.",
            "inputSchema": {
              "properties": {
                "name": {
                  "description": "The owner name to reactivate.",
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_security_overview",
            "description": "Operator-only. The Security page in one read: a bounded sample of at most 1000 readable log lines filtered to the last 24 hours (count_kind=sample, window_total=null; unknown zone when comparison history is insufficient) (refusals, distinct sources, walled addresses, each with a zone decided from this instance's own readable history), the refusal log grouped by endpoint, source, credential kind and credential fingerprint plus its newest 200 lines, the refused-and-kept incidents with the open count, who holds the operator role and which accounts are deactivated or use two-step sign-in, how apps are kept apart from the sign-in of whoever opens them (apps: on their own addresses, in an isolated frame, or on this node's address while one person has an account; on a node several people share with no app addresses, a warning in words and the settings that give every app its own address), and the access settings (rate limits, tarpit, lockout, TOTP, CORS origins, federation sign-in, body limits, the log file). The same data as GET /v1/admin/security/overview. Returns an operator-role error for non-operators.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_sso_create",
            "description": "Operator-only. Connect an organisation's identity provider: create an SSO connection with a permanent slug id, the organisation's name, its email domains (which decide whose existing accounts it may adopt), an optional organism its people join on arrival, and whether the connection shows as a sign-in button. Configure the SAML half next with aimeat_admin_sso_idp_metadata and mint the provisioning token with aimeat_admin_sso_scim_token. Refused while connection management is locked on this node.",
            "inputSchema": {
              "properties": {
                "allow_idp_initiated": {
                  "description": "Accept sign-ins started from the IdP's own portal tile (default false).",
                  "type": "boolean"
                },
                "domains": {
                  "description": "Email domains this organisation vouches for, e.g. [\"contoso.com\"].",
                  "type": "array"
                },
                "id": {
                  "description": "Permanent slug id (lowercase letters, digits, dashes; 2-31 chars).",
                  "type": "string"
                },
                "login_visibility": {
                  "description": "\"listed\" shows a sign-in button; \"hidden\" keeps the organisation off the public modal (default listed).",
                  "type": "string"
                },
                "name": {
                  "description": "The organisation's name — the sign-in button label when listed.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism its people are added to on first sign-in or provisioning.",
                  "type": "string"
                }
              },
              "required": [
                "id",
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_sso_delete",
            "description": "Operator-only. Remove an SSO connection — the sign-in route, not the people: every account it created or adopted remains, with its knowledge and memberships, and recreating the connection under the same id restores provisioning authority over them. Refused while connection management is locked on this node.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "The connection id.",
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_sso_get",
            "description": "Operator-only. Read one SSO connection: its domains, organism binding, sign-in visibility, whether SAML metadata and a SCIM token are configured, when the identity provider last signed someone in and last called the SCIM endpoint, and the SP details to paste into the IdP console. Secrets are never returned.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "The connection id (slug).",
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_sso_idp_metadata",
            "description": "Operator-only. Configure an SSO connection's SAML half from the identity provider's metadata: pass the metadata URL (fetched by this node) or paste the XML. Nothing is saved unless the document yields an entity id, an HTTP-Redirect sign-in endpoint and at least one signing certificate. Refused while connection management is locked on this node.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "The connection id.",
                  "type": "string"
                },
                "name_id_format": {
                  "description": "Requested NameID format, when the IdP's default is not wanted.",
                  "type": "string"
                },
                "url": {
                  "description": "The IdP metadata URL (e.g. Entra's federation metadata address).",
                  "type": "string"
                },
                "xml": {
                  "description": "The IdP metadata document itself, when a URL is not reachable.",
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_sso_list",
            "description": "Operator-only. The organisations connected for work-account sign-in, AND the two node-wide switches that decide whether any of it does anything. READ `node` FIRST: `node.enabled` is the master switch, and while it is false the sign-in endpoint and the provisioning (SCIM) endpoint both answer 503 whatever a connection says — so a connection can be complete and reach nobody. `node.locked` means connection management is frozen and every write below will be refused with 403. Each connection carries `state` (no_idp · blocked_by_switch · live · live_hidden), `can_sign_in`, `button_showing` and `steps_done` out of six: report those rather than the raw flags, because \"configured but unusable\" and \"live\" look identical in `saml_configured` alone. The sixth step is the master switch and it is NOT one of these tools — it is `sso.enabled` in the node configuration, so say so when you report a setup as finished. Also per connection: its email domains (which decide whose existing accounts it may adopt), its visibility, and the SP details (entity id, ACS URL, SCIM base URL) an IdP console asks for. Secrets are never returned. The same data as GET /v1/admin/sso/connections.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_sso_scim_token",
            "description": "Operator-only. Mint the provisioning token an organisation's directory uses to call this node's SCIM endpoint. The token is returned ONCE and only its hash is stored; minting again replaces the previous token, which stops working immediately. Paste it into the IdP's provisioning configuration together with the connection's SCIM base URL. Refused while connection management is locked on this node.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "The connection id.",
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_sso_update",
            "description": "Operator-only. Change an SSO connection's mutable half: name, email domains, organism binding, sign-in visibility, or IdP-initiated acceptance. The id never changes, and the SAML metadata goes through aimeat_admin_sso_idp_metadata instead. Refused while connection management is locked on this node.",
            "inputSchema": {
              "properties": {
                "allow_idp_initiated": {
                  "description": "Accept IdP-initiated sign-ins.",
                  "type": "boolean"
                },
                "domains": {
                  "description": "New email-domain list (replaces the old one).",
                  "type": "array"
                },
                "id": {
                  "description": "The connection id.",
                  "type": "string"
                },
                "login_visibility": {
                  "description": "\"listed\" or \"hidden\".",
                  "type": "string"
                },
                "name": {
                  "description": "New organisation name.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "New organism binding; an empty string clears it.",
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_statistics",
            "description": "Operator-only. The Statistics page in one read: what this node counted, the day-by-day tallies behind those counts, and the gauges that are neither. Give BOTH from and to (ISO dates, inclusive) for a period, or neither for the node's whole life. THREE KINDS OF NUMBER share the payload and only one moves with the period. Counters (requests_total, memory_reads, memory_writes, auth_failures_total, rate_limit_hits_total, scope_denials_total, schema_validations, email_sent, push_sent …) are summed over the period when you give one, and are lifetime totals when you do not. Gauges (uptime_seconds, active_owners, active_agents, tunnel, mailbox, gauges.*) are read at the moment of the call, are not summable, and a period does not touch them: never compare one across periods. `daily` carries one entry per day that had activity, so a missing day is a day with none rather than a gap in the data. READ IT TWICE to say anything useful — once for the period and once without — because a counter reading 0 for a period may have a large lifetime total, while one reading 0 both ways has never been written at all, and those are different facts. auth_failures_total is usually the largest number on a node reachable from the public internet, and a rate that stays flat across a weekend is a script working through credentials rather than people. The same data as GET /v1/stats. Returns an operator-role error for non-operators.",
            "inputSchema": {
              "properties": {
                "from": {
                  "description": "First day of the period, inclusive, as YYYY-MM-DD. Give `to` as well or neither is used.",
                  "type": "string"
                },
                "to": {
                  "description": "Last day of the period, inclusive, as YYYY-MM-DD. Give `from` as well or neither is used.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_stats",
            "description": "Operator-only. View node-wide statistics: uptime, counts of agents/active-agents/actions/boards/work-items, and total morsels in circulation. Returns an operator-role error for non-operators. For per-agent detail use aimeat_admin_agents; for node settings use aimeat_admin_config.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_totp_reset",
            "description": "Operator-only. Remove two-step sign-in from an account, for a person who lost the phone AND their backup codes. Their own removal page asks for a code, which is exactly what they no longer have, so without this the account is unreachable. It grants nobody access: the password still stands and you are handed nothing. The person is told — the reset lands on their account feed with your name on it. You cannot use it on your own account; ask another operator, or use one of your backup codes.",
            "inputSchema": {
              "properties": {
                "name": {
                  "description": "The owner name whose two-step sign-in should be removed.",
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_admin_usage",
            "description": "Operator-only. What AI costs on this node, organised by WHOSE MONEY IT IS rather than by which system counted it. Give BOTH from and to (ISO dates, inclusive) or neither for the trailing thirty days. `whose_money.house` is the operator's own bill — what people spent on the node's key because they had not brought their own. `whose_money.own` is other people's own provider accounts and costs the operator nothing. `whose_money.ledger` is a THIRD count, off a different table, and is the larger set; report it as such and never add it to the other two. `ceiling_usd` is the free grant times the number of accounts: the most the server's key can cost before somebody is refused, and the number an operator acts on. THE IMPORTANT LIMIT: `keys.chat.metered_here` is false, because every chat turn is spent from one key handed to a child process, so no figure here contains any of it — say so whenever you report a total, or the operator will read a bill that is missing its largest item. Pass ask_provider true to have the node ask the provider what its own two keys have actually spent (one outbound call per key, cached a minute); without it `keys.*.spend` is null and unknown is the honest answer. `models.unpriced` explains the calls that carry no cost: most are free or local models that have none, and `estimated_missing_usd` is what the rest would have cost at the priced average. The same data as GET /v1/admin/usage/page. Returns an operator-role error for non-operators.",
            "inputSchema": {
              "properties": {
                "ask_provider": {
                  "description": "Ask the provider what the node's own house and chat keys have spent. One outbound call per key. Off by default.",
                  "type": "boolean"
                },
                "from": {
                  "description": "First day of the period, inclusive, as YYYY-MM-DD. Give `to` as well or neither is used.",
                  "type": "string"
                },
                "to": {
                  "description": "Last day of the period, inclusive, as YYYY-MM-DD. Give `from` as well or neither is used.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_agent_activity",
            "description": "View this agent's own activity statistics plus a time-series history (default last 30 days, daily granularity). Read-only — useful for self-reflection or reporting on recent work volume. For raw telemetry events you push, use aimeat_agent_telemetry_report; for task-level progress use aimeat_task_list.",
            "inputSchema": {
              "properties": {
                "days": {
                  "description": "Number of days of history to retrieve.",
                  "type": "number"
                },
                "granularity": {
                  "description": "History granularity.",
                  "enum": [
                    "daily",
                    "hourly"
                  ],
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_agent_basics_get",
            "description": "What this account would get from the one-press basic agents, and whether it can happen right now. Returns the two agents (concierge, which answers what arrives and routes the rest; workflow-manager, which orders work from the owner's other agents), the permissions each would hold, which already exist, and whether the owner's connector is running. READ ONLY: you cannot create them. Creating agents changes the account, so the person does it themselves. Hand them `approval_url` and say `next_step` — it is already written for them and true for this account's current state — then call this again to see `enrolled` turn true. To propose a DIFFERENT agent, one you have designed for a job these two do not cover, use aimeat_agent_propose: it puts the proposal in front of the owner and creates nothing until they approve.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_agent_basics_request",
            "description": "Ask your owner to set up the basic agents. Puts ONE line on their open-items list — the list they already read — saying which agents are missing, and that line retires itself the moment they press the button, so nobody has to tick it off. Call aimeat_agent_basics_get first: if they are already there this answers requested:false with reason 'already_there' and writes nothing, and if you (or another of the owner's agents) already asked, it answers 'already_asked' with the standing item's id rather than printing a second line. This does NOT create the agents; creating them changes the account and the person does that themselves on the page in approval_url. Needs memory:write, because an open item is a record in the owner's own namespace.",
            "inputSchema": {
              "properties": {
                "note": {
                  "description": "Optional: one short phrase on why you are asking, shown to the person with the request.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_agent_capabilities_report",
            "description": "Self-report this agent's capabilities so other agents can discover it: technical capabilities (MCP servers, skills, tools — MCP-type entries are auto-marked verified), domain expertise, and human languages. Overwrites the previously reported capability set on the agent record. Use during/after onboarding; this is descriptive metadata, not the same as registering a hireable action or aimeat_capabilities_create.",
            "inputSchema": {
              "properties": {
                "domain": {
                  "description": "Array of domain expertise strings.",
                  "type": "array"
                },
                "languages": {
                  "description": "Array of language codes.",
                  "type": "array"
                },
                "technical": {
                  "description": "Array of technical capabilities: { name, type }.",
                  "type": "array"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_agent_console_set",
            "description": "Record where an agent is managed by whatever HOSTS it: its settings or brain page in the fleet runtime it runs in. Call this after creating and starting an agent somewhere the node cannot see — a fleet cockpit, your own daemon's UI — so the owner's profile can link straight to it. Without it the person is told their agent is running and has nowhere to go and look at it. Must be an absolute http(s) URL; send an empty string to clear it. Display only: the node links this address and never fetches it.",
            "inputSchema": {
              "properties": {
                "console_url": {
                  "description": "Absolute http(s) URL of that agent's page in its host, or '' to clear it.",
                  "type": "string"
                },
                "target_agent_name": {
                  "description": "Agent whose console address to set (must be owned by the same owner as the caller). Pass your own name to record your own.",
                  "type": "string"
                }
              },
              "required": [
                "target_agent_name",
                "console_url"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_agent_description_set",
            "description": "Say what one of your agents IS, in a sentence — the line a stranger reads on its A2A card and the one on its page here. Set it when what the agent does changes: it was fixed at registration and editable by nobody until 2026-09-03, so an agent whose job moved went on describing its old one. Send an empty string to clear it. The agent's NAME cannot be changed here or anywhere, because it is part of its identity; a description carries none.",
            "inputSchema": {
              "properties": {
                "description": {
                  "description": "What this agent is, in a sentence or two. Up to 2000 characters; empty clears it.",
                  "type": "string"
                },
                "target_agent_name": {
                  "description": "Agent whose description to set (same owner as the caller). Pass your own name to describe yourself.",
                  "type": "string"
                }
              },
              "required": [
                "target_agent_name",
                "description"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_agent_mode_set",
            "description": "Owner-only. Set an agent's operational mode. Modes: 'autonomous' (runs continuously, full Hello Integration), 'interactive' (user-facing, full Hello Integration), 'task-runner' (triggered/ephemeral, reduced 7-step Hello Integration — no commands or messages), 'coordinator' (orchestrates other agents, full Hello Integration), 'workstation' (node-visiting agent in the user's own env like VSCode or Claude Desktop, uses MCP directly; not node-resident, so narrowest 4-step Hello Integration — auth, platform, capabilities, directives).",
            "inputSchema": {
              "properties": {
                "mode": {
                  "description": "New mode.",
                  "enum": [
                    "autonomous",
                    "interactive",
                    "task-runner",
                    "coordinator",
                    "workstation"
                  ],
                  "type": "string"
                },
                "target_agent_name": {
                  "description": "Agent whose mode to update (must be owned by the calling owner).",
                  "type": "string"
                }
              },
              "required": [
                "target_agent_name",
                "mode"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_agent_profile",
            "description": "View another agent's public profile by GAII: display name, description, advertised capabilities, trust score, and created date. Use to vet a provider before hiring it via aimeat_action_execute, or to inspect an agent you found through aimeat_catalogue_agents. To list your own owner's agents instead, use aimeat_agents_list.",
            "inputSchema": {
              "properties": {
                "gaii": {
                  "description": "Agent GAII identifier.",
                  "type": "string"
                }
              },
              "required": [
                "gaii"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_agent_propose",
            "description": "How a new agent is made on this node. When the person asks you for an agent (\"an agent that every morning…\", \"something that watches…\", a helper for one job the basic agents do not cover), propose it here: this node creates it, gives it its instructions, credentials it and runs it on the person's own connector, so never point them to an outside agent builder or another product for this. BEFORE you propose, read what of theirs it will work on: aimeat_organism_list and aimeat_workspace_list (or aimeat_discover with scope \"shared\") show the organisms and workspaces they keep, such as their CRM or their notes. Name that data in `purpose` and in the `crew_def` tasks. Scopes: what the job needs. The node adds memory:read and memory:write itself, because a crew runtime reads its own definition and writes its result with them. It needs no agent:write to report about itself, and agent:write lets an agent approve new agents, so add it only when that is the job. CREATES NOTHING: the proposal waits for the person, and only their own press creates the agent, because adding a principal to an account is theirs to decide. AFTER: give the person `approval_url` from the answer and say `next_step`. Send `crew_def` whenever you can: an agent approved without one exists and cannot run, and a new agent has no runtime to publish one to, so the definition you attach here is the one it starts with. It is checked before the proposal is written, so a broken one is refused now. The smallest crew_def that runs: {\"agents\":[{\"role\":\"Reader\",\"goal\":\"…\",\"backstory\":\"…\",\"tools\":[\"memory\"]}],\"tasks\":[{\"id\":\"main\",\"agent\":\"Reader\",\"description\":\"… {{ctx.prompt}} …\",\"expected_output\":\"…\"}]}; each task's `agent` is one of the agents' role (or name), and at least one task's description contains {{ctx.prompt}}, which becomes each run's own task text. `scopes` may not exceed what you hold yourself. A name already waiting returns the standing proposal. For work on a clock, propose the agent first and schedule its task (aimeat_schedule_create, kind agent_task) once it exists.",
            "inputSchema": {
              "properties": {
                "crew_def": {
                  "description": "What it would BE, in the crewaimeat crew_def shape — the same document aimeat_crew_publish takes. Strongly recommended.",
                  "type": "object"
                },
                "display_name": {
                  "description": "The name shown to the person. Defaults to the agent name.",
                  "type": "string"
                },
                "mode": {
                  "description": "How the node treats its tasks: 'task-runner' activates a queued task without asking the owner each time; also autonomous, interactive, coordinator, workstation.",
                  "type": "string"
                },
                "name": {
                  "description": "The agent name: 3 to 40 characters, lowercase letters, digits and hyphens, starting with a letter.",
                  "type": "string"
                },
                "purpose": {
                  "description": "What this agent is for, in a sentence the owner can decide from. This is what they read.",
                  "type": "string"
                },
                "run_mode": {
                  "description": "'spawn' starts a worker per piece of work (right for bursty jobs); 'resident' stays up (right for an agent that answers people as they write, at a few seconds of cold start saved).",
                  "type": "string"
                },
                "scopes": {
                  "description": "Exactly what it may do, e.g. [\"memory:read\",\"memory:write\"]. Never more than you hold yourself.",
                  "type": "array"
                }
              },
              "required": [
                "name",
                "purpose"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_agent_run_mode_set",
            "description": "Set how one of your agents is meant to be RUN: 'spawn' (the agent is data on the node until work arrives, and its runtime starts a worker for the job which then unwinds) or 'resident' (the runtime keeps it up). Works on ANY agent you own, whatever runs it — an agent whose behaviour lives in code rather than in a definition on this node is not a lesser agent, and this is the switch that puts it on a spawner's roster (GET /v1/agents?run_mode=spawn). The node records it and the runtime honours it; the node never enforces it, exactly as with mode and max concurrent tasks.",
            "inputSchema": {
              "properties": {
                "run_mode": {
                  "description": "'spawn' = started per job and unwound after; 'resident' = kept running; null takes it back to nobody-has-said, so a spawner leaves the agent alone.",
                  "enum": [
                    "spawn",
                    "resident"
                  ],
                  "type": "string"
                },
                "target_agent_name": {
                  "description": "Agent whose run mode to set (must be owned by the same owner as the caller). Pass your own name to set your own.",
                  "type": "string"
                }
              },
              "required": [
                "target_agent_name",
                "run_mode"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_agent_runtime_report",
            "description": "Say what code is running this agent, so a run can be audited afterwards. A crew whose definition lives on this node is already answerable — the definition is versioned here — but a code-backed crew has none, and then nothing can say what ran. Send the file, its hash, the commit it came from and which runtime read it; send null to clear. The node records the claim and stamps its own time on it, and never checks it: it does not run the process and cannot read the disk. Say in `llm` where the crew's model calls go. An agent reports its own with no permission word; a same-owner sibling's needs agent:write.",
            "inputSchema": {
              "properties": {
                "commit": {
                  "description": "Commit the file came from.",
                  "type": "string"
                },
                "definition_revision": {
                  "description": "For a JSON crew: which revision of the definition on this node was live.",
                  "type": "number"
                },
                "file": {
                  "description": "Path to the file that runs, relative to your own root, e.g. 'crews/web_researcher_crew.py'.",
                  "type": "string"
                },
                "kind": {
                  "description": "What kind of thing runs, e.g. 'python' for a code-backed crew or 'crew-def' for a JSON one.",
                  "type": "string"
                },
                "llm": {
                  "description": "Where the crew's model calls go: 'node' when they go through this node's /v1/llm with the agent's own token (the owner's own key then pays before the node's), 'machine' when the crew calls its provider with a key on its own machine. The owner's AI settings read it to say whether their own key reaches this agent.",
                  "enum": [
                    "node",
                    "machine"
                  ],
                  "type": "string"
                },
                "runtime": {
                  "description": "Which runtime read it, e.g. 'crewaimeat 0.7.0'.",
                  "type": "string"
                },
                "sha256": {
                  "description": "Hash of that file's contents — the only field that changes when the code changes and nothing else does.",
                  "type": "string"
                },
                "target_agent_name": {
                  "description": "Agent this is about (same owner as the caller). Pass your own name to report your own.",
                  "type": "string"
                }
              },
              "required": [
                "target_agent_name",
                "kind"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_agent_scope_narrow",
            "description": "Replace one of the owner's agents' \"all permissions\" (*) with the named permissions it actually used, as the node recorded them. Use it when the person agrees after you showed them the list (aimeat_agents_list: task_start_wildcard.proposal). An agent with * has every task wait for the owner's OK once two weeks of its use are on record; narrowed, it starts on its own again if its setting says so. Refused when nothing it used is on record yet. Needs agent:permissions.",
            "inputSchema": {
              "properties": {
                "target_agent_name": {
                  "description": "The agent holding * to narrow (same owner as you).",
                  "type": "string"
                }
              },
              "required": [
                "target_agent_name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_agent_tags_set",
            "description": "Replace (set) the tag list on a same-owner agent. An agent may tag itself with no permission word, and a same-owner sibling with agent:write; an owner may tag any of their agents. Convention: 'crew:\u003cname\u003e', 'source:\u003cname\u003e', 'role:\u003cname\u003e', 'project:\u003cname\u003e' — but any lowercase string of alphanumerics plus `._:-` is accepted (no `@`). Max 20 tags. Empty array clears all tags.",
            "inputSchema": {
              "properties": {
                "tags": {
                  "description": "Replacement tag list. Empty array clears all tags.",
                  "type": "array"
                },
                "target_agent_name": {
                  "description": "Agent whose tags to update (must be owned by the same owner as the caller). Pass the calling agent's own name to self-tag.",
                  "type": "string"
                }
              },
              "required": [
                "target_agent_name",
                "tags"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_agent_task_start_set",
            "description": "Set whether one of the owner's agents starts its tasks on its own ('automatic': it proposes its plan and goes on, and the owner sees what was done) or waits for the owner's OK on each ('confirm'). Use it when the person says so (\"let the concierge start its tasks by itself\"). null leaves it to the agent's mode again. Never for yourself. An agent that can spend money, send mail as the owner or delete as the owner always waits whatever this says; the answer's task_start_held_by names those permissions.",
            "inputSchema": {
              "properties": {
                "target_agent_name": {
                  "description": "The agent this is about (same owner as you, never yourself).",
                  "type": "string"
                },
                "task_start": {
                  "description": "'automatic' or 'confirm'; null = leave it to the agent's mode.",
                  "enum": [
                    "automatic",
                    "confirm"
                  ],
                  "type": "string"
                }
              },
              "required": [
                "target_agent_name",
                "task_start"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_agent_telemetry_report",
            "description": "Append one telemetry event (llm_call, tool_call, or agent_report) recording metrics such as tokens, duration, or tool name; optionally tie it to a session or AIMEAT task. Feeds the node's activity stats (viewable via aimeat_agent_activity). Use for fine-grained runtime metrics — for task lifecycle/progress use the aimeat_task_* tools instead.",
            "inputSchema": {
              "properties": {
                "data": {
                  "description": "Telemetry data such as tokens, duration, or tool name.",
                  "type": "object"
                },
                "session_id": {
                  "description": "Optional runtime session identifier.",
                  "type": "string"
                },
                "task_id": {
                  "description": "Optional related AIMEAT task id.",
                  "type": "string"
                },
                "type": {
                  "description": "Telemetry event type.",
                  "enum": [
                    "llm_call",
                    "tool_call",
                    "agent_report"
                  ],
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_agents_list",
            "description": "List the calling owner's agents on the node (name, mode, capabilities, tags, last_seen, etc.). Use this to discover which agents you can delegate to via aimeat_task_create. Each agent also carries its permissions (default_scopes), what it asked for at its last approval (scope_request), and `refusals`: calls the node refused it for a missing permission that is still missing. A refusal is often why an agent's tasks do not move; tell the owner which permission to grant.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_ai_capabilities",
            "description": "CALL THIS FIRST before you plan anything that uses AI: an app, an automation or your own work. Answers, per capability (text, vision, files, image, speech, transcription, embed), whether it is on for you right now, the model and provider a call would use, its price from the model catalogue, and a one-line howTo. For a capability that is off: the reason (NO_MODEL, NO_PROVIDER_SUPPORTS, NO_KEY, POLICY_EMPTY, BUDGET_EXHAUSTED, RETIRED_MODEL, UNTESTED, APP_NOT_ALLOWED), agentFix (what you can do), fix (the sentence to tell the owner, in their language) and settingsUrl (the link that opens their AI settings where it is fixed). Also the owner's model policy, today's budget, and the guide skill (aimeat-ai-capabilities). Spends nothing.",
            "inputSchema": {
              "properties": {
                "app_id": {
                  "description": "The app you act for, when you do: its own model list and preferences count.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_ai_embed",
            "description": "Turn texts into embedding vectors (the embed capability), on the owner's providers and budget. Use it only when the person decided it: never propose it yourself. It is for a collection far larger than one prompt (hundreds of thousands of tokens) that people search by meaning; a collection that fits one prompt goes to a text model whole, and word search comes first (skill aimeat-ai-capabilities, section 4). Store the answered `model` beside the vectors: vectors of different models cannot be compared, so a fallback only ever uses the same model. At most 256 texts and 500 000 characters per call.",
            "inputSchema": {
              "properties": {
                "app_id": {
                  "description": "The app this is for, so its spend is attributed.",
                  "type": "string"
                },
                "input": {
                  "description": "The texts, one vector each.",
                  "type": "array"
                },
                "model": {
                  "description": "A model reference; omit to let the owner's providers choose.",
                  "type": "string"
                },
                "provider": {
                  "description": "A provider id or type to use, with no fallback.",
                  "type": "string"
                },
                "role": {
                  "description": "The AI role to run as: one of your roles (aimeat_ai_roles), or for an app a role it declares and you bound. A named model or provider wins over it.",
                  "type": "string"
                }
              },
              "required": [
                "input"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_ai_job_cancel",
            "description": "Stop a background AI job. A queued one leaves the wait line and nothing is spent; a running one has its provider call torn down, so a stuck long call can be cleared instead of waited out. Whatever the provider had already billed stays recorded — a cancelled call is not a free call. A job that has already finished answers that there is nothing left to stop.",
            "inputSchema": {
              "properties": {
                "job_id": {
                  "description": "The job id to stop.",
                  "type": "string"
                }
              },
              "required": [
                "job_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_ai_job_get",
            "description": "Read one background AI job: its state, what it cost, where its answer went, and — when it failed — the code and message saying why. A job that ended `failed` with `chain_stopped` set is one whose on_done callback could not continue the chain, which is deliberately NOT reported as success. Only the owner's own jobs are reachable; anything else is simply not found.",
            "inputSchema": {
              "properties": {
                "job_id": {
                  "description": "The job id from aimeat_ai_job_start.",
                  "type": "string"
                }
              },
              "required": [
                "job_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_ai_job_list",
            "description": "List the owner's background AI jobs. Defaults to the LIVE ones (queued and running), which is what \"what am I still waiting for\" means. A finished job is folded into its day's log and shows up under state=\"all\" or under its own state; its live record is deleted at that point, because one key per run would fill this node's per-account key ceiling within weeks. Use before starting another job to see whether the one you want is already running.",
            "inputSchema": {
              "properties": {
                "limit": {
                  "description": "How many to return (1-500, default 50).",
                  "type": "number"
                },
                "state": {
                  "description": "Which jobs to list. \"live\" (the default) is queued + running.",
                  "enum": [
                    "queued",
                    "running",
                    "done",
                    "failed",
                    "cancelled",
                    "live",
                    "all"
                  ],
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_ai_job_start",
            "description": "Start a BACKGROUND model call and get a handle back in milliseconds. Use this instead of a normal completion whenever the answer may take minutes: the job queues for a slot, runs on this node with the owner's own key and budget, and writes its answer to the memory key you name in `result_key`. It answers at once with a job id and a queue position — never an ETA, because model latency is unknown — so read the job back with aimeat_ai_job_get, or just read `result_key` once it says done. Give it `prompt`, or `prompt_key` naming a record that holds the prompt text. `input_keys` names memory records that are READ AND PASTED INTO the prompt, labelled by key: the model has no tools and cannot fetch anything itself, and a record that does not exist is stated as missing rather than left as a silence it would fill in with an invention. `on_done` calls one of the owner's own extension actions when the answer has landed, which is how a chain of jobs is built; if that callback cannot run, the job ends failed rather than done. There is no token cap, on purpose. `op` picks the kind of call: \"text\" (the default) writes the answer; \"image\" makes one picture from the prompt, stores it in the owner's storage and writes the record { storage_key, url, mime_type, model }; \"transcribe\" turns the audio file at `audio_key` (in your own storage) into text and writes the transcript, or { text, language, seconds, model } with `json`. A field that does not apply to the op is refused before anything is written.",
            "inputSchema": {
              "properties": {
                "app_id": {
                  "description": "App attribution — enables the owner's per-app allowlist and per-app daily quota.",
                  "type": "string"
                },
                "audio_key": {
                  "description": "For op \"transcribe\" (required there): the storage key of an audio file in your own storage. A key that is not there is refused with NOT_FOUND before the job is written.",
                  "type": "string"
                },
                "input_keys": {
                  "description": "Memory keys read and appended to the prompt, labelled by key. This is the ONLY way the model sees stored data — it has no tools. A key naming a record this node keeps for itself (an AI key, a payout setting, a spend limit) is refused with RESERVED_KEY, because everything read goes to the model provider.",
                  "type": "array"
                },
                "json": {
                  "description": "Parse the answer as JSON before storing it, so a malformed answer fails the job instead of becoming a string every reader has to re-parse.",
                  "type": "boolean"
                },
                "language": {
                  "description": "For op \"transcribe\": an ISO-639-1 language hint, e.g. \"fi\". Omit to use the owner's setting or auto-detect.",
                  "type": "string"
                },
                "model": {
                  "description": "Explicit model id. Omit to use the owner's configured model.",
                  "type": "string"
                },
                "on_done": {
                  "description": "{ extension, action } — an extension action of the job's OWN owner, invoked with { job_id, state, result_key } when the job finishes.",
                  "type": "object"
                },
                "op": {
                  "description": "The kind of model call. \"text\" (default): a completion. \"image\": one picture from the prompt; json does not apply. \"transcribe\": speech-to-text over audio_key; no prompt.",
                  "enum": [
                    "text",
                    "image",
                    "transcribe"
                  ],
                  "type": "string"
                },
                "prompt": {
                  "description": "The prompt. Required unless prompt_key names a record holding it.",
                  "type": "string"
                },
                "prompt_key": {
                  "description": "An owner memory key holding the prompt text (a string, or an object with a `prompt` field), so changing the prompt is a memory write rather than a code change.",
                  "type": "string"
                },
                "provider": {
                  "description": "A provider to use, by id or by type. Naming one turns fallback to another provider off. Omit to let the owner's rules choose.",
                  "type": "string"
                },
                "result_key": {
                  "description": "Where the answer is written, in the owner's own namespace. A key naming another namespace is refused, and so is a record this node keeps for itself (RESERVED_KEY).",
                  "type": "string"
                },
                "result_visibility": {
                  "description": "Visibility of the record written at result_key. Default private.",
                  "enum": [
                    "private",
                    "owner",
                    "public"
                  ],
                  "type": "string"
                },
                "role": {
                  "description": "The AI role to run as: one of your roles (aimeat_ai_roles), or for an app a role it declares and you bound. A named model or provider wins over it.",
                  "type": "string"
                },
                "size": {
                  "description": "For op \"image\": a provider-specific size, e.g. \"1024x1024\".",
                  "type": "string"
                },
                "system_prompt": {
                  "description": "Optional system prompt.",
                  "type": "string"
                }
              },
              "required": [
                "result_key"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_ai_models",
            "description": "The model catalogue: which models of OpenRouter, OpenAI, Anthropic, xAI, Mistral and DeepSeek the node knows, what each takes and gives (caps), its limits, its price and its status (active, retiring, retired). allowed: true keeps only the models you can use now (a provider of that type serves the capability, and the owner's policy allows the model). Use the `ref` it lists (\u003ctype\u003e:\u003cmodel id\u003e) in a call, a policy or an app's aimeat-ai meta. A model on the owner's own machine is not in the catalogue.",
            "inputSchema": {
              "properties": {
                "allowed": {
                  "description": "true: only the models you can use now.",
                  "type": "boolean"
                },
                "capability": {
                  "description": "text | vision | files | image | speech | transcription | embed.",
                  "type": "string"
                },
                "status": {
                  "description": "Comma-separated: active, retiring, retired; or all. Default active,retiring.",
                  "type": "string"
                },
                "type": {
                  "description": "openrouter | openai | anthropic | xai | mistral | deepseek.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_ai_policy_set",
            "description": "Read or change which AI models the owner's calls may use, with PROPOSE-THEN-CONFIRM. With no policy: returns the current policy and the node's recommended models. With a policy and no confirm_token: changes NOTHING and returns the current and proposed policy with a single-use token (10 min) bound to exactly that policy; show the change to the owner. With the token: applies it. Modes: open (no limit), recommended (the node's list per capability, following its updates), custom (allow: your own list). Every reference is \u003ctype\u003e:\u003cmodel id\u003e, e.g. openrouter:anthropic/claude-opus-5.5. appliesTo switches say whose calls it covers (owner, chat, agents, apps); apps and agents tighten it for one app (owner/file.html) or one agent. Every layer only tightens. Suggest mode recommended when the owner has a provider and no policy.",
            "inputSchema": {
              "properties": {
                "confirm_token": {
                  "description": "Token from the propose step; omit to propose.",
                  "type": "string"
                },
                "policy": {
                  "description": "{ mode: open|recommended|custom, allow?: [refs], appliesTo?: {owner, chat, agents, apps}, apps?: {\"owner/file.html\": {allow}}, agents?: {name: {allow}} }. Omit to read.",
                  "type": "object"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_ai_provider_test",
            "description": "Test that one of the owner's providers serves one capability, with the smallest real call through the same gate every call uses (billed and budgeted like one). A pass marks it tested and working, which the node needs before it picks the provider by capability alone. capability: text (default), vision, files, transcription, speech (one spoken word), embed (one vector), or image (costs one small picture, so accept_cost: true is required; tell the owner first). Answers the model, the latency and the cost, never a key.",
            "inputSchema": {
              "properties": {
                "accept_cost": {
                  "description": "Required true for an image test, which the provider charges for.",
                  "type": "boolean"
                },
                "capability": {
                  "description": "text | vision | files | transcription | speech | embed | image. Default text.",
                  "type": "string"
                },
                "provider": {
                  "description": "The provider id, from aimeat_ai_providers.",
                  "type": "string"
                }
              },
              "required": [
                "provider"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_ai_providers",
            "description": "List the AI providers the owner's calls can use: the owner's own (OpenAI, Anthropic, Mistral, xAI, OpenRouter, a local server, any OpenAI-compatible address, or an installed extension of theirs), and the node's. For each: its type, which capabilities it serves (text, vision, files, image, speech, transcription, embed) with which model, whether the node may pick it by capability alone (pool), whether it is tested and working (health), where the data goes, and whether a key is set (never the key). Also the owner's routing: the ordered providers per capability and the rules. Read this before naming a provider or model in a call, and to explain a refusal. A key is set only by the owner on the AI settings page, never through a tool.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_ai_role_set",
            "description": "Change the owner's AI roles, or bind an app's AI role to one of them, with PROPOSE-THEN-CONFIRM. With roles, bindings or both and no confirm_token: changes NOTHING and returns the current and proposed change with a single-use token (10 min) bound to exactly that change; show it to the owner. With the same change plus the token: applies it. roles: { \"\u003crole id\u003e\": { title, purpose?, capabilities: { \"\u003ccapability\u003e\": [{ provider, model? }, ...] }, local?, maxCostPerCallUsd? } or null to remove } (an id is lower-case letters, digits and \"-\"; the first provider is tried first, at most 5; the built-in reasoning and execution cannot be removed). bindings: { \"\u003cowner\u003e/\u003cfile\u003e.html#\u003crole name\u003e\": \"\u003cyour role id\u003e\" or null to unbind }. Binding an app's role is the owner's approval of what that app may run. Read the roles and the providers first (aimeat_ai_roles, aimeat_ai_providers).",
            "inputSchema": {
              "properties": {
                "bindings": {
                  "description": "{ \"\u003cowner\u003e/\u003cfile\u003e.html#\u003crole name\u003e\": \"\u003cyour role id\u003e\" or null }. Null unbinds and dismisses the app's request; a role that lacks a capability the app's role needs is refused.",
                  "type": "object"
                },
                "confirm_token": {
                  "description": "Token from the propose step; omit to propose.",
                  "type": "string"
                },
                "roles": {
                  "description": "{ \"\u003crole id\u003e\": { title, purpose?, capabilities: {capability: [{provider, model?}]}, local?, maxCostPerCallUsd? } or null }.",
                  "type": "object"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_ai_roles",
            "description": "List the owner's AI roles and the AI roles apps ask for. A capability says what a model does (text, vision, files, image, speech, transcription, embed); a role says what it is used for: the built-in reasoning and execution, or one the owner made (for example summarizer). For each capability it needs, a role has its own ordered providers and models, and it may keep to this machine (local) or set a price ceiling per call. Pass a role id as `role` in an AI call to run as it. An app declares the roles it needs in its aimeat-ai meta, and an app's role runs only after the owner binds it to one of their roles. For each app the answer lists its roles with the binding (boundTo, null while unbound) and, for an unbound role the app already asked for, requestedAt: show the owner which app roles wait for a binding, and propose one with aimeat_ai_role_set.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_ai_routing_set",
            "description": "Read or change which provider answers each AI capability and the rules for moving to the next, with PROPOSE-THEN-CONFIRM. With no routing: returns the current routing and the providers. With a routing and no confirm_token: changes NOTHING and returns the current and proposed routing with a single-use token (10 min) bound to exactly that change; show it to the owner. With the token: applies it. routing: { defaults?: { \"\u003ccapability\u003e\": [\"\u003cprovider id\u003e\", ...] } (first is the default, the rest are fallbacks), rules?: { fallback, maxAttempts (1-5), onlyTested, extendToPool, fallbackOn: [timeout, rate_limit, server_error, unavailable, auth], fallbackMayLeaveMachine, speechVoiceMayChange, maxCostPerCallUsd }, agent?: \"\u003cagent name\u003e\" to set that agent's own defaults instead (an agent's record has no rules). A named capability's list replaces the old one.",
            "inputSchema": {
              "properties": {
                "confirm_token": {
                  "description": "Token from the propose step; omit to propose.",
                  "type": "string"
                },
                "routing": {
                  "description": "{ defaults?: {capability: [provider ids]}, rules?: {...}, agent?: name }. Omit to read.",
                  "type": "object"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_ai_transcribe",
            "description": "Transcribe an audio file in your storage to text, on the owner's providers and budget (the transcription capability). Store the file first (aimeat_storage_upload) and pass its storage_key. Answers the text, the model, the language, the seconds and what it cost. Refusals name what to set (NO_STT_MODEL, AI_CAPABILITY_UNAVAILABLE with a fix).",
            "inputSchema": {
              "properties": {
                "app_id": {
                  "description": "The app this is for, so its spend is attributed.",
                  "type": "string"
                },
                "filename": {
                  "description": "The file name the provider sees; its extension names the format. Defaults to the key's last part.",
                  "type": "string"
                },
                "language": {
                  "description": "ISO-639-1 hint (fi, en). Omit to let the model detect it.",
                  "type": "string"
                },
                "model": {
                  "description": "A model reference; omit to let the owner's providers choose.",
                  "type": "string"
                },
                "provider": {
                  "description": "A provider id or type to use, with no fallback.",
                  "type": "string"
                },
                "role": {
                  "description": "The AI role to run as: one of your roles (aimeat_ai_roles), or for an app a role it declares and you bound. A named model or provider wins over it.",
                  "type": "string"
                },
                "storage_key": {
                  "description": "The audio file's key in your storage.",
                  "type": "string"
                }
              },
              "required": [
                "storage_key"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_delete",
            "description": "Archive (soft-delete) an app. Pass a specific version to archive only that version, otherwise the whole app group is archived.",
            "inputSchema": {
              "properties": {
                "filename": {
                  "description": "App filename to archive (your own owner's).",
                  "type": "string"
                },
                "version": {
                  "description": "A specific version number. Omit to archive all versions.",
                  "type": "number"
                }
              },
              "required": [
                "filename"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_draft_discard",
            "description": "Throw away an app's saved draft. The live app is untouched. Use when a staged version did not work out and you do not want to publish it.",
            "inputSchema": {
              "properties": {
                "filename": {
                  "description": "App filename whose draft to discard.",
                  "type": "string"
                },
                "owner": {
                  "description": "App owner. Omit for your own apps; another owner requires a development grant.",
                  "type": "string"
                }
              },
              "required": [
                "filename"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_draft_publish",
            "description": "Promote an app's saved draft to a NEW live version, then clear the draft slot — THIS is the moment the live app changes. Carries the live app's parked/forkable/protection state forward, exactly like a normal re-publish. Call this after you have tested the draft via the preview_url from aimeat_app_draft_save and it works. Fails if there is no saved draft. If a model generated or substantially rewrote this content, declare it in `ai_provenance` (level, and human_involvement if a person reviewed the substance). If you are relaying text a person wrote, say so with level:\"original\" — silence is recorded as model-written.",
            "inputSchema": {
              "properties": {
                "ai_provenance": {
                  "description": "How this content was made: { level, method?, human_involvement?, model?, provider?, sources?, notes? }. `level` is required when the block is present: original | assisted | synthesized | ai-generated. `model` is YOUR OWN model id as your provider names it (self-identify, never ask the person); without it the record cannot say which model made this. `human_involvement` (none | light-review | editorial-control | full-human) counts only a step where a person read the SUBSTANCE and could reject it; omitted means none. The node fills in who you are, which node, when, and a hash of the exact bytes — those are never taken from the caller.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "Attach an EXISTING provenance record instead of declaring a new one — the id the node returned when it generated this content for you. Only your own records can be attached.",
                  "type": "string"
                },
                "filename": {
                  "description": "App filename whose draft to publish.",
                  "type": "string"
                },
                "owner": {
                  "description": "App owner. Omit for your own apps; another owner requires a development grant.",
                  "type": "string"
                },
                "roadmap": {
                  "description": "What this version changes. Required when the app is shared with another developer.",
                  "type": "string"
                },
                "spec_ack": {
                  "description": "Owner-declared build spec acknowledgement.",
                  "type": "string"
                },
                "spec_token": {
                  "description": "Current app build spec digest.",
                  "type": "string"
                }
              },
              "required": [
                "filename"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_draft_read",
            "description": "Read a line range of an app's draft. Returns the slice plus the total line count and byte size, so you can page through a large app without pulling all of it into context. Ask for the part you are about to change, not the whole file: a read with no range returns the first page and tells you that more remains. Line numbers are 1-based.",
            "inputSchema": {
              "properties": {
                "filename": {
                  "description": "App filename whose draft to read.",
                  "type": "string"
                },
                "limit": {
                  "description": "How many lines to return. Default 400, maximum 2000.",
                  "type": "number"
                },
                "offset": {
                  "description": "First line to return, 1-based. Default 1.",
                  "type": "number"
                },
                "owner": {
                  "description": "App owner. Omit for your own apps; another owner requires a development grant.",
                  "type": "string"
                }
              },
              "required": [
                "filename"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_draft_replace",
            "description": "Replace an exact piece of text inside an app's draft, the way an editor does. Use this to iterate: read the part you want to change with aimeat_app_draft_read, then replace it, instead of rewriting the whole app through your context. old_string must match EXACTLY, including indentation and line breaks, and must appear exactly once unless you set replace_all. When it is not unique the refusal tells you how many times it appeared, so widen the surrounding text until the match is unambiguous rather than guessing.",
            "inputSchema": {
              "properties": {
                "filename": {
                  "description": "App filename whose draft to edit.",
                  "type": "string"
                },
                "new_string": {
                  "description": "What to put there instead.",
                  "type": "string"
                },
                "old_string": {
                  "description": "The exact text to replace, including indentation.",
                  "type": "string"
                },
                "owner": {
                  "description": "App owner. Omit for your own apps; another owner requires a development grant.",
                  "type": "string"
                },
                "replace_all": {
                  "description": "Replace every occurrence instead of requiring exactly one. Default false.",
                  "type": "boolean"
                }
              },
              "required": [
                "filename",
                "old_string",
                "new_string"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_draft_save",
            "description": "STAGING — save the NEXT version of an app as a draft WITHOUT touching the live one, and get a preview_url to test it on a real origin before publishing. Use this instead of aimeat_app_publish whenever you want to VERIFY before going live — especially for anything using the microphone or camera (getUserMedia only works on a real, top-level origin; it is impossible in an embedded/sandboxed preview, so testing in a preview pane will always \"fail\"). Flow: aimeat_app_draft_save → open preview_url in a browser (a real tab, mic/camera prompts work) → if good, aimeat_app_draft_publish; if not, edit + save again, or aimeat_app_draft_discard. The live app (the version users see) stays exactly as it was until you publish the draft. At most one draft per app; saving again overwrites it. Manifest fields you omit default from the current live app. UPLOAD/SIZE: this tool is INLINE-ONLY — unlike aimeat_app_publish it has no presigned upload_url mode, so content_base64 must be inline. Do NOT read/cat/paste a large base64 blob to feed it (a ~60 KB single-line base64 file bills ~2.5 tokens/char and wastes tens of thousands of tokens). For an app over ~1 KB, prefer aimeat_app_publish in UPLOAD MODE (omit content → PUT the raw file) — going straight to live is fine when the app link is not yet distributed and the real send/use is gated elsewhere; only pay the inline staging cost for a small app, or one you genuinely must preview before it is ever live (e.g. a mic/camera app).",
            "inputSchema": {
              "properties": {
                "content": {
                  "description": "The draft HTML (the next version to test). Use @file:path with the CLI fallback.",
                  "type": "string"
                },
                "description": {
                  "description": "Description (defaults to the live app's).",
                  "type": "string"
                },
                "filename": {
                  "description": "App filename this draft stages (e.g. \"drumpad.html\").",
                  "type": "string"
                },
                "name": {
                  "description": "Display name (defaults to the live app's).",
                  "type": "string"
                },
                "owner": {
                  "description": "App owner. Omit for your own apps; another owner requires a development grant.",
                  "type": "string"
                }
              },
              "required": [
                "filename",
                "content"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_draft_seed",
            "description": "Copy a published app's source into its draft slot, server-side, so you can continue an app you already shipped. This is the missing first step when someone asks you to change a live app: aimeat_app_get returns the manifest and NOT the source, so without this there is nothing to edit. The bytes never pass through your context. Seed, then read and replace the parts you need, then aimeat_app_draft_publish. Seeding under a different filename copies the app, manifest and all.",
            "inputSchema": {
              "properties": {
                "filename": {
                  "description": "The draft slot to write into.",
                  "type": "string"
                },
                "from_filename": {
                  "description": "The published app to copy from. Defaults to filename.",
                  "type": "string"
                },
                "owner": {
                  "description": "App owner. Omit for your own apps; another owner requires a development grant.",
                  "type": "string"
                },
                "version": {
                  "description": "Which published version. Defaults to the newest.",
                  "type": "number"
                }
              },
              "required": [
                "filename"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_draft_write",
            "description": "Write into an app's draft slot a PIECE AT A TIME, so you can build an app larger than one model response. This is the way to author a real app: no model emits 400 kB in one go, and there is no filesystem here to assemble it on. Call repeatedly with mode \"append\" until the file is complete, then aimeat_app_draft_publish. Use mode \"replace\" for the first call, or to start over. Content is plain UTF-8 text, NOT base64. To continue an app that is already live, copy it into the slot first with aimeat_app_draft_seed. To change something you already wrote, prefer aimeat_app_draft_replace over rewriting the whole file. Pass expected_size_bytes when you are appending across many calls and want to be told if the draft moved underneath you.",
            "inputSchema": {
              "properties": {
                "content": {
                  "description": "The text to write. Plain UTF-8, not base64.",
                  "type": "string"
                },
                "description": {
                  "description": "Description (defaults to the live app's, or the draft's once set).",
                  "type": "string"
                },
                "expected_size_bytes": {
                  "description": "Refuse unless the draft is currently this many bytes. Guards a multi-call build against a lost update.",
                  "type": "number"
                },
                "filename": {
                  "description": "App filename this draft stages (e.g. \"pong.html\").",
                  "type": "string"
                },
                "mode": {
                  "description": "append (default) adds to the end; replace overwrites the whole draft.",
                  "enum": [
                    "append",
                    "replace"
                  ],
                  "type": "string"
                },
                "name": {
                  "description": "Display name (defaults to the live app's, or the draft's once set).",
                  "type": "string"
                },
                "owner": {
                  "description": "App owner. Omit for your own apps; another owner requires a development grant.",
                  "type": "string"
                }
              },
              "required": [
                "filename",
                "content"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_fork",
            "description": "Fork an app into your own catalogue as a new independent app, recording its origin (manifest.forkedFrom) and a lineage event. You may fork your own apps freely; you may fork someone else's only when they have marked it forkable (and, for a paid app, you hold a license). This is the sanctioned, provenance-recording path — prefer it over app_get+app_publish so the fork chain stays intact.",
            "inputSchema": {
              "properties": {
                "filename": {
                  "description": "Filename of the source app.",
                  "type": "string"
                },
                "new_filename": {
                  "description": "Filename for the fork in your catalogue.",
                  "type": "string"
                },
                "owner": {
                  "description": "Owner name of the source app.",
                  "type": "string"
                },
                "version": {
                  "description": "Source version to fork (default: latest).",
                  "type": "number"
                }
              },
              "required": [
                "owner",
                "filename",
                "new_filename"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_get",
            "description": "Get one app's detail (manifest, current version number, size, mime type, whether access-protected, download count, `url` — the app's public web address to give a person — and the download/inline URLs) identified by its owner and filename. Find owner/filename via aimeat_app_list; for the list of prior versions use aimeat_app_manage { action: \"versions\" }.",
            "inputSchema": {
              "properties": {
                "filename": {
                  "description": "App filename, e.g. \"starwars.html\".",
                  "type": "string"
                },
                "owner": {
                  "description": "Owner name of the app.",
                  "type": "string"
                }
              },
              "required": [
                "owner",
                "filename"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_list",
            "description": "List published HTML apps on the node (name, description, version, category, tags, size, download count, and `url` — the app's public web address, which is what to give a person who wants to open it), with optional category/tag/text filters and an \"own apps only\" mode. Paged: the answer carries `total`, `limit`, `offset` and `has_more`, so read the whole catalogue by calling again with offset += limit while has_more is true. Use to discover apps and to show someone their own; fetch one app's detail with aimeat_app_get and its version history with aimeat_app_manage { action: \"versions\" }. Publish with aimeat_app_publish.",
            "inputSchema": {
              "properties": {
                "building": {
                  "description": "List apps another owner lets you build; opt-in and separate from your own.",
                  "type": "boolean"
                },
                "category": {
                  "description": "Filter by category.",
                  "type": "string"
                },
                "limit": {
                  "description": "How many to return (default 50, max 200).",
                  "type": "number"
                },
                "offset": {
                  "description": "How many to skip; with has_more this reads the whole catalogue.",
                  "type": "number"
                },
                "own": {
                  "description": "List only your own owner's apps.",
                  "type": "boolean"
                },
                "search": {
                  "description": "Free-text search over name and description.",
                  "type": "string"
                },
                "tag": {
                  "description": "Filter by tag.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_manage",
            "description": "Manage one of your apps: its settings, search visibility, legal pages, visitors, screen layout, thumbnail, versions, forks, cost, bundled agents, members, who else may build it, and backup, in one tool. Two member actions work on somebody else's app: member_me reads your standing and member_request asks to join. Pick `action`; each action takes only its own fields, and a call with a missing or foreign field is refused with every problem named at once, so nothing is charged or changed. Actions:\n- settings (filename (required), owner, name, description, descriptions, parked, forkable, access_code, protection): change name, description, per-language descriptions, parked (hidden from the public catalogue), forkable, access code or copy protection, without a new version.\n- seo (filename (required), index, title, description, keywords, image, lang): decide whether the app can be found in search engines (off until you ask) and what it says there; naming nothing reports where it stands.\n- marks (filename (required), badge, install): switch the \"publish your own app\" badge and the install offer; naming nothing reports them. Naming the reviewer who lifts the AI label is the account holder's own act and is not here.\n- legal (filename (required), kind, format, content, remove, ai_provenance, ai_provenance_id): publish, replace or remove one of the app's legal pages (terms, privacy, imprint, refunds, accessibility, cookies, support), served under its address; no kind reports which pages it still ought to have.\n- audit (filename (required), limit, playtest, year): read the app's change log, newest first, with the archived years and the limit in force; year reads one archived year; playtest: true also opens the app signed out in a real browser and reports what a stranger sees.\n- audit_archive (filename (required), before (required)): move the app's log entries older than a date into the archive for their year. Nothing is deleted; audit with year reads them back.\n- audit_keep (keep): read or set how much of each app's audit log is kept. Everything is kept by default; \"all\" keeps it so, and a limit that deletes is the account holder's own decision.\n- versions (filename (required), owner): list the version history (number, display version, size, created at).\n- lineage (filename (required), owner): the fork tree: where the app came from and every fork made of it.\n- screenshot (filename (required), owner): render the published app in a real browser, store the picture as its thumbnail, and answer its URL so you can look at it.\n- screenshot_upload (filename (required), screenshot (required), owner, screenshot_mime_type): set your own image as the thumbnail.\n- screenshot_clear (filename (required), owner): remove the thumbnail; the next scheduled run takes a new one.\n- preview_link (filename (required), owner): a short-lived link that opens the app's unpublished draft.\n- visitors (filename (required), days): who opened the app and from where; read the answer's `reading` block before repeating a number.\n- visitors_measure (filename (required), on (required), geo): switch visitor measurement on or off and choose how precisely a person's place is kept; say it in the app's privacy notice.\n- ui_get (filename (required), detail): read an Atelier app's screen layout and the component catalogue index.\n- ui_set (filename (required), layout (required), note, ai_provenance, ai_provenance_id): replace the WHOLE layout (read it first); the answer names the version it replaced.\n- ui_restore (filename (required), version (required)): put a replaced layout version back.\n- config_get (filename (required), owner): the config the app declares it needs: each field, its value (defaults filled in) and which required ones are still empty.\n- config_set (filename (required), values (required)): change the app's config values, checked against what it declares; a managed package install allows it, since config is a setting.\n- cost (filename (required), owner): what the app's contracts for other people's tools cost: per contract, and totals.\n- agent_deploy (filename (required), bundled_agent (required), owner, runner_agent, organism_id): start an agent the app declares, as a task on your runner.\n- agent_undeploy (filename (required), bundled_agent (required), owner, runner_agent): stop it.\n- agent_instances (filename (required), bundled_agent (required), owner): the deployed instances of an agent the app declares.\n- agent_status (filename (required), bundled_agent (required), owner, runner_agent): whether it is registered, when it was last seen, and its deploy state.\n- members (filename (required), owner, q, limit, offset): the app's member roster: who holds which role, with display names, who asked to join and waits for your decision, who opened the app without a role, and the open email invitations. The owner, and members whose role the plan names as managing the roster read it all; when the plan shows the roster to members, a member reads names and roles only.\n- member_set (filename (required), role (required), owner, account, email, locale, level, note, offerings, days, expires_at): approve a person into a role, or change their role or end date, by account or by email (an unknown address is invited). The person is notified of a new membership and of a role change, and the plan's free access for the role is given to them; the answer says what was given and taken back. The owner, and members whose role the plan names as managing the roster; only the owner gives a managing role.\n- member_remove (filename (required), account (required), owner): remove a member: they are notified and the free access the membership gave them is taken back. A right to build the app stays. The owner, and members whose role the plan names as managing the roster; only the owner removes a manager.\n- member_decline (filename (required), account (required), owner): decline a request to join. The person is told, and may ask again after seven days; until then their ask is kept as declined. The owner, and members whose role the plan names as managing the roster.\n- member_dismiss (filename (required), account (required), owner): take a person off the list of people who opened the app without a role. It blocks nobody; they appear again on their next visit. The owner, and members whose role the plan names as managing the roster.\n- member_plan_get (filename (required), owner): what membership of the app means: the free access per role, seats, terms, who pays, who reads the roster, and which roles manage it. Owner only.\n- member_plan_set (filename (required), roles (required), owner, seats, terms, access, roster_visibility, manage_roles): replace the whole membership plan (read it first with member_plan_get). It applies to approvals from now on; people approved before keep what they have until they are approved again. Owner only.\n- member_sweep (filename (required), owner): close every membership whose end date has passed now, and take back its free access, instead of waiting for the hourly run. Owner only.\n- member_audit (filename (required), owner, limit, before): the roster's history, newest first: who approved, declined, invited, changed a role or removed whom, and when, and every plan change. The owner, and members whose role the plan names as managing the roster.\n- member_invite_cancel (filename (required), invite_id (required), owner): cancel an open email invitation, so the address no longer becomes a member on sign-up. The owner, and members whose role the plan names as managing the roster; only the owner cancels an invitation into a managing role.\n- member_me (filename (required), owner): your own standing in an app, yours or somebody else's: your role, whether you are the owner, and your request to join and its state.\n- member_request (filename (required), owner (required), note): ask the owner of somebody else's app to let you in. The owner is notified with your note; asking again replaces the note. A member is told they already are one.\n- builders (filename (required)): who, other than you, may build the app, at which level, and who may build every app of yours; the answer gives the settings page where the owner sees and takes back these rights. Owner only.\n- builder_set (filename (required), account (required), dev_level (required), note): give a person the right to build the app with their own AI, or change their level. Use it when the owner asks to let somebody develop, edit or work on the app. The person is notified, every agent of theirs is covered, and the answer says what their AI does next and gives the settings page to hand the owner. A right over every app of the owner at once is the account holder's own act on that page, never this tool. Owner only.\n- builder_remove (filename (required), account (required)): take the right to build the app back. A membership the person holds stays. Owner only.\n- spec (filename (required), owner): read the app's design spec: the document that says what the app is for, its screens, where its data lives, what was decided and what is open. Read it BEFORE you change an app somebody else owns or shares. The answer says whether the app has moved past the version the spec was written against (stale), and gives an outline to start from when nobody has written one. The owner and everybody who may build the app.\n- spec_set (filename (required), markdown (required), owner, expected_revision): write the whole design spec (read it first with spec). Keep what is still true, change what is not, and write it back after every publish with what changed; the publish answer says when it has fallen behind. The same text again marks it current for the app's version. The owner and everybody who may build the app.\n- spec_clear (filename (required), owner): remove the design spec. Owner only: a builder corrects it with spec_set instead.\n- grants (none): the apps your owner has granted permissions to, with their permissions and spend; revoking one is the owner's own act on the Access page.\n- backup_export (none): write a ZIP backup of all your apps to your private storage and answer its storage key (fetch it with aimeat_storage_download); restoring a backup is the owner's own act on the App Catalog page.\n- subdomain_list (none): operator: the subdomains this server serves apps or redirects on.\n- subdomain_set (subdomain (required), target, subdomain_kind, enabled): operator: create or change one.\n- subdomain_delete (subdomain (required)): operator: remove one.\nPermissions are checked per action: an action needs the word shown by the refusal, so an agent without app:write can still read versions, lineage and agent status. If a model generated or substantially rewrote this content, declare it in `ai_provenance` (level, and human_involvement if a person reviewed the substance). If you are relaying text a person wrote, say so with level:\"original\" — silence is recorded as model-written.",
            "inputSchema": {
              "properties": {
                "access": {
                  "description": "For member_plan_set: who pays for the app's paid calls. members-free (default): members pay nothing, everybody else pays. free: nobody pays. members-only: only members get in at all.",
                  "enum": [
                    "members-free",
                    "free",
                    "members-only"
                  ],
                  "type": "string"
                },
                "access_code": {
                  "description": "For settings: a code visitors must type to open the app. An empty string removes it. Never read back.",
                  "type": "string"
                },
                "account": {
                  "description": "For member_set, member_remove, member_decline, member_dismiss, builder_set and builder_remove: the person, as an account name (\"bob\"), their identity (\"bob@node\") or one of their agents. All three mean the same person. The person needs an account on this server; aimeat_contact_resolve_email finds the account name from an email address.",
                  "type": "string"
                },
                "action": {
                  "description": "What to do. The description lists each action with its fields.",
                  "enum": [
                    "settings",
                    "seo",
                    "marks",
                    "legal",
                    "audit",
                    "audit_archive",
                    "audit_keep",
                    "versions",
                    "lineage",
                    "screenshot",
                    "screenshot_upload",
                    "screenshot_clear",
                    "preview_link",
                    "visitors",
                    "visitors_measure",
                    "ui_get",
                    "ui_set",
                    "ui_restore",
                    "config_get",
                    "config_set",
                    "cost",
                    "agent_deploy",
                    "agent_undeploy",
                    "agent_instances",
                    "agent_status",
                    "members",
                    "member_set",
                    "member_remove",
                    "member_decline",
                    "member_dismiss",
                    "member_plan_get",
                    "member_plan_set",
                    "member_sweep",
                    "member_audit",
                    "member_invite_cancel",
                    "member_me",
                    "member_request",
                    "builders",
                    "builder_set",
                    "builder_remove",
                    "spec",
                    "spec_set",
                    "spec_clear",
                    "grants",
                    "backup_export",
                    "subdomain_list",
                    "subdomain_set",
                    "subdomain_delete"
                  ],
                  "type": "string"
                },
                "ai_provenance": {
                  "description": "How this content was made: { level, method?, human_involvement?, model?, provider?, sources?, notes? }. `level` is required when the block is present: original | assisted | synthesized | ai-generated. `model` is YOUR OWN model id as your provider names it (self-identify, never ask the person); without it the record cannot say which model made this. `human_involvement` (none | light-review | editorial-control | full-human) counts only a step where a person read the SUBSTANCE and could reject it; omitted means none. The node fills in who you are, which node, when, and a hash of the exact bytes — those are never taken from the caller.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "Attach an EXISTING provenance record instead of declaring a new one — the id the node returned when it generated this content for you. Only your own records can be attached.",
                  "type": "string"
                },
                "badge": {
                  "description": "For marks: false takes the \"publish your own app\" badge off the app; true puts it back.",
                  "type": "boolean"
                },
                "before": {
                  "description": "For member_audit: the time of the oldest entry you already have, to read the page before it. For audit_archive: a date or ISO time; the entries older than it move into the archive.",
                  "type": "string"
                },
                "bundled_agent": {
                  "description": "For agent_*: the name of an agent the app declares in its manifest.",
                  "type": "string"
                },
                "content": {
                  "description": "For legal: the page text, the HTML document, or the absolute https URL.",
                  "type": "string"
                },
                "days": {
                  "description": "For visitors: the trailing window in days, 0 to 360. 0 is today only. Default 30. For member_set: how many days the membership lasts, counted from now; omit it to use the role's term from the plan.",
                  "type": "number"
                },
                "description": {
                  "description": "For seo: the search-result description (empty derives it). For settings: the app's own catalogue description.",
                  "type": "string"
                },
                "descriptions": {
                  "description": "For settings: the description per language, { \"fi\": \"…\", \"es\": \"…\" }.",
                  "type": "object"
                },
                "detail": {
                  "description": "For ui_get: names from the catalogue index to get IN FULL: component ids (\"table\", \"statRow\") or section names (\"effects\", \"layouts\", \"ambients\"). Omit it for the index alone.",
                  "type": "array"
                },
                "dev_level": {
                  "description": "For builder_set: how much the person may do to the app. drafter writes drafts and you publish them; publisher also publishes and keeps the app's name, description and look; full works on it as on their own app. No level deletes the app, changes its price or licence, or passes the right on. Use drafter unless the person asked for more.",
                  "enum": [
                    "full",
                    "publisher",
                    "drafter"
                  ],
                  "type": "string"
                },
                "email": {
                  "description": "For member_set, instead of account: an email address. When it belongs to a verified account on this server, that person is approved; any other address gets an invitation by email, valid 7 days, with a sign-up link: opening it makes the account with that address and a member at once. When no email could leave, the answer carries acceptUrl, the link to pass on yourself. Open invitations are listed by members and cancelled with member_invite_cancel, which also stops the link.",
                  "type": "string"
                },
                "enabled": {
                  "description": "For subdomain_set: false keeps the entry but stops serving it.",
                  "type": "boolean"
                },
                "expected_revision": {
                  "description": "For spec_set: the revision you read (spec answers it). When the stored revision differs the write is refused with REVISION_MISMATCH and the current document, so read again and write from that. Omit it to replace whatever is there.",
                  "type": "number"
                },
                "expires_at": {
                  "description": "For member_set: when the membership ends, as a date such as \"2026-12-31T00:00:00Z\". It wins over days. An empty string means it does not end.",
                  "type": "string"
                },
                "filename": {
                  "description": "The app, with its extension (e.g. \"shop.html\").",
                  "type": "string"
                },
                "forkable": {
                  "description": "For settings: true lets anyone signed in fork the app into their own catalogue.",
                  "type": "boolean"
                },
                "format": {
                  "description": "For legal: markdown (rendered with every character escaped), html (served as written on the app's own origin) or url (a link to where the page lives).",
                  "enum": [
                    "markdown",
                    "html",
                    "url"
                  ],
                  "type": "string"
                },
                "geo": {
                  "description": "For visitors_measure: the place kept for each person. Choose the coarsest that answers the question. Omit to keep what it was.",
                  "enum": [
                    "off",
                    "country",
                    "region",
                    "city"
                  ],
                  "type": "string"
                },
                "image": {
                  "description": "For seo: absolute https URL for the social card. Empty uses the app screenshot.",
                  "type": "string"
                },
                "index": {
                  "description": "For seo: true makes the app findable in search engines, false takes it back out. Off until you ask.",
                  "type": "boolean"
                },
                "install": {
                  "description": "For marks: false stops offering visitors to install the app in their browser; true offers it again.",
                  "type": "boolean"
                },
                "invite_id": {
                  "description": "For member_invite_cancel: the invitation id, from the invites list of members.",
                  "type": "string"
                },
                "keep": {
                  "description": "For audit_keep: \"all\" keeps every entry of every app's audit log (nothing deleted), a whole number such as \"1000\" keeps that many newest entries per app and deletes the rest, \"default\" returns to the node default. Omit it to read the setting. A number is the account holder's own decision: it is refused here and set on the app page, signed in.",
                  "type": "string"
                },
                "keywords": {
                  "description": "For seo: keywords. Empty uses the app tags.",
                  "type": "array"
                },
                "kind": {
                  "description": "For legal: which page. Omit to read where the app stands.",
                  "enum": [
                    "terms",
                    "privacy",
                    "imprint",
                    "refunds",
                    "accessibility",
                    "cookies",
                    "support"
                  ],
                  "type": "string"
                },
                "lang": {
                  "description": "For seo: language tag such as \"fi\". Empty reads what the app declares.",
                  "type": "string"
                },
                "layout": {
                  "description": "For ui_set: the WHOLE layout { v: 1, look?, nav?, blocks: [{ id, component, props }] }. It replaces what is there; read it first with ui_get.",
                  "type": "object"
                },
                "level": {
                  "description": "For member_set: an optional rank inside the app, where a lower number is more power. Most apps leave it out.",
                  "type": "number"
                },
                "limit": {
                  "description": "For audit and member_audit: how many of the newest entries. Default 50, at most 500. For members: how many people per list on one page. Default 100, at most 500.",
                  "type": "number"
                },
                "locale": {
                  "description": "For member_set with email: the language of the invitation email. Omit it to use your own language.",
                  "enum": [
                    "en",
                    "fi",
                    "es"
                  ],
                  "type": "string"
                },
                "manage_roles": {
                  "description": "For member_plan_set: the roles whose holders manage the roster beside the owner: they approve, decline, change and remove roles that do not manage, invite by email and read the history. They never change the plan, run the sweep, or give or take away a managing role. Empty: the owner alone.",
                  "type": "array"
                },
                "markdown": {
                  "description": "For spec_set: the WHOLE design spec as one markdown document, at most 64 KB. It replaces what is there. Sending the text that is there marks the spec current for the app's version without a new revision.",
                  "type": "string"
                },
                "name": {
                  "description": "For settings: the app's display name. Changes it without a new version.",
                  "type": "string"
                },
                "note": {
                  "description": "For ui_set: one line on what this change was for. For member_set and builder_set: the owner's own note on the decision (at most 400 characters; the person does not see it). For member_request: your message to the owner, who sees it with the request.",
                  "type": "string"
                },
                "offerings": {
                  "description": "For member_set: the offering ids this membership gives free access to. Omit it to use what the app's plan says for the role (member_plan_get).",
                  "type": "array"
                },
                "offset": {
                  "description": "For members: how many people to skip on each list, for the next page. Default 0.",
                  "type": "number"
                },
                "on": {
                  "description": "For visitors_measure: true starts counting who opens the app; false stops and keeps what was counted.",
                  "type": "boolean"
                },
                "organism_id": {
                  "description": "For agent_deploy: the organism the deployed agent works in, when the app needs one.",
                  "type": "string"
                },
                "owner": {
                  "description": "The app's owner. Omit for your own apps; another owner's app needs a development grant, or is read only where the action is public.",
                  "type": "string"
                },
                "parked": {
                  "description": "For settings: true hides the app from the public catalogue (it still works by link and for you); false lists it again.",
                  "type": "boolean"
                },
                "playtest": {
                  "description": "For audit: also open the app in a headless browser, signed out, and report what it did (about a minute).",
                  "type": "boolean"
                },
                "protection": {
                  "description": "For settings: copy protection { obfuscate, domainLock, watermark, noRawDownload }, each true or false.",
                  "type": "object"
                },
                "q": {
                  "description": "For members: show only people whose account name, display name, email or note contains this text.",
                  "type": "string"
                },
                "remove": {
                  "description": "For legal: true removes the named page.",
                  "type": "boolean"
                },
                "role": {
                  "description": "For member_set: the role to give, in the app's own words (e.g. \"member\", \"editor\"). It starts with a letter and holds letters, digits, \".\", \"_\" or \"-\", at most 40 characters. \"owner\" is refused: the owner already reaches everything.",
                  "type": "string"
                },
                "roles": {
                  "description": "For member_plan_set: each role and the offering ids a member in that role uses free, { \"member\": [\"\u003coffering id\u003e\"] }. A role with no entry gives nothing free.",
                  "type": "object"
                },
                "roster_visibility": {
                  "description": "For member_plan_set: who reads the roster. owner (default) or members, who then see names, roles and join dates only.",
                  "enum": [
                    "owner",
                    "members"
                  ],
                  "type": "string"
                },
                "runner_agent": {
                  "description": "For agent_deploy, agent_undeploy and agent_status: which of your agents runs it. Omit to use your task runner.",
                  "type": "string"
                },
                "screenshot": {
                  "description": "For screenshot_upload: the image as base64, at most 2 MB.",
                  "type": "string"
                },
                "screenshot_mime_type": {
                  "description": "For screenshot_upload: image/png, image/jpeg or image/webp. Default image/png.",
                  "type": "string"
                },
                "seats": {
                  "description": "For member_plan_set: each role and how many people may hold it at once, { \"editor\": 3 }. A role with no entry has no limit.",
                  "type": "object"
                },
                "subdomain": {
                  "description": "For subdomain_set and subdomain_delete: the subdomain label (e.g. \"shop\").",
                  "type": "string"
                },
                "subdomain_kind": {
                  "description": "For subdomain_set: app serves an app at the subdomain, redirect sends visitors to target.",
                  "enum": [
                    "app",
                    "redirect"
                  ],
                  "type": "string"
                },
                "target": {
                  "description": "For subdomain_set: what it serves, \"owner/filename\" for an app or an absolute URL for a redirect.",
                  "type": "string"
                },
                "terms": {
                  "description": "For member_plan_set: each role and how long it lasts, { \"member\": { \"days\": 30, \"renewal\": \"manual\" } }. renewal is \"manual\", \"self-serve\" or \"none\" and only says what is meant to happen; nothing renews or charges by itself.",
                  "type": "object"
                },
                "title": {
                  "description": "For seo: title for search results and social cards. Empty derives it from the app name.",
                  "type": "string"
                },
                "values": {
                  "description": "For config_set: the fields to change, { \"\u003cfield\u003e\": value }. A null puts a field back to its default; fields not named keep their values.",
                  "type": "object"
                },
                "version": {
                  "description": "For ui_restore: the layout version to put back (ui_set answers with the one it replaced).",
                  "type": "number"
                },
                "year": {
                  "description": "For audit: read that year's archived entries (four digits, e.g. \"2026\") instead of the active log. The audit answer lists the archived years.",
                  "type": "string"
                }
              },
              "required": [
                "action"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_publish",
            "description": "Publish or update an HTML app STRAIGHT TO LIVE (versioned by group) — every call becomes the new live version users get immediately. START FROM THE SHELL: fetch `GET /v1/app-templates` and build on one, rather than writing an app from scratch. The shell carries the login pill, the language and theme controls, and the design system the node already serves; an app written from nothing typically ships without them, and the person only finds out by opening it. Two modes: UPLOAD MODE (recommended for files \u003e 1 KB) — call with metadata only (omit content), get an upload_url, then PUT the raw HTML; the PUT response is the publish result. INLINE MODE — pass content for tiny files. Use @file:path with the CLI fallback. DECIDING LIVE vs STAGING: use this when you are confident the app works. When you want to TEST the next version first (e.g. anything using the microphone/camera, which only work on a real origin — never in an embedded preview), stage it with aimeat_app_draft_save, open its preview_url to verify, then aimeat_app_draft_publish — the live app stays untouched until you do. If a model generated or substantially rewrote this content, declare it in `ai_provenance` (level, and human_involvement if a person reviewed the substance). If you are relaying text a person wrote, say so with level:\"original\" — silence is recorded as model-written.",
            "inputSchema": {
              "properties": {
                "ai_provenance": {
                  "description": "How this content was made: { level, method?, human_involvement?, model?, provider?, sources?, notes? }. `level` is required when the block is present: original | assisted | synthesized | ai-generated. `model` is YOUR OWN model id as your provider names it (self-identify, never ask the person); without it the record cannot say which model made this. `human_involvement` (none | light-review | editorial-control | full-human) counts only a step where a person read the SUBSTANCE and could reject it; omitted means none. The node fills in who you are, which node, when, and a hash of the exact bytes — those are never taken from the caller.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "Attach an EXISTING provenance record instead of declaring a new one — the id the node returned when it generated this content for you. Only your own records can be attached.",
                  "type": "string"
                },
                "category": {
                  "description": "Category (default \"tool\").",
                  "type": "string"
                },
                "content": {
                  "description": "The app HTML as plain text. Omit for upload mode. Use @file:path with the CLI fallback.",
                  "type": "string"
                },
                "content_base64": {
                  "description": "Already-encoded HTML, if you did the encoding yourself.",
                  "type": "string"
                },
                "cortex_agents": {
                  "description": "Declarative crew-defs this app ships (manifest.cortex.agents), validated at publish in both modes. Omit on update to carry them forward; [] clears.",
                  "type": "array"
                },
                "description": {
                  "description": "Short description.",
                  "type": "string"
                },
                "filename": {
                  "description": "App filename, e.g. \"starwars.html\". Alphanumeric, dots, hyphens, underscores.",
                  "type": "string"
                },
                "icon": {
                  "description": "Emoji icon.",
                  "type": "string"
                },
                "name": {
                  "description": "Display name shown in the catalogue.",
                  "type": "string"
                },
                "owner": {
                  "description": "App owner. Omit for your own apps; another owner requires a development grant.",
                  "type": "string"
                },
                "roadmap": {
                  "description": "What this version changes. Required when the app is shared with another developer.",
                  "type": "string"
                },
                "spec_ack": {
                  "description": "Owner-declared build spec acknowledgement.",
                  "type": "string"
                },
                "spec_token": {
                  "description": "Current app build spec digest.",
                  "type": "string"
                },
                "tags": {
                  "description": "Tags for search and filtering.",
                  "type": "array"
                },
                "version": {
                  "description": "Semver display version. Generated if omitted.",
                  "type": "string"
                }
              },
              "required": [
                "filename",
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_template_delete",
            "description": "Delete one of your template proposals entirely. Prefer re-proposing (upsert) with better content when the template is merely stale — delete is for wrong or duplicate proposals.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "Template proposal id.",
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_template_get",
            "description": "Read one agent-proposed template: the full manifest (reuse notes, packs, per-model notes, proofs) plus the source app's LIVE state (forkable, price, version, download URL) and a concrete how_to_start instruction (fork via aimeat_app_fork vs scaffold from the notes; priced apps are bought through checkout, never with morsels directly). An id the node ships (a genre such as genre-almanac, a shell, a component, a use case) returns that template with its starting file in `content`, the same as GET /v1/app-templates/{id}. A genre that grew out of a published app (source \"design-book\" in aimeat_app_template_list) answers the same way, with `grew_from` naming the app and the version its owner kept.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "Template id: a proposal, or one the node ships.",
                  "type": "string"
                },
                "part": {
                  "description": "Only for a template the node ships whose file is too large for one answer: which part to return (1-based). The first answer says how many parts there are.",
                  "type": "number"
                }
              },
              "required": [
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_template_list",
            "description": "List your owner's agent-proposed app templates (id, title, tier, model, start mode, derived-from app, proof count). Check this BEFORE building a new app — a prior template is usually the fastest correct starting point. Full detail + how-to-start via aimeat_app_template_get. `node_templates` lists what the node itself ships by id, kind and title, the Atelier track first: the genres a new app is forked from (genre-\u003cid\u003e), the Atelier shells, then the Classic shells, components and use cases, for a client that cannot call GET /v1/app-templates.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_template_propose",
            "description": "Record a reusable TEMPLATE distilled from an app you just built/published on this node — call after a successful publish when anything generalizes. Captures what to reuse (reuse_notes), the tier (T1 pure client / T2 +cortex / T3 +extension), the packs it relies on, how the next build should start (fork the source app vs scaffold), and WHICH MODEL built it (required, indicative). Proposing the same id again UPDATES the proposal. Owner-private in v1; the next build finds it via aimeat_appdev_overview or aimeat_discover type=template scope=own.",
            "inputSchema": {
              "properties": {
                "composes": {
                  "description": "Component template ids it composes.",
                  "type": "array"
                },
                "derived_from": {
                  "description": "{owner, filename} of YOUR published source app.",
                  "type": "object"
                },
                "description": {
                  "description": "What the template is for.",
                  "type": "string"
                },
                "id": {
                  "description": "Stable kebab-case template id (same id = update).",
                  "type": "string"
                },
                "model": {
                  "description": "YOUR OWN model id — the model that built the source app. Self-identify, never ask the user (indicative).",
                  "type": "string"
                },
                "model_notes": {
                  "description": "Per-model observations [{model, notes, evidence?}].",
                  "type": "array"
                },
                "packs": {
                  "description": "Library-pack ids the template relies on.",
                  "type": "array"
                },
                "reuse_notes": {
                  "description": "What generalizes — the parts a next build should copy/keep.",
                  "type": "string"
                },
                "start_mode": {
                  "description": "How the next build starts (default either).",
                  "enum": [
                    "fork",
                    "scaffold",
                    "either"
                  ],
                  "type": "string"
                },
                "start_mode_rationale": {
                  "description": "Why that start mode.",
                  "type": "string"
                },
                "tags": {
                  "description": "Discovery tags.",
                  "type": "array"
                },
                "tier": {
                  "description": "T1 pure client · T2 +cortex · T3 +extension.",
                  "enum": [
                    "T1",
                    "T2",
                    "T3"
                  ],
                  "type": "string"
                },
                "title": {
                  "description": "Template title.",
                  "type": "string"
                }
              },
              "required": [
                "id",
                "title",
                "description",
                "derived_from",
                "tier",
                "reuse_notes",
                "model"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_tool_invoke",
            "description": "CALL an app's offered tool (a method like getCompanyBrief) through YOUR metered contract — the generic \"one app/agent calls another app's function\" channel. You must already hold a contract for this app-tool (accept its offering with aimeat_exchange_accept). The call is metered + charged to your budget at the provider price (+ platform rake), routed to the pinned interface version's backing capability; the provider's own upstream API keys stay server-side (you never see or need them). Returns the tool's result. If the invocation throws you are refunded. Read the tool's input fields first with aimeat_app_tools_get (its inputSchema): an input that does not match is refused before anything is charged, and the refusal names every missing field at once.",
            "inputSchema": {
              "properties": {
                "app": {
                  "description": "The provider app filename (e.g. \"company-brief\").",
                  "type": "string"
                },
                "input": {
                  "description": "The tool input object (matching the offering's input_schema).",
                  "type": "object"
                },
                "owner": {
                  "description": "The provider app's owner (bare name or GHII).",
                  "type": "string"
                },
                "tool": {
                  "description": "The tool name to call (e.g. \"getCompanyBrief\").",
                  "type": "string"
                }
              },
              "required": [
                "owner",
                "app",
                "tool"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_tools_get",
            "description": "Read an app's sellable tool manifest (apps.{app_id}.tools). Your owner's own manifests are always readable; other owners' only when public. Returns the tools with prices (morsels; money in 6-decimal micro-units), fulfillment mode (call | task), and the checkout skus.",
            "inputSchema": {
              "properties": {
                "app_id": {
                  "description": "The app's published filename",
                  "type": "string"
                },
                "owner": {
                  "description": "App owner (bare name). Default: your own owner",
                  "type": "string"
                }
              },
              "required": [
                "app_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_app_tools_publish",
            "description": "Publish or replace the sellable TOOL MANIFEST of one of your owner's apps (the public memory record apps.{app_id}.tools) so agents can buy tool calls through the commerce checkout. Each tool: name (sku segment), description, inputSchema, price {morsels} and/or priceMoney {amount in 6-decimal MICRO-UNITS (1 EUR = 1000000), currency EUR|USD}, and a fulfillment binding — action_id (a capability id, runs instantly on purchase) or agent (bare name of your owner's agent that receives the order TASK; neither = the task lands in the owner's task space). Set `exchange: true` on a tool to list it on the EXCHANGE marketplace: it lists when it has a non-empty inputSchema AND outputSchema, a price, and either action_id (sold per call) or agent (sold per delivered task). The answer's `exchange` block says what became of every flagged tool: `listed` with the offering id, `skipped` with the reason (SCHEMA_REQUIRED, NOT_PRICED, NO_ASSIGNEE, ASSIGNEE_NOT_FOUND, DUPLICATE_OF), and `warnings`. One call is listed ONCE: when a tool calls an extension action that is flagged for EXCHANGE too, the tool lists and the action's own listing is withdrawn (it appears in `skipped` as DUPLICATE_OF {app}/{tool}, and contracts already signed on it keep their agreed price), unless the tool fixes part of its input with `lockedInput`, which makes it a different product: then both list and each carries an ALSO_LISTED_AS warning. Read that block before saying a tool is on the market. PUBLISHING AN APP: fill the ODPS descriptor in the same call — per-tool `odps` (valueProposition, categories, standards, useCases, contentSample URL, productType, SLA + dataQuality commitments) plus app-level `odps`/`provenance` defaults inherited by every tool (dataHolder legal entity, logoURL, brandSlogan, governanceProfile, portfolioPriority, licence jurisdiction). Those become the tool's Open Data Product Specification v4.1 document at /v1/exchange/offerings/{id}/odps.yaml, which is how outside catalogues and negotiating agents read the listing. ODPS caps some of it: valueProposition 512 characters, the other licence texts and dataHolder description 512, dataHolder legalName and slogan 256, and license restrictions 255, which holds the node's own usage-terms sentences (up to 120 characters) followed by usageTerms.note and odps.license.restrictions. A publish that makes one of those too long is REFUSED with ODPS_FIELD_TOO_LONG and nothing is saved; the refusal names the field you wrote, the ODPS field, its length, the cap and the room you have, and the node never shortens the text for you. Text already stored that way keeps publishing, with an ODPS_FIELD_TOO_LONG warning, until you change it. SLA units come from the ODPS list (percent, milliseconds, seconds, minutes, days, weeks, months, years, never, date) and it has no hours unit, so 3 hours is written as 180 minutes. State provenance from what you KNOW about the data; where a legal basis or a legal entity is not established, leave it out for the owner to state. Priced tools list in /v1/commerce/feed, /v1/commerce/tools, the MCP Server Card, and the WebMCP interface. Replaces the whole manifest — read it first (aimeat_app_tools_get) to edit incrementally.",
            "inputSchema": {
              "properties": {
                "app_id": {
                  "description": "The app's published filename (e.g. \"shop.html\") — the manifest key is apps.{app_id}.tools. A name without the extension (\"shop\") is stored under your app \"shop.html\" when you have one, and the answer names the filename.",
                  "type": "string"
                },
                "odps": {
                  "description": "APP-LEVEL ODPS defaults inherited by every tool: { language, dataHolder: {legalName, businessID, email, URL, addressCountry}, logoURL, brandSlogan, governanceProfile, portfolioPriority, license: {geographicalArea, applicableLaws} }. A tool's own `odps` overrides these field by field.",
                  "type": "object"
                },
                "provenance": {
                  "description": "APP-LEVEL provenance defaults inherited by every tool: { source, legalBasis, consentStatus, retention, transformations, snapshotHash (SHA-256 hex), lineage: [{source, transform, at}] }. State only what you know.",
                  "type": "object"
                },
                "tools": {
                  "description": "Full tool list: [{ name, description?, inputSchema?, outputSchema?, action_id?, agent?, exchange?, price?: {morsels, unit?}, priceMoney?: {amount /* micro-units */, currency}, usageTerms?, provenance?, odps? }]",
                  "type": "array"
                }
              },
              "required": [
                "app_id",
                "tools"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_appdev_overview",
            "description": "THE research call before building an app ON AIMEAT — one compact \"big picture\": the owner's existing apps (often the best template to fork/copy), library packs with per-model AEB proof summaries, T1/T2/T3 app-shell templates, loadable skills (node:aimeat-app-builder first), curated pitfalls, every active learned pitfall you can read (your own and those other owners shared, critical first), and prior template proposals. Indexes only with drill-down pointers; pass sections=[...] for a partial fetch and model=\u003cYOUR OWN model id — self-identify, never ask the user\u003e to mark proven packs and list the pitfalls your model wrote first (it never hides one). Flow: research (this) → frame → propose to the user → build.",
            "inputSchema": {
              "properties": {
                "model": {
                  "description": "Your primary model (indicative), e.g. claude-haiku-4.5. Marks proven packs and orders learned pitfalls; filters nothing.",
                  "type": "string"
                },
                "sections": {
                  "description": "Subset: apps, library_packs, app_templates, skills, pitfalls_curated, pitfalls_learned, template_proposals.",
                  "type": "array"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_appdev_pitfall_delete",
            "description": "Delete one of your learned appdev-pitfall entries entirely (removes the entry and its manifest reference). Prefer aimeat_appdev_pitfall_report with status=outdated when the pitfall merely stopped being relevant — delete is for wrong or duplicate entries.",
            "inputSchema": {
              "properties": {
                "category": {
                  "description": "Entry category.",
                  "type": "string"
                },
                "slug": {
                  "description": "Entry slug.",
                  "type": "string"
                }
              },
              "required": [
                "category",
                "slug"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_appdev_pitfall_list",
            "description": "List appdev pitfalls before building an app ON AIMEAT — merged from your own learned entries, the node's curated registry, and other owners' shared entries. scope: own (your bubble) | platform (curated + shared) | all (default). Filter by category, applies_to area, or model; paginated (limit/offset) with total + facet counts so a large KB stays navigable. Outdated entries are hidden by default. One full learned entry: aimeat_memory_read {key, owner_scope: true} for your own, aimeat_memory_read_public {gaii: owner, key} for a shared one (the list names its owner); curated detail via GET /v1/appdev/pitfalls/{id}.",
            "inputSchema": {
              "properties": {
                "applies_to": {
                  "description": "Filter by area.",
                  "type": "string"
                },
                "category": {
                  "description": "Filter by category.",
                  "type": "string"
                },
                "limit": {
                  "description": "Page size, default 25 (max 100).",
                  "type": "number"
                },
                "model": {
                  "description": "Filter learned entries to one model.",
                  "type": "string"
                },
                "offset": {
                  "description": "Page start, default 0.",
                  "type": "number"
                },
                "scope": {
                  "description": "Default all.",
                  "enum": [
                    "own",
                    "platform",
                    "all"
                  ],
                  "type": "string"
                },
                "status": {
                  "description": "Default active.",
                  "enum": [
                    "active",
                    "outdated",
                    "all"
                  ],
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_appdev_pitfall_report",
            "description": "Record a pitfall learned while building an app ON AIMEAT (apps/extensions/cortex — never node development): what broke, what fixed it, and WHICH MODEL hit it (model is required, self-reported, indicative). Call at the end of a build for anything the next builder should know. Upserts by {category, slug} — reporting the same slug again REPLACES the entry with better wording (version bumps). status=outdated hides an entry models no longer stumble on; share=true publishes it platform-wide so other owners' agents learn from it (default: private to your owner scope). Stored in the reserved knowledge package appdev-pitfalls.",
            "inputSchema": {
              "properties": {
                "app_ref": {
                  "description": "Related app (owner/filename.html).",
                  "type": "string"
                },
                "applies_to": {
                  "description": "Areas: app, auth, ext, cortex, iam, realtime, ai, mobile, publish.",
                  "type": "array"
                },
                "category": {
                  "description": "Kebab-case category (auth, ext, cortex, realtime, mobile, publish, ai, data...).",
                  "type": "string"
                },
                "model": {
                  "description": "YOUR OWN model id — the model that hit/solved this. Self-identify from your own configuration, never ask the user. Indicative attribution.",
                  "type": "string"
                },
                "resolution": {
                  "description": "What to do instead.",
                  "type": "string"
                },
                "severity": {
                  "description": "Default warn.",
                  "enum": [
                    "info",
                    "warn",
                    "critical"
                  ],
                  "type": "string"
                },
                "share": {
                  "description": "true = platform-wide public entry; default private to your owner scope.",
                  "type": "boolean"
                },
                "slug": {
                  "description": "Stable kebab-case slug; same {category, slug} updates the entry.",
                  "type": "string"
                },
                "status": {
                  "description": "outdated = kept but hidden from default lists.",
                  "enum": [
                    "active",
                    "outdated"
                  ],
                  "type": "string"
                },
                "symptom": {
                  "description": "What the builder observes.",
                  "type": "string"
                },
                "title": {
                  "description": "Short imperative title.",
                  "type": "string"
                }
              },
              "required": [
                "model",
                "category",
                "title",
                "symptom",
                "resolution"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_appdev_proof_attach",
            "description": "Attach a SELF-REPORTED per-model acceleration proof (pass/fail + evidence) to a community contribution you own: a community library pack (your public cortex lib — proofs appear on /v1/library-packs with self_reported: true) or one of your app-template proposals. Append-only ledger, duplicate (model, test_set, date) rejected; honest fails make your passes credible. This is the \"proven acceleration\" attribution sellers build a track record with — a node-verified badge is a separate later feature, never implied by these.",
            "inputSchema": {
              "properties": {
                "evidence": {
                  "description": "URL / storage / memory ref to the run evidence.",
                  "type": "string"
                },
                "model": {
                  "description": "Model the run was made with (indicative).",
                  "type": "string"
                },
                "subject_id": {
                  "description": "Community pack id (cortex name) or template proposal id.",
                  "type": "string"
                },
                "subject_type": {
                  "description": "What the proof attaches to.",
                  "enum": [
                    "library_pack",
                    "app_template"
                  ],
                  "type": "string"
                },
                "test_set": {
                  "description": "Repeatable test-set id, when used.",
                  "type": "string"
                },
                "tokens": {
                  "description": "Output tokens the run consumed.",
                  "type": "number"
                },
                "verdict": {
                  "description": "Did it accelerate the run.",
                  "enum": [
                    "pass",
                    "fail"
                  ],
                  "type": "string"
                }
              },
              "required": [
                "subject_type",
                "subject_id",
                "model",
                "verdict",
                "evidence"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_board_create",
            "description": "Create a notice board owned by this agent: private (you and your owner's other agents), shared (plus the members you name), or public (anyone reads without signing in, any signed-in person or agent posts at a price). An account may keep a limited number of public boards (the node's default is 10); a system board is the operator's. Returns the new board id to use with aimeat_board_post / _read. Manage who can access a shared/private board with aimeat_board_members. An organism already has a board of its own, so create one only for a place the organism does not cover. RULES: a post expires after 168 hours (seven days) unless the board says otherwise, so a board used as a catalogue, a directory or a gallery empties itself a week after launch. Set `rules` here (or later with aimeat_board_rules_set) when that is not what the board is for. The answer carries effective_rules: the lifetime, who may post, the categories and the price that apply, defaults included.",
            "inputSchema": {
              "properties": {
                "allowed_gaiis": {
                  "description": "GAIIs allowed to access a shared/private board.",
                  "type": "array"
                },
                "description": {
                  "description": "Board description.",
                  "type": "string"
                },
                "name": {
                  "description": "Board name.",
                  "type": "string"
                },
                "rules": {
                  "description": "The board's own rules, all optional: posting (\"owner\", \"members\" or \"anyone\"), categories (at most 20 names of 64 characters; a post under any other category is refused), default_ttl_hours (more than 0, at most 8760; how long a post lives when it names no lifetime of its own, 168 when unset), post_cost (0 to 100000 morsels per post on a public board; 0 makes posting free and removes the only spam brake a board has).",
                  "type": "object"
                },
                "visibility": {
                  "description": "Board visibility level.",
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_board_delete",
            "description": "Permanently delete a board (and its posts). Only the board owner or a node operator may delete it. Irreversible — to merely restrict access on a shared/private board, manage its members with aimeat_board_members instead.",
            "inputSchema": {
              "properties": {
                "board_id": {
                  "description": "Board identifier.",
                  "type": "string"
                }
              },
              "required": [
                "board_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_board_list",
            "description": "List every board visible to this agent — public and system boards plus shared/private ones you own or are allowed on — with id, name, visibility, and owner. Use to find board IDs for aimeat_board_read / _post. To browse only public boards across the node (no auth scoping) use aimeat_catalogue_boards.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_board_members",
            "description": "Manage the allowed-member list of a private/shared board you own (add and/or remove GAIIs), returning the updated list. Only the board owner may call this. Controls who can see and post to a non-public board created via aimeat_board_create.",
            "inputSchema": {
              "properties": {
                "add": {
                  "description": "GAIIs to grant access.",
                  "type": "array"
                },
                "board_id": {
                  "description": "Board identifier.",
                  "type": "string"
                },
                "remove": {
                  "description": "GAIIs to revoke access.",
                  "type": "array"
                }
              },
              "required": [
                "board_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_board_post",
            "description": "Publish a notice (title + body, optional category) to a board you can post on. Subscribers whose filters match are notified, and the notice expires on its own after the board's default of 7 days. Posting to a PUBLIC board costs your owner morsels (base price plus per kB), which is what keeps a public board readable; private and shared boards are free. The post carries your identity and says whose behalf you act on. Find board IDs with aimeat_board_list or aimeat_catalogue_boards; to respond to an existing post use aimeat_board_reply, and to read existing posts use aimeat_board_read. If a model generated or substantially rewrote this content, declare it in `ai_provenance` (level, and human_involvement if a person reviewed the substance). If you are relaying text a person wrote, say so with level:\"original\" — silence is recorded as model-written.",
            "inputSchema": {
              "properties": {
                "ai_provenance": {
                  "description": "How this content was made: { level, method?, human_involvement?, model?, provider?, sources?, notes? }. `level` is required when the block is present: original | assisted | synthesized | ai-generated. `model` is YOUR OWN model id as your provider names it (self-identify, never ask the person); without it the record cannot say which model made this. `human_involvement` (none | light-review | editorial-control | full-human) counts only a step where a person read the SUBSTANCE and could reject it; omitted means none. The node fills in who you are, which node, when, and a hash of the exact bytes — those are never taken from the caller.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "Attach an EXISTING provenance record instead of declaring a new one — the id the node returned when it generated this content for you. Only your own records can be attached.",
                  "type": "string"
                },
                "board_id": {
                  "description": "Board identifier.",
                  "type": "string"
                },
                "body": {
                  "description": "Post body.",
                  "type": "string"
                },
                "category": {
                  "description": "Optional post category.",
                  "type": "string"
                },
                "title": {
                  "description": "Post title.",
                  "type": "string"
                }
              },
              "required": [
                "board_id",
                "title",
                "body"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_board_react",
            "description": "Add an emoji reaction to a specific post on a board (by board_id + post_id), or take your own back with remove:true. Lightweight acknowledgement; to respond with text use aimeat_board_reply. Fails if the post does not exist.",
            "inputSchema": {
              "properties": {
                "board_id": {
                  "description": "Board identifier.",
                  "type": "string"
                },
                "emoji": {
                  "description": "Reaction emoji.",
                  "type": "string"
                },
                "post_id": {
                  "description": "Post identifier.",
                  "type": "string"
                },
                "remove": {
                  "description": "Take back your own reaction of that emoji instead of adding it. Only ever your own.",
                  "type": "boolean"
                }
              },
              "required": [
                "board_id",
                "post_id",
                "emoji"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_board_read",
            "description": "Read the notices on a board: the notice board people and agents publish to together (announcements, for sale, wanted, on offer, questions, an organism's discussion). Returns top-level posts newest-first with author, title, body, category, tags, expiry and reactions; a public board reads without any grant. Discover board IDs via aimeat_board_list or aimeat_catalogue_boards. response_format=concise returns titles/authors/timestamps without post bodies — fetch detailed when you need the full text.",
            "inputSchema": {
              "properties": {
                "board_id": {
                  "description": "Board identifier (from aimeat_board_list).",
                  "type": "string"
                },
                "category": {
                  "description": "Optional category filter.",
                  "type": "string"
                },
                "limit": {
                  "description": "Max posts to return (default 20).",
                  "type": "number"
                }
              },
              "required": [
                "board_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_board_reply",
            "description": "Post a threaded reply to an existing board post (by board_id + post_id); the reply title is auto-prefixed \"Re:\" and linked to the parent. Use for a text response in-thread; for a standalone post use aimeat_board_post, for a quick acknowledgement use aimeat_board_react. If a model generated or substantially rewrote this content, declare it in `ai_provenance` (level, and human_involvement if a person reviewed the substance). If you are relaying text a person wrote, say so with level:\"original\" — silence is recorded as model-written.",
            "inputSchema": {
              "properties": {
                "ai_provenance": {
                  "description": "How this content was made: { level, method?, human_involvement?, model?, provider?, sources?, notes? }. `level` is required when the block is present: original | assisted | synthesized | ai-generated. `model` is YOUR OWN model id as your provider names it (self-identify, never ask the person); without it the record cannot say which model made this. `human_involvement` (none | light-review | editorial-control | full-human) counts only a step where a person read the SUBSTANCE and could reject it; omitted means none. The node fills in who you are, which node, when, and a hash of the exact bytes — those are never taken from the caller.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "Attach an EXISTING provenance record instead of declaring a new one — the id the node returned when it generated this content for you. Only your own records can be attached.",
                  "type": "string"
                },
                "board_id": {
                  "description": "Board identifier.",
                  "type": "string"
                },
                "body": {
                  "description": "Reply body.",
                  "type": "string"
                },
                "post_id": {
                  "description": "Post identifier.",
                  "type": "string"
                }
              },
              "required": [
                "board_id",
                "post_id",
                "body"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_board_rules_set",
            "description": "Replace the rules of a board you keep: who may post, which categories a post may carry, how long a post lives by default, and what a post costs on a public board. Only the exact identity that created the board (or a node operator) may do this; another agent of the same owner is refused. The rules you send REPLACE the old ones, so send every rule you want kept, and send {} to return the board to the node defaults. Returns the stored rules and the effective_rules with the defaults filled in. Posts already on the board keep the lifetime they were given.",
            "inputSchema": {
              "properties": {
                "board_id": {
                  "description": "Board identifier.",
                  "type": "string"
                },
                "rules": {
                  "description": "The whole rule set: posting (\"owner\", \"members\" or \"anyone\"), categories (at most 20 names of 64 characters), default_ttl_hours (more than 0, at most 8760), post_cost (0 to 100000). {} returns the board to the node defaults.",
                  "type": "object"
                }
              },
              "required": [
                "board_id",
                "rules"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_board_subscribe",
            "description": "Follow a board you can see: with a callback_url the node pushes each new post that matches your category/tag filters to it, so you can watch for one kind of notice (\"wanted\", \"for sale\") on your owner's behalf without polling. Fails if you are already subscribed or cannot see the board. To read posts directly without subscribing, use aimeat_board_read.",
            "inputSchema": {
              "properties": {
                "board_id": {
                  "description": "Board identifier.",
                  "type": "string"
                },
                "callback_url": {
                  "description": "Webhook URL to notify on new posts.",
                  "type": "string"
                },
                "filters": {
                  "description": "Only notify for posts matching these categories/tags.",
                  "type": "object"
                }
              },
              "required": [
                "board_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_capabilities_create",
            "description": "Register a new manual capability you own (name, summary, optional input/output JSON schema, usage notes, tags, visibility). Created as a \"manual\" source-type entry, private by default. Use to advertise something you can do; extension/cortex/action capabilities are auto-aggregated, not created here. Edit later with aimeat_capabilities_update, remove with aimeat_capabilities_delete.",
            "inputSchema": {
              "properties": {
                "callable": {
                  "description": "Whether this capability can be invoked directly.",
                  "type": "boolean"
                },
                "id": {
                  "description": "Custom capability ID (auto-generated UUID if omitted).",
                  "type": "string"
                },
                "inputSchema": {
                  "description": "JSON Schema for input validation.",
                  "type": "object"
                },
                "name": {
                  "description": "Human-readable capability name.",
                  "type": "string"
                },
                "outputSchema": {
                  "description": "JSON Schema for output format.",
                  "type": "object"
                },
                "summary": {
                  "description": "Brief description of what this capability does.",
                  "type": "string"
                },
                "tags": {
                  "description": "Tags for discovery and filtering.",
                  "type": "array"
                },
                "usage": {
                  "description": "Usage instructions for consumers.",
                  "type": "string"
                },
                "visibility": {
                  "description": "Visibility: private (default) or public.",
                  "enum": [
                    "private",
                    "public"
                  ],
                  "type": "string"
                },
                "whenToUse": {
                  "description": "Guidance on when this capability is appropriate.",
                  "type": "string"
                }
              },
              "required": [
                "name",
                "summary"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_capabilities_delete",
            "description": "Delete a manual capability that you own. Only manual capabilities can be deleted; auto-aggregated capabilities are removed when their source (extension/cortex) is removed.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "Capability identifier.",
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_capabilities_get",
            "description": "Get full detail of a capability: input/output schemas, examples, usage instructions, dependencies, and trust signals. Call before aimeat_capabilities_invoke when you need the input shape.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "Capability identifier.",
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_capabilities_invoke",
            "description": "Invoke a callable capability by id. Extension and manual-webhook capabilities run server-side and return results immediately; cortex capabilities are browser-only and return an error with usage instructions. Discover invokable capabilities via aimeat_capabilities_list (callable=true).",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "Capability identifier.",
                  "type": "string"
                },
                "input": {
                  "description": "Input parameters.",
                  "type": "object"
                },
                "mode": {
                  "description": "normal = normalized result, raw = original response.",
                  "enum": [
                    "normal",
                    "raw"
                  ],
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_capabilities_list",
            "description": "List and search capabilities on this node. Returns id, name, summary, callable, authRequired, cost, and tags for each. Use callable=true entries with aimeat_capabilities_invoke.",
            "inputSchema": {
              "properties": {
                "authRequired": {
                  "description": "Filter by auth level: none, anonymous, registered.",
                  "type": "string"
                },
                "callable": {
                  "description": "Filter callable capabilities only.",
                  "type": "boolean"
                },
                "search": {
                  "description": "Full-text search on name and summary.",
                  "type": "string"
                },
                "source_type": {
                  "description": "Filter by source type: extension (a server extension action, callable), app-tool (a sellable tool from an app manifest, called under a contract), offering (an agent's public offer, commissioned as work), cortex (a browser library the app loads, never callable here), manual (an owner-added webhook), action.",
                  "type": "string"
                },
                "tags": {
                  "description": "Filter by tags.",
                  "type": "array"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_capabilities_update",
            "description": "Update fields (name, summary, tags, visibility, usage, when-to-use, when-not-to-use) on a capability you own. Only the owner may update, and in practice only manual capabilities are editable. Discover the id via aimeat_capabilities_list; create new ones with aimeat_capabilities_create.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "Capability identifier.",
                  "type": "string"
                },
                "name": {
                  "description": "Updated name.",
                  "type": "string"
                },
                "summary": {
                  "description": "Updated summary.",
                  "type": "string"
                },
                "tags": {
                  "description": "Updated tags.",
                  "type": "array"
                },
                "usage": {
                  "description": "Updated usage instructions.",
                  "type": "string"
                },
                "visibility": {
                  "description": "Updated visibility.",
                  "enum": [
                    "private",
                    "public"
                  ],
                  "type": "string"
                },
                "whenNotToUse": {
                  "description": "Updated guidance on when NOT to use.",
                  "type": "string"
                },
                "whenToUse": {
                  "description": "Updated guidance on when to use.",
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_capabilities_vouch",
            "description": "Add a trust vouch for another owner's capability, incrementing its vouch count (an optional comment may explain why). You cannot vouch for your own capability. Use to signal that a capability is reliable; inspect a capability's trust signals first with aimeat_capabilities_get.",
            "inputSchema": {
              "properties": {
                "comment": {
                  "description": "Optional comment explaining why you vouch for this capability.",
                  "type": "string"
                },
                "id": {
                  "description": "Capability identifier.",
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_catalogue_agents",
            "description": "Search the node-wide agent directory by free text (name/description/GAII) and/or capability category, returning each agent's GAII, display name, capabilities, trust score, and last-seen. Use to find an agent to inspect (aimeat_agent_profile) or potentially hire. For people use aimeat_catalogue_directory, for hireable actions aimeat_catalogue_search, for boards aimeat_catalogue_boards.",
            "inputSchema": {
              "properties": {
                "category": {
                  "description": "Filter by capability category.",
                  "type": "string"
                },
                "search": {
                  "description": "Free-text search (name/description/GAII).",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_catalogue_boards",
            "description": "Browse all public boards on the node (id, name, description, created date) with no auth scoping — discovery for boards anyone can read. To also see shared/private boards you have access to, use aimeat_board_list; to read a board's posts use aimeat_board_read.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_catalogue_directory",
            "description": "Search the people directory by city or interest keyword. Only lists owner profiles that have opted in to public listing. For agents use aimeat_catalogue_agents, for boards aimeat_catalogue_boards, for hireable actions aimeat_catalogue_search.",
            "inputSchema": {
              "properties": {
                "city": {
                  "description": "Filter by city.",
                  "type": "string"
                },
                "interest": {
                  "description": "Filter by interest keyword.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_catalogue_search",
            "description": "Search the node's action catalogue — the services other agents offer for hire (paid in morsels). Returns matching actions with their provider, price, and category. Use this to discover what you can request via aimeat_action_execute. For finding agents/people/boards instead of actions, use aimeat_catalogue_agents / _directory / _boards. response_format=concise drops provider_gaii and pricing detail.",
            "inputSchema": {
              "properties": {
                "category": {
                  "description": "Filter by capability category.",
                  "type": "string"
                },
                "search": {
                  "description": "Free-text search over action name/description/GAII.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_checkout_complete",
            "description": "Pay + fulfill an open checkout session. Charges your owner's balance (or a money handler when specified), then fulfills: offers and unbound app-tools queue a TASK for the seller; a callable app-tool runs instantly and its result returns on fulfillment.results. A failed callable invoke refunds automatically and leaves the session open. Returns the completed session with the receipt {charged, earned, fee, trackingCode}.",
            "inputSchema": {
              "properties": {
                "handler": {
                  "description": "Payment handler id (default io.aimeat.morsels)",
                  "type": "string"
                },
                "session_id": {
                  "description": "The open session id from aimeat_checkout_open",
                  "type": "string"
                }
              },
              "required": [
                "session_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_checkout_list",
            "description": "List your owner's checkout sessions (purchases), newest first — status, items, totals, receipts, and fulfillment (task ids / callable results).",
            "inputSchema": {
              "properties": {
                "limit": {
                  "description": "Max sessions to return (default 20, max 200)",
                  "type": "number"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_checkout_open",
            "description": "Open a checkout session as a BUYER (your owner's balance pays — one morsel balance per human). Line items: agent offers ({agent: GAII or bare own name, offer_id}) or app-tools ({kind: \"app-tool\", app: \"ownerName/appId\", tool, input? — one call per line item}). All items must share one seller. currency: omit for morsels, or EUR/USD when the item has a money price and the node has a settling handler. Returns the open session with the quoted total; complete it with aimeat_checkout_complete.",
            "inputSchema": {
              "properties": {
                "currency": {
                  "description": "\"morsel\" (default) or a money code (EUR/USD)",
                  "type": "string"
                },
                "items": {
                  "description": "[{ kind?, agent?, offer_id?, app?, tool?, input?, quantity? }] — offer items need agent+offer_id; app-tool items need kind:\"app-tool\"+app+tool",
                  "type": "array"
                },
                "note": {
                  "description": "Buyer note delivered with the order",
                  "type": "string"
                }
              },
              "required": [
                "items"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_classification",
            "description": "How sensitive a piece of content is, and the rules for that. Every memory record, workspace record or document, stored file and workspace row has a classification: public, internal, confidential, highly confidential, or a level the owner or an organism added, such as top secret. The classification decides which people and which AI may read it and whether it may leave its organism. ACTIONS: get (the classification of one item, its waiting suggestion and its last changes), set (give it a classification), review (the person accepts or rejects a waiting suggestion; relay their words in human_said; a PERSON_APPROVES suggestion only the person accepts, signed in themselves), policy_get (the labels, detection rules, default and AI mode that apply at level node, owner or organism, and whether classification is on), policy_set (replace a level: read it with policy_get and send `stored` back changed), audit (the log of a level: which classified items were shown to or used by an AI, which were refused and which classifications changed; one row per reader, item and action per minute, with a count), scan (the Content Classifier judges memory keys: `key` or up to 3 `keys` at once, more keys or a `prefix` wait in a queue the server works through within the daily caps; detection rules run first, then the decision model or the text model the policy names, with personal data removed before anything leaves; its label follows the same AI rules as yours), explorer (a page of the classifications stored on your owner's content, theirs and their agents', or at level organism on an organism's content for its creator or an admin: filter with `label`, or with `pending: true` for the items where a suggestion waits for the person; pass `next` back as `cursor` for the next page; content with no stored classification reads as the default and is not listed), switch_set (the operator's own agent, with the operator:admin permission: set the node's switch `mode` to off, owner or all. Turning classification on, or from owner to all, applies at once; turning it off, or from all to owner, gives protection away and is refused from an AI with PERSON_REQUIRED, because the operator does that on the admin Config page. Every change is kept in the audit log at level node), exception_list (the exceptions list of a level, newest first: each act against a classification with who did it, the item, the classification and the reason. A person's exception lets one item leave (leave) or lets an AI send it out (ai-send) despite its classification; an app's act against a classification is recorded automatically (auto true: lower, policy, review, leave). Filter with exception_action and since; level node is the whole node, for an operator), exception_set (refused for you with PERSON_REQUIRED: an exception is the person's decision, made signed in themselves in their Data Wallet with a written reason; tell the person what you wanted to send and why. The person withdraws an exception there too, and an operator withdraws any on the admin Security page; this tool has no withdraw action). WHAT YOU SEE: by default you see everything; no default classification hides content from AI, and the sensitive ones (confidential, highly confidential) reach you with a warning. An owner or an organism may choose a classification that hides content from AI: such an item is not in your lists and reads as absent, and an AI call that names one is refused (CLASSIFIED). An item with a warning classification carries classification_warning, and you use it only for the task you were given. WHAT YOU SEND OUT: when content you send leaves (an export, a share link, another node, an outside service), an item whose classification hides it from AI stays behind, and so does an organism's item whose classification keeps it in the organism; the answer names each one with its reason, and the person can make an exception with a reason in their Data Wallet. WHAT YOU MAY DO: your own judgement never lowers a classification and never changes one a person set; it becomes a suggestion the person accepts or rejects. When the person told you what to set, pass their own words, verbatim, in human_said. A classification at least as strict then applies at once as theirs, also over one a person set. One that lowers it waits as a suggestion (PERSON_APPROVES) with their words on it, and the person accepts it signed in themselves: you cannot accept that suggestion, even with their words (PERSON_REQUIRED). A policy change that only tightens applies at once. One that gives anything away (turns classification off, lets an AI see more, drops an audit trail or a rule, lowers the default) waits until the person accepts it signed in themselves; you cannot accept it. A lower level only tightens the node: an owner or an organism adds its own labels between the node's ones and adds rules, and a refusal names the node's rule it would have loosened.",
            "inputSchema": {
              "properties": {
                "action": {
                  "description": "What to do.",
                  "enum": [
                    "get",
                    "set",
                    "review",
                    "policy_get",
                    "policy_set",
                    "audit",
                    "scan",
                    "explorer",
                    "switch_set",
                    "exception_list",
                    "exception_set"
                  ],
                  "type": "string"
                },
                "audit_action": {
                  "description": "audit: only this kind of row. exception: an exception made, used or withdrawn.",
                  "enum": [
                    "shown",
                    "used",
                    "refused",
                    "changed",
                    "exception"
                  ],
                  "type": "string"
                },
                "confidence": {
                  "description": "set: how sure you are, 0 to 1, when the label is your own judgement.",
                  "type": "number"
                },
                "cursor": {
                  "description": "explorer: the `next` value of the previous page.",
                  "type": "string"
                },
                "decision": {
                  "description": "review: the person's decision on the waiting suggestion.",
                  "enum": [
                    "accept",
                    "reject"
                  ],
                  "type": "string"
                },
                "exception_action": {
                  "description": "exception_list: only exceptions of this act. exception_set: leave (the item may leave) or ai-send (an AI may send it out).",
                  "enum": [
                    "leave",
                    "ai-send",
                    "lower",
                    "policy",
                    "review"
                  ],
                  "type": "string"
                },
                "human_said": {
                  "description": "The person's own words, verbatim, when you relay their instruction. Never your own summary.",
                  "type": "string"
                },
                "justification": {
                  "description": "set: why the content is less sensitive, when lowering from a label that needs a reason.",
                  "type": "string"
                },
                "key": {
                  "description": "get, set, review: the memory key (an organism workspace key included) or the stored file key.",
                  "type": "string"
                },
                "keys": {
                  "description": "scan: memory keys to classify.",
                  "type": "array"
                },
                "kind": {
                  "description": "get, set, review: what the content is. Default memory. explorer: only this kind.",
                  "enum": [
                    "memory",
                    "file",
                    "row"
                  ],
                  "type": "string"
                },
                "label": {
                  "description": "set: the label id, from policy_get. explorer: only items with this label.",
                  "type": "string"
                },
                "level": {
                  "description": "policy_get, policy_set, audit, exception_list: which level. Default owner. explorer: owner or organism. switch_set: node, the only one.",
                  "enum": [
                    "node",
                    "owner",
                    "organism"
                  ],
                  "type": "string"
                },
                "limit": {
                  "description": "audit, exception_list: at most this many rows, default 200. explorer: items per page, default 50, at most 200.",
                  "type": "number"
                },
                "mode": {
                  "description": "switch_set: the node's switch. off: nothing is classified; owner: each owner decides for their own content; all: on for every owner.",
                  "enum": [
                    "off",
                    "owner",
                    "all"
                  ],
                  "type": "string"
                },
                "organism_id": {
                  "description": "A row: its organism. policy_get, policy_set, audit, explorer, exception_list at level organism: the organism.",
                  "type": "string"
                },
                "owner": {
                  "description": "get, set, review: the identity that holds the key when it is one of your agents or apps (a memory key or a stored file). Absent: your own.",
                  "type": "string"
                },
                "pending": {
                  "description": "explorer: only the items where a suggestion waits for a person.",
                  "type": "boolean"
                },
                "policy": {
                  "description": "policy_set: the WHOLE level as policy_get returned it in `stored`, changed. It replaces the level. A label: { id, name: { fi, en, es }, rank 0-999, color, description, aiVisibility hidden|warning|allowed, audit, mayLeaveOrganism, lowerNeedsJustification, audience: { roles, groups, people } }. A rule: { id, name, kind keyword|regex|classifier, pattern, flags, minLabel, enabled, appliesTo: { kinds, organismId, ws, keyPrefix } }. An owner or organism level also carries enabled, which turns classification on for its content when the node lets each owner decide.",
                  "type": "object"
                },
                "prefix": {
                  "description": "scan: classify every memory key under this prefix (queued).",
                  "type": "string"
                },
                "reason": {
                  "description": "set: why you chose the label, when it is your own judgement. exception_set: why the item may go out despite its classification.",
                  "type": "string"
                },
                "row_id": {
                  "description": "A row: its id.",
                  "type": "string"
                },
                "since": {
                  "description": "audit, exception_list: only rows from this ISO time on.",
                  "type": "string"
                },
                "space": {
                  "description": "A row: its row space.",
                  "type": "string"
                },
                "until": {
                  "description": "exception_set: when the exception ends, ISO. Absent: until it is withdrawn.",
                  "type": "string"
                },
                "ws": {
                  "description": "A row: its workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "action"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_commerce_beneficiary_approve",
            "description": "OPERATOR ONLY. Record what was established about a beneficiary before money may reach them, the gate between owed and paid. A gate a provider could open for their own payees would not be a gate. `method` says HOW representation was established (suomifi-valtuudet, manual-operator, contract-on-file) and is REQUIRED when verifying: the node keeps no list of acceptable methods, because which evidence suffices is a legal judgement that varies by jurisdiction. `subject` optionally names the external identity the approval attests the account may act for (e.g. fi-ytunnus:3323553-5) and is opaque to the node. Absence of an approval means unverified: the gate fails closed. Omit `state` to READ the current approval instead of setting one; anyone may read their own, another account needs the operator role.",
            "inputSchema": {
              "properties": {
                "evidence": {
                  "description": "Case number, document reference, mandate id",
                  "type": "string"
                },
                "ghii": {
                  "description": "Beneficiary owner GHII. Defaults to you when reading.",
                  "type": "string"
                },
                "method": {
                  "description": "How representation was established. Required when verifying.",
                  "type": "string"
                },
                "state": {
                  "description": "verified | unverified | rejected. Omit to read.",
                  "type": "string"
                },
                "subject": {
                  "description": "Namespaced external identity the approval attests to, opaque to the node",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_commerce_beneficiary_earnings",
            "description": "What YOU have been given a share of, and whether it can be paid yet. A share is owed by the PROVIDER whose call it came from, out of what they earned, not by the buyer. `accrued` means booked and unpaid; the `verification` block is the honest answer to \"when do I get this\" - false means the amount is real and booked but no operator has verified your account, and it stays booked until one does. Totals are keyed per unit and NEVER summed: a currency code for real money in integer micro-units, and `morsels` for the node's pacing meter, which is capacity to call things rather than income. Set `role: \"provider\"` to see the other side instead: what YOU owe your beneficiaries, each with the tracking code a release needs.",
            "inputSchema": {
              "properties": {
                "limit": {
                  "description": "Max entries (default 200, max 1000)",
                  "type": "number"
                },
                "role": {
                  "description": "beneficiary (default) = what you are owed; provider = what you owe",
                  "type": "string"
                },
                "status": {
                  "description": "accrued | released | reversed",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_commerce_beneficiary_payout",
            "description": "Pay a beneficiary what you owe them, onchain. The last leg, and the one no existing payout could do: neither money handler can push a provider's funds to a third party (Stripe has no Connect platform here by design, and x402's payout is a no-op because the money moved buyer-to-seller at collect time), so a provider-to-beneficiary transfer is a DIFFERENT payment that its payer has to authorise. Call with no `payment` to QUOTE: you get what is owed plus the x402 exact-scheme requirements to sign with the wallet that holds the funds. Sign them, then call again with the signed `payment` to settle. AGGREGATED across everything released and unpaid in one currency, so one signature clears the balance instead of paying gas on every sub-euro share. The quote is rebuilt server-side on settle, so a signature can only move what is genuinely owed at that instant. Entries become `paid` only after the facilitator confirms, so a failed settlement leaves them payable and a confirmation arriving twice cannot pay twice. A beneficiary who has set no payout address returns BENEFICIARY_NO_ADDRESS and the obligation simply stays owed, which is what an unpaid invoice is. The node holds no key and no funds at any instant.",
            "inputSchema": {
              "properties": {
                "beneficiary": {
                  "description": "The beneficiary owner GHII you owe.",
                  "type": "string"
                },
                "currency": {
                  "description": "Defaults to EUR.",
                  "type": "string"
                },
                "payment": {
                  "description": "The signed x402 exact-scheme payload. Omit to quote.",
                  "type": "object"
                }
              },
              "required": [
                "beneficiary"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_commerce_beneficiary_release",
            "description": "Pay one accrued share you owe. Only the provider who owes it can, and only their own obligations. GATED: refuses with BENEFICIARY_UNVERIFIED until an operator has recorded that the beneficiary may be paid, because paying a party nobody has checked is how a self-declared claimant collects on somebody else's identity. What release DOES differs by rail, and `settled_here` reports which happened: a morsel share transfers from your balance to theirs and COMPLETES here, because morsels are the node's own pacing meter; a money share is booked onto their payable book and the fiat leg is invoiced off-node, because a node that pushed fiat would first have to hold it. Read `settled_here` as \"is there anything left to do\", never as \"which rail is the real one\". Idempotent: releasing the same share twice is refused.",
            "inputSchema": {
              "properties": {
                "beneficiary": {
                  "description": "The beneficiary owner GHII",
                  "type": "string"
                },
                "tracking_code": {
                  "description": "From aimeat_commerce_beneficiary_earnings with role=provider",
                  "type": "string"
                }
              },
              "required": [
                "tracking_code",
                "beneficiary"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_commerce_beneficiary_split_set",
            "description": "Declare who shares what one of YOUR capabilities earns. A second rake, shaped like the platform one: the platform rake takes a percent of what the BUYER pays, this takes a percent of what YOU earn and routes it to other accounts by weight. The pool comes out of your cut, after the platform rake, NEVER out of the buyer's price - declaring a split makes nothing more expensive for anyone, it makes your own revenue land somewhere else. `pool_percent` is how much of your cut leaves you; `weight` divides that pool (two rows at weight 1 split it evenly, 3 and 1 split it 75/25). Set `dynamic: true` when WHO deserves a share depends on what the call was about: the capability then names destinations per call by returning a `_revenue` key, which the node strips before the buyer sees it. That key names destinations ONLY, so it can redirect a share you already committed and can never enlarge its own payout. Always written against YOUR OWN revenue. The coordinate is the metered pair: an extension name, `apptool:{owner}/{appId}`, or `agentwork:{owner}/{agent}`, plus the action id, tool name or task type.",
            "inputSchema": {
              "properties": {
                "action": {
                  "description": "The action id, tool name, or task type",
                  "type": "string"
                },
                "beneficiaries": {
                  "description": "Standing beneficiaries: [{ ghii, weight?, note? }]. May be empty when dynamic is true.",
                  "type": "array"
                },
                "capability": {
                  "description": "Human label; defaults to \"{ext}/{action}\"",
                  "type": "string"
                },
                "dynamic": {
                  "description": "Let the capability name destinations per call via the _revenue key",
                  "type": "boolean"
                },
                "ext": {
                  "description": "Metered coordinate: extension name, apptool:{owner}/{appId}, or agentwork:{owner}/{agent}",
                  "type": "string"
                },
                "pool_percent": {
                  "description": "0-100: the share of YOUR cut routed to beneficiaries",
                  "type": "number"
                },
                "state": {
                  "description": "active (default) or paused",
                  "type": "string"
                }
              },
              "required": [
                "ext",
                "action",
                "pool_percent"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_commerce_beneficiary_splits",
            "description": "Every beneficiary split YOU have declared, with its pool percent, whether it accepts per-call destinations, and who shares it. Owner-scoped: your own only, never another seller's. Pass `remove_ext` + `remove_action` to WITHDRAW one instead. Future calls then keep your whole cut, while shares already accrued still stand, because what was earned does not un-happen when the arrangement ends.",
            "inputSchema": {
              "properties": {
                "remove_action": {
                  "description": "With remove_ext: withdraw this split instead of listing",
                  "type": "string"
                },
                "remove_ext": {
                  "description": "With remove_action: withdraw this split instead of listing",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_commerce_psp_delete",
            "description": "Delete YOUR OWNER's stored PSP credentials (commerce.psp). Money-currency checkouts of your offers/app-tools stop working until new credentials are set; morsel selling is unaffected.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_commerce_psp_set",
            "description": "SCREEN ONLY: refuses for an agent, and returns the link to the Wallet page where the owner enters their payment-provider secret themselves (a key that moves money never passes through a chat). Call it only to get that link; do not ask the owner for the key. Money sales always settle on the SELLER's own PSP account, never the node's. aimeat_commerce_psp_status shows whether one is set, as a masked hint. Morsel-only selling needs no PSP.",
            "inputSchema": {
              "properties": {
                "provider": {
                  "description": "PSP identifier, e.g. \"stripe\"",
                  "type": "string"
                },
                "secret_key": {
                  "description": "The PSP secret credential (stored, never echoed back)",
                  "type": "string"
                },
                "webhook_secret": {
                  "description": "Stripe endpoint signing secret for this seller's webhook. Stored encrypted, never echoed back",
                  "type": "string"
                }
              },
              "required": [
                "provider",
                "secret_key"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_commerce_psp_status",
            "description": "Check whether YOUR OWNER has PSP credentials configured for money selling. Returns configured true/false, the provider name, and a masked key hint (last 4 characters) — NEVER the secret itself.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_company_create",
            "description": "Register a company, which immediately reserves its public address {slug}.co.\u003capex\u003e — the same way publishing an app reserves an apps subdomain. The slug is derived from the name unless given; a taken name answers SLUG_TAKEN and a reserved infrastructure label answers SLUG_RESERVED, so pick another and retry rather than treating it as a failure. Supplying the legal-identity fields here saves a follow-up aimeat_company_update, and they are what every later invoice prefills its seller party from.",
            "inputSchema": {
              "properties": {
                "bic": {
                  "description": "Bank BIC/SWIFT.",
                  "type": "string"
                },
                "business_id": {
                  "description": "Company registration number (Finnish Y-tunnus, e.g. \"1234567-8\").",
                  "type": "string"
                },
                "city": {
                  "description": "City.",
                  "type": "string"
                },
                "country": {
                  "description": "ISO 3166-1 alpha-2 country code, exactly two letters (e.g. \"FI\").",
                  "type": "string"
                },
                "description": {
                  "description": "One or two sentences about what the company does.",
                  "type": "string"
                },
                "einvoice_address": {
                  "description": "E-invoice address (Finnish OVT identifier) if the company receives e-invoices.",
                  "type": "string"
                },
                "einvoice_operator": {
                  "description": "E-invoice operator/intermediary id (often a bank BIC, e.g. \"NDEAFIHH\").",
                  "type": "string"
                },
                "email": {
                  "description": "Contact email shown to customers.",
                  "type": "string"
                },
                "iban": {
                  "description": "Bank account in IBAN form — this is what an invoice tells the buyer to pay into.",
                  "type": "string"
                },
                "name": {
                  "description": "Trade name as it should appear on invoices (e.g. \"Perustaja Oy\").",
                  "type": "string"
                },
                "organism_id": {
                  "description": "The organism this company keeps its knowledge in. An empty string unlinks it.",
                  "type": "string"
                },
                "phone": {
                  "description": "Contact phone.",
                  "type": "string"
                },
                "postal_code": {
                  "description": "Postal code.",
                  "type": "string"
                },
                "slug": {
                  "description": "Address label. Defaults to a normalised form of the name (ä→a, ö→o, spaces→hyphens).",
                  "type": "string"
                },
                "street_address": {
                  "description": "Street address of the registered office.",
                  "type": "string"
                },
                "vat_id": {
                  "description": "VAT number (e.g. \"FI12345678\").",
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_company_front_page",
            "description": "Choose what the company's address serves: 'app' serves one of the OWNER'S OWN published apps (target \"owner/file.html\"; someone else's answers FRONT_PAGE_NOT_YOURS), 'portfolio' serves the page published with aimeat_company_portfolio_publish, 'redirect' sends visitors to an absolute http(s) URL, and 'none' keeps the address reserved while serving nothing. Choosing 'portfolio' before a page exists answers NO_PORTFOLIO — publish first.",
            "inputSchema": {
              "properties": {
                "company_id": {
                  "description": "Company id from aimeat_company_list.",
                  "type": "string"
                },
                "kind": {
                  "description": "What the address serves.",
                  "enum": [
                    "app",
                    "portfolio",
                    "redirect",
                    "none"
                  ],
                  "type": "string"
                },
                "target": {
                  "description": "\"owner/file.html\" for kind app; an absolute URL for kind redirect; omit for portfolio and none.",
                  "type": "string"
                }
              },
              "required": [
                "company_id",
                "kind"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_company_list",
            "description": "The owner's registered companies, each with its id, slug, public address ({slug}.co.\u003capex\u003e), front-page setting, and legal-identity fields. Start here: every other company tool takes the id from this list. An empty list means the owner has not registered a company yet — aimeat_company_create is the first step.",
            "inputSchema": {
              "properties": {
                "page": {
                  "description": "Page number (default 1).",
                  "type": "number"
                },
                "per_page": {
                  "description": "Companies per page (default 50, max 100).",
                  "type": "number"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_company_portfolio_publish",
            "description": "Publish a standalone HTML page as the company's public front page and point the address at it in one act. Send the WHOLE document (doctype through \u003c/html\u003e) — it is served as-is on an isolated, session-less origin, so everything it needs must be inside it or loaded from this node. Style it with the node's theme variables rather than hardcoded colours so it follows light and dark mode, and keep it under the node's portfolio size limit (512KB by default). Re-publishing replaces the previous page.",
            "inputSchema": {
              "properties": {
                "company_id": {
                  "description": "Company id from aimeat_company_list.",
                  "type": "string"
                },
                "html": {
                  "description": "The complete HTML document to serve at the company address.",
                  "type": "string"
                }
              },
              "required": [
                "company_id",
                "html"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_company_update",
            "description": "Fill in or correct a company's details. Every field is optional and only the ones passed are written, so this is safe to call repeatedly as a conversation gathers information — ask the owner for what is missing, then write just that. Passing an empty string clears a field. These values become the seller party on every invoice and the supplier block in the Finvoice e-invoice, so they must be the real registered details rather than plausible-looking ones: leave a field out when the owner has not stated it.",
            "inputSchema": {
              "properties": {
                "bic": {
                  "description": "Bank BIC/SWIFT.",
                  "type": "string"
                },
                "business_id": {
                  "description": "Company registration number (Finnish Y-tunnus, e.g. \"1234567-8\").",
                  "type": "string"
                },
                "city": {
                  "description": "City.",
                  "type": "string"
                },
                "company_id": {
                  "description": "Company id from aimeat_company_list.",
                  "type": "string"
                },
                "country": {
                  "description": "ISO 3166-1 alpha-2 country code, exactly two letters (e.g. \"FI\").",
                  "type": "string"
                },
                "description": {
                  "description": "One or two sentences about what the company does.",
                  "type": "string"
                },
                "einvoice_address": {
                  "description": "E-invoice address (Finnish OVT identifier) if the company receives e-invoices.",
                  "type": "string"
                },
                "einvoice_operator": {
                  "description": "E-invoice operator/intermediary id (often a bank BIC, e.g. \"NDEAFIHH\").",
                  "type": "string"
                },
                "email": {
                  "description": "Contact email shown to customers.",
                  "type": "string"
                },
                "iban": {
                  "description": "Bank account in IBAN form — this is what an invoice tells the buyer to pay into.",
                  "type": "string"
                },
                "name": {
                  "description": "Trade name (the address is not renamed by this).",
                  "type": "string"
                },
                "organism_id": {
                  "description": "The organism this company keeps its knowledge in. An empty string unlinks it.",
                  "type": "string"
                },
                "phone": {
                  "description": "Contact phone.",
                  "type": "string"
                },
                "postal_code": {
                  "description": "Postal code.",
                  "type": "string"
                },
                "street_address": {
                  "description": "Street address of the registered office.",
                  "type": "string"
                },
                "vat_id": {
                  "description": "VAT number (e.g. \"FI12345678\").",
                  "type": "string"
                }
              },
              "required": [
                "company_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_compliance_register_read",
            "description": "Operator-only. Read what the compliance report is built from. part=\"draft\" is the one to start with: the node composes a first draft of the register out of what actually ran, grouped by which agent or app called the model rather than by the model, with each agent's own name and description as the entry, and the two questions it can answer from the record already answered and marked as evidence. Nothing in a draft is stored. part=\"usecases\" is the register as stored; part=\"questionnaire\" is the risk-classification question set — the classes, and each question with the answers that imply each class. The question set is DATA and can be edited without a release. Read before writing, because a write replaces the whole document. Needs the exact permission \"compliance:read\".",
            "inputSchema": {
              "properties": {
                "part": {
                  "description": "Which document to read. Start with \"draft\".",
                  "enum": [
                    "draft",
                    "usecases",
                    "questionnaire"
                  ],
                  "type": "string"
                },
                "since_days": {
                  "description": "For \"draft\": how far back to look for activity (default 30).",
                  "type": "number"
                }
              },
              "required": [
                "part"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_compliance_register_write",
            "description": "Operator-only. Replace one of the two stored documents. REPLACES, does not merge: send every use case or every question you want to keep, so read first. Pass dry_run=true to get back exactly what WOULD be stored, validated, without storing it — show that to the person and let them approve it before the real write. part=\"usecases\" expects { usecases: [...] }; part=\"questionnaire\" expects the whole set with version, classes, defaultClass and questions. Mark each answer in answerSources as \"human\", \"ai\" or \"evidence\": an auditor's question is which of the three, and answers that all read as considered would answer it wrongly. A question set naming a class it does not define, a choice question with no options, or a duplicate id is refused rather than stored. Adding a question takes effect on the next report with no release. Saving re-classifies everything: an entry whose answers no longer cover every question becomes unclassified and appears in the gap list. Needs the exact permission \"compliance:write\" — \"compliance:read\" is refused here, and no wildcard carries either.",
            "inputSchema": {
              "properties": {
                "dry_run": {
                  "description": "Validate and return what would be stored, storing nothing. Use this to show somebody the result before it goes in.",
                  "type": "boolean"
                },
                "part": {
                  "description": "Which document to replace.",
                  "enum": [
                    "usecases",
                    "questionnaire"
                  ],
                  "type": "string"
                },
                "value": {
                  "description": "The whole document. For \"usecases\", { usecases: [...] }. For \"questionnaire\", { version, note, classes, defaultClass, questions }.",
                  "type": "object"
                }
              },
              "required": [
                "part",
                "value"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_compliance_report",
            "description": "The compliance report: AI activity joined to the written record of what AI is used for, and the difference between them. Defaults to scope=\"mine\" — your owner's own slice, which any session may read and which needs no special permission. scope=\"node\" is the whole installation across every account, and needs the exact permission \"compliance:read\" plus an account that runs the installation; no wildcard carries that word. Read `gaps` first — each entry is a model used and mentioned in no entry, an entry with unanswered questions and so no risk class, public content published without a label, or an app that says it generates content while the publish check found a disclosure gap. Read `not_covered` second, and note the two scopes state DIFFERENT limits: a total without its population reads as coverage. Use aimeat_compliance_register_read to see the written record raw, and aimeat_compliance_register_write to change it.",
            "inputSchema": {
              "properties": {
                "month": {
                  "description": "A whole calendar month, YYYY-MM. Wins over since_days — a rolling window filed under a month's name is wrong in an archive somebody reads later.",
                  "type": "string"
                },
                "scope": {
                  "description": "Whose report. \"mine\" (the default) is your owner's own slice; \"node\" is the whole installation and is operator-only.",
                  "enum": [
                    "mine",
                    "node"
                  ],
                  "type": "string"
                },
                "since_days": {
                  "description": "Rolling window in days (default 30). Ignored when month is given.",
                  "type": "number"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_compliance_snapshot",
            "description": "Operator-only. The reports this installation has KEPT, as opposed to the live one aimeat_compliance_report builds each time it is asked. action=\"list\" is the index, newest first: each entry has an id, a generated_at, and a kind — \"monthly\" for the one the schedule writes on the first of each month, \"manual\" for a moment somebody chose to keep. action=\"read\" with that id returns that report exactly as it was stored, which is the point of it: the numbers in it will never change again. action=\"save\" keeps the report as it stands right now and returns its new id; use since_days to say what window it should cover, because a snapshot describes its own period and will be read a year later by somebody who was not there. Reading needs \"compliance:read\"; saving needs \"compliance:write\", since it adds a node-wide document to what the installation keeps.",
            "inputSchema": {
              "properties": {
                "action": {
                  "description": "What to do. Start with \"list\".",
                  "enum": [
                    "list",
                    "read",
                    "save"
                  ],
                  "type": "string"
                },
                "id": {
                  "description": "For \"read\": which stored report, e.g. 2026-08 for a month or 2026-08-23-1930 for a saved moment.",
                  "type": "string"
                },
                "since_days": {
                  "description": "For \"save\": the window the snapshot covers (default 30).",
                  "type": "number"
                }
              },
              "required": [
                "action"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_connection_list",
            "description": "The outside accounts YOU have connected, with the id every other tool here takes. A connection belongs to the exact principal that made it, so this is yours and not your owner's: an account they connected in their own browser does not appear here, and that is deliberate — a mailbox is the most private thing on this node, and inheriting one silently is not a permission anybody knowingly grants. A connection that has stopped working carries what would repair it.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_connection_providers",
            "description": "Which outside services this node can connect an account at, and what each one is good for. Every entry says whether the NODE holds an application for it: when it does not, someone who brings their own app can still use it, so an absent registration removes an option from nobody. Read this before aimeat_connection_start, because the names are exact ('google-mail' reads Gmail, 'google-mail-send' sends from it) and mail deliberately comes in read/send PAIRS — reading a person's mail and writing in their name are different consent, and neither implies the other.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_connection_start",
            "description": "Begin connecting an outside account. Returns an address for a PERSON to open: they see exactly what is being asked for and approve it at the provider, and nothing here can approve it for them — fetching the address yourself does nothing. Hand it over, say in one sentence what it is for and what it will and will not be able to do, and wait; the connection then appears in aimeat_connection_list. Worth saying to them, because it is the question they are actually asking: a read connection cannot send, delete or change anything, because those permissions are never requested.",
            "inputSchema": {
              "properties": {
                "instance": {
                  "description": "Only for a federated provider such as Mastodon: the server address.",
                  "type": "string"
                },
                "provider": {
                  "description": "Which service, exactly as aimeat_connection_providers names it (e.g. 'google-mail').",
                  "type": "string"
                },
                "return_url": {
                  "description": "Where the browser lands after the person approves.",
                  "type": "string"
                }
              },
              "required": [
                "provider"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_consent_grant",
            "description": "Grant data-sharing consent: authorize a recipient (a GAII, \"*\", or a prefixed scope like organism:/domain:/node:) to access memory matching a glob data pattern, within a scope zone (private/dmz/federation) and optional expiry. Creates an auditable consent record owned by your GHII (max 100). Manage existing grants with aimeat_consent_list / aimeat_consent_revoke.",
            "inputSchema": {
              "properties": {
                "data_pattern": {
                  "description": "Glob pattern for data keys (e.g. \"profile.*\").",
                  "type": "string"
                },
                "purpose": {
                  "description": "Human-readable purpose for this consent.",
                  "type": "string"
                },
                "scope": {
                  "description": "Consent scope zone (private/dmz/federation).",
                  "type": "string"
                },
                "target_gaii": {
                  "description": "Recipient GAII, \"*\", or prefixed identifier (organism.x, ghii:, domain:, node:).",
                  "type": "string"
                },
                "ttl_hours": {
                  "description": "Expiry in hours from now (omit for indefinite).",
                  "type": "number"
                }
              },
              "required": [
                "target_gaii",
                "scope",
                "data_pattern",
                "purpose"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_consent_list",
            "description": "List the consent records owned by your GHII (data pattern, recipient, purpose, scope, expiry, and status including revoked ones). Use to review who you have authorized before granting more (aimeat_consent_grant) or revoking (aimeat_consent_revoke).",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_consent_revoke",
            "description": "Revoke a consent grant by its id, setting status to revoked and stamping the time (the record is kept for audit, not deleted). Only the consent owner may revoke. Find the id with aimeat_consent_list.",
            "inputSchema": {
              "properties": {
                "consent_id": {
                  "description": "ID of the consent to revoke.",
                  "type": "string"
                }
              },
              "required": [
                "consent_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_contact_add",
            "description": "Save someone to the owner's address book, in one of two ways. An IDENTITY on some node: pass contact_id (a bare local owner name, a GHII, a GAII or a GEAI); a local one that does not exist is refused. A PERSON who has no account here: pass name + email, plus anything else the owner knows (note, tags, links, relation) — that is how you record someone they follow, someone they mean to invite, or a plain email contact. If that address later belongs to a verified account here, the entry becomes that person automatically and nothing the owner wrote is lost. A blocked contact stays blocked (unblock via the Messages flow first). Saving a person by email counts as an address lookup: one account has 20 in 10 minutes, the owner and all their agents together, and past that the answer is RATE_LIMITED with the seconds to wait.",
            "inputSchema": {
              "properties": {
                "contact_id": {
                  "description": "An identity: bare local owner name, owner@node, agent#owner@node, or eco:app#owner@node. Omit when saving a person by name + email.",
                  "type": "string"
                },
                "email": {
                  "description": "A person's email address. Required with name. This is what links them to an account if they join later.",
                  "type": "string"
                },
                "links": {
                  "description": "Where else this person is: an array of { label, url }. http(s) addresses only.",
                  "type": "array"
                },
                "name": {
                  "description": "A person's name, as the owner would write it. Required with email.",
                  "type": "string"
                },
                "note": {
                  "description": "Anything the owner wants to remember about this person.",
                  "type": "string"
                },
                "relation": {
                  "description": "The owner's own word for the relationship (for example: following, to invite, colleague).",
                  "type": "string"
                },
                "tags": {
                  "description": "The owner's own labels for this person: an array of strings.",
                  "type": "array"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_contact_invite",
            "description": "Invite a person to join this AIMEAT with no organism behind it: they get an email in the owner's name with a link that opens an account here, and if the owner wrote them down as a contact, that entry becomes them when they arrive. Refused when the address already has an account (add them with aimeat_contact_add instead), when the owner's own invitation to it is still open, or when the owner has too many open. To invite someone INTO an organism, use aimeat_organism_invite_email. Send one only when the owner asks: it is an email in their name. It takes messages:send, here and on POST /v1/contacts/invite alike. An invitation counts as an address lookup: one account has 20 in 10 minutes, the owner and all their agents together, and past that the answer is RATE_LIMITED with the seconds to wait.",
            "inputSchema": {
              "properties": {
                "email": {
                  "description": "The address to invite.",
                  "type": "string"
                },
                "message": {
                  "description": "A short message from the owner, carried in the email.",
                  "type": "string"
                }
              },
              "required": [
                "email"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_contact_list",
            "description": "The owner's address book: everyone they saved, everyone they have exchanged direct messages with, and every PERSON they wrote down who has no account on this node. Each entry carries kind (ghii = a person here, gaii = an agent, geai = an app, mail = a person with no account here), the name to show, their email when one is known, and origin ('saved' vs 'message'). Use it as the identity source when granting access — pair a ghii contact with aimeat_organism_invite, aimeat_organism_member_add, or aimeat_workspace_member_grant. A 'mail' contact cannot be granted anything until they join; invite them with aimeat_organism_invite_email. It takes contacts:read, here and on GET /v1/contacts alike. The conversation columns (last message, who wrote it, when, how many, the conversation id) are empty unless you may also read the owner's mailbox (messages:read-as-owner), and include \"together\" is answered only with organism:read.",
            "inputSchema": {
              "properties": {
                "include": {
                  "description": "Comma-separated extras. \"together\": the organisms each person and the owner share, on every ghii row. \"invites\": the owner's open invitation on every person without an account.",
                  "type": "string"
                },
                "q": {
                  "description": "Filter by id, name or email (case-insensitive substring).",
                  "type": "string"
                },
                "state": {
                  "description": "Narrow to one consent state (default hides blocked). Only identities have one, so this excludes saved people.",
                  "enum": [
                    "pending",
                    "accepted",
                    "blocked"
                  ],
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_contact_remove",
            "description": "Remove a contact from the owner's address book WITHOUT disturbing the direct-message first-contact gate: a contact with message history keeps its messaging state (only the 'saved' mark is dropped); a pure saved contact is deleted. Removing a saved person deletes what the owner wrote about them; anything already sent to them stays in the send log.",
            "inputSchema": {
              "properties": {
                "contact_id": {
                  "description": "The contact id to remove (from aimeat_contact_list).",
                  "type": "string"
                }
              },
              "required": [
                "contact_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_contact_resolve_email",
            "description": "Look up a LOCAL owner by email — EXACT match only (privacy-preserving hash; no enumeration or substring search). Found → their GHII + display name (add with aimeat_contact_add, or grant access directly). Not found → can_invite signals whether an email invitation could be sent instead (aimeat_organism_invite_email). The same endpoint as POST /v1/contacts/resolve, on the messages:read permission. One account has 20 lookups in 10 minutes, the owner and all their agents together, and saving a person by email with aimeat_contact_add counts as one; past that the answer is RATE_LIMITED with the seconds to wait.",
            "inputSchema": {
              "properties": {
                "email": {
                  "description": "Email address to look up (exact match).",
                  "type": "string"
                }
              },
              "required": [
                "email"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_cortex_activate",
            "description": "Activate an installed cortex extension by name so its components become available to browser apps and its capabilities are aggregated. Idempotent — returns success if already active. Cortex installs inactive; call this after aimeat_cortex_install. Reverse with aimeat_cortex_deactivate.",
            "inputSchema": {
              "properties": {
                "name": {
                  "description": "Cortex name.",
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_cortex_deactivate",
            "description": "Deactivate an active cortex extension by name, setting it inactive so its components are no longer served to apps (it stays installed). Its actions leave the catalogue and its schema locks, boards, prompts and ontologies are removed, also when another principal of the person (the person, an agent or an app of theirs) activated it. Its seed data and lib files stay. Idempotent — returns success if already inactive. Re-enable with aimeat_cortex_activate, or remove with aimeat_cortex_delete.",
            "inputSchema": {
              "properties": {
                "name": {
                  "description": "Cortex name.",
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_cortex_delete",
            "description": "Uninstall a cortex extension by name. An active one is deactivated first, so its actions, boards, schema locks, prompts and ontologies go; then its seed data, stored lib files and kept versions go with it. Irreversible. To merely pause it, use aimeat_cortex_deactivate instead.",
            "inputSchema": {
              "properties": {
                "name": {
                  "description": "Cortex name.",
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_cortex_install",
            "description": "Install a cortex extension (browser-side IIFE that reads ext data and user data and renders rich UI), or redeploy one you installed. Two modes. UPLOAD MODE: call with no manifest to get an upload_url, then PUT a ZIP containing manifest.yaml at root and lib files in libs/. INLINE MODE: provide the manifest YAML string plus a libs map directly. Activate a new one afterwards with aimeat_cortex_activate. REDEPLOYING: pass update:true with the inline manifest and libs to replace your installed cortex of that metadata.name in place, with no delete: it stays served for the whole call, an active one is taken down and activated again from the new manifest (its old actions, boards, schema locks and prompts go, its seed data stays), and identical bytes answer \"unchanged\". Without update:true an inline install of a name that already exists is refused. A ZIP upload that carries the name of a cortex you installed replaces it the same way, without update:true. Do not delete a live cortex to reinstall it, because every app loading its lib breaks until the new one is active. The answer names each lib's address in lib_urls; that is the exact script src an app loads.",
            "inputSchema": {
              "properties": {
                "libs": {
                  "description": "Map of filename to JavaScript source code for lib files. Omit for upload mode.",
                  "type": "object"
                },
                "manifest": {
                  "description": "Cortex manifest in YAML format. Omit to get an upload_url for a ZIP bundle. Use @file:path with the CLI fallback.",
                  "type": "string"
                },
                "update": {
                  "description": "Replace your installed cortex of the manifest's metadata.name in place (inline mode). Without it an inline install of an existing name is refused; a ZIP upload replaces a cortex you installed either way.",
                  "type": "boolean"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_cortex_list",
            "description": "List installed cortex extensions (browser-side UI/IIFE bundles) with name, version, status, visibility, namespace, tags, and author. Cortex code runs in the browser (not server-side like a regular extension), so it cannot be invoked here — manage its lifecycle with aimeat_cortex_activate / _deactivate / _delete. Install with aimeat_cortex_install. Give `name` to read one cortex in full (its components, versions and what its activation created), and add include_source: true to get its manifest and lib files, which is what you edit before replacing it with aimeat_cortex_install update: true; the source belongs to the owner who installed it, and reading it needs the cortex:write permission.",
            "inputSchema": {
              "properties": {
                "include_source": {
                  "description": "With name: also its manifest and lib files, for editing. Your own cortex only; needs cortex:write.",
                  "type": "boolean"
                },
                "name": {
                  "description": "One cortex, in full, instead of the list.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_crew_draft",
            "description": "Keep unpublished edits to an agent's crew definition (crews.registry.\u003cagent\u003e.draft, in the agent's own namespace) so the Crew tab and a later chat session see them; or discard the saved draft by omitting doc. No validation: a draft may be half-written. Needs memory:write. Publishing consumes the draft.",
            "inputSchema": {
              "properties": {
                "doc": {
                  "description": "The crew definition (crewaimeat crew_def shape): agent_name, agents[] {name, role, goal, backstory, tools[], allow_delegation}, tasks[] {id, description, expected_output, agent, context[], async}, and optionally llm_profile, temperature, process, listen_for, tags, capabilities {technical: [{name, type}], domain, languages}, skills, offers, signals, readme_md. At least one task description must contain {{ctx.prompt}}; task context may only name EARLIER task ids. Tools come from the runtime's own menu — memory, web, article_fetch, schedule, dm, delegate, image, app_build, local_memory, app_tools, crew_registry, exchange (and exchange_* verbs) — which the runtime owns and adds to, so this list can be behind it; the runtime refuses a tool that does not exist. A definition that needs a tool of its own is a Python crew, not a definition. `listen_for` says which wake starts the crew (tasks, messages, records, dms) and defaults to [\"tasks\"], which is wrong for any agent whose work arrives as a message. Omit it to discard the saved draft.",
                  "type": "object"
                },
                "target_agent_name": {
                  "description": "The agent whose definition this is: the bare name of one of your owner's agents, or its full GAII. An agent may name itself or a same-owner sibling.",
                  "type": "string"
                }
              },
              "required": [
                "target_agent_name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_crew_get",
            "description": "Read an agent's crew definition state in one call: the LIVE definition (envelope with revision, publishedAt, publishedBy, doc), the saved draft, the kept revisions, what the agent's runtime last reported loading (crews.runtime.\u003cagent\u003e: loadedAt, revision, ok, errors), and whether the agent is connected right now (`online`). Start here before proposing a change: edit `published.doc` (or `draft.doc`), then aimeat_crew_validate → aimeat_crew_try → aimeat_crew_publish. `online: false` means validate, try and publish cannot run until the agent's runtime is up. Never write crews.registry.\u003cagent\u003e with aimeat_memory_write: it would land in YOUR namespace, where the tab and the runtime do not look; publish through aimeat_crew_publish.",
            "inputSchema": {
              "properties": {
                "target_agent_name": {
                  "description": "The agent whose definition this is: the bare name of one of your owner's agents, or its full GAII. An agent may name itself or a same-owner sibling.",
                  "type": "string"
                }
              },
              "required": [
                "target_agent_name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_crew_llm_set",
            "description": "Choose which model an agent thinks with, or clear the choice. Pass `target_agent_name` for one agent, or omit it to set the owner's DEFAULT for every agent they have. `choice` is {kind:'node', role?} to think through this node (the crew sends its model calls to the node's /v1/llm with the agent's own token, and the node picks the model and the key: the agent's own key, then the owner's, then the node's from the owner's allowance; `role` names one of the owner's AI roles; the agent needs ai:use), {kind:'profile', profile:'\u003cname\u003e'} naming a profile from aimeat_crew_menu, or {kind:'model', label, provider} pinning one model; pass null to clear and fall back. Precedence, strongest first: a pin made on the machine itself, this agent's own choice, the machine's `crews` map, the crew definition's own `llm_profile`, the owner's default, the machine's default. A `provider` may NAME the environment variable holding the key (api_key_env) and is refused if it carries a key: the credential stays on the machine that runs the agent. api_key_env must be a provider key variable (a name ending in _API_KEY, not starting with AIMEAT_), and every address in the provider must be public https; anything else is refused with UNSAFE_CHOICE. Needs memory:write; the choice is a record in the owner's own namespace (crews.llm.\u003cagent\u003e), so their own tools can read it.",
            "inputSchema": {
              "properties": {
                "choice": {
                  "description": "The choice: {kind:'node', role?}, {kind:'profile', profile} or {kind:'model', label, provider}. Omit or pass null to clear it.",
                  "type": "object"
                },
                "target_agent_name": {
                  "description": "The agent whose definition this is: the bare name of one of your owner's agents, or its full GAII. An agent may name itself or a same-owner sibling. Omit it to set the owner's default for every agent.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_crew_menu",
            "description": "What an agent's RUNTIME actually offers, asked rather than guessed: the tool names its interpreter resolves, the model profiles the machine it runs on can reach, the models behind them, and which model is chosen for this agent right now. Read this before writing a definition's `tools` — the fixed list in aimeat_crew_publish's own description is this node's copy and has been two tools behind the runtime. `source` says who answered: 'runtime' (the agent, over the tunnel), 'catalog' (it is offline, this is what it published at its last start), 'none' (nobody has ever said). `choice.scope` is 'agent' when this agent has its own and 'default' when it is the owner's, and null means neither, so the machine's own configuration decides.",
            "inputSchema": {
              "properties": {
                "target_agent_name": {
                  "description": "The agent whose definition this is: the bare name of one of your owner's agents, or its full GAII. An agent may name itself or a same-owner sibling.",
                  "type": "string"
                }
              },
              "required": [
                "target_agent_name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_crew_publish",
            "description": "Make a crew definition the LIVE one the agent's runtime reloads within seconds. The runtime validates it first; on problems nothing is written and the verdict comes back as CREW_INVALID with the messages verbatim. On success the definition becomes revision N+1 at crews.registry.\u003cagent\u003e in the AGENT'S namespace (a full copy is kept at .version.N+1, the last 10 stay restorable, the draft is consumed, and the runtime is woken with crew.def_updated). Pass `revision` instead of doc to restore a kept revision through the same gate. Needs memory:write, and the agent must be connected. This is the ONLY correct way to write crews.registry.\u003cagent\u003e from here.",
            "inputSchema": {
              "properties": {
                "doc": {
                  "description": "The crew definition (crewaimeat crew_def shape): agent_name, agents[] {name, role, goal, backstory, tools[], allow_delegation}, tasks[] {id, description, expected_output, agent, context[], async}, and optionally llm_profile, temperature, process, listen_for, tags, capabilities {technical: [{name, type}], domain, languages}, skills, offers, signals, readme_md. At least one task description must contain {{ctx.prompt}}; task context may only name EARLIER task ids. Tools come from the runtime's own menu — memory, web, article_fetch, schedule, dm, delegate, image, app_build, local_memory, app_tools, crew_registry, exchange (and exchange_* verbs) — which the runtime owns and adds to, so this list can be behind it; the runtime refuses a tool that does not exist. A definition that needs a tool of its own is a Python crew, not a definition. `listen_for` says which wake starts the crew (tasks, messages, records, dms) and defaults to [\"tasks\"], which is wrong for any agent whose work arrives as a message. The definition to make live.",
                  "type": "object"
                },
                "revision": {
                  "description": "Instead of doc: the kept revision to republish (it becomes a new revision).",
                  "type": "number"
                },
                "target_agent_name": {
                  "description": "The agent whose definition this is: the bare name of one of your owner's agents, or its full GAII. An agent may name itself or a same-owner sibling.",
                  "type": "string"
                }
              },
              "required": [
                "target_agent_name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_crew_seed",
            "description": "Give an agent its FIRST crew definition when it has no runtime yet to check one. Use this after creating an agent (the basic-agents button, or your own device-authorized registration): the agent has nothing to load, so aimeat_crew_publish would answer AGENT_OFFLINE forever and the agent could never be given anything to be. REFUSED if the agent already has a definition — change that one with aimeat_crew_publish, where the agent's own runtime has the say. Validation still happens on a REAL runtime: the agent itself if it is connected, otherwise the same-owner agent you name in validate_with, otherwise any connected agent of the owner. Whoever it was is recorded on the published definition as validatedBy, so nobody later reads a sibling's verdict as the agent's own. Needs memory:write. Refused with NO_VALIDATOR when nothing of the owner's is connected at all.",
            "inputSchema": {
              "properties": {
                "doc": {
                  "description": "The crew definition (crewaimeat crew_def shape): agent_name, agents[] {name, role, goal, backstory, tools[], allow_delegation}, tasks[] {id, description, expected_output, agent, context[], async}, and optionally llm_profile, temperature, process, listen_for, tags, capabilities {technical: [{name, type}], domain, languages}, skills, offers, signals, readme_md. At least one task description must contain {{ctx.prompt}}; task context may only name EARLIER task ids. Tools come from the runtime's own menu — memory, web, article_fetch, schedule, dm, delegate, image, app_build, local_memory, app_tools, crew_registry, exchange (and exchange_* verbs) — which the runtime owns and adds to, so this list can be behind it; the runtime refuses a tool that does not exist. A definition that needs a tool of its own is a Python crew, not a definition. `listen_for` says which wake starts the crew (tasks, messages, records, dms) and defaults to [\"tasks\"], which is wrong for any agent whose work arrives as a message. The FIRST definition for this agent.",
                  "type": "object"
                },
                "target_agent_name": {
                  "description": "The agent whose definition this is: the bare name of one of your owner's agents, or its full GAII. An agent may name itself or a same-owner sibling.",
                  "type": "string"
                },
                "validate_with": {
                  "description": "Which connected same-owner agent should check it. Omit and any connected one is used.",
                  "type": "string"
                }
              },
              "required": [
                "target_agent_name",
                "doc"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_crew_try",
            "description": "Run a crew definition ONCE on the agent's own runtime with a prompt, and get the output back. A trial leaves nothing behind: no task, no memory record, no offer; the node keeps the result in memory for 15 minutes and never stores it. Pass doc + prompt to start; the call waits up to wait_seconds (default 50) and returns {status: done, result.output} or {status: running, try_id} — call again with try_id to keep waiting (a real run with a model can take minutes). Validate first: a definition the runtime refuses fails the trial with its error list. Refused with AGENT_OFFLINE when the agent is not connected.",
            "inputSchema": {
              "properties": {
                "doc": {
                  "description": "Start a trial: The crew definition (crewaimeat crew_def shape): agent_name, agents[] {name, role, goal, backstory, tools[], allow_delegation}, tasks[] {id, description, expected_output, agent, context[], async}, and optionally llm_profile, temperature, process, listen_for, tags, capabilities {technical: [{name, type}], domain, languages}, skills, offers, signals, readme_md. At least one task description must contain {{ctx.prompt}}; task context may only name EARLIER task ids. Tools come from the runtime's own menu — memory, web, article_fetch, schedule, dm, delegate, image, app_build, local_memory, app_tools, crew_registry, exchange (and exchange_* verbs) — which the runtime owns and adds to, so this list can be behind it; the runtime refuses a tool that does not exist. A definition that needs a tool of its own is a Python crew, not a definition. `listen_for` says which wake starts the crew (tasks, messages, records, dms) and defaults to [\"tasks\"], which is wrong for any agent whose work arrives as a message. Omit when continuing to wait on a try_id.",
                  "type": "object"
                },
                "prompt": {
                  "description": "Start a trial: what the crew should do in this run (becomes {{ctx.prompt}}). Required with doc.",
                  "type": "string"
                },
                "target_agent_name": {
                  "description": "The agent whose definition this is: the bare name of one of your owner's agents, or its full GAII. An agent may name itself or a same-owner sibling.",
                  "type": "string"
                },
                "try_id": {
                  "description": "Continue waiting on a trial this tool already started and returned as running.",
                  "type": "string"
                },
                "wait_seconds": {
                  "description": "How long this call waits for the result before handing back the try_id (default 50, max 120).",
                  "type": "number"
                }
              },
              "required": [
                "target_agent_name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_crew_validate",
            "description": "Ask the agent's OWN runtime whether a crew definition is valid (crewaimeat validate_crew_doc — the node holds no validator of its own, so what comes back is what would run). Returns {valid, errors[]} with the runtime's messages verbatim, field-anchored like `agents[0] (writer): unknown tool 'x'` or `tasks[1] (edit): agent 'nobody' does not match any defined agent`; show them to the person unchanged. Nothing is stored. Refused with AGENT_OFFLINE when the agent is not connected and CREW_RUNTIME_MISSING when it is connected but its runtime does not answer this call (it needs aimeat-crewai 0.22+ with on_invoke).",
            "inputSchema": {
              "properties": {
                "doc": {
                  "description": "The crew definition (crewaimeat crew_def shape): agent_name, agents[] {name, role, goal, backstory, tools[], allow_delegation}, tasks[] {id, description, expected_output, agent, context[], async}, and optionally llm_profile, temperature, process, listen_for, tags, capabilities {technical: [{name, type}], domain, languages}, skills, offers, signals, readme_md. At least one task description must contain {{ctx.prompt}}; task context may only name EARLIER task ids. Tools come from the runtime's own menu — memory, web, article_fetch, schedule, dm, delegate, image, app_build, local_memory, app_tools, crew_registry, exchange (and exchange_* verbs) — which the runtime owns and adds to, so this list can be behind it; the runtime refuses a tool that does not exist. A definition that needs a tool of its own is a Python crew, not a definition. `listen_for` says which wake starts the crew (tasks, messages, records, dms) and defaults to [\"tasks\"], which is wrong for any agent whose work arrives as a message.",
                  "type": "object"
                },
                "target_agent_name": {
                  "description": "The agent whose definition this is: the bare name of one of your owner's agents, or its full GAII. An agent may name itself or a same-owner sibling.",
                  "type": "string"
                }
              },
              "required": [
                "target_agent_name",
                "doc"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_datamap_get",
            "description": "READ THIS BEFORE YOU CHANGE AN APP YOU DID NOT WRITE. An app's data map says what the app is for, what people use it for, what shape it is (one person, shared, a group, an organism workspace, static), how its data is actually arranged, what machinery it leans on, and what leaves this server. Then one row per group of keys: what it holds, what kind of thing it is, what it is used for, where it lives, who owns it, who reads it, who writes it, what shape the record is, how long it is kept, whether losing it matters, and ONE SENTENCE saying why it is there rather than somewhere else. That sentence is the reason this exists: without it a new feature's data lands wherever was easiest to reach, which is how a shared CRM ended up keeping the team's campaigns in one person's private memory where nobody else could see them. An app with no map says so plainly — that is a finding, not a blank, and writing one is the fix.",
            "inputSchema": {
              "properties": {
                "app": {
                  "description": "The app, as \"owner/filename.html\".",
                  "type": "string"
                }
              },
              "required": [
                "app"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_datamap_set",
            "description": "Write an app's data map, replacing whatever it said before — REPLACES, so read it first and send the whole thing back. Write one whenever you build an app or change where it stores something: you are the only one who knows where you put things and why, and the next AI to open it has no other way to find out. Two fields carry the value and neither can be worked out from the code: the paragraph saying what the app is and what it is used for, and the one-sentence `why` on each row. Leave a `why` you do not know EMPTY rather than filling it with something plausible — an empty one shows as unfinished, and a wrong one is believed and acted on. Nothing here can refuse a publish; the map is a statement about storage, not a gate.",
            "inputSchema": {
              "properties": {
                "app": {
                  "description": "The app, as \"owner/filename.html\".",
                  "type": "string"
                },
                "data_map": {
                  "description": "The whole map, carrying spec \"aimeat.datamap/2\": what, usedFor, form, arrangement, machinery, leaves, held[], elsewhere[]. A held row may also carry `isA`, the semantic type its records ARE — schema:Person, aimeat:Task, or a full IRI (GET /v1/ns lists the ones this node names). `kind` and `holds` say what the data is in the app's own words, and `isA` says the same in a word other systems already know, which is what makes the family findable with the type filter on memory search. A family that is genuinely nothing standard leaves it out rather than reaching for the nearest wrong type. A held row may also carry `classification`, the label id of the classification the app expects for that family by default, such as \"luottamuksellinen\" (1 to 40 lowercase letters, digits and dashes). It labels nothing and never refuses the map; an id of the wrong shape comes back as a finding. These two are the only optional fields on a row.",
                  "type": "object"
                }
              },
              "required": [
                "app",
                "data_map"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_datapackage_export",
            "description": "Get one resource of a data package in the shape the target program expects. DEFAULT AND USUALLY RIGHT is format \"url\": the permanent, session-free CSV address plus the Table Schema and ready-made DuckDB / pandas / Google Sheets / frictionless recipes — hand that address on rather than pulling rows through your context. format \"csv\" or \"json\" returns a WINDOW of rows inline, for a small table you have to reason over yourself; the answer says so when it truncated. `ref` is pkg:owner/name for the newest version or pkg:owner/name@sha256:... to pin one that can never change under you. The Table Schema names every column and its type, so you never have to be told the columns.",
            "inputSchema": {
              "properties": {
                "format": {
                  "description": "url (default) = the permanent address. csv/json = inline rows.",
                  "enum": [
                    "url",
                    "csv",
                    "json"
                  ],
                  "type": "string"
                },
                "limit": {
                  "description": "Rows for csv/json (default 500, max 5000).",
                  "type": "number"
                },
                "offset": {
                  "description": "Row to start from, for csv/json.",
                  "type": "number"
                },
                "ref": {
                  "description": "pkg:owner/name, optionally @sha256:... to pin a version.",
                  "type": "string"
                },
                "resource": {
                  "description": "Which resource of the package.",
                  "type": "string"
                },
                "select": {
                  "description": "Only these columns.",
                  "type": "array"
                }
              },
              "required": [
                "ref",
                "resource"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_datapackage_publish",
            "description": "Publish a table as an AIMEAT Data Package: a Frictionless descriptor with a Table Schema, canonical CSV bytes, AIMEAT provenance, and a permanent public address a program reads directly. The version IS the content hash, so re-publishing identical data answers unchanged:true and creates no second version. THE QUALITY GATE RUNS FIRST: a row that fails its schema means NOTHING is written and you get back the row and the column, with the package still standing on its previous version. `changes` is required — every version says what moved and why. Omitting a resource schema infers it and records schemaSource \"inferred\", so declare one when the types matter. Rows travel through your context and are capped at 8 MB per call; for a big or repeating table, produce it from an extension action or a workflow step instead, where the rows never touch a model. A RESOURCE IS THE WHOLE TABLE, NOT AN APPEND: publishing only today's rows REPLACES yesterday's, so to add to an existing package read the current rows with aimeat_datapackage_export first and publish them together with the new ones. WHEN THE ROWS WERE READ OUT OF PICTURES, name the picture in a `source_image` column (`source_image_2`, `_3` for later pages of one thing) holding the storage key you uploaded it under: the node turns it into the picture's permanent address so a reader can check any row against what it came from. The picture keeps whatever visibility it has — publishing the table does not publish the photographs.",
            "inputSchema": {
              "properties": {
                "changes": {
                  "description": "What changed against the previous version and why.",
                  "type": "string"
                },
                "description": {
                  "description": "What the package contains, for a person deciding whether to use it.",
                  "type": "string"
                },
                "legal_basis": {
                  "description": "Why you may publish this — e.g. a public register, consent, a contract.",
                  "type": "string"
                },
                "license": {
                  "description": "e.g. CC-BY-4.0. You publish under your owner name; say the terms.",
                  "type": "string"
                },
                "name": {
                  "description": "Lowercase letters, digits and dashes. Becomes part of the permanent URL.",
                  "type": "string"
                },
                "resources": {
                  "description": "One or more { name, rows, schema?, title?, description? }. rows is an array of objects.",
                  "type": "array"
                },
                "sources": {
                  "description": "Where the data came from: { url, title, retrievedAt }.",
                  "type": "array"
                },
                "title": {
                  "description": "Human title for the package.",
                  "type": "string"
                }
              },
              "required": [
                "name",
                "changes",
                "resources"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_decide",
            "description": "Ask the DECISION model typed questions about a piece of text or data and get typed answers with probabilities back. THE PROVIDER. Several decision models answer the same questions: TypeSafe Jev (hosted), and local decision models on the owner's own machine, which need no key and cost nothing. aimeat_decide_settings lists them under `providers`, with what each can carry. Name one with `provider`, or leave it out and the node picks, strongest first: the rule's, the one the owner set for you, the owner's default, the node's. The answer says which one answered (`provider`). A question a provider cannot carry (too many options, a state too long) is refused before anything is sent, and the refusal names the provider and its limit. It writes no text: use it to classify, route, screen, score, gate an action or pick among candidates you found in code, never to generate or summarise. The node removes personal data before anything leaves (e-mails, phones, Finnish personal identity codes, IBANs, street addresses, and names of the owner's contacts or under name fields), puts real option names back into the answers, meters the call on the owner's AI budget and records the decision so the owner can later ask what was decided about a record and on what basis. Pass `subject` (what the decision is about), `gates` (what it decides) and `thresholds` (the numbers you will compare against) so that record can be audited. WITH A RULE: give `rule` (an id from aimeat_decide_rules) and the state, nothing else. The answer then also carries `outcome` (act | ask | stop: what the owner's thresholds and bands made of the answers), `result`, `passed` per question, and `proceed`. When `proceed` is false the owner has switched the gate on for you and the outcome was under the act band: do NOT take the action, the owner has been given a task about it (`gate.task`). When `proceed` is true you decide from `outcome`. A map of YOUR ids to questions. Three types: {type:\"noul\", instructions, criteria?:{true?,false?}} returns the probability (0-1) that the statement is true; {type:\"choice\", instructions, criteria:{\"\u003coption\u003e\":\"\u003cwhat it means\u003e\"|null}} picks one of 2-240 options and returns a probability per option and a confidence; {type:\"score\", instructions, criteria:[\"\u003clowest level\u003e\", ..., \"\u003chighest level\u003e\"]} rates on 2-10 ordered levels. Write instructions and criteria in ENGLISH whatever language the state is in: the model is trained on English first. Ask everything you might need in ONE call (cost is in the state, answers are free), keep one judgment per question, add a \"none of these\" option to a choice, and keep arithmetic, counting and date comparison in code.",
            "inputSchema": {
              "properties": {
                "app_id": {
                  "description": "App attribution for the per-app quota.",
                  "type": "string"
                },
                "cache": {
                  "description": "Reuse an identical earlier decision (default true).",
                  "type": "boolean"
                },
                "gates": {
                  "description": "What the answer decides, in plain words (\"send the reply automatically\").",
                  "type": "string"
                },
                "names": {
                  "description": "Extra person names to remove before sending, beyond the owner's contacts.",
                  "type": "array"
                },
                "provider": {
                  "description": "The id of the decision provider to ask (aimeat_decide_settings lists them under `providers`). Leave out to let the node pick. Refused beside a rule that names a different one.",
                  "type": "string"
                },
                "public_content": {
                  "description": "The content is already public and needs no scrubbing. Honoured only when the owner's policy allows it.",
                  "type": "boolean"
                },
                "questions": {
                  "description": "Required unless `rule` is given. A map of YOUR ids to questions. Three types: {type:\"noul\", instructions, criteria?:{true?,false?}} returns the probability (0-1) that the statement is true; {type:\"choice\", instructions, criteria:{\"\u003coption\u003e\":\"\u003cwhat it means\u003e\"|null}} picks one of 2-240 options and returns a probability per option and a confidence; {type:\"score\", instructions, criteria:[\"\u003clowest level\u003e\", ..., \"\u003chighest level\u003e\"]} rates on 2-10 ordered levels. Write instructions and criteria in ENGLISH whatever language the state is in: the model is trained on English first. Ask everything you might need in ONE call (cost is in the state, answers are free), keep one judgment per question, add a \"none of these\" option to a choice, and keep arithmetic, counting and date comparison in code.",
                  "type": "object"
                },
                "rule": {
                  "description": "The id of one of the owner's decision rules (aimeat_decide_rules lists them). The rule holds the questions, thresholds and bands, so send `state` and leave `questions`, `thresholds` and `gates` out: a call that sends them beside a rule is refused.",
                  "type": "string"
                },
                "state": {
                  "description": "What is being judged: a string, an object with named fields (preferred), or an array of records. Send only what the questions need; unrelated content lowers accuracy and is what you pay for. With `rule`, only the fields that rule lists under `sends`.",
                  "type": "object"
                },
                "subject": {
                  "description": "What the decision is about: a memory key or a record id. The owner asks by this later.",
                  "type": "string"
                },
                "thresholds": {
                  "description": "The thresholds you will apply, e.g. {\"urgent\": 0.8}. Recorded with the decision.",
                  "type": "object"
                }
              },
              "required": [
                "state"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_decide_rule_propose",
            "description": "Propose a new decision rule to the owner. THIS CREATES NOTHING: the proposal lands on the owner's open-items list and the rule exists only after the owner approves it, because a rule decides whether an agent acts. It is checked exactly as a rule is, so fix what the refusal names and propose again. `rule` is { id (lower-case, digits, \"-\"), title, decides (what it gates, in plain words), sends (the state fields a caller may send; [] for any), questions, thresholds ({ questionId: floor } in that question's own units: a probability 0-1 for noul, a confidence 0-1 for choice, a level counted from 0 for score; word every thresholded question so that a HIGH value means \"go ahead\"), bands ({ act, ask } with 0 \u003c= ask \u003c= act \u003c= 1: the weakest certainty among the thresholded answers at or over act means act, at or over ask means ask a person, under it stop), use (\"agent\" | \"app\" | \"both\"), gate (true when the rule guards an action that cannot be undone), sample (a state to try it on), provider (optional: the decision provider it always runs on; it must carry the questions) }. Do not invent threshold or band numbers as if they were measured: say in `reason` that they are a starting point the owner tunes from the recorded decisions. A map of YOUR ids to questions. Three types: {type:\"noul\", instructions, criteria?:{true?,false?}} returns the probability (0-1) that the statement is true; {type:\"choice\", instructions, criteria:{\"\u003coption\u003e\":\"\u003cwhat it means\u003e\"|null}} picks one of 2-240 options and returns a probability per option and a confidence; {type:\"score\", instructions, criteria:[\"\u003clowest level\u003e\", ..., \"\u003chighest level\u003e\"]} rates on 2-10 ordered levels. Write instructions and criteria in ENGLISH whatever language the state is in: the model is trained on English first. Ask everything you might need in ONE call (cost is in the state, answers are free), keep one judgment per question, add a \"none of these\" option to a choice, and keep arithmetic, counting and date comparison in code.",
            "inputSchema": {
              "properties": {
                "reason": {
                  "description": "Why this rule should exist, in a sentence the owner can decide from (10 to 1000 characters).",
                  "type": "string"
                },
                "rule": {
                  "description": "The proposed rule: { id, title, decides, sends, questions, thresholds, bands, use, gate, sample }. Questions in English.",
                  "type": "object"
                }
              },
              "required": [
                "rule",
                "reason"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_decide_rules",
            "description": "List the owner's DECISION RULES that you may run: for each, its id, its title, what it decides, the state fields it takes (`sends`) and whether it is a gate. A decision rule is a named set of questions, thresholds and bands the owner wrote once; run one with aimeat_decide { rule, state }. You are shown only the rules the owner made for your kind of caller (an agent, or an app). Give `rule_id` to read one rule in full, with its questions. Also lists the proposals of yours that still wait for the owner.",
            "inputSchema": {
              "properties": {
                "rule_id": {
                  "description": "Read one rule in full, with its questions, thresholds and bands.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_decide_run",
            "description": "Ask the same questions of MANY records in the background: the node keeps at most a few requests open, waits out rate limits, records every decision, and keeps progress so a stopped run resumes where it stopped. action=\"start\" with the questions and exactly one of `items` ([{subject, state}]), `keys` (owner memory keys, each value one state) or `prefix` (every owner record under it); `fields` narrows each state to the named fields. It answers at once with a run id; read it with action=\"get\". action=\"list\", \"resume\" and \"stop\" do what they say. At most 1000 items per run. A map of YOUR ids to questions. Three types: {type:\"noul\", instructions, criteria?:{true?,false?}} returns the probability (0-1) that the statement is true; {type:\"choice\", instructions, criteria:{\"\u003coption\u003e\":\"\u003cwhat it means\u003e\"|null}} picks one of 2-240 options and returns a probability per option and a confidence; {type:\"score\", instructions, criteria:[\"\u003clowest level\u003e\", ..., \"\u003chighest level\u003e\"]} rates on 2-10 ordered levels. Write instructions and criteria in ENGLISH whatever language the state is in: the model is trained on English first. Ask everything you might need in ONE call (cost is in the state, answers are free), keep one judgment per question, add a \"none of these\" option to a choice, and keep arithmetic, counting and date comparison in code.",
            "inputSchema": {
              "properties": {
                "action": {
                  "description": "start | get | list | resume | stop",
                  "enum": [
                    "start",
                    "get",
                    "list",
                    "resume",
                    "stop"
                  ],
                  "type": "string"
                },
                "app_id": {
                  "description": "App attribution for the per-app quota.",
                  "type": "string"
                },
                "fields": {
                  "description": "For start: keep only these top-level fields of each state.",
                  "type": "array"
                },
                "gates": {
                  "description": "What the answers decide.",
                  "type": "string"
                },
                "items": {
                  "description": "For start: [{ subject, state }].",
                  "type": "array"
                },
                "keys": {
                  "description": "For start: owner memory keys; each record's value is one state. A key the node reads to decide what it does (its AI and decision keys, a payout record) is refused.",
                  "type": "array"
                },
                "names": {
                  "description": "Extra person names to remove before sending.",
                  "type": "array"
                },
                "prefix": {
                  "description": "For start: every owner record under this key prefix, less the records the node reads to decide what it does.",
                  "type": "string"
                },
                "provider": {
                  "description": "For start: the decision provider every item is asked on. Leave out to let the node pick.",
                  "type": "string"
                },
                "questions": {
                  "description": "For start: the questions, as for aimeat_decide. Leave out when `rule` is given.",
                  "type": "object"
                },
                "rule": {
                  "description": "For start: one of the owner's decision rules, in place of questions, thresholds and gates. Each result then carries the rule's outcome.",
                  "type": "string"
                },
                "run_id": {
                  "description": "The run, for get, resume and stop.",
                  "type": "string"
                },
                "thresholds": {
                  "description": "The thresholds you will apply.",
                  "type": "object"
                }
              },
              "required": [
                "action"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_decide_settings",
            "description": "Read the owner's decision-model settings: whether the operator has it on, the pinned model version, whether the owner has their own TypeSafe key or the node's key pays, and which classes of personal data the owner lets leave unscrubbed. It never shows a key. For an agent it also says whether the owner gave THIS agent a key of its own, the NAME of the environment variable that holds that key where the agent runs its own calls (never the key), its daily cap, and whether its gate is on. When the model cannot be used the answer says what to set and where, and `setup_order` gives the one order everything is set up in. `providers` lists every decision provider the owner may use, each with where it runs (`kind`: hosted or local), what it can carry (`limits`), its price, whether the data leaves the machine and a sentence saying where it goes; `default` is the owner's choice and `this_agent` the one you get. Nothing here can change them: the owner changes the key and the data policy on the AI settings page, because they decide what the scrubber lets through.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_decision_list",
            "description": "Read what the decision model decided for this owner, newest first: the model version that answered, the questions as sent, every answer with its probabilities, the thresholds in force, what it gated, whether a person reviewed it, and what personal data was removed first. Give `decision_id` for one decision, or filter by `subject` to answer \"what did an AI decide about this record\".",
            "inputSchema": {
              "properties": {
                "app_id": {
                  "description": "Only decisions made for this app.",
                  "type": "string"
                },
                "before": {
                  "description": "Only decisions made before this ISO time (paging cursor: the createdAt of the last one you have).",
                  "type": "string"
                },
                "decision_id": {
                  "description": "Read one decision.",
                  "type": "string"
                },
                "limit": {
                  "description": "How many (1-200, default 50).",
                  "type": "number"
                },
                "principal": {
                  "description": "Only decisions one principal asked for: an agent's full identity, e.g. \"bot#alice@node-id\".",
                  "type": "string"
                },
                "provider": {
                  "description": "Only decisions one decision provider answered (its id).",
                  "type": "string"
                },
                "rule": {
                  "description": "Only decisions one decision rule made (its id).",
                  "type": "string"
                },
                "stats_by": {
                  "description": "Return the QUALITY NUMBERS instead of the decisions, counted by the node: \"rule\" gives one group per decision rule, \"principal\" one per asker, \"provider\" one per decision provider. Each group is { key, decisions, outcomes: { act, ask, stop }, gateStops, overridden, confirmed, costUsd, lastAt }. `rule`, `principal` and `provider` narrow what is counted. This is what thresholds are tuned from.",
                  "enum": [
                    "rule",
                    "principal",
                    "provider"
                  ],
                  "type": "string"
                },
                "subject": {
                  "description": "Only decisions about this subject.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_decision_review",
            "description": "Record that a person looked at a decision and confirmed it or overrode it. This is the one change a decision record accepts, and it is what makes the record say whether a human was in the loop. Record it when the person actually decided, not on their behalf. A decision you asked for yourself is refused with OWN_DECISION: the owner reviews it, in person or through another of their agents. The review names you as the one who recorded it.",
            "inputSchema": {
              "properties": {
                "decision_id": {
                  "description": "The decision.",
                  "type": "string"
                },
                "note": {
                  "description": "Why, in the person's words.",
                  "type": "string"
                },
                "outcome": {
                  "description": "confirmed | overridden",
                  "enum": [
                    "confirmed",
                    "overridden"
                  ],
                  "type": "string"
                },
                "override": {
                  "description": "What the person decided instead, when overridden.",
                  "type": "object"
                }
              },
              "required": [
                "decision_id",
                "outcome"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_designbook_adopt",
            "description": "Take one part for one of your own Atelier apps. A COMPONENT is taken BEFORE the app exists: the answer carries `snippet` { html, css, use, prefix }, two texts to build into your page and how to wire them (a component carries no script), nothing is written and the app need not be published yet; name it in your page's build notes (`took`) and the publish counts it as used. A component whose stored markup or stylesheet no longer passes the bench is refused with the bench's reason. Every other kind goes into a PUBLISHED app through the same validated, versioned write every layout takes; the app renders it on its next open. A layout or fill REPLACES the app's stored arrangement (the replaced one is archived, so putting it back is one restore). A look, motion recipe, illustration style or ambient MERGES into the arrangement the app already has — an ambient lands as its `ambient` with its tokens beside the existing ones, never its look, and is proven again on the app's own look — and refuses with words when there is no arrangement to season. A genre is never adopted: it is forked from its template, and the refusal carries the address. Published parts are adoptable by anyone; a proposed one only by its own proposer. Adopting counts as usage — it is the signal that keeps a part alive. If a model generated or substantially rewrote this content, declare it in `ai_provenance` (level, and human_involvement if a person reviewed the substance). If you are relaying text a person wrote, say so with level:\"original\" — silence is recorded as model-written.",
            "inputSchema": {
              "properties": {
                "ai_provenance": {
                  "description": "How this content was made: { level, method?, human_involvement?, model?, provider?, sources?, notes? }. `level` is required when the block is present: original | assisted | synthesized | ai-generated. `model` is YOUR OWN model id as your provider names it (self-identify, never ask the person); without it the record cannot say which model made this. `human_involvement` (none | light-review | editorial-control | full-human) counts only a step where a person read the SUBSTANCE and could reject it; omitted means none. The node fills in who you are, which node, when, and a hash of the exact bytes — those are never taken from the caller.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "Attach an EXISTING provenance record instead of declaring a new one — the id the node returned when it generated this content for you. Only your own records can be attached.",
                  "type": "string"
                },
                "filename": {
                  "description": "Your published app file the layout lands in, e.g. \"errands.html\".",
                  "type": "string"
                },
                "id": {
                  "description": "The part to adopt.",
                  "type": "string"
                }
              },
              "required": [
                "id",
                "filename"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_designbook_get",
            "description": "Read one Design Book part whole: its body is exactly what an adopt writes into an app — a layout or fill whole; a look's or motion's tokens and preset; an illustration's style; an ambient's preset, alpha, speed, the look it was proven on and its tokens; a genre's template id, which is forked rather than adopted — so reading it IS the preview. The answer carries the part, its record version (its evolution is the version history), its adoption count, and `reasons`: how often builders TOOK it, in how many apps an owner was then satisfied with (`kept`, the number to trust), how often it was passed over, and the reason each builder gave, the ones for leaving it included. Read those before you choose it, and read them as accounts, not measurements. A COMPONENT also answers `bench`: { passes: true }, or { passes: false, why, note } when its stored markup or stylesheet no longer passes the bench this node runs. Such a component cannot be taken, and its html and css are shown only to its proposer, who needs them to fix it and propose it again under the same id.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "The part id, from the search.",
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_designbook_keep",
            "description": "Record that the OWNER is satisfied with one of their apps: it turned out well and they mean to keep it. Call it when they say so, in whatever words, and never because a build finished: an app is often rebuilt before anybody likes it, and a finished build that gets thrown away must not teach the Design Book anything. It marks the reasons that app's live version wrote down (what it took from the Book, what it passed over, what it made by hand) as coming from an app somebody was satisfied with, which is the one number about a part that says more than \"an AI favoured it\". The answer lists what that version made by hand, which is what is now worth offering to the next builder. `kept: false` takes it back. The app must carry build notes (\u003cscript type=\"application/json\" id=\"aimeat-build-notes\"\u003e); one that carries none is answered with how to add them.",
            "inputSchema": {
              "properties": {
                "filename": {
                  "description": "The published app the owner is satisfied with, e.g. \"habits.html\". It must belong to your owner.",
                  "type": "string"
                },
                "kept": {
                  "description": "false takes it back. Default true.",
                  "type": "boolean"
                }
              },
              "required": [
                "filename"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_designbook_propose",
            "description": "Propose a part into the Design Book, or update one you already proposed. The bench runs BEFORE anything lands, per kind: the layout validator every app layout passes (layout, fill), the signature-token bench with the contrast-matrix pair proof (look, motion), the imagery-style bench (illustration), the template registry (genre), and the ambient bench, which proves the preset on the part's look through the contrast matrix so a layer too loud for its ground refuses with numbers (ambient). A refusal carries the validator's words with the nearest real name. A new part lands as `proposed` — publishing it into the shared catalogue is the node operator's call. A part id is a node-wide address: once someone holds it, it is theirs, and updating your own re-runs the bench and flows as a minor to later adopts. A COMPONENT is the ninth kind and the one the Book grows by: what an app made by hand because the Book had nothing for it, offered to the next builder as { prefix, html, css, use, judgement: { reach: \"general\" | \"special\", why }, from_app? }. It is markup and a stylesheet and NO script (its preview is served from this node, so script in it would be anybody's code running as the node; the app that takes it wires the behaviour); every class starts with its prefix; the markup closes every element it opens, and the stylesheet every block, bracket, comment and string, because one left open takes in whatever the page writes after it; a rule nested inside another starts with \"\u0026\" (\"\u0026 .\u003cprefix\u003e-cell { … }\", \"\u0026:hover { … }\"); the stylesheet reaches only the component, so the at-rules it may carry are a list: @media, @supports, @container and @starting-style, which condition its own rules, and @keyframes, @property, @counter-style, @font-palette-values, @position-try, @function and @font-feature-values under a name that starts with its prefix (\"@keyframes \u003cprefix\u003e-spin\", \"@property --\u003cprefix\u003e-x\"), because the whole page shares that name, with the blocks of @font-feature-values (@styleset, @swash, …) inside it and a @function's parameters named without types, defaults or \"returns\", which the bench's CSS parser cannot read; every other at-rule, @scope, @layer, @page, @view-transition and @import among them, is refused; a declaration that names a counter, an anchor, a view transition or a timeline (counter-reset, counter-set, counter-increment, anchor-name, view-transition-name, the timeline names and timeline-scope) names only its own, under the prefix (\"counter-increment: \u003cprefix\u003e-step\"), or none, as the word itself and never through var(), and \"all\" takes only unset, initial, revert or revert-layer; an animation, counter style, counter or anchor the page defines is still used by its name; a list item stays inside a list of the component, because a browser numbers any other as an item of the page's own list: an \u003cli\u003e stands only inside a \u003cul\u003e or \u003col\u003e, no display holds list-item or is written through var() or inherit, and where the markup carries a \u003csummary\u003e every counter-increment also writes \"list-item 0\"; where it carries a \u003cul\u003e or \u003col\u003e, every counter-reset also names list-item and \"all\" takes only revert or revert-layer, because a counter-reset replaces the list's own reset, and only there does list-item pass in a counter-reset; every colour is a var(--ak-…) token, so it wears whatever page it lands in. YOU JUDGE ITS REACH, honestly: \"general\" when another kind of app would use it, \"special\" when it belongs to one app, with the reason. A general component whose from_app is an app the owner said turned out well (aimeat_designbook_keep) is PUBLISHED BY ITSELF, with no person in between; any other stays proposed, listed and usable by you, and the answer says which and why. A GENRE CAN GROW OUT OF AN APP the same way: a published page with a look of its own (its head says aimeat-register \"custom:\u003cname\u003e\") is proposed as kind \"genre\", id \"genre-\u003cname\u003e\", body { app: { owner, filename }, judgement: { reach, why } }, naming YOUR OWN app. A general one is published by itself when its owner said the app turned out well AND opened it for forking, which only the owner can do, because a genre hands the page's source to every builder; it is then forked with aimeat_app_template_get like any genre, and it stops being offered the moment the app is deleted, parked or closed for forking. If a model generated or substantially rewrote this content, declare it in `ai_provenance` (level, and human_involvement if a person reviewed the substance). If you are relaying text a person wrote, say so with level:\"original\" — silence is recorded as model-written.",
            "inputSchema": {
              "properties": {
                "ai_provenance": {
                  "description": "How this content was made: { level, method?, human_involvement?, model?, provider?, sources?, notes? }. `level` is required when the block is present: original | assisted | synthesized | ai-generated. `model` is YOUR OWN model id as your provider names it (self-identify, never ask the person); without it the record cannot say which model made this. `human_involvement` (none | light-review | editorial-control | full-human) counts only a step where a person read the SUBSTANCE and could reject it; omitted means none. The node fills in who you are, which node, when, and a hash of the exact bytes — those are never taken from the caller.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "Attach an EXISTING provenance record instead of declaring a new one — the id the node returned when it generated this content for you. Only your own records can be attached.",
                  "type": "string"
                },
                "part": {
                  "description": "The part: { id, kind: \"layout\"|\"fill\"|\"look\"|\"motion\"|\"illustration\"|\"genre\"|\"ambient\"|\"effect\"|\"component\", title, summary, body, tags? }. A COMPONENT has body { prefix, html, css, use, judgement: { reach: \"general\"|\"special\", why }, from_app? }: markup that closes every element it opens and a stylesheet under one class prefix that closes every block, bracket, comment and string it opens (a nested rule starts with \"\u0026\"; the only at-rules are @media, @supports, @container and @starting-style, and @keyframes, @property, @counter-style, @font-palette-values, @position-try, @function and @font-feature-values under a name that starts with the prefix, with the blocks of @font-feature-values inside it and the parameters of a @function untyped; a counter, anchor, view transition or timeline a declaration names starts with the prefix too, as the word itself, never through var(); an \u003cli\u003e stands only inside a \u003cul\u003e or \u003col\u003e, no display holds list-item, and with a \u003csummary\u003e in the markup every counter-increment also writes list-item 0; with a \u003cul\u003e or \u003col\u003e in the markup every counter-reset also names list-item and all takes only revert or revert-layer), every colour a var(--ak-…) token, NO script. The kind decides the body: a whole mosaic layout, the vocabulary aimeat_app_manage action \"ui_get\" hands you (layout, fill); { tokens, look? } (look); { tokens } of motion tokens only (motion); { style, palette_words? } (illustration); { template } naming a served genre template, or { app: { owner, filename }, judgement: { reach, why } } naming your own published page whose look is its own (genre); { ambient: waves|aurora|dust|grid|static|ink, alpha?, speed?, look?, tokens? } (ambient — \"none\" is an arrangement's choice, never a part).",
                  "type": "object"
                }
              },
              "required": [
                "part"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_designbook_search",
            "description": "Browse the Design Book: the node's shared library of proven parts. Each row is a part — `layout` (a complete Atelier mosaic arrangement), `fill` (the same shape with \u003cplaceholder\u003e slots, a starting shape), `look` (a signature token sheet with an optional preset), `motion` (a motion-token recipe), `illustration` (art direction for the imagery pipeline), `genre` (one of the node's served page templates, shown and forked rather than adopted) or `ambient` (the one layer allowed to move at idle: a preset with its alpha and speed, proven on a look) — with its title, what it is for, lifecycle status and how many builds have adopted it. Published parts are what everyone builds from; proposed ones are still earning it. Filter by kind, status or a word. CALLED WITH NOTHING it answers the whole published Book on one page of text, every part on a line under its kind: start there when you do not know yet what the Book holds. With view \"reasons\" it answers what builders WROTE DOWN about the Book, as the list of what it should become next: the things made by hand because the Book had nothing for them, and the parts most often looked at and left, each with the reasons given. A component whose stored markup or stylesheet no longer passes the bench this node runs is left out of the rows and the page, because nobody can take it.",
            "inputSchema": {
              "properties": {
                "kind": {
                  "description": "Only this part kind: layout, fill, look, motion, illustration, genre, ambient, effect or component.",
                  "type": "string"
                },
                "limit": {
                  "description": "Rows to return, 1-200. Default 50.",
                  "type": "number"
                },
                "q": {
                  "description": "A word matched against id, title, summary and tags.",
                  "type": "string"
                },
                "status": {
                  "description": "Only this lifecycle state: proposed, published, aging or retired. Omit for all.",
                  "type": "string"
                },
                "view": {
                  "description": "\"reasons\": what builders wrote down about the Book, as the list of what it should become next. \"map\": the whole published Book on one page (also what calling with nothing answers). Omit it to search rows.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_discover",
            "description": "Master directory — discover what exists across the WHOLE node from one place: capabilities, workflows, knowledge, decisions, research, produced material, companies + offerings, live documents, apps, and memory. Two modes: mode=\"map\" returns a cheap catalog-of-catalogs (counts by type/segment/tag) so you can see WHAT exists before pulling content; mode=\"find\" (default) returns ranked, faceted entries. Filter with q (free text), type (CSV of types), tags (CSV — an entry must carry ALL), segment (CSV). scope: \"own\" (your owner's reachable content, default), \"public\" (public content node-wide), \"shared\" (content in organisms you belong to that you are allowed to read). Prefer this over the per-domain search tools (aimeat_memory_search / _catalogue_search / _knowledge_list / _capabilities_list) when you do not yet know which domain holds what you need.",
            "inputSchema": {
              "properties": {
                "limit": {
                  "description": "Max entries to return (default 20, max 100).",
                  "type": "number"
                },
                "mode": {
                  "description": "\"find\" (default) returns entries; \"map\" returns only facet counts (cheap probe).",
                  "enum": [
                    "map",
                    "find"
                  ],
                  "type": "string"
                },
                "q": {
                  "description": "Free-text query. Omit to browse by filters only.",
                  "type": "string"
                },
                "scope": {
                  "description": "own (default), public, or shared.",
                  "enum": [
                    "own",
                    "public",
                    "shared"
                  ],
                  "type": "string"
                },
                "segment": {
                  "description": "CSV of segments (coarse area within a type) to include.",
                  "type": "string"
                },
                "tags": {
                  "description": "CSV of tags; an entry must carry ALL of them.",
                  "type": "string"
                },
                "type": {
                  "description": "CSV of types: capability, workflow, knowledge, decision, research, material, company, offering, document, organism, app, tool, template, skill, designbook, memory.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_dm_archive_as_owner",
            "description": "Archive conversations in the OWNER's Messages list, as the owner, or bring them back with restore: true. Use it when the human asks you to tidy their inbox: \"archive my agents' coordination threads\", \"put those announcements away\". Nothing is deleted. An archived conversation moves to the Archive section at the bottom of the list, and comes back by itself when somebody other than the owner's own agents writes in it; one of their agents writing (an acknowledgement, a heartbeat) leaves it archived. Restoring keeps a conversation in the list, so no rule and no age limit archives it again on its own. Get conversation ids from aimeat_dm_inbox_as_owner, whose rows say which section each is in. The list is always your OWN owner's (derived server-side). Tell the human what you archived. Requires the messages:organize-as-owner scope, which the owner grants on its own tick (\"Full access\" does not carry it); without it this tool is not available.",
            "inputSchema": {
              "properties": {
                "conversation_ids": {
                  "description": "Conversation ids to archive or restore (1-500), from aimeat_dm_inbox_as_owner.",
                  "type": "array"
                },
                "restore": {
                  "description": "true brings the conversations back to the list instead of archiving them.",
                  "type": "boolean"
                }
              },
              "required": [
                "conversation_ids"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_dm_ask",
            "description": "Ask a person a STRUCTURED question through the federated inbox — a federated AskUserQuestion. Instead of free text, you send option-based questions the human answers by tapping choices (radio for single-select, checkboxes for multiSelect) plus an always-available \"Other\" freeform, then Send. Use this to map intent / clarify BEFORE acting. Send one or more questions; for adaptive follow-ups, send another aimeat_dm_ask after reading the answer. The answer comes back as a normal reply you read via aimeat_dm_inbox / aimeat_dm_thread, where interactive.answers is the machine-readable result keyed by your question id. Same recipients + threading as aimeat_dm_send. Requires the messages:send scope. If a model generated or substantially rewrote this content, declare it in `ai_provenance` (level, and human_involvement if a person reviewed the substance). If you are relaying text a person wrote, say so with level:\"original\" — silence is recorded as model-written.",
            "inputSchema": {
              "properties": {
                "ai_provenance": {
                  "description": "How this content was made: { level, method?, human_involvement?, model?, provider?, sources?, notes? }. `level` is required when the block is present: original | assisted | synthesized | ai-generated. `model` is YOUR OWN model id as your provider names it (self-identify, never ask the person); without it the record cannot say which model made this. `human_involvement` (none | light-review | editorial-control | full-human) counts only a step where a person read the SUBSTANCE and could reject it; omitted means none. The node fills in who you are, which node, when, and a hash of the exact bytes — those are never taken from the caller.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "Attach an EXISTING provenance record instead of declaring a new one — the id the node returned when it generated this content for you. Only your own records can be attached.",
                  "type": "string"
                },
                "body": {
                  "description": "Optional intro text shown above the questions (GFM markdown).",
                  "type": "string"
                },
                "conversation_id": {
                  "description": "Continue a specific existing thread by id.",
                  "type": "string"
                },
                "questions": {
                  "description": "1–20 questions, each { id, header (short chip), prompt, options:[{id,label}], multiSelect?, allowOther? (default true), required? }.",
                  "type": "array"
                },
                "subject": {
                  "description": "Open a NEW topic thread with this title (else the default thread / conversation_id).",
                  "type": "string"
                },
                "submit_label": {
                  "description": "Optional label for the submit button (default localized \"Send answers\").",
                  "type": "string"
                },
                "to": {
                  "description": "Recipient: owner@node, agent#owner@node, or eco:app#owner@node.",
                  "type": "string"
                }
              },
              "required": [
                "to",
                "questions"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_dm_broadcast",
            "description": "Tell MANY people or agents the same thing in ONE call, instead of looping aimeat_dm_send. Every copy is an ordinary 1:1 thread the recipient can answer privately, and every copy carries one shared broadcast id — which is what lets their inbox fold the copies into a single row instead of one row per recipient. Use this for an announcement, a status notice, or a question put to a whole fleet; use aimeat_dm_send when you are writing to one person. `subject` titles the thread each recipient sees, so name the actual thing. `mode` \"announcement\" makes the copies read-only (nobody can reply); \"broadcast\" (the default) lets each recipient answer you in their own thread. Recipients come from `to` (a list), `group_id` (a Share Group as a distribution list), or `audience` (every human on this node, or across the federation — operator only). The reply is a broadcast_id you read results with. Requires the messages:send scope. If a model generated or substantially rewrote this content, declare it in `ai_provenance` (level, and human_involvement if a person reviewed the substance). If you are relaying text a person wrote, say so with level:\"original\" — silence is recorded as model-written.",
            "inputSchema": {
              "properties": {
                "ai_provenance": {
                  "description": "How this content was made: { level, method?, human_involvement?, model?, provider?, sources?, notes? }. `level` is required when the block is present: original | assisted | synthesized | ai-generated. `model` is YOUR OWN model id as your provider names it (self-identify, never ask the person); without it the record cannot say which model made this. `human_involvement` (none | light-review | editorial-control | full-human) counts only a step where a person read the SUBSTANCE and could reject it; omitted means none. The node fills in who you are, which node, when, and a hash of the exact bytes — those are never taken from the caller.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "Attach an EXISTING provenance record instead of declaring a new one — the id the node returned when it generated this content for you. Only your own records can be attached.",
                  "type": "string"
                },
                "attachments": {
                  "description": "Up to 20 attachment descriptors { storage_key, mime, kind, size, name }, each pre-uploaded via aimeat_storage_upload.",
                  "type": "array"
                },
                "audience": {
                  "description": "\"node-users\" (every human on this node) or \"federation-users\" (that plus every owner on each active peer). OPERATOR ONLY.",
                  "type": "string"
                },
                "body": {
                  "description": "Message body (GFM markdown). Optional only if you attach a file or send questions.",
                  "type": "string"
                },
                "group_id": {
                  "description": "A Share Group whose members are the audience — a reusable distribution list.",
                  "type": "string"
                },
                "interactive": {
                  "description": "A question set { role:\"questions\", v:1, questions:[…] } — makes it a poll fanned out to everyone.",
                  "type": "object"
                },
                "mode": {
                  "description": "\"broadcast\" (default, each recipient can reply) or \"announcement\" (read-only, replies disabled).",
                  "type": "string"
                },
                "subject": {
                  "description": "Titles the thread each recipient sees. Without it the copies land in the nameless per-pair thread.",
                  "type": "string"
                },
                "to": {
                  "description": "Recipient identities (owner@node, agent#owner@node, eco:app#owner@node), up to 500.",
                  "type": "array"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_dm_delete_as_owner",
            "description": "Remove one message from the OWNER's mailbox, as the owner — the same delete a person makes from the Messages page. Use it when the human asks you to clear something out of their inbox: a thread they are done with, a message they do not want kept. It removes the owner's copy only; the other side keeps theirs, and there is no undo, so name what you are about to remove and let them say yes before you call this. The mailbox is always your OWN owner's (derived server-side), so you can never reach another account's messages. Requires the messages:delete-as-owner scope, which the owner grants on its own tick — \"Full access\" does not carry it, and without it this tool is not available and you should hand back the message id for the owner to remove themselves.",
            "inputSchema": {
              "properties": {
                "message_id": {
                  "description": "Id of the message to remove, from aimeat_dm_inbox or aimeat_dm_thread.",
                  "type": "string"
                }
              },
              "required": [
                "message_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_dm_inbox",
            "description": "Read recent federated direct messages addressed to THIS agent (across the inbox / \"Postilaatikko\") — replies and messages people sent you, newest first. A reply to an agent is delivered to its owner's inbox, so this lists messages where you are the recipient. Each item has id, conversation_id, subject, from, body, attachments, interactive (a question spec or the human's answers) and created_at. Use aimeat_dm_thread for a full conversation. Distinct from aimeat_message_inbox (the agent↔owner dashboard channel). Requires the messages:read scope.",
            "inputSchema": {
              "properties": {
                "page": {
                  "description": "Page number (default 1).",
                  "type": "number"
                },
                "per_page": {
                  "description": "Messages per page (default 20, max 100).",
                  "type": "number"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_dm_inbox_as_owner",
            "description": "Read the OWNER's own mailbox, as the owner: their conversations newest first, each with the other party, the last message and how many are unread, plus the first-contact requests waiting for them and a display name for everyone listed. Use it when the human asks what is in their inbox, or before you reply for them, to find the thread. aimeat_dm_inbox is different: it reads the messages sent to YOU. This shows the owner's own threads only (not the threads their other agents had), and reading marks nothing as read. The mailbox is always your OWN owner's (derived server-side). Requires the messages:read-as-owner scope, which the owner grants on its own tick (\"Full access\" does not carry it); without it this tool is not available.",
            "inputSchema": {
              "properties": {
                "limit": {
                  "description": "At most this many conversations, newest first (default 30, max 200). conversations_total says how many there are.",
                  "type": "number"
                },
                "unread_only": {
                  "description": "Only conversations with something unread.",
                  "type": "boolean"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_dm_organize_as_owner",
            "description": "Read or change how the OWNER's Messages list is organised, as the owner. Called with nothing, it returns the current settings and rules. The list has sections: people, the owner's own agents (conversations between the owner and their agents, and between those agents), one heading per group rule, and the archive. auto_archive_enabled and auto_archive_days archive the own agents' conversations after that many days without a message, unless a message to the owner in them is unread (on by default, 14 days). fold_same_subject shows conversations that one sender opened with the same subject within an hour as one row; a conversation somebody answered gets its own row back, except between the owner's own agents. add_rule adds a rule { name, action, match }: action \"fold\" makes the matching conversations one row, \"group\" puts them under a heading of their own (the rule's name), \"archive\" sends them to the archive; match takes with (part of an identity in the conversation), subject (text the subject contains), body (text the newest message contains), older_than_days, and scope \"agents\" (default: only the own agents' conversations) or \"all\". The first enabled rule that matches decides. An archived conversation comes back when somebody other than the owner's own agents writes in it after the rule was made. Give add_rule an existing id to edit that rule; remove_rule takes an id; rules replaces the whole list. Say what you changed in words the human uses. The list is always your OWN owner's. Requires the messages:organize-as-owner scope, which the owner grants on its own tick (\"Full access\" does not carry it).",
            "inputSchema": {
              "properties": {
                "add_rule": {
                  "description": "A rule { id?, name, enabled?, action: \"fold\" | \"group\" | \"archive\", match: { with?, subject?, body?, scope?: \"agents\" | \"all\", older_than_days? } }.",
                  "type": "object"
                },
                "auto_archive_days": {
                  "description": "Days without a message before that happens (1-365).",
                  "type": "number"
                },
                "auto_archive_enabled": {
                  "description": "Archive the own agents' conversations by age.",
                  "type": "boolean"
                },
                "fold_same_subject": {
                  "description": "One row for conversations one sender opened with the same subject within an hour.",
                  "type": "boolean"
                },
                "remove_rule": {
                  "description": "Id of a rule to remove.",
                  "type": "string"
                },
                "rules": {
                  "description": "Replace every rule with this list (same shape as add_rule).",
                  "type": "array"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_dm_send",
            "description": "Send a direct message across the AIMEAT federation FROM this agent TO any person (owner@node), agent (agent#owner@node) or app (eco:app#owner@node) — this is the federation-wide inbox (\"Postilaatikko\"), NOT the agent↔owner channel (that is aimeat_message_send). The recipient sees it is from you, the agent. A message to an agent/app is delivered to that identity's owner inbox. First contact lands in the recipient's requests until they accept. To attach files (up to 20): first upload each via aimeat_storage_upload (presigned — MCP cannot carry the bytes), then pass the returned { storage_key, mime, kind, size, name } in attachments. Requires the messages:send scope. If a model generated or substantially rewrote this content, declare it in `ai_provenance` (level, and human_involvement if a person reviewed the substance). If you are relaying text a person wrote, say so with level:\"original\" — silence is recorded as model-written.",
            "inputSchema": {
              "properties": {
                "ai_provenance": {
                  "description": "How this content was made: { level, method?, human_involvement?, model?, provider?, sources?, notes? }. `level` is required when the block is present: original | assisted | synthesized | ai-generated. `model` is YOUR OWN model id as your provider names it (self-identify, never ask the person); without it the record cannot say which model made this. `human_involvement` (none | light-review | editorial-control | full-human) counts only a step where a person read the SUBSTANCE and could reject it; omitted means none. The node fills in who you are, which node, when, and a hash of the exact bytes — those are never taken from the caller.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "Attach an EXISTING provenance record instead of declaring a new one — the id the node returned when it generated this content for you. Only your own records can be attached.",
                  "type": "string"
                },
                "attachments": {
                  "description": "Up to 20 attachment descriptors { storage_key, mime, kind, size, name }, each pre-uploaded via aimeat_storage_upload.",
                  "type": "array"
                },
                "body": {
                  "description": "Message body (GFM markdown). Optional only if you attach ≥1 file.",
                  "type": "string"
                },
                "conversation_id": {
                  "description": "Continue a specific existing thread by its id: the one a send returned, or one from aimeat_dm_inbox.",
                  "type": "string"
                },
                "reply_to": {
                  "description": "Id of a message you are replying to (keeps the same thread).",
                  "type": "string"
                },
                "subject": {
                  "description": "Open a NEW topic thread with this title, instead of one endless thread with the recipient. Give one when you write to support@operators, so the operators see what the thread is about.",
                  "type": "string"
                },
                "to": {
                  "description": "Recipient: owner@node, agent#owner@node, or eco:app#owner@node.",
                  "type": "string"
                }
              },
              "required": [
                "to"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_dm_send_as_owner",
            "description": "Send a federated direct message AS THE OWNER (a consented delegation), not as your own agent identity — this is how you reply to the owner's \"Postilaatikko\" conversations on their behalf so the reply comes FROM the owner, in the owner's existing thread. The recipient sees it as from the owner (the human), exactly as if they had sent it from the AIMEAT UI. Requires the messages:send-as-owner scope, which the owner grants explicitly; without it this tool is not available and you should hand the drafted reply back for the owner to send themselves. The sender is always your OWN owner (derived server-side) — you can never send as anyone else. Pass the owner's conversation_id (from the reply context) so it lands in the right thread. Attach files via aimeat_storage_upload first. Prefer this over aimeat_dm_send when the human asked you to reply for them. If a model generated or substantially rewrote this content, declare it in `ai_provenance` (level, and human_involvement if a person reviewed the substance). If you are relaying text a person wrote, say so with level:\"original\" — silence is recorded as model-written.",
            "inputSchema": {
              "properties": {
                "ai_provenance": {
                  "description": "How this content was made: { level, method?, human_involvement?, model?, provider?, sources?, notes? }. `level` is required when the block is present: original | assisted | synthesized | ai-generated. `model` is YOUR OWN model id as your provider names it (self-identify, never ask the person); without it the record cannot say which model made this. `human_involvement` (none | light-review | editorial-control | full-human) counts only a step where a person read the SUBSTANCE and could reject it; omitted means none. The node fills in who you are, which node, when, and a hash of the exact bytes — those are never taken from the caller.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "Attach an EXISTING provenance record instead of declaring a new one — the id the node returned when it generated this content for you. Only your own records can be attached.",
                  "type": "string"
                },
                "attachments": {
                  "description": "Up to 20 attachment descriptors { storage_key, mime, kind, size, name }, each pre-uploaded via aimeat_storage_upload.",
                  "type": "array"
                },
                "body": {
                  "description": "Message body (GFM markdown). Optional only if you attach ≥1 file.",
                  "type": "string"
                },
                "conversation_id": {
                  "description": "The owner's existing thread with the recipient, so the reply lands there.",
                  "type": "string"
                },
                "reply_to": {
                  "description": "Id of a message you are replying to (keeps the same thread).",
                  "type": "string"
                },
                "subject": {
                  "description": "Open a NEW topic thread with this title (else the default thread / conversation_id).",
                  "type": "string"
                },
                "to": {
                  "description": "Recipient: owner@node, agent#owner@node, or eco:app#owner@node.",
                  "type": "string"
                }
              },
              "required": [
                "to"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_dm_thread",
            "description": "Read a full federated direct-message thread as THIS agent sees it (your sent messages + the messages addressed to you), oldest-first, for one conversation_id (from aimeat_dm_inbox or aimeat_dm_send). Requires the messages:read scope.",
            "inputSchema": {
              "properties": {
                "conversation_id": {
                  "description": "Conversation id to read.",
                  "type": "string"
                },
                "page": {
                  "description": "Page number (default 1).",
                  "type": "number"
                },
                "per_page": {
                  "description": "Messages per page (default 50, max 200).",
                  "type": "number"
                }
              },
              "required": [
                "conversation_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_dm_thread_as_owner",
            "description": "Read one conversation from the OWNER's own mailbox, as the owner, oldest first: every message the owner sent and received in it, with attachments and how each message was made. Use it to read the thread you are about to answer with aimeat_dm_send_as_owner, so the reply fits what was already said. Get the conversation_id from aimeat_dm_inbox_as_owner or from the reply context. Reading marks nothing as read. The mailbox is always your OWN owner's (derived server-side). Requires the messages:read-as-owner scope, which the owner grants on its own tick (\"Full access\" does not carry it); without it this tool is not available.",
            "inputSchema": {
              "properties": {
                "conversation_id": {
                  "description": "The owner's conversation id.",
                  "type": "string"
                },
                "page": {
                  "description": "Page number (default 1).",
                  "type": "number"
                },
                "per_page": {
                  "description": "Messages per page (default 50, max 200).",
                  "type": "number"
                }
              },
              "required": [
                "conversation_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_exchange_accept",
            "description": "Accept a contract on an offering → mint a durable METERED ENTITLEMENT for YOU (the caller's own identity is the consumer — you can never accept on someone else's behalf). The per-call PRICE is read AUTHORITATIVELY from the provider's extension action, so you cannot undercut the provider or be charged a price you did not accept; you choose only your BUDGET cap (your own spend ceiling) and a contract ref. Re-accepting the same capability carries prior spend forward (renegotiation, not a meter reset). Morsels are integers; money is 6-decimal micro-units. After this, calling /v1/ext/{ext}/{action} is metered against the budget.",
            "inputSchema": {
              "properties": {
                "action": {
                  "description": "The action id on that extension (must be priced).",
                  "type": "string"
                },
                "app_id": {
                  "description": "The consuming app id (\"owner/filename\") when this contract powers an app — shown on the per-app cost view.",
                  "type": "string"
                },
                "cap_units": {
                  "description": "Budget ceiling in the action's unit (morsels or money micro-units). Must cover one charge. Omit = uncapped.",
                  "type": "number"
                },
                "contract_ref": {
                  "description": "Your reference for this contract. Omit to auto-generate one (mcp:\u003cuuid\u003e).",
                  "type": "string"
                },
                "ext": {
                  "description": "The provider extension name.",
                  "type": "string"
                },
                "plan_id": {
                  "description": "A provider-declared plan id (bundle/subscription). Omit = per_call.",
                  "type": "string"
                }
              },
              "required": [
                "ext",
                "action"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_exchange_bid",
            "description": "Bid on an open NEED with an action YOUR OWN extension provides (you must own the extension — pricing stays authoritative from your action). Optionally link an existing `offering_id`, pick a `plan_id`, and add a `note`. The requester accepts one bid (aimeat_exchange_bid_accept), which mints the entitlement with you as provider.",
            "inputSchema": {
              "properties": {
                "action": {
                  "description": "The action id on your extension.",
                  "type": "string"
                },
                "ext": {
                  "description": "Your extension name (you must own it).",
                  "type": "string"
                },
                "need_id": {
                  "description": "The open need id (e.g. \"need-…\").",
                  "type": "string"
                },
                "note": {
                  "description": "A note to the requester.",
                  "type": "string"
                },
                "offering_id": {
                  "description": "Link an existing offering of yours.",
                  "type": "string"
                },
                "plan_id": {
                  "description": "A plan id declared on your action (bundle/subscription).",
                  "type": "string"
                }
              },
              "required": [
                "need_id",
                "ext",
                "action"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_exchange_bid_accept",
            "description": "As the NEED's requester, accept a bid → mint the metered entitlement (consumer = you, provider = the bidder). Price + unit are read authoritatively from the bidder's action; you may set `cap_units` (defaults to the need's budget cap). Marks the bid accepted and the need matched.",
            "inputSchema": {
              "properties": {
                "bid_id": {
                  "description": "The open bid to accept.",
                  "type": "string"
                },
                "cap_units": {
                  "description": "Budget ceiling for the minted contract (defaults to the need's budget cap).",
                  "type": "number"
                },
                "need_id": {
                  "description": "Your need id.",
                  "type": "string"
                }
              },
              "required": [
                "need_id",
                "bid_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_exchange_consumers",
            "description": "Provider data-lineage for one of YOUR offerings: who holds a contract against it, how many calls they made, how much settled, contract state, and last use — \"where is my data used, by whom, and how much?\". Provider-only (you must own the offering).",
            "inputSchema": {
              "properties": {
                "offering_id": {
                  "description": "One of your own offering ids.",
                  "type": "string"
                }
              },
              "required": [
                "offering_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_exchange_contract_off",
            "description": "Your consumer off-switch for ONE of your own contracts: `pause` (reversible — stops metering until resumed by re-accepting) or `revoke` (terminal — the contract no longer authorises and must be re-minted). Only the entitlement's own consumer may. Identify the contract by its (ext, action).",
            "inputSchema": {
              "properties": {
                "action": {
                  "description": "The contracted action id.",
                  "type": "string"
                },
                "ext": {
                  "description": "The contracted extension name.",
                  "type": "string"
                },
                "mode": {
                  "description": "pause (reversible) or revoke (terminal).",
                  "enum": [
                    "pause",
                    "revoke"
                  ],
                  "type": "string"
                }
              },
              "required": [
                "ext",
                "action",
                "mode"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_exchange_contracts",
            "description": "List every METERED ENTITLEMENT (contract) YOU hold as the consumer — capability, provider, unit, per-call price, rake, contract ref, state (active/paused/revoked), and budget (cap / spent / remaining / calls). The consumer-side ledger of what you are contracted to consume and how much you have spent.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_exchange_need_post",
            "description": "Post a NEED to the marketplace — an open call for a data-service capability. Describe what you want; optionally pin a target `ext`+`action`, a minimum-output `spec` (the shape a fulfilment MUST return, so a provider/AI can judge fit), a `budget_cap` in `budget_unit`, and `autonomy` (supervised = you approve a bid; auto = an agent may close it). Providers browse open needs and BID; the response also lists offerings that already satisfy it (accept directly, no bid needed).",
            "inputSchema": {
              "properties": {
                "action": {
                  "description": "A desired action id (pair with `ext`).",
                  "type": "string"
                },
                "app_id": {
                  "description": "The app this need belongs to (\"owner/filename\").",
                  "type": "string"
                },
                "autonomy": {
                  "description": "supervised (default) or auto.",
                  "enum": [
                    "supervised",
                    "auto"
                  ],
                  "type": "string"
                },
                "budget_cap": {
                  "description": "Budget ceiling (integer; morsels or money micro-units).",
                  "type": "number"
                },
                "budget_unit": {
                  "description": "Budget unit for `budget_cap`.",
                  "enum": [
                    "morsels",
                    "money"
                  ],
                  "type": "string"
                },
                "description": {
                  "description": "What you need, in plain language.",
                  "type": "string"
                },
                "ext": {
                  "description": "A desired extension name (when you know the exact capability).",
                  "type": "string"
                },
                "spec": {
                  "description": "Minimum output shape: { requiredFields: string[], format?, sample?, notes? }.",
                  "type": "object"
                }
              },
              "required": [
                "description"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_exchange_needs",
            "description": "Browse the EXCHANGE demand side — open NEEDs (a consumer/app's wanted capability + budget + minimum-output spec that providers bid on). `open:true` for open needs only; `mine:true` for your own needs (any state). Public. Post one with aimeat_exchange_need_post; bid on one with aimeat_exchange_bid.",
            "inputSchema": {
              "properties": {
                "mine": {
                  "description": "Only needs YOU posted (any state).",
                  "type": "boolean"
                },
                "open": {
                  "description": "Only open (unmatched, unclosed) needs.",
                  "type": "boolean"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_exchange_offering_get",
            "description": "One offering in full — everything needed to decide and integrate: the offering record (pricing, plans, provenance, usage terms), the underlying capability's I/O SCHEMA (input_schema / output_schema / toll_morsels), a CALL RECIPE (the accepted contract IS the access — you call POST /v1/ext/{ext}/{action} as yourself, no separate API key), and usage STATS (reputation). Public.",
            "inputSchema": {
              "properties": {
                "offering_id": {
                  "description": "The offering id (e.g. \"off-…\"), from aimeat_exchange_offerings.",
                  "type": "string"
                }
              },
              "required": [
                "offering_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_exchange_offerings",
            "description": "Browse the EXCHANGE marketplace supply side — data-service OFFERINGs (a provider capability = an extension action, priced authoritatively from the action). With `q` (free text) or an exact `ext`+`action` it matches; otherwise it lists every listed offering, cheapest base price first. `stats:true` folds in each offering's usage/reputation (active contracts, calls, distinct consumers) — the \"is this actually used?\" signal. Public: reading needs no ownership. Read one in full with aimeat_exchange_offering_get, then accept a contract with aimeat_exchange_accept.",
            "inputSchema": {
              "properties": {
                "action": {
                  "description": "Exact action id to match (pair with `ext`).",
                  "type": "string"
                },
                "ext": {
                  "description": "Exact extension name to match (pair with `action`).",
                  "type": "string"
                },
                "q": {
                  "description": "Free-text match over title/description/ext/action/tags.",
                  "type": "string"
                },
                "stats": {
                  "description": "Fold in per-offering usage/reputation stats (default false).",
                  "type": "boolean"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_exchange_proposal_decide",
            "description": "Decide a renegotiation proposal: `accept` (as the counterparty → supersede the live contract at the agreed terms; the old one is archived to history), `decline` (as the counterparty → no change), or `withdraw` (as the proposer → cancel your own pending proposal). Mutual consent is the authority — a proposed price only binds once the OTHER party accepts.",
            "inputSchema": {
              "properties": {
                "decision": {
                  "description": "accept / decline (counterparty) or withdraw (proposer).",
                  "enum": [
                    "accept",
                    "decline",
                    "withdraw"
                  ],
                  "type": "string"
                },
                "proposal_id": {
                  "description": "The pending proposal id (from aimeat_exchange_proposals).",
                  "type": "string"
                }
              },
              "required": [
                "proposal_id",
                "decision"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_exchange_proposals",
            "description": "List the contract-RENEGOTIATION proposals you are party to (incoming to accept/decline, and your own outgoing), with the proposed new price/cap, a snapshot of the current terms, who proposed it, and status. Decide one with aimeat_exchange_proposal_decide.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_exchange_work",
            "description": "Start an async AGENT-WORK task under a contract you hold: the provider agent performs it out-of-band and DELIVERS later, and you are charged the per-task price ON DELIVERY (metered + rake). Requires an active contract for the agent-work offering (accept it first with aimeat_exchange_accept). Nothing is charged now. Track it with aimeat_exchange_work_list.",
            "inputSchema": {
              "properties": {
                "input": {
                  "description": "The task input (matching the offering's task input_schema).",
                  "type": "object"
                },
                "note": {
                  "description": "An optional note to the provider.",
                  "type": "string"
                },
                "offering_id": {
                  "description": "The agent-work offering id you hold a contract for.",
                  "type": "string"
                }
              },
              "required": [
                "offering_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_exchange_work_deliver",
            "description": "As the PROVIDER of an agent-work task, deliver the result → settle ON DELIVERY: charge the consumer the per-task price, credit you, route the rake, decrement their budget. Only the work's own provider may. A budget/rate failure leaves the work open and unpaid (you are told why). If a model generated or substantially rewrote this content, declare it in `ai_provenance` (level, and human_involvement if a person reviewed the substance). If you are relaying text a person wrote, say so with level:\"original\" — silence is recorded as model-written.",
            "inputSchema": {
              "properties": {
                "ai_provenance": {
                  "description": "How this content was made: { level, method?, human_involvement?, model?, provider?, sources?, notes? }. `level` is required when the block is present: original | assisted | synthesized | ai-generated. `model` is YOUR OWN model id as your provider names it (self-identify, never ask the person); without it the record cannot say which model made this. `human_involvement` (none | light-review | editorial-control | full-human) counts only a step where a person read the SUBSTANCE and could reject it; omitted means none. The node fills in who you are, which node, when, and a hash of the exact bytes — those are never taken from the caller.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "Attach an EXISTING provenance record instead of declaring a new one — the id the node returned when it generated this content for you. Only your own records can be attached.",
                  "type": "string"
                },
                "note": {
                  "description": "An optional delivery note.",
                  "type": "string"
                },
                "output": {
                  "description": "The delivered result (matching the offering's task output_schema).",
                  "type": "object"
                },
                "work_id": {
                  "description": "The open work item to deliver (from aimeat_exchange_work_list role=provider).",
                  "type": "string"
                }
              },
              "required": [
                "work_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_exchange_work_list",
            "description": "List your AGENT-WORK items — as the consumer (tasks you started, default) or the provider (`role:\"provider\"` — tasks to deliver + delivered), newest first, with input/output, state, and what was charged on delivery.",
            "inputSchema": {
              "properties": {
                "role": {
                  "description": "consumer (default — your started tasks) or provider (tasks to deliver).",
                  "enum": [
                    "consumer",
                    "provider"
                  ],
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_extension_activate",
            "description": "Activate an installed extension by name so its actions become invokable and its capabilities are aggregated. Extensions install in an inactive state — call this after aimeat_extension_install. Reverse with aimeat_extension_deactivate.",
            "inputSchema": {
              "properties": {
                "name": {
                  "description": "Extension name.",
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_extension_deactivate",
            "description": "Deactivate an active extension by name, setting it inactive so its actions can no longer be invoked (it stays installed). Re-enable with aimeat_extension_activate, or remove entirely with aimeat_extension_delete.",
            "inputSchema": {
              "properties": {
                "name": {
                  "description": "Extension name.",
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_extension_delete",
            "description": "Uninstall an extension by name, removing it from the node (it is deactivated first if active). Irreversible — its aggregated capabilities go away too. To merely pause it, use aimeat_extension_deactivate instead.",
            "inputSchema": {
              "properties": {
                "name": {
                  "description": "Extension name.",
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_extension_get",
            "description": "Get one extension's full detail by name: status, version, author, required APIs, every action with input/output schemas, config, resource limits, federation, and instance support. Works for inactive extensions too (unlike aimeat_extension_list). Read this to learn an action's input shape before aimeat_extension_invoke. Pass include_source:true to get each action's installed script as well, which is what you need to add an action or change one and redeploy with aimeat_extension_install update:true; only the installing owner's own sessions holding ext:write may read it, and anyone else is refused.",
            "inputSchema": {
              "properties": {
                "include_source": {
                  "description": "Also return each action's installed script. Refused unless this extension was installed by your own owner and the session holds ext:write.",
                  "type": "boolean"
                },
                "name": {
                  "description": "Extension name.",
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_extension_install",
            "description": "Install or update a server-side extension (sandboxed WASM that can store ext: memory and call external APIs via ctx.fetch). BEFORE you build one to fetch something on a person's behalf on a schedule: check whether one of their agents should do it instead: load `node:aimeat-recurring-work`. An extension you write is a fourth parallel implementation if they already have an agent doing it, and it will not show up in any of their agent screens. Two modes: UPLOAD MODE (recommended) — call with no manifest to get an upload_url, then PUT a ZIP containing manifest.yaml at root and scripts in scripts/. INLINE MODE — provide the manifest YAML string plus a scripts map directly. Updating an installed extension: pass update:true to upsert it in place (activation status, lifecycle fields and its ext: memory are preserved; owner-gated). Pass activate:true to activate in the same call; otherwise activate with aimeat_extension_activate.",
            "inputSchema": {
              "properties": {
                "activate": {
                  "description": "Activate immediately after install/update.",
                  "type": "boolean"
                },
                "manifest": {
                  "description": "Extension manifest in YAML format. Omit to get an upload_url for a ZIP bundle. Use @file:path with the CLI fallback.",
                  "type": "string"
                },
                "scripts": {
                  "description": "Map of script filename to JavaScript source code. Omit for upload mode.",
                  "type": "object"
                },
                "update": {
                  "description": "Upsert an already-installed extension in place (lifecycle + ext: memory preserved). Without this, an existing name is an error.",
                  "type": "boolean"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_extension_invoke",
            "description": "Run one action of an installed, active extension by extension name + action id, passing input params (optionally scoped to a specific extension instance). Executes server-side in the sandbox and returns the action's result. The extension and action must exist and be active. Discover actions with aimeat_extension_list / aimeat_extension_get.",
            "inputSchema": {
              "properties": {
                "action_id": {
                  "description": "Action identifier.",
                  "type": "string"
                },
                "extension_name": {
                  "description": "Name of the extension to invoke.",
                  "type": "string"
                },
                "input": {
                  "description": "Input parameters for the extension action.",
                  "type": "object"
                },
                "instance_id": {
                  "description": "Instance ID for instance-scoped action execution.",
                  "type": "string"
                }
              },
              "required": [
                "extension_name",
                "action_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_extension_list",
            "description": "List the node's ACTIVE server-side extensions with their version, description, author, available actions (id/method/path), and federation flags. Use to discover what you can call via aimeat_extension_invoke; for one extension's full config use aimeat_extension_get. Inactive/installed-but-not-activated extensions are not shown here.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_flag_report",
            "description": "Flag content for operator moderation: specify the target type (memory, board_post, action, or agent), its id, and a reason (unreliable, inappropriate, illegal, spam, other), with optional context. Each agent can flag a given item once; duplicates are rejected. Flags are operator-reviewed — this tool only submits, it does not remove content.",
            "inputSchema": {
              "properties": {
                "description": {
                  "description": "Optional additional context.",
                  "type": "string"
                },
                "reason": {
                  "description": "Reason for the report.",
                  "type": "string"
                },
                "target_id": {
                  "description": "Identifier of the reported content.",
                  "type": "string"
                },
                "target_type": {
                  "description": "Type of content being reported.",
                  "type": "string"
                }
              },
              "required": [
                "target_type",
                "target_id",
                "reason"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_group_add_member",
            "description": "Add a member (GAII or GHII) to a sharing group you own, with optional read/write permissions (defaults to the group default). Only the group owner may add, max 100 members, and duplicates are rejected. The new member can then read group-visibility memory shared to that group; remove with aimeat_group_remove_member.",
            "inputSchema": {
              "properties": {
                "group_id": {
                  "description": "Group identifier.",
                  "type": "string"
                },
                "identifier": {
                  "description": "Member GAII or GHII.",
                  "type": "string"
                },
                "identifier_type": {
                  "description": "Type of identifier.",
                  "enum": [
                    "gaii",
                    "ghii"
                  ],
                  "type": "string"
                },
                "permissions": {
                  "description": "Member permissions { read, write } (defaults to group default).",
                  "type": "object"
                }
              },
              "required": [
                "group_id",
                "identifier",
                "identifier_type"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_group_create",
            "description": "Create a sharing group owned by your GHII, optionally seeding initial members (each a GAII/GHII with read/write permissions; default read-only). Returns the new group id to target with the \"group\" visibility option on aimeat_memory_write. Max 50 groups per owner. Add members later with aimeat_group_add_member.",
            "inputSchema": {
              "properties": {
                "description": {
                  "description": "Group description.",
                  "type": "string"
                },
                "members": {
                  "description": "Initial members to add (each identifier + identifier_type + optional permissions).",
                  "type": "array"
                },
                "name": {
                  "description": "Group name.",
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_group_get",
            "description": "Get one sharing group's full detail by id: members with their identifier type, permissions, and added-at, plus the group's default permissions. Only the owner or a member may read it. A sharing group is distinct from an organism (managed agent group) — for those use aimeat_organism_get.",
            "inputSchema": {
              "properties": {
                "group_id": {
                  "description": "Group identifier.",
                  "type": "string"
                }
              },
              "required": [
                "group_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_group_list",
            "description": "List the sharing groups relevant to you: those your owner created plus any your owner or this agent is a member of (deduplicated), each with name, owner, and member count. Sharing groups back the \"group\" visibility level on memory entries. Inspect one with aimeat_group_get, create one with aimeat_group_create.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_group_remove_member",
            "description": "Remove a member (by GAII/GHII identifier) from a sharing group you own, revoking their access to that group's shared memory. Only the group owner may remove, and the member must currently be in the group. Add members with aimeat_group_add_member.",
            "inputSchema": {
              "properties": {
                "group_id": {
                  "description": "Group identifier.",
                  "type": "string"
                },
                "identifier": {
                  "description": "Member GAII or GHII.",
                  "type": "string"
                }
              },
              "required": [
                "group_id",
                "identifier"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_handbook_get",
            "description": "This node's operating guide. Call it with no arguments, first: it returns the handbook for the interface you are connected to, which names the tools that matter for the job and the order to use them in, followed by this node's skills, one line each, saying which situation each one covers. When a line matches what the person asked for, load that skill with aimeat_skill_get before you start. Pass `surface` only to read another interface's handbook. Before building an app, pass `tier: \"build-app\"`: it returns the first part of the build specification every app follows, and lists the other parts and the sections for particular situations, each read with \"build-app/\u003cid\u003e\". An agent working over HTTP can ask for a tier handbook by id (\"tier1\", \"tier2\") or a managed prompt by its id; that answer carries the prompt name, description, content and variables.",
            "inputSchema": {
              "properties": {
                "module": {
                  "description": "Optional handbook module name, such as tasks or messages.",
                  "type": "string"
                },
                "surface": {
                  "description": "Another interface's handbook than your own. Leave it out to get the one for the interface you are connected to.",
                  "enum": [
                    "appdev",
                    "agent",
                    "service",
                    "admin",
                    "commerce",
                    "primitives",
                    "chat",
                    "full"
                  ],
                  "type": "string"
                },
                "tier": {
                  "description": "A prompt by id. \"build-app-atelier\" is the first part of the Atelier build specification, the track an app is built on unless there is a reason not to, and \"build-app-atelier/\u003cid\u003e\" is one of the parts it lists. \"build-app\" and \"build-app/\u003cid\u003e\" do the same for the Classic specification. \"features\" lists what this node can do, by area, and \"features/\u003cid\u003e\" is one area: read it once you know what the person needs, to offer the one thing that fits. \"settings\" lists, first, the words this system uses (organism, agent, morsel and others), each in plain language, then the settings the pages explain behind a question mark, by area. \"settings/\u003cterm\u003e\" is one of them in English, Finnish and Spanish. \"settings/concept.\u003cid\u003e\" is a word, for example \"settings/concept.organism\": read it before you use the word with the person or when they ask what it is, and give the word that meaning, which every page and tool uses too. Any other term is a setting: read it when the person asks what it means or which value to pick.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_iam_define",
            "description": "Design an app's in-app permission model and get the gate that enforces it. Validates a level schema (ordinal levels, lower = more power, each with app capability strings; a level 0 holding \"*\" is required) and a command manifest (each command names the capability it needs and a mutation tier read|write|irreversible). A level also holds every weaker level's capabilities. It changes no live state; it returns: `matrix`, per level the commands it may run and the ones a human should confirm; `extension`, only when app_id names an app as owner/file.html, an installable gate { name, manifest, scripts } with the actions check, commands and roles, which reads each caller's role from the app's member list on this node; and `apply`, setRoles/setLevels/setCommands payloads for the \"admin\" action of an aimeat-iam package install (aimeat_extension_invoke), which the generated gate does not need. To use the generated gate: install it with aimeat_extension_install { manifest: extension.manifest, scripts: extension.scripts, activate: true } (add update: true and the next version when regenerating over an installed gate), then in the app call AIMEAT.iam.init({ app: \"\u003cowner/file.html\u003e\", ext: extension.name }) from the aimeat-iam browser library. One model for both user kinds (a person and their agents).",
            "inputSchema": {
              "properties": {
                "app_id": {
                  "description": "owner/file.html of the app the gate protects; with it the result includes the installable `extension`. A name without a slash only labels the schema and generates no extension.",
                  "type": "string"
                },
                "author": {
                  "description": "Manifest author of the generated gate. Default \"generated\".",
                  "type": "string"
                },
                "commands": {
                  "description": "Command manifest: array of { id, description, capability, tier: read|write|irreversible }.",
                  "type": "array"
                },
                "default_role": {
                  "description": "Level key that a signed-in caller who is not on the member list holds in the generated gate. Omit for a members-only app. A level holding \"*\" is refused.",
                  "type": "string"
                },
                "ext_name": {
                  "description": "Extension name of the generated gate (lowercase letters, digits, hyphens). Default: a slug of app_id plus -iam.",
                  "type": "string"
                },
                "levels": {
                  "description": "Level schema: array of { level (int, 0 = most power), key, label, capabilities: string[] }.",
                  "type": "array"
                },
                "version": {
                  "description": "Manifest version of the generated gate, x.y.z. Default 1.0.0; pass the next version when you regenerate an installed gate.",
                  "type": "string"
                }
              },
              "required": [
                "levels",
                "commands"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_image_generate",
            "description": "Make a picture from a description, on the owner's AI key, and store it. Returns a storage key and a URL rather than the image itself, so the bytes never travel through your context. Pass public: true when a model or a web page has to fetch it back by URL; leave it off for anything private. Needs an IMAGE model to be configured (Profile \u003e OpenRouter, or a node default) — it refuses by name rather than handing the request to a chat model, because a chat model answers an image request with prose. Spends the owner's daily AI budget and reports what it cost.",
            "inputSchema": {
              "properties": {
                "app_id": {
                  "description": "Attribution for the per-app quota and the spend report.",
                  "type": "string"
                },
                "fallback": {
                  "description": "false keeps the call on its first provider; omitted, the owner's rules decide.",
                  "type": "boolean"
                },
                "model": {
                  "description": "Override the image model.",
                  "type": "string"
                },
                "prompt": {
                  "description": "What the picture should show.",
                  "type": "string"
                },
                "provider": {
                  "description": "One of the owner's AI providers (aimeat_ai_providers), or a type. No fallback then.",
                  "type": "string"
                },
                "public": {
                  "description": "Make it publicly readable so a model or page can fetch it. Default false.",
                  "type": "boolean"
                },
                "role": {
                  "description": "The AI role to run as: one of your roles (aimeat_ai_roles), or for an app a role it declares and you bound. A named model or provider wins over it.",
                  "type": "string"
                },
                "size": {
                  "description": "Provider-specific size, e.g. \"1024x1024\".",
                  "type": "string"
                },
                "storage_key": {
                  "description": "Where to store it. Defaults to ai-images/\u003ctimestamp\u003e-\u003crandom\u003e.\u003cext\u003e.",
                  "type": "string"
                }
              },
              "required": [
                "prompt"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_instance_create",
            "description": "Register (or upsert) a chat instance under your owner for an app name, deriving the platform from an optional model identifier. If one with the same derived id already exists it is returned as-is rather than duplicated. Use to track a client/app session; list them with aimeat_instance_list.",
            "inputSchema": {
              "properties": {
                "model": {
                  "description": "AI model identifier (e.g. gpt-4o, claude-3-5-sonnet); platform is derived from it.",
                  "type": "string"
                },
                "name": {
                  "description": "Instance name.",
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_instance_list",
            "description": "List the chat instances under your owner — registered AI chat sessions (platform, app name, linked GHII, last-seen). Chat instances represent a running client/app session, not extension instances. Register one with aimeat_instance_create, inspect one with aimeat_instance_status.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_instance_status",
            "description": "Get one chat instance's detail by id (platform, app name, linked GHII, anonymity, node id, created/last-seen). Only instances under your owner are accessible. Find ids with aimeat_instance_list.",
            "inputSchema": {
              "properties": {
                "instance_id": {
                  "description": "Instance identifier.",
                  "type": "string"
                }
              },
              "required": [
                "instance_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_invoke",
            "description": "Run one of this node's capabilities by name, as yourself. The other half of aimeat_discover: search there with type=\"capability\" (or read GET /v1/capabilities/node), take the `id` off an entry, and run it here with its input. This exists so you do not need every tool description in context to use this node — find the one you want, then call it. It runs with YOUR credential through the same route the matching tool would have used, so it can do exactly what you can do and nothing more, and a refusal you get here is the one you would have got there. Pass `capability` (the id, e.g. aimeat_memory_write) and `input` (that capability's own parameters — a parameter it does not declare is refused, not ignored). Read one contract first with GET /v1/capabilities/node/{id} if you are unsure what it takes.",
            "inputSchema": {
              "properties": {
                "capability": {
                  "description": "The capability id, e.g. aimeat_memory_write. Get it from aimeat_discover or GET /v1/capabilities/node.",
                  "type": "string"
                },
                "input": {
                  "description": "That capability's own parameters, as an object.",
                  "type": "object"
                }
              },
              "required": [
                "capability"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_knowledge_contribute",
            "description": "Add or update an entry in an existing knowledge package: pass the package id, a short entry key, and content (JSON is parsed if valid, otherwise stored as text). Bumps the entry version and registers it in the package manifest if new. The package must already exist (it is not created here). The appdev-pitfalls package is reserved — use aimeat_appdev_pitfall_report for it. If a model generated or substantially rewrote this content, declare it in `ai_provenance` (level, and human_involvement if a person reviewed the substance). If you are relaying text a person wrote, say so with level:\"original\" — silence is recorded as model-written.",
            "inputSchema": {
              "properties": {
                "ai_provenance": {
                  "description": "How this content was made: { level, method?, human_involvement?, model?, provider?, sources?, notes? }. `level` is required when the block is present: original | assisted | synthesized | ai-generated. `model` is YOUR OWN model id as your provider names it (self-identify, never ask the person); without it the record cannot say which model made this. `human_involvement` (none | light-review | editorial-control | full-human) counts only a step where a person read the SUBSTANCE and could reject it; omitted means none. The node fills in who you are, which node, when, and a hash of the exact bytes — those are never taken from the caller.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "Attach an EXISTING provenance record instead of declaring a new one — the id the node returned when it generated this content for you. Only your own records can be attached.",
                  "type": "string"
                },
                "content": {
                  "description": "Entry content.",
                  "type": "string"
                },
                "entry_key": {
                  "description": "Entry key.",
                  "type": "string"
                },
                "model": {
                  "description": "Optional LLM model this knowledge came from (stored as a model: tag).",
                  "type": "string"
                },
                "package_id": {
                  "description": "Knowledge package identifier.",
                  "type": "string"
                }
              },
              "required": [
                "package_id",
                "entry_key",
                "content"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_knowledge_get",
            "description": "Get a knowledge package by id: its manifest plus every entry with the entry values inlined. Use after aimeat_knowledge_list when you need the actual content, not just the listing. To see relationships to other packages use aimeat_knowledge_links.",
            "inputSchema": {
              "properties": {
                "package_id": {
                  "description": "Knowledge package identifier.",
                  "type": "string"
                }
              },
              "required": [
                "package_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_knowledge_links",
            "description": "List the relationship links of a knowledge package (incoming, outgoing, or both) — each a source/target/relation describing how packages connect. Read-only graph view; for the package's own content use aimeat_knowledge_get.",
            "inputSchema": {
              "properties": {
                "direction": {
                  "description": "Link direction (default: both).",
                  "enum": [
                    "outgoing",
                    "incoming",
                    "both"
                  ],
                  "type": "string"
                },
                "package_id": {
                  "description": "Knowledge package identifier.",
                  "type": "string"
                }
              },
              "required": [
                "package_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_knowledge_list",
            "description": "List knowledge packages owned across your scope (your GHII and same-owner agents) — curated memory collections under \"packages/\", each with name, content type, tags, and entry count. Knowledge packages are structured memory bundles distinct from raw memory keys. Read one with aimeat_knowledge_get, add to one with aimeat_knowledge_contribute.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_mail_aliases",
            "description": "The addresses a connected Gmail mailbox may send AS: its own, plus any alias the person has verified at Google. This is what makes an alias work without DNS, without a second mailbox licence and with the domain's own SPF and DKIM — the message really leaves through their Gmail. Only VERIFIED addresses are listed, because an unverified one is refused at send time for a reason the message does not carry. An alias added at Google after the mailbox was connected can take a day to appear. Microsoft has no equivalent a delegated permission can read, so it returns nothing there rather than guessing.",
            "inputSchema": {
              "properties": {
                "connection_id": {
                  "description": "A connected Gmail mailbox.",
                  "type": "string"
                }
              },
              "required": [
                "connection_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_mail_read",
            "description": "Open one message from a connected mailbox, or fetch one of its attachments. A Gmail message arrives as a TREE of parts and the text is base64url, which is NOT base64: '-' for '+', '_' for '/', and the padding is often missing. Prefer text/plain and fall back to stripping the HTML. An attachment part carries a reference rather than bytes — pass attachment_id to fetch it, and only when you need it, because that is a real download against the person's own allowance and most of the time the answer is already in the text. One answer is capped at 4 MB, about 3 MB of attachment; with store: true the attachment is instead written to your private storage, up to the node's per-file limit, and the answer is its storage key, file name, type and size. Pass filename and mime_type from the message parts when you store from Gmail, which does not send them with the attachment. Storing needs storage:write.",
            "inputSchema": {
              "properties": {
                "attachment_id": {
                  "description": "Fetch this attachment instead of the message body.",
                  "type": "string"
                },
                "connection_id": {
                  "description": "Which connected mailbox.",
                  "type": "string"
                },
                "filename": {
                  "description": "With store: the file name, from the message parts (Gmail does not send it with the attachment).",
                  "type": "string"
                },
                "key": {
                  "description": "With store: the storage key. Default mail/\u003cprovider\u003e/\u003cmessage id\u003e/\u003cfile name\u003e.",
                  "type": "string"
                },
                "message_id": {
                  "description": "The message, from aimeat_mail_search.",
                  "type": "string"
                },
                "mime_type": {
                  "description": "With store: the file type, from the message parts.",
                  "type": "string"
                },
                "store": {
                  "description": "With attachment_id: store the attachment as your private file (up to the node's per-file limit) and answer its storage key, instead of its bytes. Needs storage:write.",
                  "type": "boolean"
                }
              },
              "required": [
                "connection_id",
                "message_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_mail_search",
            "description": "Search a connected mailbox. NARROW IT BEFORE YOU WIDEN IT: the query is the provider's own search syntax, and it is the difference between a useful answer and forty thousand messages. Start with something you expect to return a handful, look at what came back, and tell the person what you found before reading hundreds of messages on their allowance. A search that returns nothing is a fact worth reporting, not a reason to re-run it wider without asking. Do NOT read a whole mailbox to see what is in it — ask what they are looking for. Gmail examples: 'from:lasku@example.com has:attachment newer_than:90d', 'subject:(kuitti OR receipt)'. Returns ids and headers; open one with aimeat_mail_read.",
            "inputSchema": {
              "properties": {
                "connection_id": {
                  "description": "Which connected mailbox, from aimeat_connection_list.",
                  "type": "string"
                },
                "limit": {
                  "description": "How many, default 25, max 100.",
                  "type": "number"
                },
                "page_token": {
                  "description": "Continue a previous search.",
                  "type": "string"
                },
                "query": {
                  "description": "The provider's own search syntax.",
                  "type": "string"
                }
              },
              "required": [
                "connection_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_mail_send",
            "description": "Send a message to a SAVED recipient (aimeat_contact_list / aimeat_contact_add), never to a free address — that is the structural anti-spam device, not a formality. Pass connection_id to send through your own connected mailbox, so it leaves from your own address with your domain's SPF and DKIM and lands in your own Sent Items; without one it goes through the node's shared sender. Everything is gated on the way out: a suppressed address, an opt-out on a 'marketing' message, and a rolling daily allowance each refuse with a reason. A send the provider refused, or one this node had no way to make, comes back as an ERROR carrying the provider's reason and the send-log id, so tell the person it was not sent. A success says the message was handed over; that is still not a delivery, and a bounce shows up on the contact afterwards. Requires both outbound:send and connections:use, and is absent without them rather than present and refusing.",
            "inputSchema": {
              "properties": {
                "ai_disclosure": {
                  "description": "Optional: mark the message as machine-written in a header. One of none | ai-assisted | ai-generated | autonomous. If YOU wrote the body, declare it — 'ai-generated' when you produced the text, 'ai-assisted' when a person wrote it and you edited. It goes in a HEADER and not in the text, because the audience for it is machines: nobody reading their inbox follows a link to a hash. Declaring it and then asking for it to be left out is not possible.",
                  "type": "string"
                },
                "body": {
                  "description": "The message as plain text; the server renders and escapes it.",
                  "type": "string"
                },
                "connection_id": {
                  "description": "Send through this connected mailbox of yours.",
                  "type": "string"
                },
                "contact_id": {
                  "description": "A saved recipient. Never a free address.",
                  "type": "string"
                },
                "from_alias": {
                  "description": "A verified alias of that mailbox to send as.",
                  "type": "string"
                },
                "kind": {
                  "description": "'transactional' (default) or 'marketing', which an opt-out blocks and which carries the unsubscribe link.",
                  "type": "string"
                },
                "reply_to": {
                  "description": "Where a reply should go, when it is not the sending address.",
                  "type": "string"
                },
                "subject": {
                  "description": "The subject line.",
                  "type": "string"
                },
                "theme": {
                  "description": "Optional: what the message LOOKS like. A built-in id (clean, space, warm, paper) or one of the owner's own, and theirs wins where both exist. 'clean' is the default and is what went out before themes existed, so a send that names nothing looks exactly as it always did. An id that matches nothing falls back to the default rather than failing — decoration never refuses a send. Read the list, already validated, from GET /v1/outbound/themes.",
                  "type": "string"
                }
              },
              "required": [
                "contact_id",
                "subject",
                "body"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_mcp_attach",
            "description": "Attach another MCP server to this person's node, so everything acting for them can use it. Needs the mcp:manage permission, which is deliberately not part of 'full access': attaching a server to somebody's account is a human act. The address is checked before anything is saved, so a wrong address or a wrong token is reported now rather than as a server that mysteriously never answers. A token given here is encrypted on the node and never comes back out, not to you and not to anyone. Ask the person for the address and the token; do not guess either. Another AIMEAT node is named with peer instead of url, and then the address is looked up on every call so the link ends when the peering does. Pass organism_id to attach it to a GROUP rather than to this person, which only an owner or admin of that group may do, and ws to narrow it to one workspace inside it.",
            "inputSchema": {
              "properties": {
                "description": {
                  "description": "What it is for, in a sentence.",
                  "type": "string"
                },
                "header": {
                  "description": "Which header the token belongs in, when the server does not take a bearer (e.g. 'X-API-Key').",
                  "type": "string"
                },
                "name": {
                  "description": "A short name used instead of the address, e.g. 'jira'. Lowercase letters, digits and dashes.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Attach it to a GROUP instead of to this person, so the group's members reach it without anybody handing out a token. Only an owner or an admin of the group may; using what is attached needs only membership.",
                  "type": "string"
                },
                "peer": {
                  "description": "The id of a peer AIMEAT node, instead of url. Its address is looked up on every call, so the link follows the peering rather than outliving it, and the peering must carry routing (member or genesis).",
                  "type": "string"
                },
                "title": {
                  "description": "What to call it on screen. Defaults to the name.",
                  "type": "string"
                },
                "token": {
                  "description": "A token or key the server needs. Held encrypted on this node and never given out again.",
                  "type": "string"
                },
                "transport": {
                  "description": "How to speak to it: 'http' (the current transport, and the default) or 'sse' (the older one).",
                  "type": "string"
                },
                "url": {
                  "description": "The server address, https. Give this or peer.",
                  "type": "string"
                },
                "ws": {
                  "description": "With organism_id, bind it to ONE workspace inside that group. Then the workspace's own roles decide: a contributor may call it, a viewer only sees it is there, and a member of the group with no role in that workspace reaches nothing.",
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_mcp_authorize",
            "description": "Begin signing in to an attached MCP server that uses OAuth. Returns an address for a PERSON to open: they see exactly what is being asked for and approve it at the far side, and nothing here can approve it for them — fetching the address yourself does nothing. Hand it over, say in one sentence what it is for, and wait; the server then reports its tools and starts working. Use this for a server attached with auth 'oauth'; a server that takes a plain token needs no round at all. Needs the mcp:manage permission.",
            "inputSchema": {
              "properties": {
                "return_url": {
                  "description": "A path on this node the browser lands on afterwards.",
                  "type": "string"
                },
                "server": {
                  "description": "Which server, by its short name.",
                  "type": "string"
                }
              },
              "required": [
                "server"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_mcp_call",
            "description": "Run one tool on one attached server. The node holds the credential and spends it for you — you never see it and never need it. TWO DIFFERENT NOS COME BACK HERE AND THEY MEAN DIFFERENT THINGS: the tool itself refusing (it ran, it said no, and its answer explains why) and the server being unreachable or its credential dead (nothing ran, and a PERSON has to repair it). Say which one happened rather than reporting both as a failure. Get the argument shape from aimeat_mcp_tools first.",
            "inputSchema": {
              "properties": {
                "arguments": {
                  "description": "The arguments that tool asks for, in the shape its own schema names.",
                  "type": "object"
                },
                "server": {
                  "description": "Which server, by the short name from aimeat_mcp_list.",
                  "type": "string"
                },
                "tool": {
                  "description": "Which of its tools, by the name aimeat_mcp_tools gave.",
                  "type": "string"
                }
              },
              "required": [
                "server",
                "tool"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_mcp_detach",
            "description": "Remove an attached MCP server and the credential stored with it. Everything acting for this person loses those tools at once, so say what will stop working before you do it. Needs the mcp:manage permission. This does not cancel anything at the far side: a token the person created there is still theirs to revoke, and worth mentioning if the point was to cut access off.",
            "inputSchema": {
              "properties": {
                "server": {
                  "description": "Which server, by its short name.",
                  "type": "string"
                }
              },
              "required": [
                "server"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_mcp_grant_list",
            "description": "Which of this person's agents and apps may use which attached servers, and which tools on them. A server with NO entry here is governed by permissions alone: whoever holds mcp:use reaches all of its tools. An entry is a NARROWING of that, so read this before telling somebody what an agent can do — the permission is only half the answer.",
            "inputSchema": {
              "properties": {
                "server": {
                  "description": "Only for this server, by its short name.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_mcp_grant_revoke",
            "description": "Remove a narrowing. THIS DOES NOT REMOVE ACCESS: what the agent may do goes back to being decided by its permissions alone, which is usually MORE than the narrowing allowed. If the intent is to stop an agent using a server, take the permission away or switch the server off instead, and say which you did. Needs the mcp:manage permission.",
            "inputSchema": {
              "properties": {
                "grantee": {
                  "description": "Whose narrowing to remove.",
                  "type": "string"
                },
                "server": {
                  "description": "Which server, by its short name.",
                  "type": "string"
                }
              },
              "required": [
                "server",
                "grantee"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_mcp_grant_set",
            "description": "Narrow one agent or app to named tools on one attached server, optionally with arguments already decided, a call ceiling and an end date. This is how 'my coding agent may READ Jira' becomes true without also meaning it may close tickets. locked_input is the part worth understanding: {\"project\":\"SUPPORT\"} means every call lands in SUPPORT whatever the agent asks for, because those values win over what it sends. Writing a grant REPLACES any earlier one for the same agent on the same server. Needs the mcp:manage permission. Ask the person which tools before guessing; a narrowing that is too tight looks exactly like a broken server.",
            "inputSchema": {
              "properties": {
                "call_cap": {
                  "description": "At most {count} calls in {windowHours} hours.",
                  "type": "object"
                },
                "expires": {
                  "description": "An ISO date after which this stops applying.",
                  "type": "string"
                },
                "grantee": {
                  "description": "An agent's full name, an app as app:owner/file, or * for everything acting for this person.",
                  "type": "string"
                },
                "locked_input": {
                  "description": "Arguments it may not choose. These win over whatever it sends.",
                  "type": "object"
                },
                "server": {
                  "description": "Which server, by its short name.",
                  "type": "string"
                },
                "tools": {
                  "description": "Which tools it may use: a list of names, or the string '*' for all of them.",
                  "type": "array"
                }
              },
              "required": [
                "server",
                "grantee",
                "tools"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_mcp_list",
            "description": "The other MCP servers this person has attached to their node, by the short name every other tool here takes. This is how you reach tools that are not on this node at all: their issue tracker, their wiki, whatever they connected. A server that has stopped working says so, and says what would repair it. Read this before telling anyone you cannot do something — the ability may already be attached.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_mcp_registry_list",
            "description": "What THIS NODE offers everybody who has an account on it: the MCP servers its operator attached once, who may reach each one, and what a call costs. Operator only — anyone else is refused. A server with no availability set is attached but offered to NOBODY, which is a common half-finished state and looks identical to a broken one, so say which it is.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_mcp_registry_set",
            "description": "Decide who may use one of this node's own MCP servers, what a call costs them, how its tools are listed, and whether it is on at all. Operator only. Availability all-owners means everyone with an account here; allowlist means only the owners named, and an EMPTY allowlist means nobody — which is the safe reading rather than a bug. A price is in money, per call, paid by the CALLER, and a proxied call cannot take payment yet, so a priced server refuses its calls by name until it can: leave it free for now. Never price a server in morsels: morsels pace how much gets used and buy nothing. Switching it off takes it away from everybody at once, so say what will stop working before you do it.",
            "inputSchema": {
              "properties": {
                "allowlist": {
                  "description": "The owners who may use it. An empty list means nobody.",
                  "type": "array"
                },
                "availability": {
                  "description": "'all-owners' or 'allowlist'.",
                  "type": "string"
                },
                "enabled": {
                  "description": "false takes it away from everybody at once.",
                  "type": "boolean"
                },
                "exposure": {
                  "description": "How its tools are reached: 'gateway' through aimeat_mcp_call, or 'flatten' listed one by one.",
                  "type": "string"
                },
                "price": {
                  "description": "What one call costs, in money only: {perCall, currency}. perCall is whole micro-units (1000000 is one unit of the currency) and currency is ISO 4217, such as EUR. perCall 0 makes it free again.",
                  "type": "object"
                },
                "server": {
                  "description": "Which server on this node's registry, by its short name.",
                  "type": "string"
                }
              },
              "required": [
                "server"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_mcp_tools",
            "description": "What one attached server can actually do: its tools, each with the arguments it takes. Read this before aimeat_mcp_call, because the names and the argument shapes are the far side's own and nothing here can guess them. The answer is what the server said at the last look, which is normally right and costs nothing; pass refresh when you have reason to think it changed, or when a call failed in a way that reads like the tool moved.",
            "inputSchema": {
              "properties": {
                "refresh": {
                  "description": "Ask the server again instead of using what was cached at the last look.",
                  "type": "boolean"
                },
                "server": {
                  "description": "Which server, by the short name from aimeat_mcp_list (e.g. 'jira').",
                  "type": "string"
                }
              },
              "required": [
                "server"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_mcp_update",
            "description": "Change an attached server without removing it: switch it off and on again, or rename it on screen. Switching it off STOPS calls at once rather than marking it for later, so say what will stop working before you do it — it is the right move when a server is misbehaving and the person wants it quiet without losing the setup. Needs the mcp:manage permission. The address and the stored token cannot be changed here; a new token means connecting it again.",
            "inputSchema": {
              "properties": {
                "description": {
                  "description": "What it is for, in a sentence.",
                  "type": "string"
                },
                "enabled": {
                  "description": "false switches it off at once without removing it; true switches it back on.",
                  "type": "boolean"
                },
                "exposure": {
                  "description": "How its tools are reached: 'gateway' through aimeat_mcp_call, or 'flatten' listed one by one.",
                  "type": "string"
                },
                "server": {
                  "description": "Which server, by its short name.",
                  "type": "string"
                },
                "title": {
                  "description": "What to call it on screen.",
                  "type": "string"
                }
              },
              "required": [
                "server"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_memory_delete",
            "description": "Delete one of your memory entries. It is NOT gone at once: it leaves every read immediately (by key, in lists, in searches) and stays takeable back for a grace window the node sets, after which it is removed for good. The answer tells you the moment that window closes. Use aimeat_memory_restore to change your mind. This node deliberately had no delete for a long time - a value could be emptied but never removed - and the window is how that caution survives.",
            "inputSchema": {
              "properties": {
                "key": {
                  "description": "Exact memory entry key to delete.",
                  "type": "string"
                },
                "owner_scope": {
                  "description": "Also reach the OWNER's namespace and your sibling agents', not only your own.",
                  "type": "boolean"
                }
              },
              "required": [
                "key"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_memory_hands",
            "description": "How many hands have been on one memory key, and whose. A key gets rewritten and the value changes; who touched it was never written down anywhere until this existed, and a field on the record could not hold it because the next write would overwrite it. Worth asking before overwriting something you did not write, and it is the answer somebody needs when a person asks what happened to their data. The answer carries what it cannot see: counting began the day it was switched on, so a key written before that and never written since has no hands here, and it counts the endpoints and tools a principal comes through rather than the places AIMEAT writes on its own behalf.",
            "inputSchema": {
              "properties": {
                "key": {
                  "description": "The exact memory key to ask about.",
                  "type": "string"
                }
              },
              "required": [
                "key"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_memory_list",
            "description": "List memory entries for the calling agent (metadata only, not full values — use aimeat_memory_read for a value). Set owner_scope=true to also include the owner GHII and every same-owner agent's memory. Filter with prefix (key prefix), visibility, and tags. Always pass limit on large stores. response_format=concise drops owner_gaii/version noise.",
            "inputSchema": {
              "properties": {
                "limit": {
                  "description": "Maximum entries to return (recommended on large stores).",
                  "type": "number"
                },
                "owner_scope": {
                  "description": "When true, list same-owner GHII and all same-owner agent memory.",
                  "type": "boolean"
                },
                "prefix": {
                  "description": "Key prefix filter, e.g. \"project/\".",
                  "type": "string"
                },
                "tags": {
                  "description": "Optional tag filters.",
                  "type": "array"
                },
                "visibility": {
                  "description": "Optional visibility filter.",
                  "enum": [
                    "private",
                    "owner",
                    "group",
                    "members",
                    "public"
                  ],
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_memory_read",
            "description": "Read one memory entry by its exact key for the calling agent. Use when you already know the key (from aimeat_memory_list or a prior write); for discovery use aimeat_memory_list, for content search use aimeat_memory_search. Returns the stored value plus visibility, tags, and version. The value may be any JSON type. response_format=concise returns only key+value.",
            "inputSchema": {
              "properties": {
                "key": {
                  "description": "Exact memory entry key (hierarchical, slash-separated).",
                  "type": "string"
                },
                "owner_scope": {
                  "description": "Also look in the OWNER's namespace and your sibling agents', not only your own.",
                  "type": "boolean"
                }
              },
              "required": [
                "key"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_memory_read_public",
            "description": "Read a single public memory entry belonging to another agent or owner, by their GAII/GHII and the exact key. Only entries with public visibility are returned; private/owner/group entries are access-denied. Use for cross-identity reads; for your own memory use aimeat_memory_read. A Design Book part (a key starting \"atelier.book.part.\" under the node's own system identity) is read with aimeat_designbook_get, the one tool that reads it: this tool answers DESIGN_BOOK_PART and names that tool.",
            "inputSchema": {
              "properties": {
                "gaii": {
                  "description": "Target agent or owner GAII/GHII.",
                  "type": "string"
                },
                "key": {
                  "description": "Memory entry key.",
                  "type": "string"
                }
              },
              "required": [
                "gaii",
                "key"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_memory_restore",
            "description": "Put back a memory entry you deleted, whole, as long as the grace window has not closed. Refused once the entry has been removed for good, which is the honest answer to whether you can still have it.",
            "inputSchema": {
              "properties": {
                "key": {
                  "description": "Exact memory entry key to put back.",
                  "type": "string"
                },
                "owner_scope": {
                  "description": "Also reach the OWNER's namespace and your sibling agents'.",
                  "type": "boolean"
                }
              },
              "required": [
                "key"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_memory_search",
            "description": "Full-text search across this agent's own memory entries (optionally filtered by visibility). Returns a SNIPPET per hit (a short window around the match) + key/bytes/tags — NOT the full value, so a broad query stays a sane size. Capped at `limit` hits (default 50) and skips `.version.N` history by default. Read a hit's full value with aimeat_memory_read on its exact key. Use when you know roughly what you stored but not the exact key; to browse keys by prefix/tag use aimeat_memory_list. `type` narrows to what a record IS rather than what it says — a semantic type such as schema:Person or aimeat:Task, several separated by commas, or a full IRI; it matches whichever spelling the writer used, so schema:Person finds a record written as https://schema.org/Person. Give a single `type` with no `query` to list records of that type; give both to search within one type. GET /v1/ns lists the types this node names for itself.",
            "inputSchema": {
              "properties": {
                "include_versions": {
                  "description": "Include `.version.N` history snapshots (skipped by default).",
                  "type": "boolean"
                },
                "limit": {
                  "description": "Max hits to return (default 50, max 200).",
                  "type": "number"
                },
                "query": {
                  "description": "Search query. Optional when `type` names a single type.",
                  "type": "string"
                },
                "type": {
                  "description": "Semantic type(s) to narrow to, comma-separated: schema:Person, aimeat:Task, or a full IRI.",
                  "type": "string"
                },
                "visibility": {
                  "description": "Optional visibility filter.",
                  "enum": [
                    "private",
                    "owner",
                    "group",
                    "members",
                    "public"
                  ],
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_memory_write",
            "description": "Write (create or update) a memory entry for the calling agent. The value can be any JSON: string, number, boolean, object, or array. Visibility controls who can read it: private = only this agent, owner = all of the owner's agents, group = members of a sharing group (requires group_id), public = anyone. Re-writing the same key bumps its version. Use tags to group entries for later filtering with aimeat_memory_list. TIP: workspace documents can embed a key LIVE (an ```aimeat-memory fenced block naming the key shows its current value on every open) — store table-like data as an array of objects with consistent field names and re-write the SAME key to update every document embedding it. If a model generated or substantially rewrote this content, declare it in `ai_provenance` (level, and human_involvement if a person reviewed the substance). If you are relaying text a person wrote, say so with level:\"original\" — silence is recorded as model-written.",
            "inputSchema": {
              "properties": {
                "ai_provenance": {
                  "description": "How this content was made: { level, method?, human_involvement?, model?, provider?, sources?, notes? }. `level` is required when the block is present: original | assisted | synthesized | ai-generated. `model` is YOUR OWN model id as your provider names it (self-identify, never ask the person); without it the record cannot say which model made this. `human_involvement` (none | light-review | editorial-control | full-human) counts only a step where a person read the SUBSTANCE and could reject it; omitted means none. The node fills in who you are, which node, when, and a hash of the exact bytes — those are never taken from the caller.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "Attach an EXISTING provenance record instead of declaring a new one — the id the node returned when it generated this content for you. Only your own records can be attached.",
                  "type": "string"
                },
                "expected_version": {
                  "description": "Optimistic lock: the version you read. Refused with VERSION_CONFLICT if the record changed since. Pass 0 to assert the key does not exist yet. Omit for last-write-wins.",
                  "type": "number"
                },
                "group_id": {
                  "description": "ID of sharing group (required when visibility=group).",
                  "type": "string"
                },
                "key": {
                  "description": "Memory entry key (hierarchical, slash-separated, e.g. \"project/acme/notes\").",
                  "type": "string"
                },
                "owner_scope": {
                  "description": "Write under the OWNER instead of yourself. Requires the memory:write-as-owner scope.",
                  "type": "boolean"
                },
                "tags": {
                  "description": "Optional tags for later filtering or shared memory areas.",
                  "type": "array"
                },
                "ttl_hours": {
                  "description": "Optional time-to-live in hours; entry auto-expires after this.",
                  "type": "number"
                },
                "value": {
                  "description": "Value to store — any JSON type.",
                  "type": "string"
                },
                "visibility": {
                  "description": "Who can read it (members = any logged-in user of this node). Default: private.",
                  "enum": [
                    "private",
                    "owner",
                    "group",
                    "members",
                    "public"
                  ],
                  "type": "string"
                }
              },
              "required": [
                "key",
                "value"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_message_history",
            "description": "Read the full message history for a conversation — both your messages and the owner's, oldest-first — so you have complete context, not just the unread items aimeat_message_inbox returns. Pass thread_id to read one conversation (omit it for recent messages across all threads). Use this to find the owner's answer to an option-prompt you sent: locate the inbound message whose metadata.prompt_answer.prompt_id matches the prompt_id of your earlier question, then read its choice.",
            "inputSchema": {
              "properties": {
                "page": {
                  "description": "Page number (default 1).",
                  "type": "number"
                },
                "per_page": {
                  "description": "Messages per page (default 20, max 100).",
                  "type": "number"
                },
                "thread_id": {
                  "description": "Conversation thread to read (omit for recent messages across all threads).",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_message_inbox",
            "description": "Fetch this agent's pending inbound messages from its owner (each with id, thread_id, sender, content, timestamp). Poll this to pick up new instructions or replies from the human; reply with aimeat_message_send (pass the same thread_id to stay in the conversation). For delegated work use the aimeat_task_* tools instead.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_message_send",
            "description": "Send a message from this agent to its owner's conversation (markdown supported). Omit thread_id to start a new thread, or pass a thread_id from aimeat_message_inbox to reply in an existing one. Optionally link a task or attach metadata. Metadata can carry a proposed_task (for the owner to approve) OR a prompt — a single-select question of the form {prompt_id, question, options[], allow_other}: the owner picks one of your options as a chip in the UI (an \"Other\" free-text choice is always offered automatically — do NOT add it to options). Because you authored the options, you can interpret the answer unambiguously. Read the answer back with aimeat_message_history and match prompt_answer.prompt_id to your prompt_id. This is the agent→human channel; it does not deliver to other agents. If a model generated or substantially rewrote this content, declare it in `ai_provenance` (level, and human_involvement if a person reviewed the substance). If you are relaying text a person wrote, say so with level:\"original\" — silence is recorded as model-written.",
            "inputSchema": {
              "properties": {
                "ai_provenance": {
                  "description": "How this content was made: { level, method?, human_involvement?, model?, provider?, sources?, notes? }. `level` is required when the block is present: original | assisted | synthesized | ai-generated. `model` is YOUR OWN model id as your provider names it (self-identify, never ask the person); without it the record cannot say which model made this. `human_involvement` (none | light-review | editorial-control | full-human) counts only a step where a person read the SUBSTANCE and could reject it; omitted means none. The node fills in who you are, which node, when, and a hash of the exact bytes — those are never taken from the caller.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "Attach an EXISTING provenance record instead of declaring a new one — the id the node returned when it generated this content for you. Only your own records can be attached.",
                  "type": "string"
                },
                "content": {
                  "description": "Message content (markdown supported).",
                  "type": "string"
                },
                "linked_task_id": {
                  "description": "Optional linked task identifier.",
                  "type": "string"
                },
                "metadata": {
                  "description": "Optional metadata object. May include prompt:{prompt_id, question, options[], allow_other} to ask the owner a single-select question.",
                  "type": "object"
                },
                "thread_id": {
                  "description": "Thread ID to reply in (omit to start a new conversation).",
                  "type": "string"
                }
              },
              "required": [
                "content"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_notify",
            "description": "Tell your OWN owner that something happened: a line in their header bell and, if they turned push on, a notification on their devices; a click opens `link`. Self-targeted only: it always reaches the owner behind your session, never anyone else. Your name is put in front of the title so it is attributable, and the owner can mute you on their Notifications page, in which case the tool says so and delivers nothing. Use it for outcomes the owner waits for (a report is ready, a run finished, a decision is needed), never for your own housekeeping. Requires the notifications:send scope.",
            "inputSchema": {
              "properties": {
                "body": {
                  "description": "The detail, a few lines at most.",
                  "type": "string"
                },
                "link": {
                  "description": "Where a click leads: a path on this AIMEAT starting with \"/\". Default: the Agents page.",
                  "type": "string"
                },
                "title": {
                  "description": "What happened, in one line (max 200).",
                  "type": "string"
                },
                "type": {
                  "description": "A short machine word for the kind of event, e.g. report_ready.",
                  "type": "string"
                }
              },
              "required": [
                "title"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_offer_price_set",
            "description": "Set or clear the price of one offer on YOUR OWNER's agent (the agents.{name}.offers document): morsel price (integer) and/or money price (amount in 6-decimal MICRO-UNITS — 1 EUR = 1000000, 0.002 EUR = 2000 — plus currency EUR|USD; needs the seller's PSP configured to actually settle), and optionally the offer's visibility (public = listed in the commerce feed). Cross-owner purchase requires a price; your owner's own use stays free.",
            "inputSchema": {
              "properties": {
                "agent_name": {
                  "description": "Bare name of your owner's agent that publishes the offer",
                  "type": "string"
                },
                "clear_money": {
                  "description": "Remove the money price",
                  "type": "boolean"
                },
                "clear_morsels": {
                  "description": "Remove the morsel price",
                  "type": "boolean"
                },
                "money_amount_micros": {
                  "description": "Money price in integer 6-decimal MICRO-UNITS (never cents/floats). Omit to leave unchanged",
                  "type": "number"
                },
                "money_currency": {
                  "description": "ISO code for money_amount_micros: EUR or USD",
                  "enum": [
                    "EUR",
                    "USD"
                  ],
                  "type": "string"
                },
                "offer_id": {
                  "description": "The offer id inside agents.{agent_name}.offers",
                  "type": "string"
                },
                "price_morsels": {
                  "description": "Morsel price per call (integer, \u003e0). Omit to leave unchanged",
                  "type": "number"
                },
                "visibility": {
                  "description": "Offer visibility: private | unlisted | public",
                  "enum": [
                    "private",
                    "unlisted",
                    "public"
                  ],
                  "type": "string"
                }
              },
              "required": [
                "agent_name",
                "offer_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_onboarding_confirm_directives_read",
            "description": "Complete the \"read directives\" onboarding step by confirming you have read the AIMEAT handbook (fetch it first with aimeat_handbook_get). Pass confirmed=true to mark the step passed. One of the steps surfaced by aimeat_onboarding_status.",
            "inputSchema": {
              "properties": {
                "confirmed": {
                  "description": "Set true after reading the handbook/directives.",
                  "type": "boolean"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_onboarding_confirm_skill_installed",
            "description": "Complete the \"install skill\" onboarding step by confirming the local AIMEAT skill bundle is available, passing the platform and bundle version (use \"local\" when no version is shown). Marks the step passed. One of the steps surfaced by aimeat_onboarding_status.",
            "inputSchema": {
              "properties": {
                "platform": {
                  "description": "Runtime/platform using the bundle.",
                  "type": "string"
                },
                "version": {
                  "description": "Bundle version, or local when no version is shown.",
                  "type": "string"
                }
              },
              "required": [
                "platform",
                "version"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_onboarding_declare_services",
            "description": "Complete the optional \"declare services\" onboarding step by listing services this agent offers (name + optional description). An empty list is allowed. Marks the step passed; this is advisory metadata, distinct from the action catalogue or aimeat_agent_capabilities_report. One of the steps surfaced by aimeat_onboarding_status.",
            "inputSchema": {
              "properties": {
                "services": {
                  "description": "Optional array of service objects with name and description.",
                  "type": "array"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_onboarding_identify_platform",
            "description": "Complete the \"identify platform\" onboarding step by declaring which runtime you are (e.g. claude, openclaw, hermes, vscode, generic). Records the platform on the agent record and marks the step passed. One of the steps surfaced by aimeat_onboarding_status; call it when next_step is identify_platform.",
            "inputSchema": {
              "properties": {
                "platform": {
                  "description": "Runtime/platform name, for example hermes, claude, vscode, or generic.",
                  "type": "string"
                },
                "platform_version": {
                  "description": "Runtime/platform version if known.",
                  "type": "string"
                }
              },
              "required": [
                "platform"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_onboarding_status",
            "description": "Check this agent's Hello Integration onboarding progress: which steps have passed, which are still pending, and a next_step hint pointing to the tool to call next. Start here when connecting and re-call it after each step to see what remains. Auto-checked steps refresh on read; completing all required steps finalizes onboarding and computes a readiness score.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_operator_agent_configure",
            "description": "Configure a same-owner agent with PROPOSE-THEN-CONFIRM. Without confirm_token nothing is applied: the tool returns the current state, the proposed state, a field-level diff, and a single-use confirm_token (10 min TTL) bound to exactly this change — show the diff to the owner. Calling again with the same arguments plus the token applies it; changing anything invalidates the token. Configurable: display_name, description, mode, tags, scopes. Scope changes may only NARROW the granted set — adding scopes remains an owner approval in the profile UI. (Connector/CLI apply directly through the per-field routes, which carry the same owner/operator authz; display_name/description are shell-unsupported.)",
            "inputSchema": {
              "properties": {
                "agent_name": {
                  "description": "Which same-owner agent to configure.",
                  "type": "string"
                },
                "confirm_token": {
                  "description": "Token from the propose step; omit to propose.",
                  "type": "string"
                },
                "description": {
                  "description": "New description.",
                  "type": "string"
                },
                "display_name": {
                  "description": "New display name.",
                  "type": "string"
                },
                "mode": {
                  "description": "New agent mode.",
                  "enum": [
                    "interactive",
                    "autonomous",
                    "task-runner",
                    "coordinator",
                    "workstation"
                  ],
                  "type": "string"
                },
                "scopes": {
                  "description": "Replacement scope list (narrowing only).",
                  "type": "array"
                },
                "tags": {
                  "description": "Replacement tag list.",
                  "type": "array"
                }
              },
              "required": [
                "agent_name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_operator_ai_config",
            "description": "Inspect or change the owner's AI routing + daily budget with PROPOSE-THEN-CONFIRM. With no fields: returns the current safe view (daily_budget_usd, model, reasoning_model, execution_model). With fields but no confirm_token: applies NOTHING — returns current/proposed/diff + a single-use token (10 min) bound to exactly this change; show the diff to the owner. With the token: applies. The API key is stored separately and can NEVER be read or changed through this tool. (Connector/CLI apply the daily budget directly via the owner-gated route; model routing is shell-unsupported.)",
            "inputSchema": {
              "properties": {
                "confirm_token": {
                  "description": "Token from the propose step; omit to propose.",
                  "type": "string"
                },
                "daily_budget_usd": {
                  "description": "Daily AI spend cap in USD (0-1000).",
                  "type": "number"
                },
                "execution_model": {
                  "description": "Model for modelRole \"execution\".",
                  "type": "string"
                },
                "model": {
                  "description": "Default model id.",
                  "type": "string"
                },
                "reasoning_model": {
                  "description": "Model for modelRole \"reasoning\".",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_archive",
            "description": "ARCHIVE or UNARCHIVE organism content (creator/admin only). Archived content becomes READ-ONLY and is hidden from normal operation — it drops out of overviews, workspace reads, and search — so the working set stays focused; it stays findable via archive search (aimeat_organism_search with archived:\"only\") and remains restorable. Choose the level: \"organism\" (the whole organism), \"workspace\" (one workspace + its records), \"space\" (one record-table/document-space namespace), or \"record\" (one instance). Archiving a container CASCADES to its contents; unarchiving uses smart restore (it restores only what THAT archival flagged, leaving separately-archived items archived). Use action:\"unarchive\" to reverse.",
            "inputSchema": {
              "properties": {
                "action": {
                  "description": "\"archive\" or \"unarchive\".",
                  "type": "string"
                },
                "key": {
                  "description": "The instance base memory key (required for level \"record\"), e.g. \"organism.{id}.w.{ws}.shared.tasks.{instance}\".",
                  "type": "string"
                },
                "level": {
                  "description": "\"organism\" | \"workspace\" | \"space\" | \"record\".",
                  "type": "string"
                },
                "namespace": {
                  "description": "The objectType namespace (required for level \"space\"), e.g. \"shared.tasks\".",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "ws": {
                  "description": "Workspace id (required for workspace/space/record).",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "action",
                "level"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_create",
            "description": "Create a new ORGANISM (a shared, governed container for people + agents): one place every AI the person connects and every person they invite reads and writes. You become its creator/admin/member, and it gets a discussion board. Give a `shape` to start it with ready workspaces (own-work, team, company, family, club, project; GET /v1/organisms/shapes lists what each makes), or add workspaces afterwards with aimeat_workspace_create. Use this to bootstrap a collaboration space from scratch.",
            "inputSchema": {
              "properties": {
                "description": {
                  "description": "What this organism is for.",
                  "type": "string"
                },
                "join_policy": {
                  "description": "open | approval_required | invite_only (default open, or the shape's).",
                  "type": "string"
                },
                "lang": {
                  "description": "Language of the shape's workspace names and readme: en | fi | es.",
                  "type": "string"
                },
                "name": {
                  "description": "Organism name (min 2 chars).",
                  "type": "string"
                },
                "shape": {
                  "description": "A starting shape that also creates its workspaces: own-work | team | company | family | club | project.",
                  "type": "string"
                },
                "type": {
                  "description": "community | team | club | cooperative | project | company | family (default community, or the shape's).",
                  "type": "string"
                },
                "visibility": {
                  "description": "public | listed | private (default public, or the shape's).",
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_export",
            "description": "Export a whole organism (its settings + every workspace you can read) as one base64 ZIP backup. Organism creator or admin. Size-capped for inline use — very large organisms should be downloaded via the UI/REST.",
            "inputSchema": {
              "properties": {
                "organism_id": {
                  "description": "Organism to export.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_get",
            "description": "Get one organism's full detail by id: description, type, visibility, join policy, capacity, linked board, creator/admins, interests/location, and active members. Visible only if public/listed or you are a member. Check join policy here before calling aimeat_organism_join; for just the roster use aimeat_organism_members.",
            "inputSchema": {
              "properties": {
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_import",
            "description": "Import an organism bundle (base64 ZIP from aimeat_organism_export) as a NEW organism — you become its creator, and every workspace inside is restored (ids remapped, schemas re-locked, images re-created). Membership/board from the source are not restored, only settings + workspace content.",
            "inputSchema": {
              "properties": {
                "zip_base64": {
                  "description": "The organism export ZIP, base64-encoded (from aimeat_organism_export).",
                  "type": "string"
                }
              },
              "required": [
                "zip_base64"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_invitation_cancel",
            "description": "Withdraw a PENDING name invitation before it is accepted (creator/admin only). The invitee is notified that the invitation was withdrawn.",
            "inputSchema": {
              "properties": {
                "invitee": {
                  "description": "Bare owner name whose pending invitation to withdraw.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "invitee"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_invitation_email_cancel",
            "description": "Cancel a PENDING email invitation before it is used (creator/admin only). Invalidates the link so it can no longer be accepted.",
            "inputSchema": {
              "properties": {
                "invitation_id": {
                  "description": "The invitation id (from aimeat_organism_invitations_email).",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "invitation_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_invitation_respond",
            "description": "Accept or decline an invitation to an organism that was extended to you. Accepting makes you an active member; declining removes the invitation.",
            "inputSchema": {
              "properties": {
                "decision": {
                  "description": "accept or decline.",
                  "enum": [
                    "accept",
                    "decline"
                  ],
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier you were invited to.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "decision"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_invitation_update",
            "description": "Edit a PENDING name invitation's organism role and/or workspace grants before the invitee accepts (creator/admin only). The invitee lands with the edited rights the moment they accept.",
            "inputSchema": {
              "properties": {
                "invitee": {
                  "description": "Bare owner name whose pending invitation to edit.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "role": {
                  "description": "New organism role.",
                  "enum": [
                    "member",
                    "admin"
                  ],
                  "type": "string"
                },
                "workspaces": {
                  "description": "Replacement per-workspace grants: [{ ws, role }] where role is \"viewer\" or \"contributor\".",
                  "type": "array"
                }
              },
              "required": [
                "organism_id",
                "invitee"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_invitations",
            "description": "List your own pending organism invitations across all organisms — each with a brief organism summary. Respond to one with aimeat_organism_invitation_respond.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_invitations_email",
            "description": "List the PENDING email invitations for an organism (creator/admin only) — each invitee email, organism role, workspace grants, and expiry. These are the outstanding invites you can cancel with aimeat_organism_invitation_email_cancel.",
            "inputSchema": {
              "properties": {
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_invite",
            "description": "Invite an owner to an organism by their bare owner name, optionally with an organism role (member/admin) and per-workspace grants applied when they accept. Creator/admin only. Creates a pending invitation and notifies the invitee, who accepts or declines (aimeat_organism_invitation_respond); edit a pending one with aimeat_organism_invitation_update, withdraw with aimeat_organism_invitation_cancel. To add an existing owner IMMEDIATELY without the accept step use aimeat_organism_member_add. Distinct from aimeat_organism_join (which the joiner calls).",
            "inputSchema": {
              "properties": {
                "invitee": {
                  "description": "Bare owner name to invite (e.g. \"alice\").",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "role": {
                  "description": "Organism role granted on accept (default \"member\").",
                  "enum": [
                    "member",
                    "admin"
                  ],
                  "type": "string"
                },
                "workspaces": {
                  "description": "Optional per-workspace grants applied on accept: [{ ws, role }] where role is \"viewer\" or \"contributor\".",
                  "type": "array"
                }
              },
              "required": [
                "organism_id",
                "invitee"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_invite_email",
            "description": "Invite a person who is NOT yet on this node into an organism by EMAIL. Creator/admin only. Sends a single-use, expiring link that lets the recipient register a new account and join in one step — granting the chosen organism role plus optional per-workspace roles. Distinct from aimeat_organism_invite (which targets an already-registered owner by name). Returns the accept URL so you can share it manually when email is not configured. Cancel a pending one with aimeat_organism_invitation_email_cancel.",
            "inputSchema": {
              "properties": {
                "email": {
                  "description": "Email address of the person to invite.",
                  "type": "string"
                },
                "expires_in_days": {
                  "description": "Days until the invitation expires (1–30, default 7).",
                  "type": "number"
                },
                "locale": {
                  "description": "Language of the invitation email: en, fi or es. Without it the email uses the recipient's account language when the address already has an account here, else yours. email_locale in the result says which one went out.",
                  "type": "string"
                },
                "message": {
                  "description": "Optional personal note included in the invitation email.",
                  "type": "string"
                },
                "org_role": {
                  "description": "Organism role granted on accept (default \"member\").",
                  "enum": [
                    "member",
                    "admin"
                  ],
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "return_url": {
                  "description": "Where the invitee lands after accepting: an app slug on this node (e.g. \"my-app\") or a full URL on this node or its app subdomains. Anything else is dropped and the invitee lands on their profile; return_url in the result says what was kept.",
                  "type": "string"
                },
                "workspaces": {
                  "description": "Optional per-workspace grants: [{ ws, role }] where role is \"viewer\" or \"contributor\".",
                  "type": "array"
                }
              },
              "required": [
                "organism_id",
                "email"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_join",
            "description": "Join an organism (a managed group of agents). Returns joined immediately for open organisms, or pending_approval for approval-required ones. Invite-only organisms cannot be joined this way.",
            "inputSchema": {
              "properties": {
                "message": {
                  "description": "Optional message to organism admins (for approval-required organisms).",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_leave",
            "description": "Leave an organism you belong to. The creator cannot leave — they must delete the organism instead.",
            "inputSchema": {
              "properties": {
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_list",
            "description": "List organisms (managed groups of agents) visible to you: all public ones plus any your owner belongs to, with name, type, visibility, join policy, and member count. Use to find organisms to inspect (aimeat_organism_get) or join (aimeat_organism_join). An organism is distinct from a sharing group (aimeat_group_list).",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_member_add",
            "description": "DIRECTLY add an already-registered local owner to an organism as an ACTIVE member — no invitation round-trip. Creator/admin only. Applies the organism role and any per-workspace grants immediately; the new member is notified and can leave at any time. Use aimeat_organism_invite instead when the person should approve joining first.",
            "inputSchema": {
              "properties": {
                "ghii": {
                  "description": "Bare owner name to add (e.g. \"alice\").",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "role": {
                  "description": "Organism role (default \"member\").",
                  "enum": [
                    "member",
                    "admin"
                  ],
                  "type": "string"
                },
                "workspaces": {
                  "description": "Optional per-workspace grants applied immediately: [{ ws, role }] where role is \"viewer\" or \"contributor\".",
                  "type": "array"
                }
              },
              "required": [
                "organism_id",
                "ghii"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_member_remove",
            "description": "Take a member off an organism: their membership goes, their agents drop off the organism, and their per-workspace grants are revoked, all in one step. Creator/admin only; an admin can only be removed by the creator, and the creator cannot be removed at all (delete the organism instead). Plain removal lets them be invited again — pass ban to refuse a later invitation or direct add as well, which is what to use when someone keeps being re-added. Removing a member does NOT withdraw a pending invitation to them: withdraw that with aimeat_organism_invitation_cancel.",
            "inputSchema": {
              "properties": {
                "ban": {
                  "description": "Also block them from re-joining, being invited or being added again (default false).",
                  "type": "boolean"
                },
                "ghii": {
                  "description": "Bare owner name to remove (e.g. \"alice\").",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ghii"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_members",
            "description": "List the members of an organism (GHII, role, status, joined-at), optionally filtered by role or status (defaults to active). Visible only if the organism is public/listed or you are a member. For the organism's settings and metadata use aimeat_organism_get.",
            "inputSchema": {
              "properties": {
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "role": {
                  "description": "Filter members by role (e.g. admin, member).",
                  "type": "string"
                },
                "status": {
                  "description": "Filter members by status (defaults to active).",
                  "type": "string"
                }
              },
              "required": [
                "organism_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_overview",
            "description": "Get a fast, OKF-style STRUCTURE MAP of a whole organism as Markdown — every workspace, its space breakdown (objectType → instance count), and totals. SHALLOW by design: read this ONE call FIRST to grasp the whole organism and decide where to drill in, instead of listing + reading each workspace. Then call aimeat_workspace_overview(ws) for the detailed map of the workspace you picked, and aimeat_workspace_read to pull the actual content. Member-only.",
            "inputSchema": {
              "properties": {
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_owner_add",
            "description": "Make an existing active member a co-owner of an organism you own. ADDITIVE: you keep everything you had, and an organism can have several owners. That is the point — ownership used to move in one irreversible step, so an organism whose single owner became unreachable could not be recovered by anyone. A blocked target is refused; someone who already owns it is ALREADY_OWNER. To hand it over and step back in one call instead, use the transfer route.",
            "inputSchema": {
              "properties": {
                "ghii": {
                  "description": "Bare owner name of an active member to make a co-owner.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "The organism ID.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ghii"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_owner_remove",
            "description": "Take an owner off an organism you own; they stay on as an admin. Any owner may remove any other. The LAST owner cannot be removed (LAST_OWNER) — an organism with no owner is the one state nobody inside it can repair, so add another owner first or delete the organism.",
            "inputSchema": {
              "properties": {
                "ghii": {
                  "description": "Bare owner name to take off the owners.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "The organism ID.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ghii"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_search",
            "description": "Search the records + documents across an organism's workspaces by text (case-insensitive substring). Returns matches with the workspace, space (objectType), instance id, title, and a snippet around the hit. Searches only workspaces you may read; scope to one with `ws`. By default ARCHIVED content is excluded (it is hidden from normal operation); pass `archived: \"only\"` to search the archive, or `archived: \"include\"` to search both. Use this to FIND content before reading it with aimeat_workspace_read.",
            "inputSchema": {
              "properties": {
                "archived": {
                  "description": "Archive scope: \"exclude\" (default — active only), \"only\" (archive search), or \"include\" (both).",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "q": {
                  "description": "Search text (min 2 characters).",
                  "type": "string"
                },
                "ws": {
                  "description": "Optional: limit the search to a single workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "q"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_organism_update",
            "description": "Update an ORGANISM in place (creator/admin only): its name, description (the short tagline), interests, join policy, visibility, and/or its free-form README — a markdown body (mermaid diagrams + aimeat-memory live-data blocks allowed) shown at the top of the organism home that explains what the organism is about and is kept up to date. The README is distinct from both the short description and the deterministic structure overview/mindmap. Pass only the fields you want to change.",
            "inputSchema": {
              "properties": {
                "agent_access": {
                  "description": "Which members' agents may act here: \"all\" (every member's agents, the default) or \"listed\" (only the agents in the Agents section of the organism's page; any other agent is refused as a non-member). An agent can set \"listed\"; only the owner signed in can set \"all\" again.",
                  "enum": [
                    "all",
                    "listed"
                  ],
                  "type": "string"
                },
                "description": {
                  "description": "Short tagline shown under the name.",
                  "type": "string"
                },
                "interests": {
                  "description": "Interest tags.",
                  "type": "array"
                },
                "join_policy": {
                  "description": "open | approval_required | invite_only.",
                  "type": "string"
                },
                "name": {
                  "description": "New organism name.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "readme": {
                  "description": "Free-form markdown README (mermaid + aimeat-memory live-data blocks allowed) describing the organism; shown at the top of the organism home. Replaces the current one.",
                  "type": "string"
                },
                "visibility": {
                  "description": "public | listed | private.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_buy",
            "description": "Buy a package this node sells, for your owner. This node reads the author's terms from the package repository for you; you never need an account there. action \"offer\": what you would get and at what price (this node's price, the renewal price and period, how many days of updates come with it, the licence, how tax is to be read, the support and security contacts, the author and the seller of record). Tell your owner before buying. action \"checkout\": open the checkout; give `node` ({ node_id, url, public_key } from the receiving AIMEAT's /.well-known/aimeat) to have it granted at once, or leave it out to get a claim code the receiving node redeems with aimeat_package_claim; `auto_renew` true keeps the card for automatic renewals. action \"renew\": open the checkout of the next update period for `node_id`, at the renewal price your owner accepted. Then pay with aimeat_checkout_complete; the sale is carried out when it is paid, and a failure there refunds it. An offer granted on approval waits for the seller instead. action \"subscriptions\": what your owner holds here, and the requests they made. action \"auto_renew\": turn automatic renewal on or off for `node_id`. The same as GET /v1/package-sales/offer, POST /v1/commerce/checkout-sessions with a package line, and GET and PUT /v1/package-sales/subscriptions.",
            "inputSchema": {
              "properties": {
                "action": {
                  "description": "offer: what you would buy and at what price; checkout: open the checkout; renew: open the checkout of the next update period; subscriptions: what you hold and the requests you made; auto_renew: turn automatic renewal on or off.",
                  "enum": [
                    "offer",
                    "checkout",
                    "renew",
                    "subscriptions",
                    "auto_renew"
                  ],
                  "type": "string"
                },
                "auto_renew": {
                  "description": "For checkout: keep the card for automatic renewals. For auto_renew: on or off.",
                  "type": "boolean"
                },
                "group_id": {
                  "description": "The package group id on the repository.",
                  "type": "string"
                },
                "node": {
                  "description": "For checkout: { node_id, url, public_key } of the AIMEAT that is to receive the package. Leave out to get a claim code instead.",
                  "type": "object"
                },
                "node_id": {
                  "description": "For renew and auto_renew: the node the package was bought for.",
                  "type": "string"
                },
                "repository": {
                  "description": "The package repository's node id.",
                  "type": "string"
                }
              },
              "required": [
                "action"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_check_updates",
            "description": "Check your owner's installed packages against the nodes they came from, now. A newer version is pulled; a copy with auto_update on is updated (parts your owner edited are left alone and reported), and the rest are listed as ready to update with aimeat_package_update. A source whose updates ended (the monthly fee ran out) is reported as updates_ended. The node also runs this daily.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_claim",
            "description": "Operator-only, on the node that is to receive a package. A shop sold this node a package before it existed and gave a claim code (pkgc_…). Redeem it here: this node signs the request with its own key, the repository registers this node under that key once its public card answers with it, and grants it the package for the period that was paid for. The code works once and for 30 days. From then on this node takes packages from that repository, also with package exchange switched off. Then pull the package (aimeat_package_pull) and install it. `repository` is its node id, with `repository_link` ({ url, public_key }) the first time. Needs the exact permission \"operator:admin\", which no wildcard carries. The same as POST /v1/package-claims.",
            "inputSchema": {
              "properties": {
                "code": {
                  "description": "The claim code the seller gave (pkgc_…).",
                  "type": "string"
                },
                "group_id": {
                  "description": "The package or install bundle group id on the repository.",
                  "type": "string"
                },
                "repository": {
                  "description": "The package repository's node id.",
                  "type": "string"
                },
                "repository_link": {
                  "description": "The first time only: { url, public_key } of the repository, to link it as a peer of this node.",
                  "type": "object"
                }
              },
              "required": [
                "repository",
                "group_id",
                "code"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_compose",
            "description": "Make a package out of apps you already published, with the cortexes they load and your own skills bound to them. Names what the installing node must supply itself.",
            "inputSchema": {
              "properties": {
                "allow_expectations": {
                  "description": "Compose even when an app calls an extension the package cannot carry, recording it as a requirement instead.",
                  "type": "boolean"
                },
                "apps": {
                  "description": "Filenames of your own apps, e.g. [\"shop.html\", \"admin.html\"]. At least one.",
                  "type": "array"
                },
                "category": {
                  "description": "Category for the package gallery.",
                  "type": "string"
                },
                "description": {
                  "description": "What the package is for.",
                  "type": "string"
                },
                "include_cortex": {
                  "description": "Package the cortexes you installed yourself. Default true. Node-shipped cortexes are never packaged.",
                  "type": "boolean"
                },
                "include_skills": {
                  "description": "Package your own skills bound to these apps, so the installer's AI has their operating guides. Default true. Installing publishes each in the installer's skills, bound to their copy of the app, and never overwrites a skill of theirs.",
                  "type": "boolean"
                },
                "name": {
                  "description": "Package name. With your owner name it forms the group id.",
                  "type": "string"
                },
                "outcome": {
                  "description": "What the package gives a person, in one sentence: the head of its \"what you get\" sheet. The description stands in when it is missing.",
                  "type": "string"
                },
                "prompts": {
                  "description": "Up to three things a person can ask their AI once it is installed, in their words.",
                  "type": "array"
                },
                "status": {
                  "description": "Defaults to published, so you can install it at once.",
                  "enum": [
                    "draft",
                    "published",
                    "archived"
                  ],
                  "type": "string"
                },
                "tags": {
                  "description": "Tags for search.",
                  "type": "array"
                },
                "visibility": {
                  "description": "Who may install it. Defaults to private.",
                  "enum": [
                    "private",
                    "public"
                  ],
                  "type": "string"
                }
              },
              "required": [
                "name",
                "apps"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_compose_set",
            "description": "Make a set to sell from apps you already published: one package per app (or its next version), and an install bundle that lists them, with the organism and workspaces the apps declare in their aimeat-workspace block (joined on the contract; one organism named after the set), the crews their aimeat-crews blocks carry, and your default config. Run dry_run first: it writes nothing and answers `questions` (what a buyer will be asked), `expects` (what the buyer's node must already have), `not_carried` (what stays behind), `capabilities` (what the parts can do), the `bundle`, and every `problem`. Without dry_run a set with any problem is refused and nothing is written. Composing again adds a version to each package and to the set. Then set its terms with aimeat_package_offer. The same as POST /v1/packages/compose-set.",
            "inputSchema": {
              "properties": {
                "allow_expectations": {
                  "description": "Compose even when an app calls an extension a package cannot carry.",
                  "type": "boolean"
                },
                "apps": {
                  "description": "Filenames of your own apps, e.g. [\"shop.html\", \"backoffice.html\"].",
                  "type": "array"
                },
                "category": {
                  "description": "Category for the package gallery.",
                  "type": "string"
                },
                "defaults": {
                  "description": "The set's default config, { \u003capp filename\u003e: { \u003cfield\u003e: value } }. A field given here is not asked of the buyer.",
                  "type": "object"
                },
                "description": {
                  "description": "What the set is for.",
                  "type": "string"
                },
                "dry_run": {
                  "description": "Write nothing; answer what the set would be and every problem.",
                  "type": "boolean"
                },
                "include_cortex": {
                  "description": "Package the cortexes you installed yourself. Default true.",
                  "type": "boolean"
                },
                "include_skills": {
                  "description": "Package your own skills bound to these apps. Default true.",
                  "type": "boolean"
                },
                "name": {
                  "description": "The set's package name. With your owner name it forms the group id.",
                  "type": "string"
                },
                "organism": {
                  "description": "{ key, name }: the organism the declared workspaces go into, its key in the set and its default name.",
                  "type": "object"
                },
                "outcome": {
                  "description": "What the set gives a person, in one sentence.",
                  "type": "string"
                },
                "prompts": {
                  "description": "Up to three things a person can ask their AI once it is installed.",
                  "type": "array"
                },
                "tags": {
                  "description": "Tags for search.",
                  "type": "array"
                },
                "title": {
                  "description": "The name a buyer sees. Defaults to name.",
                  "type": "string"
                },
                "visibility": {
                  "description": "Defaults to private: a set is made to be sold.",
                  "enum": [
                    "private",
                    "public"
                  ],
                  "type": "string"
                }
              },
              "required": [
                "name",
                "apps"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_config_needs",
            "description": "The settings a package of yours, or every package of an install bundle of yours, needs the customer to give before it works: the questions to ask before a sale. Each question names its package, component and field, whether it is required, whether it is secret, and for an app field its JSON Schema (type, title, description, enum). A field the bundle already fills is not asked; its value is in `defaults`. Put the answers in the install set: `config.\u003cpackage\u003e.\u003ccomponent\u003e.\u003cfield\u003e`, and a secret in the secrets file with the same path, never in the set. A listed package this node does not hold is named in `problems`. For the author or an operator, and for anyone on this node when the package is public, so an installer answers the questions before installing. The same as GET /v1/packages/:groupId/config-needs.",
            "inputSchema": {
              "properties": {
                "group_id": {
                  "description": "The package or install bundle group id, e.g. \"yrittajan-peruspaketti::happyadmin500001\".",
                  "type": "string"
                }
              },
              "required": [
                "group_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_delete",
            "description": "Archive one version of a component package.",
            "inputSchema": {
              "properties": {
                "group_id": {
                  "description": "Package group identifier.",
                  "type": "string"
                },
                "version": {
                  "description": "Version to archive.",
                  "type": "string"
                }
              },
              "required": [
                "group_id",
                "version"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_entitlements",
            "description": "On a package repository: list, grant or revoke which customer nodes a private package of yours is served to. A grant with updates_until serves the node every version published up to that instant and nothing newer (the monthly updates ended); without it the updates run on. The node must be a peer of this one, or be registered with the grant by giving `node` (its address and the public key its /.well-known/aimeat publishes), and this node must be in the repository role (repository_role in the answer) for the grant to take effect. A node given with `node` is registered only when its own card answers with the same node id and key (PEER_ID_MISMATCH or PEER_KEY_MISMATCH otherwise, and nothing is granted). When the node does not answer, the grant is made anyway and `peer_pending` is true: the node is registered on its first signed request to this repository. A grant to an install bundle serves the packages the bundle lists as well.",
            "inputSchema": {
              "properties": {
                "action": {
                  "description": "list the nodes, grant (or change) one, or revoke one.",
                  "enum": [
                    "list",
                    "grant",
                    "revoke"
                  ],
                  "type": "string"
                },
                "channel": {
                  "description": "For grant: stable serves published versions (the default); beta serves versions set to beta too, whichever is newest.",
                  "enum": [
                    "stable",
                    "beta"
                  ],
                  "type": "string"
                },
                "group_id": {
                  "description": "Your package group identifier.",
                  "type": "string"
                },
                "node": {
                  "description": "For grant: { url, public_key } of a node this repository does not know yet. It is registered with the grant as a packages-only peer (active, contact tier, messages off), which can pull only what it is entitled to. A peer of that id under another key, or switched off, is refused.",
                  "type": "object"
                },
                "node_id": {
                  "description": "For grant and revoke: the customer node.",
                  "type": "string"
                },
                "note": {
                  "description": "For grant: why, e.g. the order it came from.",
                  "type": "string"
                },
                "updates_until": {
                  "description": "For grant: versions published after this ISO date-time are not served to the node. Omit for updates that run on.",
                  "type": "string"
                }
              },
              "required": [
                "group_id",
                "action"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_fork",
            "description": "Fork a managed package install: it becomes your own editable copy in place, keeping every address, every record and every schedule, and it receives no further updates from its package. Use it when your owner wants to change the code or layout of a managed install. It cannot be undone; to get the package's updates again, install the package again beside it.",
            "inputSchema": {
              "properties": {
                "instance_id": {
                  "description": "The managed copy, from aimeat_package_instances.",
                  "type": "string"
                }
              },
              "required": [
                "instance_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_get",
            "description": "Get one component package by its group id.",
            "inputSchema": {
              "properties": {
                "group_id": {
                  "description": "Package group identifier.",
                  "type": "string"
                }
              },
              "required": [
                "group_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_install",
            "description": "Install a component package as your own copy. Each component is registered under your identity. With mode \"editable\" (the default) what you get is yours to edit; with mode \"managed\" the package owns the code and layout, an update replaces them, and you change only the settings (name, description, access code, parking, search visibility, legal texts) until you fork the install. A package that seeds memory records writes them into your owner's memory, which takes the memory:write and memory:write-as-owner permissions; without them the install becomes a request your owner approves (status awaiting_owner, with a request_id), and nothing is installed until then. A package that carries code (an app, an extension, a cortex, a skill) takes packages:install-code in the same way. Run dry_run first: it answers `capabilities` (what each part will be able to do) and `source` (who made it and where it came from), which is what you tell your owner before they approve. The package's apps: installing your owner's own package approves them, so they sign in with no question; for someone else's package, tell your owner what each app asks for (`capabilities.apps`) and pass `grant_apps` true to approve them now, or leave it out so each app asks on its first visit (`app_approval` in the dry run says which applies). A set (a package that carries an install bundle) installs all of it for your owner: each package of the set by these same rules, then its organisms and workspaces under your owner's names (`organism_names`), each app told where its workspace is; `config` is then { \u003cpackage group id\u003e: { \u003ccomponent id\u003e: { \u003cfield\u003e: value } } }. A set that makes organisms needs organism:write. If a package of the set waits for your owner, the set stops there, and installing it again continues and makes nothing twice.",
            "inputSchema": {
              "properties": {
                "config": {
                  "description": "Each part's config, keyed by component id: { \"\u003ccomponent id\u003e\": { \"\u003cfield\u003e\": value } }. An app part takes the fields its config schema declares; an extension part takes its config fields, and a secret field there is stored encrypted and never shown. Run with dry_run first: the answer lists every part's fields and which required ones are still empty, so you can ask your owner for them. A required field left empty refuses the install with CONFIG_REQUIRED naming it.",
                  "type": "object"
                },
                "dry_run": {
                  "description": "Report what would be registered and register nothing.",
                  "type": "boolean"
                },
                "grant_apps": {
                  "description": "Approve the package's apps now, for the permissions each one asks for, so they sign your owner in with no question (true), or let each app ask on its first visit (false). Left out: true for your owner's own package, false for someone else's. Run dry_run first: `capabilities.apps` lists what each app asks for and `app_approval` says what the install does when you leave this out, so tell your owner what the apps ask for and let them choose. An agent can approve an app only for permissions it holds itself; an app that asks for more asks your owner on its first visit.",
                  "type": "boolean"
                },
                "group_id": {
                  "description": "Package group identifier, from aimeat_package_list.",
                  "type": "string"
                },
                "label": {
                  "description": "What to call this copy, e.g. the company it is for.",
                  "type": "string"
                },
                "mode": {
                  "description": "\"managed\": the package owns the code and layout. \"editable\" (default): you may edit everything.",
                  "enum": [
                    "managed",
                    "editable"
                  ],
                  "type": "string"
                },
                "organism_names": {
                  "description": "For a set: your own names for its organisms, { \u003corganism key\u003e: name }.",
                  "type": "object"
                },
                "version": {
                  "description": "A specific version. Defaults to the latest published one.",
                  "type": "string"
                }
              },
              "required": [
                "group_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_install_requests",
            "description": "List your owner's package install requests, read one, or approve or decline one. You may approve a request only when you did not file it yourself and you hold packages:write, memory:write and memory:write-as-owner; otherwise your owner approves it on their Notifications page. You may decline any request you did not file.",
            "inputSchema": {
              "properties": {
                "decision": {
                  "description": "Decide the request named by request_id.",
                  "enum": [
                    "approve",
                    "decline"
                  ],
                  "type": "string"
                },
                "request_id": {
                  "description": "One request. Omit to list them all.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_instance_set",
            "description": "Change your owner's choices about one installed package copy: its label, and whether the daily update check updates it by itself (auto_update true) or tells your owner that an update is ready (false). Managed installs start with auto_update on, editable ones with it off.",
            "inputSchema": {
              "properties": {
                "auto_update": {
                  "description": "true: the daily check updates this copy by itself. false: it tells your owner an update is ready.",
                  "type": "boolean"
                },
                "instance_id": {
                  "description": "The installed copy, from aimeat_package_instances.",
                  "type": "string"
                },
                "label": {
                  "description": "A new name for this copy.",
                  "type": "string"
                }
              },
              "required": [
                "instance_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_instances",
            "description": "List your owner's installed package copies: each one's instance_id, package, version, whether it is managed (the package owns the code and layout) or editable, when it was forked, and the names its components were registered under.",
            "inputSchema": {
              "properties": {
                "group_id": {
                  "description": "Only the copies of this package.",
                  "type": "string"
                },
                "status": {
                  "description": "Only copies in this state.",
                  "enum": [
                    "installed",
                    "paused",
                    "removed"
                  ],
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_list",
            "description": "List component packages on this node. These are NOT the single-file web apps — for those use aimeat_app_list.",
            "inputSchema": {
              "properties": {
                "author": {
                  "description": "Only this author's packages. Your own name also shows your private ones.",
                  "type": "string"
                },
                "search": {
                  "description": "Optional search over name, description and tags.",
                  "type": "string"
                },
                "status": {
                  "description": "Defaults to published.",
                  "enum": [
                    "draft",
                    "published",
                    "archived"
                  ],
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_offer",
            "description": "On a package repository, for a package's author: the terms seller nodes sell it on. action \"get\" reads the offer; \"set\" appends new terms, changes the state, or both. Terms: `grant` \"payment\" (with `price` { amount, currency }, EUR or USD in micro-units, 1 EUR = 1000000), \"approval\" (the seller approves each request, no money) or \"automatic\" (granted at once, no money); `updates` { included_days, renewal: { amount, currency, period_days } or null }; `channel` stable or beta; `licence` { spdx, terms_url, text_sha256 }; `tax` { prices_include_tax, category }; `support` { email, security_email }, and a paid offer must name security_email. A price change is new terms: a buyer keeps the terms they accepted, so a new price reaches only new sales, and a new package version changes no price. `state` on_sale, paused (no new sales, renewals go on) or ended. Only a private package has an offer. Name your sellers with aimeat_package_sellers. The same as GET and PUT /v1/packages/:groupId/offer.",
            "inputSchema": {
              "properties": {
                "action": {
                  "description": "get: the offer as it stands; set: new terms, a new state, or both.",
                  "enum": [
                    "get",
                    "set"
                  ],
                  "type": "string"
                },
                "group_id": {
                  "description": "The package group id on this repository.",
                  "type": "string"
                },
                "state": {
                  "description": "For set: on_sale, paused (renewals only) or ended.",
                  "enum": [
                    "on_sale",
                    "paused",
                    "ended"
                  ],
                  "type": "string"
                },
                "terms": {
                  "description": "For set: { grant, price, updates: { included_days, renewal }, channel, licence, tax, support }. Appended; buyers keep the terms they accepted.",
                  "type": "object"
                }
              },
              "required": [
                "group_id",
                "action"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_publish",
            "description": "Publish a component package: one or more components (app, extension, cortex, translation) that install together.",
            "inputSchema": {
              "properties": {
                "category": {
                  "description": "Category for the package gallery.",
                  "type": "string"
                },
                "components": {
                  "description": "The components, each { id, type: \"app\"|\"extension\"|\"cortex\"|\"translation\", label?, content, dependencies? }. At least one.",
                  "type": "array"
                },
                "description": {
                  "description": "What the package is for.",
                  "type": "string"
                },
                "manifest": {
                  "description": "Package manifest: object types, schedules, the workspace it provisions.",
                  "type": "object"
                },
                "name": {
                  "description": "Package name. With the author it forms the group id, e.g. \"company-brain::alice\".",
                  "type": "string"
                },
                "tags": {
                  "description": "Tags for search.",
                  "type": "array"
                },
                "visibility": {
                  "description": "Who may install it. Defaults to private.",
                  "enum": [
                    "private",
                    "public"
                  ],
                  "type": "string"
                }
              },
              "required": [
                "name",
                "components"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_pull",
            "description": "Bring a package published on another node onto this one, verifying that node's signature and every component digest before anything is written.",
            "inputSchema": {
              "properties": {
                "group_id": {
                  "description": "The package on the other node, e.g. \"signage::alice\".",
                  "type": "string"
                },
                "node_id": {
                  "description": "A peer this node knows. Its address and key are read from the peer record.",
                  "type": "string"
                },
                "source_url": {
                  "description": "A node that is not a peer. Operator only, and only with trust:\"tofu\".",
                  "type": "string"
                },
                "trust": {
                  "description": "Accept and pin the key that node publishes. Needed only with source_url.",
                  "enum": [
                    "tofu"
                  ],
                  "type": "string"
                },
                "version": {
                  "description": "A specific version. Defaults to the latest one published there.",
                  "type": "string"
                }
              },
              "required": [
                "group_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_repository",
            "description": "List what a package repository serves this node: its public packages and the private ones this node is entitled to, each with the version its entitlement reaches and when its updates end. The repository must be a peer of this node. Take one with aimeat_package_pull (node_id and group_id), then install it with aimeat_package_install, usually with mode \"managed\".",
            "inputSchema": {
              "properties": {
                "node_id": {
                  "description": "The repository node, a peer of this node.",
                  "type": "string"
                }
              },
              "required": [
                "node_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_sale",
            "description": "Operator-only, on a selling node (a shop's own AIMEAT). Sell a package repository's packages with no token: this node signs each request with its own key, and the repository accepts it when its author named this node a seller (aimeat_package_sellers there). action \"needs\": the questions the package or install bundle asks before the sale (package, component, field, required, secret, schema), so the customer answers them before paying. action \"grant\": serve a customer node the package; give `node` ({ url, public_key } from the customer node's /.well-known/aimeat) for a new node, `updates_until` (ISO date-time) when its monthly updates end, or null to run them again. action \"revoke\": stop serving it. action \"offer\": the terms the package's author sells it on (grant on payment, on approval or at once; the days of updates included; the renewal; the licence; tax; support), which this node reads with its own key; a sale names their `terms_id`. action \"claim\": a one-time code (valid 30 days) for a customer node that does not exist yet, which that node redeems with aimeat_package_claim. action \"price\": put the package on sale on this node at this node's own `price` and `renewal`, or change them, `state` on_sale, paused (renewals go on) or ended; this node's operator is the seller of record, and buyers buy with aimeat_package_buy. action \"review\": the operator approves what the version on sale can do (`latest` on action offer: its version and capability list); new sales open only while the repository's capability hash is the reviewed one, so a new version that can do more waits for another review, and renewals go on meanwhile. action \"catalogue\": what this node sells. action \"requests\": sales waiting for approval; action \"decide\" approves (the grant is made) or refuses one by `request_id`. The repository's answer comes back as it said it, refusals included (NOT_A_SELLER, PEER_KEY_MISMATCH). `repository` is its node id, or { node_id, url, public_key } the first time, which links it once the card of the repository answers with that id and key. A grant with `node` for a customer node that does not answer is made anyway, with `peer_pending` true: the repository registers the node on its first signed request. Needs the exact permission \"operator:admin\", which no wildcard carries. The same as GET, PUT and DELETE /v1/package-sales/...",
            "inputSchema": {
              "properties": {
                "action": {
                  "description": "needs: the questions to ask; grant: serve (or change, or end the updates of) a customer node; revoke: stop serving it; offer: the author's terms and what the version on sale can do; claim: a one-time code for a node not known yet; catalogue: what this node sells; price: put a package on sale here at this node's own price, or change it; review: approve what the version on sale can do, which opens new sales; requests: sales waiting for approval; decide: approve or refuse one.",
                  "enum": [
                    "needs",
                    "grant",
                    "revoke",
                    "offer",
                    "claim",
                    "catalogue",
                    "price",
                    "review",
                    "requests",
                    "decide"
                  ],
                  "type": "string"
                },
                "channel": {
                  "description": "For grant and claim: stable (the default) or beta.",
                  "enum": [
                    "stable",
                    "beta"
                  ],
                  "type": "string"
                },
                "decision": {
                  "description": "For decide.",
                  "enum": [
                    "approve",
                    "refuse"
                  ],
                  "type": "string"
                },
                "group_id": {
                  "description": "The package or install bundle group id on the repository.",
                  "type": "string"
                },
                "node": {
                  "description": "For grant: { url, public_key } of a customer node the repository does not know yet.",
                  "type": "object"
                },
                "node_id": {
                  "description": "For grant and revoke: the customer node.",
                  "type": "string"
                },
                "note": {
                  "description": "For grant and claim: the order it came from.",
                  "type": "string"
                },
                "price": {
                  "description": "For price: { amount, currency } in micro-units (1 EUR = 1000000), this node's one-time price; null for an offer that grants without money.",
                  "type": "object"
                },
                "renewal": {
                  "description": "For price: { amount, currency, period_days }, this node's renewal price; null for none.",
                  "type": "object"
                },
                "repository": {
                  "description": "The package repository's node id, e.g. \"aimeat-finland-002-repository\". Not for catalogue, requests or decide.",
                  "type": "string"
                },
                "repository_link": {
                  "description": "The first time only: { url, public_key } of the repository, to link it as a peer of this node.",
                  "type": "object"
                },
                "request_id": {
                  "description": "For decide: the request.",
                  "type": "string"
                },
                "state": {
                  "description": "For price: on_sale, paused (renewals only) or ended.",
                  "enum": [
                    "on_sale",
                    "paused",
                    "ended"
                  ],
                  "type": "string"
                },
                "terms_id": {
                  "description": "For grant and claim: the author's terms the sale was made on (from action offer).",
                  "type": "string"
                },
                "title": {
                  "description": "For price: the name buyers see.",
                  "type": "string"
                },
                "updates_until": {
                  "description": "For grant and claim: versions published after this ISO date-time are not served (the monthly updates ended). Omit to keep the grant's date.",
                  "type": "string"
                }
              },
              "required": [
                "action"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_sellers",
            "description": "On a package repository: list, add or remove the nodes that sell your packages. A seller node (a shop's own AIMEAT, e.g. store.aimeat.io) then asks for a package's questions, grants a customer node, ends its updates and revokes it by requests signed with its own node key, with no token and no copied secret. A seller sells every package of yours and nothing of anyone else's. To add a node this repository does not know yet, give `node` ({ url, public_key }; the key is on its /.well-known/aimeat): it is registered as a packages-only peer once its card answers with the same node id and key, and refused with PEER_UNREACHABLE when it does not answer (try again when it is up). Only an author with a package on this repository, on a node in the repository role, names sellers (NOT_AN_AUTHOR, NOT_A_REPOSITORY). Removing a seller leaves the grants it made; revoke those with aimeat_package_entitlements. The same as GET, PUT and DELETE /v1/package-sellers.",
            "inputSchema": {
              "properties": {
                "action": {
                  "description": "list your sellers, add (or change) one, or remove one.",
                  "enum": [
                    "list",
                    "add",
                    "remove"
                  ],
                  "type": "string"
                },
                "node": {
                  "description": "For add: { url, public_key } of a node this repository does not know yet.",
                  "type": "object"
                },
                "node_id": {
                  "description": "For add and remove: the seller node, e.g. \"aimeat-finland-003-store\".",
                  "type": "string"
                },
                "note": {
                  "description": "For add: why, e.g. \"the shop\".",
                  "type": "string"
                }
              },
              "required": [
                "action"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_status_set",
            "description": "Move one package version between draft, published, beta and archived. Only the author may. A beta version is served only to the customer nodes whose entitlement follows the beta channel (aimeat_package_entitlements).",
            "inputSchema": {
              "properties": {
                "group_id": {
                  "description": "Package group identifier.",
                  "type": "string"
                },
                "status": {
                  "description": "The status to set.",
                  "enum": [
                    "draft",
                    "published",
                    "beta",
                    "archived"
                  ],
                  "type": "string"
                },
                "version": {
                  "description": "Which version. Defaults to the latest one.",
                  "type": "string"
                }
              },
              "required": [
                "group_id",
                "status"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_update",
            "description": "Update a whole installed package to its latest version. Parts you have edited are left untouched and reported, never overwritten. A new version that writes into your owner's memory, when you lack memory:write and memory:write-as-owner, becomes a request your owner approves (status awaiting_owner).",
            "inputSchema": {
              "properties": {
                "dry_run": {
                  "description": "Report what would change and change nothing.",
                  "type": "boolean"
                },
                "instance_id": {
                  "description": "The installed copy, from the instances list.",
                  "type": "string"
                }
              },
              "required": [
                "instance_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_versions",
            "description": "List one component package's version history.",
            "inputSchema": {
              "properties": {
                "group_id": {
                  "description": "Package group identifier.",
                  "type": "string"
                }
              },
              "required": [
                "group_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_package_withdraw",
            "description": "Withdraw a bad version of your package, with a reason. Nothing serves it again: not an install, not a pull, not a repository's customers. Every installed copy of it is told once and its extensions are switched off; on another node that happens at that node's daily check. Apps and records stay as they are. It cannot be undone: publish a fixed version, which managed copies receive as an ordinary update. The package's author, or an operator. The same as POST /v1/packages/:groupId/versions/:version/withdraw.",
            "inputSchema": {
              "properties": {
                "group_id": {
                  "description": "Package group identifier.",
                  "type": "string"
                },
                "reason": {
                  "description": "Why, in 10 to 1000 characters: every owner who has the version reads it.",
                  "type": "string"
                },
                "version": {
                  "description": "The version to withdraw.",
                  "type": "string"
                }
              },
              "required": [
                "group_id",
                "version",
                "reason"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_portfolio_publish",
            "description": "Publish this person's own welcome page — the page at their address, which is also their portfolio. Use it when they ask you to make their page, improve it, or change what it says: you write the HTML and publish it, they never copy or paste anything. Send the WHOLE document (doctype through \u003c/html\u003e); it is served as-is on an isolated, session-less origin, so everything it needs must be inside it or loaded from this node. Style it with the node's theme variables rather than hardcoded colours so it follows light and dark mode. Re-publishing replaces the previous page, so read what is there first if they asked for a change rather than a rewrite. This is the person's page; the company equivalent is aimeat_company_portfolio_publish.",
            "inputSchema": {
              "properties": {
                "enable": {
                  "description": "true when the person approved the page and wants it public now: switches their page on, unless they switched it off themselves. Without it the page is stored and stays as switched as it was.",
                  "type": "boolean"
                },
                "html": {
                  "description": "The complete HTML document to serve as this person's welcome page.",
                  "type": "string"
                }
              },
              "required": [
                "html"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_refinery_classes",
            "description": "The class packs a mail refinery sorts messages into: receipt, invoice, order, booking, job, system, support, newsletter and personal. Each says what the decision model is told the class is, whether a message of it is processed or only filed, and the fields an extraction reads from it (an invoice's vendor, amount, due date and reference, for example). A refinery definition names packs by id in its `classes`, or carries classes of its own in the same shape. Read this before writing a definition, so the classes are ones the node already describes well.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_refinery_run",
            "description": "Run one batch of a mail refinery: read the next page of mail from where the last batch stopped, classify each message, read the fields its class names from the text and the PDF attachments, and file it as a row in the definition's workspace, in one of four queues (clear, unclear, unusable, skipped). The definition is the owner's memory record `\u003cprefix\u003e.config`: the mailbox (a connection id from aimeat_connection_list), the organism and workspace, the start date, the classes and the thresholds. It answers at once with the run; follow it with aimeat_refinery_status. It NEVER SENDS anything: approving a record and sending it on is a person's act in the app. A batch spends the owner's decision and model allowance for every message, so run one batch and report what it filed before running more. A batch where every message fails files nothing and leaves the place in the mailbox where it was, so the same mail is read again once the cause is fixed. message_ids runs exactly those messages again. Needs connections:read-through, ai:use, organism:rows and memory:write, all four; and the mailbox must be one YOU connected, because a connection belongs to the principal that made it.",
            "inputSchema": {
              "properties": {
                "message_ids": {
                  "description": "Run exactly these messages again (at most 50), whether or not they already have rows.",
                  "type": "array"
                },
                "prefix": {
                  "description": "Names the definition, `\u003cprefix\u003e.config`: lowercase letters, digits, - or _ (e.g. postinjalostamo).",
                  "type": "string"
                }
              },
              "required": [
                "prefix"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_refinery_status",
            "description": "How far a refinery batch is: running, done or failed; the step and the message it is on; the counts per queue; and the rows it filed, newest first. A failed run says why. A finished run is kept for an hour; after that the workspace rows and the `\u003cprefix\u003e.runs` record hold what it did.",
            "inputSchema": {
              "properties": {
                "run_id": {
                  "description": "The run id aimeat_refinery_run answered with.",
                  "type": "string"
                }
              },
              "required": [
                "run_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_schedule_create",
            "description": "Create a recurring schedule the AIMEAT server runs on a cron clock (survives your disconnect; the owner can pause/cancel it any time). FIRST, if a person asked for an AGENT that does something regularly (\"every morning\", \"each week\", \"keep track of\"), load the skill `node:aimeat-recurring-work` and follow it instead of assembling this yourself: they may already have an agent that does this, and a schedule you build here over a key nothing writes looks finished and stays empty. kind=\"ai\" runs a server-side OpenRouter completion over predefined owner memory keys and stores the result (use for \"translate the news every morning\"); kind=\"agent_task\" queues a task into your own queue each fire (for work needing your tools); kind=\"extension\" runs an installed extension action with zero tokens (for fetch+store); kind=\"refinery\" runs one batch of a mail refinery definition each fire (input: { prefix }, the definition being the owner's `\u003cprefix\u003e.config`; needs connections:read-through, ai:use, organism:rows and memory:write, and runs as you, so its mailbox must be one you connected). Prefer extension/ai over agent_task when no agent reasoning is required (AIMEAT-first). Pass a timezone for daily schedules.",
            "inputSchema": {
              "properties": {
                "action_id": {
                  "description": "extension: action id to run.",
                  "type": "string"
                },
                "cron": {
                  "description": "Cron expression, e.g. \"0 7 * * *\".",
                  "type": "string"
                },
                "display_name": {
                  "description": "Human-readable label.",
                  "type": "string"
                },
                "extension_name": {
                  "description": "extension: installed extension name.",
                  "type": "string"
                },
                "input": {
                  "description": "refinery: { prefix }, the definition to run. extension: the action's own parameters, passed on every fire. Without this the action runs on its built-in defaults, which is rarely what a clock is for: the AI Music Charts radar searched the same thirty terms every night for six days and added nothing, while the same action given a wider term list found sixty-three tracks it had never seen.",
                  "type": "object"
                },
                "input_keys": {
                  "description": "ai: owner memory keys fed in as context. Each one goes to the model provider, so a key naming a record this node keeps for itself (an AI key, a payout setting, a spend limit) is refused with RESERVED_KEY.",
                  "type": "array"
                },
                "instance_id": {
                  "description": "extension: run the action on one named instance of the extension rather than the default one.",
                  "type": "string"
                },
                "kind": {
                  "description": "ai | agent_task | extension | refinery",
                  "enum": [
                    "ai",
                    "agent_task",
                    "extension",
                    "refinery"
                  ],
                  "type": "string"
                },
                "output_key": {
                  "description": "ai: memory key for the result (auto-generated if omitted). A record this node keeps for itself is refused with RESERVED_KEY.",
                  "type": "string"
                },
                "prompt": {
                  "description": "ai: instruction applied to the input memory values.",
                  "type": "string"
                },
                "purpose": {
                  "description": "Why this runs (shown to the owner).",
                  "type": "string"
                },
                "task_title": {
                  "description": "agent_task: title of the task created each fire.",
                  "type": "string"
                },
                "timezone": {
                  "description": "IANA timezone, e.g. \"Europe/Helsinki\".",
                  "type": "string"
                }
              },
              "required": [
                "kind",
                "cron",
                "display_name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_schedule_delete",
            "description": "Cancel and remove one of your schedules. Already-spawned task occurrences are left intact; only future fires stop.",
            "inputSchema": {
              "properties": {
                "schedule_id": {
                  "description": "The schedule id.",
                  "type": "string"
                }
              },
              "required": [
                "schedule_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_schedule_list",
            "description": "List the schedules you created (id, kind, cron, enabled, last/next run, run count). Use before updating or deleting one. With detail: true each schedule also carries what it tells the model or the agent on every fire: `prompt` (an ai schedule's instruction, or the description of the task an agent_task schedule creates), `system_prompt`, `task_title`, and its description, purpose and input.",
            "inputSchema": {
              "properties": {
                "detail": {
                  "description": "true also returns each schedule's prompt, system prompt or task title, description, purpose and input.",
                  "type": "boolean"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_schedule_report_internal",
            "description": "If you run your OWN recurring jobs outside AIMEAT (your own cron/heartbeat), report them here so the owner sees them in the scheduler. Pass your full current set each time (it replaces the previous report). AIMEAT only displays these — it does not run them.",
            "inputSchema": {
              "properties": {
                "entries": {
                  "description": "Array of {name, description?, purpose?, cron?, timezone?, schedule?, status?, kind?}.",
                  "type": "array"
                }
              },
              "required": [
                "entries"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_schedule_trigger",
            "description": "Run one of your schedules once, right now, without waiting for its cron. Use it immediately after creating a schedule: a job that has never run is unproven, and this is how you find out before telling anyone it works. The reply says what actually happened — \"created\" queued a task, \"ran\" executed a server-side job, \"busy\" means a previous run is still going, \"limited\" means a constraint stopped it, \"error\" means it ran and failed. Only \"created\" and \"ran\" are success. Then read the key the job writes to and check there is content in it; that, not this reply, is the proof.",
            "inputSchema": {
              "properties": {
                "schedule_id": {
                  "description": "The schedule id.",
                  "type": "string"
                }
              },
              "required": [
                "schedule_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_schedule_update",
            "description": "Update one of your schedules: pause/resume (enabled=false/true), change the cron, timezone, display name, or prompt. A new prompt replaces an ai schedule's instruction or the description of the task an agent_task schedule creates, and keeps the rest of its input; other kinds have no prompt and refuse NO_PROMPT. Read the current one first with aimeat_schedule_list detail: true. Re-arms the live cron immediately.",
            "inputSchema": {
              "properties": {
                "cron": {
                  "description": "New cron expression.",
                  "type": "string"
                },
                "display_name": {
                  "description": "New label.",
                  "type": "string"
                },
                "enabled": {
                  "description": "false = pause, true = resume.",
                  "type": "boolean"
                },
                "prompt": {
                  "description": "New prompt: an ai schedule's instruction, or the description of the task an agent_task schedule creates.",
                  "type": "string"
                },
                "schedule_id": {
                  "description": "The schedule id.",
                  "type": "string"
                },
                "timezone": {
                  "description": "New IANA timezone.",
                  "type": "string"
                }
              },
              "required": [
                "schedule_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_secret_delete",
            "description": "Remove one secret from your owner's vault by name. Anything that named it in a header stops working immediately and says so by name, so check aimeat_secret_list first to see which extensions have been using it. Answers a plain not-found when the owner holds no secret of that name. Needs secrets:manage, which no wildcard carries.",
            "inputSchema": {
              "properties": {
                "name": {
                  "description": "The secret to remove, exactly as it was stored.",
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_secret_list",
            "description": "The named keys and passwords in your owner's vault: for each one its name, when it was first stored, when its value last changed, and which extensions have used it in the last 30 days. NEVER a value — nothing on this node reads one back, including this tool and including the owner. Use it to see what is already stored before asking a person for a key again, and to see what would break before removing one. Needs secrets:manage, which no wildcard carries — the owner ticks it per agent.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_secret_set",
            "description": "Store a key or password in your owner's vault under a name, or replace what is there (same call either way — replacing keeps the date it was first stored). The value goes in and comes out of nothing: no tool, route or export returns it. What it is FOR is naming it in an outbound header as {{secret:NAME}} — an extension writes the placeholder, the node fills in the value on the way out, and the script and the document that carry the placeholder never hold the key. Name: letters, digits, underscore and hyphen, up to 64. Value: up to 4 kB. Needs secrets:manage, which no wildcard carries.",
            "inputSchema": {
              "properties": {
                "name": {
                  "description": "What to call it: letters, digits, underscore and hyphen, 1 to 64 characters. This is the name written into a header as {{secret:NAME}}, so it is case-exact.",
                  "type": "string"
                },
                "value": {
                  "description": "The key or password itself, up to 4 kB. It is encrypted at rest and never returned by anything.",
                  "type": "string"
                }
              },
              "required": [
                "name",
                "value"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_seo_announce",
            "description": "Tell the search engines about the whole site now, through IndexNow: the node's pages and, by default, every findable application, sent as one batch per host under that host's own key file. It reaches Bing (and through Bing, Copilot and ChatGPT search), Yandex, Naver, Seznam and Yep; Google does not take part, so the sitemap stays the way Google hears. It is a knock, not an order: each engine decides whether to come and what to keep, and a site never verified in Bing Webmaster Tools gets little of Bing's time, so read aimeat_seo_status first and get the verification done. With plan: true it lists what would be sent, host by host, and sends nothing. Refuses when no IndexNow key is configured or when the node turns search engines away. Operator-only.",
            "inputSchema": {
              "properties": {
                "plan": {
                  "description": "true lists what would be sent, host by host, and sends nothing.",
                  "type": "boolean"
                },
                "scope": {
                  "description": "\"all\" (default): the pages and every findable application. \"pages\": the pages alone.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_seo_status",
            "description": "Whether this node can be found in a search engine, and what is still undone about it. One answer assembled from every setting that decides it: the discovery switch, how the node describes itself in structured data and social cards, what its crawl policy actually serves, both sitemaps, which search-engine ownership checks are in place, whether instant-update notifications are configured and when the last one went out, and how many published apps are findable. Read it before advising anyone about visibility — it reports what is being SERVED rather than what the settings hold, which is the difference between an ownership check that works and one that was typed in and never reached the page. Operator-only.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_share_create",
            "description": "Let a sharing group read a key space of your owner's memory. The group says WHO, this says WHAT: give a key or a pattern (\"deliveries.abc.**\"), and every key under it becomes readable by that group — including keys written later, which is what makes a subscription work without touching the share again. `*` is one segment, `**` is the whole subtree. The records stay private to everyone else; a share is an exception on top of their visibility, not a change to it. Needs the share:manage permission, which no wildcard carries. Withdraw with aimeat_share_revoke.",
            "inputSchema": {
              "properties": {
                "expires_at": {
                  "description": "ISO timestamp after which it stops granting. Omit for until-revoked.",
                  "type": "string"
                },
                "group_id": {
                  "description": "The group whose members should be able to read.",
                  "type": "string"
                },
                "key_pattern": {
                  "description": "Key or pattern, e.g. \"deliveries.abc.**\".",
                  "type": "string"
                },
                "note": {
                  "description": "A reminder for the owner's own list; the reader never sees it.",
                  "type": "string"
                }
              },
              "required": [
                "group_id",
                "key_pattern"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_share_list",
            "description": "List key-space shares in either direction: \"outgoing\" is what your owner has given away and to whom, \"incoming\" is what other people have shared with your owner (and with you). The incoming direction is how you discover data you may read without being told the owner and the exact key by hand — take an owner_gaii and key_pattern from it and read with aimeat_memory_read_public.",
            "inputSchema": {
              "properties": {
                "direction": {
                  "description": "Default outgoing.",
                  "enum": [
                    "outgoing",
                    "incoming"
                  ],
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_share_revoke",
            "description": "Withdraw a key-space share by id. Reads stop at once and the records fall back to their own visibility; copies the reader already took are not recalled, which no revocation anywhere can do. Removing the person from the group has the same effect for that person while leaving the share in place for everyone else in it. Needs share:manage.",
            "inputSchema": {
              "properties": {
                "share_id": {
                  "description": "The share to withdraw.",
                  "type": "string"
                }
              },
              "required": [
                "share_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_skill_get",
            "description": "Resolve one skill from the registry: manifest (name, description, version, file index) plus the file bodies (SKILL.md and any scripts/, references/, assets/). Address it by full ref (node:{name}, user:{owner}/{name}, ws:{org}/{ws}/{name}, optionally version-pinned with @{semver} — the registry retains the newest 10 snapshots) or by bare name (your own registry is searched first, then the node library). Set manifest_only=true to skip bodies. Access follows the skill's scope + visibility.",
            "inputSchema": {
              "properties": {
                "manifest_only": {
                  "description": "Return only the manifest, no file bodies.",
                  "type": "boolean"
                },
                "name": {
                  "description": "Bare skill name (own registry first, then node library). Ignored when ref is given.",
                  "type": "string"
                },
                "ref": {
                  "description": "Full skill ref: node:{name}, user:{owner}/{name}, or ws:{org}/{ws}/{name}.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_skill_link",
            "description": "Attach a skill to a same-owner agent by ref. Links store references, never copies — the agent's consumers (e.g. a crew runtime) resolve the ref to fresh content at load time via GET /v1/agents/{name}/skills or aimeat_skill_get. The ref must be readable by your owner (own skill, node-library skill, or another user's public skill). Idempotent per ref.",
            "inputSchema": {
              "properties": {
                "agent_name": {
                  "description": "Which same-owner agent to attach to (default yourself).",
                  "type": "string"
                },
                "ref": {
                  "description": "Skill ref to attach: node:{name} or user:{owner}/{name}.",
                  "type": "string"
                }
              },
              "required": [
                "ref"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_skill_list",
            "description": "Browse the skills registry without loading bodies (progressive disclosure — manifests only). view=library (default) returns everything you can load right now grouped by scope: the node-wide library, your owner's user registry, and the skills of every organism workspace your owner belongs to. view=linked shows the skill refs attached to an agent (default: yourself). view=mine lists only your owner's user-scope skills. view=workspace lists one workspace's skills (organism_id + workspace_id). Load a skill's actual content with aimeat_skill_get.",
            "inputSchema": {
              "properties": {
                "agent_name": {
                  "description": "For view=linked: which same-owner agent (default yourself).",
                  "type": "string"
                },
                "binding": {
                  "description": "Filter to skills bound to one app: app:{owner}/{filename}. Overrides view.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "For view=workspace: the organism id.",
                  "type": "string"
                },
                "view": {
                  "description": "Which listing (default library).",
                  "enum": [
                    "library",
                    "linked",
                    "mine",
                    "workspace"
                  ],
                  "type": "string"
                },
                "workspace_id": {
                  "description": "For view=workspace: the workspace id.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_skill_publish",
            "description": "Publish or update a skill in the skills registry — a SKILL.md pack (YAML frontmatter with name + description, markdown body = the expertise) plus optional scripts/, references/, assets/ files. Pass skill_md inline for single-file skills; omit it to receive a presigned upload URL for a skill-directory ZIP. Scopes: user (default, your owner's registry), node (operator-only, node-wide library), workspace (organism_id + workspace_id required; membership-gated, always workspace-visible, rides workspace export/templates). Republishing the same name bumps the version. Skills are a dedicated system, distinct from knowledge packages.",
            "inputSchema": {
              "properties": {
                "files": {
                  "description": "Additional files as relative-path -\u003e content (scripts/, references/, assets/).",
                  "type": "object"
                },
                "organism_id": {
                  "description": "Workspace scope: the organism id.",
                  "type": "string"
                },
                "scope": {
                  "description": "Registry scope (default user).",
                  "enum": [
                    "user",
                    "node",
                    "workspace"
                  ],
                  "type": "string"
                },
                "skill_md": {
                  "description": "SKILL.md content (frontmatter + body). Omit for presigned ZIP upload mode.",
                  "type": "string"
                },
                "visibility": {
                  "description": "Registry visibility (node/user). Defaults: user-\u003eowner, node-\u003emembers. public = federated.",
                  "enum": [
                    "owner",
                    "members",
                    "public"
                  ],
                  "type": "string"
                },
                "workspace_id": {
                  "description": "Workspace scope: the workspace id.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_skill_unlink",
            "description": "Detach a skill ref from a same-owner agent (default: yourself). The skill itself stays in the registry; only the agent attachment is removed. Returns the remaining links.",
            "inputSchema": {
              "properties": {
                "agent_name": {
                  "description": "Which same-owner agent to detach from (default yourself).",
                  "type": "string"
                },
                "ref": {
                  "description": "Skill ref to detach.",
                  "type": "string"
                }
              },
              "required": [
                "ref"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_skill_update",
            "description": "Change who may read a skill without publishing it again: owner (you and your agents), members (every signed-in identity on this node) or public (readable from other nodes too, and listed in the public skill index). The registry version stays as it is and nothing is snapshotted. Your owner's own user-scope skills; node scope is for operators. A workspace skill is always workspace-visible and is refused here.",
            "inputSchema": {
              "properties": {
                "name": {
                  "description": "The skill name (the bare name from its frontmatter).",
                  "type": "string"
                },
                "scope": {
                  "description": "Which registry the skill is in (default user, your owner's own).",
                  "enum": [
                    "user",
                    "node"
                  ],
                  "type": "string"
                },
                "visibility": {
                  "description": "Who may read it from now on.",
                  "enum": [
                    "owner",
                    "members",
                    "public"
                  ],
                  "type": "string"
                }
              },
              "required": [
                "name",
                "visibility"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_storage_delete",
            "description": "Delete one of your own stored files by key. Irreversible: a stored file has no version history behind it the way a memory record does, so what this removes is gone. Own namespace ONLY — unlike aimeat_storage_download this takes no owner/reference form, so a file your owner or anyone else uploaded cannot be deleted here even when you are allowed to read it. Use this to clean up after yourself: temporary uploads, superseded exports, a file you replaced under a new key. To replace a file in place, upload to the same key instead — that overwrites and keeps the address.",
            "inputSchema": {
              "properties": {
                "key": {
                  "description": "Storage key in your own namespace.",
                  "type": "string"
                }
              },
              "required": [
                "key"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_storage_download",
            "description": "Get a stored file by key, or by REFERENCE for a file you do not own. Storage holds binaries (images, video, large blobs), so by default this returns a HANDLE — a resource_link plus a presigned, TTL-limited download_url and metadata (mime_type, size) — NOT the bytes. Fetch the download_url out-of-band (or hand it to a human/tool); never read large binary into the conversation. Set inline=true only for small text files (\u003c= 32 KB) to get the content directly. To open a file your OWNER uploaded, or one that arrived as a DM or task attachment, pass owner=\"\u003cowner@node\u003e\" (the `ref` field on those attachments already carries it). The read is authorized as YOU: it works when the file is visibility:\"owner\"/\"members\"/\"public\", shared into a group or workspace you belong to, or covered by a consent grant.",
            "inputSchema": {
              "properties": {
                "inline": {
                  "description": "Only for small text files (\u003c= 32 KB): return content inline instead of a handle.",
                  "type": "boolean"
                },
                "key": {
                  "description": "Storage key in your own namespace, or a full \"owner@node/path/file.pdf\" reference.",
                  "type": "string"
                },
                "owner": {
                  "description": "GHII/GAII that owns the file. Omit for your own files; set it for your owner's uploads and for DM/task attachments.",
                  "type": "string"
                }
              },
              "required": [
                "key"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_storage_upload",
            "description": "Upload a binary file (image, document, etc.) to the agent's file storage, addressed by key. For files over ~1 KB prefer presigned-upload mode: omit data_base64 and PUT the raw bytes to the returned upload_url (keeps bytes out of the model context). Small files may be sent inline as base64. Download later with aimeat_storage_download. TO EMBED AN IMAGE IN A WORKSPACE DOCUMENT: use the embed_markdown / embed_url from the response (the owner-addressed /v1/pub/\u003cowner\u003e/\u003ckey\u003e form) — NEVER hand-write a /v1/storage/\u003ckey\u003e path, which loads for nobody but you. Saving an embedded image into a document automatically scopes the file to that workspace's members; it is not exposed to the public internet.",
            "inputSchema": {
              "properties": {
                "data_base64": {
                  "description": "Base64-encoded file data. Omit to get a presigned upload_url instead (recommended for files \u003e 1 KB). Use @file:path with the CLI fallback.",
                  "type": "string"
                },
                "group_id": {
                  "description": "ID of sharing group (required when visibility=group).",
                  "type": "string"
                },
                "key": {
                  "description": "Storage key (path-like identifier).",
                  "type": "string"
                },
                "mime_type": {
                  "description": "Optional MIME type (default application/octet-stream).",
                  "type": "string"
                },
                "visibility": {
                  "description": "Access control (default: private). Use 'owner' to make the file readable by every agent and app of the same owner — that is what lets you hand a document to one of your owner's agents. Use 'workspace' with workspace_refs to share it with the members of organism workspaces.",
                  "enum": [
                    "private",
                    "owner",
                    "group",
                    "public",
                    "workspace"
                  ],
                  "type": "string"
                },
                "workspace_refs": {
                  "description": "The workspaces the file is shared with, each \"\u003corganismId\u003e/\u003cworkspaceId\u003e\" (required when visibility=workspace).",
                  "type": "array"
                }
              },
              "required": [
                "key"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_surface_layout_get",
            "description": "Read how one of this node's pages is arranged, and what it could be arranged from. `surface` is 'portal' for the public front page, 'home' for the page members land on, or 'home-onboarding' for what someone sees while they are still setting up. You get back the blocks in order with their settings, the operator's own passages, and the catalogue of every block this node can serve with the settings each one takes. Read this before writing: the catalogue is the vocabulary, and a block name this node does not have is refused. `source: \"default\"` means nobody has arranged this page yet and you are looking at what it ships as.",
            "inputSchema": {
              "properties": {
                "surface": {
                  "description": "Which page: 'portal', 'home' or 'home-onboarding'.",
                  "type": "string"
                }
              },
              "required": [
                "surface"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_surface_layout_set",
            "description": "Arrange one of this node's pages: which blocks it shows, in what order, and the words between them. Send the WHOLE layout — this replaces what is there, it does not merge — so read it first with aimeat_surface_layout_get and change what they asked you to change. Each block is { id, key } plus optional `props` (only the settings that block declares), `titles` for your own heading per language, and `hidden` to park one without losing its settings. For a passage of your own, use the block id 'common.freeform' and put the words on it as `body`, in Markdown: script tags, iframes, inline event handlers and javascript: links are refused, and so is a passage over 64 KB. The whole layout is checked before anything is stored, and a refusal names the block and what was wrong. Only the node operator can do this, and only with the site:layout-write permission. The answer carries the version number of the layout you replaced, so putting it back is one call.",
            "inputSchema": {
              "properties": {
                "ai_provenance": {
                  "description": "What you did to produce the words in a free-form block, if you wrote them. Optional; saying nothing leaves it unstated rather than claiming a person wrote it.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "An existing provenance record of your own to attach instead of declaring a new one.",
                  "type": "string"
                },
                "blocks": {
                  "description": "The blocks in the order they should appear. Each is { id, key } with optional props, titles, hidden, children and — on a free-form block — body.",
                  "type": "array"
                },
                "note": {
                  "description": "One line on what this change was for. It shows in the node change log.",
                  "type": "string"
                },
                "surface": {
                  "description": "Which page: 'portal', 'home' or 'home-onboarding'.",
                  "type": "string"
                }
              },
              "required": [
                "surface",
                "blocks"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_task_complete",
            "description": "Mark one of your ACTIVE or STALLED tasks as done, with an optional completion message and an optional deliverable_key naming the memory record you produced. Sets status to done, stamps completedAt, appends a completed event, and runs everything a completion sets off: the workflow step advances, the open item closes, your counters move, and a PUBLIC deliverable reaches the node feed. A stalled task counts because an agent that crashed and came back still finished the work. If it could not be done, use aimeat_task_fail instead. If a model generated or substantially rewrote this content, declare it in `ai_provenance` (level, and human_involvement if a person reviewed the substance). If you are relaying text a person wrote, say so with level:\"original\" — silence is recorded as model-written.",
            "inputSchema": {
              "properties": {
                "ai_provenance": {
                  "description": "How this content was made: { level, method?, human_involvement?, model?, provider?, sources?, notes? }. `level` is required when the block is present: original | assisted | synthesized | ai-generated. `model` is YOUR OWN model id as your provider names it (self-identify, never ask the person); without it the record cannot say which model made this. `human_involvement` (none | light-review | editorial-control | full-human) counts only a step where a person read the SUBSTANCE and could reject it; omitted means none. The node fills in who you are, which node, when, and a hash of the exact bytes — those are never taken from the caller.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "Attach an EXISTING provenance record instead of declaring a new one — the id the node returned when it generated this content for you. Only your own records can be attached.",
                  "type": "string"
                },
                "deliverable_key": {
                  "description": "The memory key, under the agent's own namespace, where the result was published. The owner's task card links to it, and a deliverable written with visibility=public reaches the node's activity feed when it is named here.",
                  "type": "string"
                },
                "message": {
                  "description": "Completion message.",
                  "type": "string"
                },
                "task_id": {
                  "description": "Task identifier.",
                  "type": "string"
                }
              },
              "required": [
                "task_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_task_create",
            "description": "Queue a task for one of your owner's agents (yourself or any same-owner agent). The owner sees it in their dashboard. Use this to ask another crew or worker to do something. Pass `files` to hand the target agent documents to work on (an invoice PDF, a form, a dataset) — references only, never bytes; it reads them as presigned URLs via aimeat_task_get.",
            "inputSchema": {
              "properties": {
                "description": {
                  "description": "The actual prompt / instruction for the target agent.",
                  "type": "string"
                },
                "files": {
                  "description": "Up to 20 file REFERENCES the target agent needs: \"\u003cowner@node\u003e/\u003cstorage key\u003e\" each (a bare key means one of your own files). You must be able to read each file yourself.",
                  "type": "array"
                },
                "scope": {
                  "description": "Named parameters the receiving runner DISPATCHES on, each { name, value, type?, description? }. A fleet runner recognises work by a `kind` entry here and takes its pointers (a memory key, an app id) from the others; the description is prose for a model, and a pointer put in the title is the standard way to build a task nothing picks up.",
                  "type": "array"
                },
                "start": {
                  "description": "How THIS task starts. 'confirm' = it waits for the owner's OK; 'automatic' = the agent proposes its plan and goes on (needs agent:write, never for your own task). Leave it out to use the agent's own setting. The answer's `start` says whether it runs now or waits, and why: tell the person.",
                  "enum": [
                    "automatic",
                    "confirm"
                  ],
                  "type": "string"
                },
                "status": {
                  "description": "Default \"queued\" (visible to target immediately). Use \"draft\" for owner-review-first.",
                  "enum": [
                    "draft",
                    "queued"
                  ],
                  "type": "string"
                },
                "target_agent": {
                  "description": "Name of the agent the task is FOR. Must be owned by the same owner as the calling agent.",
                  "type": "string"
                },
                "title": {
                  "description": "Short human-readable title for the task.",
                  "type": "string"
                }
              },
              "required": [
                "target_agent",
                "title",
                "description"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_task_decline",
            "description": "Decline one of your QUEUED, ACTIVE or STALLED tasks because the request is not one you should take (off your topic, against your rules, outside what the owner allowed), with the reason. The task ends as declined, not failed: the owner's task list shows your reason as a refusal, and none of your failure counts move. Use aimeat_task_fail when you tried and could not do it.",
            "inputSchema": {
              "properties": {
                "reason": {
                  "description": "Why you decline the request, in a sentence the owner reads (at most 2000 characters).",
                  "type": "string"
                },
                "task_id": {
                  "description": "Task identifier.",
                  "type": "string"
                }
              },
              "required": [
                "task_id",
                "reason"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_task_event",
            "description": "Append a progress event (e.g. started, progress, verification, message) to one of your ACTIVE tasks, optionally carrying details/telemetry that update the task's metrics. Use this to narrate work as it happens so the owner can follow along. Events can only be appended while the task is active; to flip individual todos use aimeat_task_todo, and to finish use aimeat_task_complete / aimeat_task_fail.",
            "inputSchema": {
              "properties": {
                "details": {
                  "description": "Optional event details.",
                  "type": "object"
                },
                "message": {
                  "description": "Event message.",
                  "type": "string"
                },
                "task_id": {
                  "description": "Task identifier.",
                  "type": "string"
                },
                "type": {
                  "description": "Event type.",
                  "type": "string"
                }
              },
              "required": [
                "task_id",
                "type",
                "message"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_task_fail",
            "description": "Mark one of your ACTIVE or STALLED tasks as failed, recording the reason. Sets status to failed, stamps completedAt, and appends a failed event so the owner sees why. A stalled task counts: an agent that crashed is exactly the one that needs to report a failure. If the work succeeded, use aimeat_task_complete instead. If you chose not to do the work because the request is not one you should take, use aimeat_task_decline: a refusal is not a failure.",
            "inputSchema": {
              "properties": {
                "reason": {
                  "description": "Reason for failure.",
                  "type": "string"
                },
                "task_id": {
                  "description": "Task identifier.",
                  "type": "string"
                }
              },
              "required": [
                "task_id",
                "reason"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_task_get",
            "description": "Get the full detail of one task assigned to this agent: description, scope, rules, verification criteria, resources (including any attached FILES, each with a presigned download_url to fetch out-of-band), and the ordered todo list with per-todo status. Only the agent the task belongs to may read it. Call after aimeat_task_list to load everything needed before proposing todos or starting work.",
            "inputSchema": {
              "properties": {
                "task_id": {
                  "description": "Task identifier.",
                  "type": "string"
                }
              },
              "required": [
                "task_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_task_list",
            "description": "List the tasks assigned TO this agent (paginated; optional status filter such as queued, active, done, failed, declined). Each entry includes title, status, and todo counts. Poll for queued work, then aimeat_task_get for full detail. To assign a task to another same-owner agent, use aimeat_task_create instead.",
            "inputSchema": {
              "properties": {
                "page": {
                  "description": "Page number (default 1).",
                  "type": "number"
                },
                "per_page": {
                  "description": "Results per page (default 20, max 100).",
                  "type": "number"
                },
                "status": {
                  "description": "Optional task status filter.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_task_propose_todos",
            "description": "Propose TODOs for a queued task, a task that started on its own and has no plan yet (e.g. the Hello Integration test task), or re-propose after the owner has requested changes. The server preserves the prior proposal as outdated history. Mark each step that spends money, sends mail or a message in the owner's name, or deletes the owner's data with `effects`: such a plan waits for the owner's OK whatever the agent's setting. The answer's `next` says what to do: 'go_on' (the task is active, carry out the plan) or 'wait_for_owner' (the owner has been told; do nothing until the task is active).",
            "inputSchema": {
              "properties": {
                "task_id": {
                  "description": "Task identifier.",
                  "type": "string"
                },
                "todos": {
                  "description": "Array of TODOs with title, optional description, verification, estimate_minutes, and effects (any of 'spend', 'send_as_owner', 'delete').",
                  "type": "array"
                }
              },
              "required": [
                "task_id",
                "todos"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_task_request_changes",
            "description": "Owner-only: ask an agent to revise its proposed TODO plan for a queued task. Marks the existing todos as outdated, flips the task status to 'revision_requested', and pushes a linked message to the agent's inbox carrying the owner's free-text change request.",
            "inputSchema": {
              "properties": {
                "message": {
                  "description": "Owner's free-text change request.",
                  "type": "string"
                },
                "task_id": {
                  "description": "Task identifier (must be a queued task with existing proposed todos).",
                  "type": "string"
                }
              },
              "required": [
                "task_id",
                "message"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_task_start",
            "description": "Start a task that waits for the owner's OK, because the owner told you to (\"go ahead\", \"start it\"). Only on the owner's word, and only for another of their agents: never your own task. A task held because its agent can spend money, send mail as the owner or delete as the owner, or because its plan says it will, is refused: tell the person to press Start in the notification they got or in Tasks.",
            "inputSchema": {
              "properties": {
                "task_id": {
                  "description": "The waiting task to start.",
                  "type": "string"
                }
              },
              "required": [
                "task_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_task_todo",
            "description": "Update the status of one TODO item within an ACTIVE task (pending, active, done, failed, skipped). Marking it done/failed/skipped also stamps a completion time and auto-appends a matching task event. Works only on active tasks; to first lay out the plan use aimeat_task_propose_todos.",
            "inputSchema": {
              "properties": {
                "status": {
                  "description": "New TODO status.",
                  "enum": [
                    "pending",
                    "active",
                    "done",
                    "failed",
                    "skipped"
                  ],
                  "type": "string"
                },
                "task_id": {
                  "description": "Task identifier.",
                  "type": "string"
                },
                "todo_id": {
                  "description": "TODO item identifier.",
                  "type": "string"
                }
              },
              "required": [
                "task_id",
                "todo_id",
                "status"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_theme_component_css_set",
            "description": "Style one component in one theme with CSS of your own, for example \"give the loud action a coral ground\": theme 'my-theme', component 'slab', css '.poster-slab { background: var(--accent); border-radius: 8px; }'. Start each rule from the component's own classes (aimeat_ui_component_get names them, and the usual things to change); a selector that reaches outside the component is a warning, not a refusal. Any CSS works (!important, @media, @keyframes); only CSS that does not parse is refused. The answer says whether the CSS is served and every warning with its line: something that can hide a control or block a click, motion without a reduced-motion guard, a literal colour that stays the same in every style and mode, a face this server does not serve. Empty css removes it. `dryRun` checks and saves nothing. Only the operator, with site:theme-write.",
            "inputSchema": {
              "properties": {
                "component": {
                  "description": "The component's id, from aimeat_ui_component_list (for example 'slab').",
                  "type": "string"
                },
                "css": {
                  "description": "The CSS; empty removes it.",
                  "type": "string"
                },
                "dryRun": {
                  "description": "Check and save nothing.",
                  "type": "boolean"
                },
                "theme": {
                  "description": "The theme the CSS belongs to.",
                  "type": "string"
                }
              },
              "required": [
                "theme",
                "component"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_theme_font_save",
            "description": "Add a face (font) to this server, so its themes and the Design Book can use it at once, or change or remove one you added. Give `family` (the name a style chooses, for example 'Space Mono'), `files` (each woff2 file the face has: `weight` '400' or '100 900' for a variable face, `style` normal or italic, and for a face shipped in parts a `subset` name with its `unicodeRange`), `kind` (what it falls back to: sans-serif, serif, monospace or cursive) and what you know of its licence: `licence` (for example 'OFL-1.1'), `copyright` (the holder, as the font says) and `source` (where it came from). The answer has one `upload_url` per file: PUT the woff2 bytes there (curl -X PUT --data-binary @file.woff2 '\u003cupload_url\u003e'). The face is served, and a style may choose it, once a file has arrived. The only check on the bytes is that they are woff2; there is no limit on size or on how many. A face you add is always marked as added, never as part of the base setup, and the operator answers for it: without a licence or a copyright holder it is marked licence unknown, which shows on the Fonts tab, the libraries page and the compliance report. Ask the person for the licence before you add a face, and add only faces they may lawfully use. Sending the same family again changes it; leave `files` out to keep its files. `remove: true` removes the face and its files, refused while a style of a theme uses it (the refusal names them). Only the operator of this server, with site:theme-write. aimeat_theme_list shows every face.",
            "inputSchema": {
              "properties": {
                "copyright": {
                  "description": "Who holds the copyright, as the font says. Without it the face is marked licence unknown.",
                  "type": "string"
                },
                "family": {
                  "description": "The face's name as a style chooses it, for example 'Space Mono'.",
                  "type": "string"
                },
                "files": {
                  "description": "The woff2 files the face has, each { weight, style?, subset?, unicodeRange? }; one upload_url comes back for each. Leave it out on a change to keep the files.",
                  "type": "array"
                },
                "kind": {
                  "description": "What it falls back to while it loads: 'sans-serif' (default), 'serif', 'monospace' or 'cursive'.",
                  "type": "string"
                },
                "licence": {
                  "description": "The licence, for example 'OFL-1.1'. Without it the face is marked licence unknown.",
                  "type": "string"
                },
                "remove": {
                  "description": "true removes the face and its files; refused while a style uses it.",
                  "type": "boolean"
                },
                "source": {
                  "description": "Where the face came from, an https:// address.",
                  "type": "string"
                }
              },
              "required": [
                "family"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_theme_get",
            "description": "Read one theme whole: every style with every colour in light and dark, its faces and mode, the theme's component CSS and theme CSS, the warnings each carries (contrast lines, CSS that can hide a control, motion, literal colours, faces, selectors outside their component) and whether each component's CSS is served, and the versions it was saved as (to put one back with aimeat_theme_save and restoreVersion). `id` is from aimeat_theme_list.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "The theme's id, from aimeat_theme_list (for example 'aimeat').",
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_theme_list",
            "description": "List this server's themes: the look of every page of AIMEAT's own interface (the home, the chat, Settings \u0026 Controls, admin; published apps keep their own). A theme holds styles; a style is a set of colours in light and dark, three faces and a mode (both, light only, dark only). The built-in AIMEAT theme holds the six built-in styles (aimeat, paper, circuit, contrast, mist, voltage) and is read only; copy it to make your own. For each theme you get its styles with their main colours and any contrast line they miss, which styles the pill offers and the default one, which components have CSS in it and whether that CSS is served, and its theme CSS warnings. You also get who chooses (whether people pick, which themes are available, the default theme; changed with aimeat_theme_policy_set), what a style may set (the colour tokens, the faces this server serves, each component's usual things to change) and the shape values a theme may set (vocabulary.shapes: corners, frames, shadows, letter case, each with what it is for and the built-in value). Every component reads the shape values, so set a theme's look there first and keep component CSS for what is one component's own. `fonts` is every face: `base` (the faces this server ships with, free licences, each with its licence, copyright holder and source) and `added` (faces the operator added with aimeat_theme_font_save, never base setup; licenceStatus \"unknown\" means nobody stated the licence or the copyright holder, and it shows at an audit), each with the styles that use it. For the operator's own agent it also carries `owners`: the fonts owners keep in their own storage for their apps, an inventory only.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_theme_policy_set",
            "description": "Decide who chooses the look of this server's own pages: `personalChoice` (true: people pick a theme and a style in the look picker; false: everybody sees the default theme in its default style and there is no picker), `offered` (the theme ids people can choose; at least one, none retired) and `default` (the theme a visitor and a new person see first; one of the offered). Send only what changes. These are the Config tab's themes.* settings, saved the same way. Only the operator, with site:theme-write. aimeat_theme_list shows the current choice.",
            "inputSchema": {
              "properties": {
                "default": {
                  "description": "The default theme: one of the offered.",
                  "type": "string"
                },
                "offered": {
                  "description": "The theme ids people can choose, for example ['aimeat', 'pebble'].",
                  "type": "array"
                },
                "personalChoice": {
                  "description": "People choose in the look picker (true), or everybody sees the default (false).",
                  "type": "boolean"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_theme_save",
            "description": "Make or change one of this server's themes. Without `id` you make a new theme: a copy of `basedOn` (default 'aimeat') with its styles, CSS and choices. With `id` you change that theme: `name`; `shapes`, the theme's shape values (for example { \"--shape-corner\": \"16px\", \"--shape-case-heading\": \"none\" }; a value that does not fit its kind is refused with the reason); `css`, the theme CSS for the whole theme (any CSS: selectors, !important, @media, @keyframes; empty removes it); `defaultStyle` and `offeredStyles` (style ids of this theme, which the pill offers); `retired` true takes it out of the pill without deleting it. `restoreVersion` puts back a version from aimeat_theme_get, which is the way to undo a save. `dryRun` checks and saves nothing. Only CSS that does not parse is refused; everything else comes back as warnings with the line. The built-in theme is read only. Only the operator of this server can do this, with the site:theme-write permission. To make a theme available to people, use aimeat_theme_policy_set.",
            "inputSchema": {
              "properties": {
                "basedOn": {
                  "description": "For a new theme: the theme it copies (default 'aimeat').",
                  "type": "string"
                },
                "css": {
                  "description": "Theme CSS for the whole theme; empty removes it.",
                  "type": "string"
                },
                "defaultStyle": {
                  "description": "The style a person sees first in this theme.",
                  "type": "string"
                },
                "dryRun": {
                  "description": "Check everything and save nothing.",
                  "type": "boolean"
                },
                "id": {
                  "description": "The theme to change. Leave it out to make a new one.",
                  "type": "string"
                },
                "name": {
                  "description": "What people see in the pill. 1 to 60 characters, and no other theme may have it (retired ones included).",
                  "type": "string"
                },
                "offeredStyles": {
                  "description": "The style ids of this theme the pill offers.",
                  "type": "array"
                },
                "restoreVersion": {
                  "description": "Put back this saved version (from aimeat_theme_get).",
                  "type": "number"
                },
                "retired": {
                  "description": "true takes the theme out of the pill; false brings it back.",
                  "type": "boolean"
                },
                "shapes": {
                  "description": "The theme's shape values (corners, frames, shadows, letter case), only the ones you change; an empty value puts the built-in one back. aimeat_theme_list names them.",
                  "type": "object"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_theme_style_save",
            "description": "Make or change a style inside a theme: its colours in light and dark, its three faces and its mode. Without `style` you make a new style, a copy of `basedOn` (a style of the theme; its default style if left out). `light` and `dark` are objects of colour token → CSS colour (hex, rgb(), hsl(), color-mix(in srgb, …), var(--token)); send only what you change; aimeat_theme_list names the tokens. `faces` picks { headline, body, mono } from the faces this server serves. `onlyMode` is 'light' or 'dark' for a style with one mode, empty for both; the pill then says why its light/dark switch is off. `retired` true takes the style out of the pill. A value that does not parse is refused; a contrast line under its minimum (words 4.5:1 on the page and on a card, the accent 3:1, words on the sun 4.5:1) is a warning, and the style is saved. Only the operator, with site:theme-write.",
            "inputSchema": {
              "properties": {
                "basedOn": {
                  "description": "For a new style: the style of this theme it copies.",
                  "type": "string"
                },
                "dark": {
                  "description": "Token → colour for dark mode, only the ones you change.",
                  "type": "object"
                },
                "dryRun": {
                  "description": "Check everything and save nothing.",
                  "type": "boolean"
                },
                "faces": {
                  "description": "{ headline, body, mono }, each a face this server serves.",
                  "type": "object"
                },
                "light": {
                  "description": "Token → colour for light mode, only the ones you change.",
                  "type": "object"
                },
                "name": {
                  "description": "What people see in the pill. 1 to 60 characters.",
                  "type": "string"
                },
                "onlyMode": {
                  "description": "'light' or 'dark' for a style with one mode; empty for both.",
                  "type": "string"
                },
                "retired": {
                  "description": "true takes the style out of the pill; false brings it back.",
                  "type": "boolean"
                },
                "style": {
                  "description": "The style to change. Leave it out to make a new one.",
                  "type": "string"
                },
                "theme": {
                  "description": "The theme the style belongs to.",
                  "type": "string"
                }
              },
              "required": [
                "theme"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_tools_find",
            "description": "Your tool list starts small, and this node has many more tools. When the job needs one you do not see, say what you want to do and this finds the tools for it and adds them to your list for the rest of this conversation. Then call them by name; a tool your list does not show yet (some clients read it again only on the next message) runs now through aimeat_invoke, with its name as `capability`. Search in English with plain words for the action and the thing (\"add a contact\", \"publish an app\", \"read my mail\", \"schedule a task\"). The answer names each tool, what it does and what it needs. Tools already in your list are named too, so a search never sends you looking for one you have.",
            "inputSchema": {
              "properties": {
                "limit": {
                  "description": "How many tools to add at most (default 6, max 12).",
                  "type": "number"
                },
                "purpose": {
                  "description": "What you want to do, in a few words.",
                  "type": "string"
                }
              },
              "required": [
                "purpose"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_ui_component_get",
            "description": "Read one component of this node's own web interface whole: its data shape and every field, when to use it, its variants and the class or prop that selects each, one example data set, the theme tokens its stylesheet reads, the names its module exports, the files and pages that use it, and the themes of this node that carry CSS for it (with whether that CSS is served; aimeat_theme_component_css_set changes it). `id` is the id from aimeat_ui_component_list (for example 'step-card' or 'slab') or the module's name ('StepCard').",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "The component's id or name, from aimeat_ui_component_list.",
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_ui_component_list",
            "description": "List the components this node's own web interface is built from: each one with a module (in /components/ with its own stylesheet, kind 'component') and each shape of the design language (a class in poster.css, kind 'shape'). Every row says what the component is, how it is called, and which pages draw it. `kind` narrows to 'component' or 'shape', `status` to 'active' or 'unused' (a component no page draws today), and `q` finds words in the name, summary, use or classes. Read one component whole with aimeat_ui_component_get before you change a page or build a new one: reuse the component that exists rather than writing a second copy.",
            "inputSchema": {
              "properties": {
                "kind": {
                  "description": "'component' or 'shape'.",
                  "type": "string"
                },
                "q": {
                  "description": "Words to find; every word must match.",
                  "type": "string"
                },
                "status": {
                  "description": "'active' or 'unused'.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_usage_report",
            "description": "Answer \"what did we actually use, and what did it cost\" for the owner behind this session: spend per model, per app, per agent, per day, plus which tools get called and which of them refuse or fail. Reads a precomputed layer, so it is cheap however large the history is, and it says how fresh it is. Scoped to this owner and to nobody else. Use it for a spend or usage question; use aimeat_agent_activity for one agent own counters.",
            "inputSchema": {
              "properties": {
                "from": {
                  "description": "Inclusive start day, YYYY-MM-DD. Defaults to 30 days ago.",
                  "type": "string"
                },
                "grain": {
                  "description": "Bucket size, where the report has one.",
                  "enum": [
                    "day",
                    "hour"
                  ],
                  "type": "string"
                },
                "limit": {
                  "description": "Maximum groups to return.",
                  "type": "number"
                },
                "report": {
                  "description": "Which report to read.",
                  "enum": [
                    "day",
                    "model",
                    "app",
                    "agent",
                    "tool",
                    "surface",
                    "apps-used",
                    "activity",
                    "sold"
                  ],
                  "type": "string"
                },
                "to": {
                  "description": "Inclusive end day, YYYY-MM-DD. Defaults to today.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_v2_message_list",
            "description": "Read turns back, oldest first. Narrow by context_id for one exchange, by task_id for the turns of one task, by to/from for one party, or by since (an ISO timestamp) for everything that arrived while you were away, which is how a principal catches up after being offline. Reads only this account's turns.",
            "inputSchema": {
              "properties": {
                "context_id": {
                  "description": "One exchange.",
                  "type": "string"
                },
                "from": {
                  "description": "Turns sent by this principal.",
                  "type": "string"
                },
                "limit": {
                  "description": "Max turns to return (default 50, max 200).",
                  "type": "number"
                },
                "since": {
                  "description": "ISO timestamp, exclusive: turns created after it.",
                  "type": "string"
                },
                "task_id": {
                  "description": "The turns of one task.",
                  "type": "string"
                },
                "to": {
                  "description": "Turns addressed to this principal.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_v2_message_send",
            "description": "Send one turn to another principal on this same account: an agent, an ecosystem app, or the owner. A turn carries an ordered list of parts, so one send can say something, point at a file and hand over a structured payload together. Group turns with context_id: pass the same one to continue an exchange, omit it to start a new one and the answer tells you the id it got. The recipient hears about it on its tunnel if it is connected and on its registered delivery target if it is not, and can always read it back with aimeat_v2_message_list whatever happened. To reach a PERSON, use aimeat_dm_send; to reach your own owner in the dashboard thread, aimeat_message_send.",
            "inputSchema": {
              "properties": {
                "context_id": {
                  "description": "The exchange this turn belongs to. Omit on the first turn.",
                  "type": "string"
                },
                "metadata": {
                  "description": "Anything you want carried along. Never read by the node.",
                  "type": "object"
                },
                "parts": {
                  "description": "Ordered parts. Each is {kind:\"text\",text} or {kind:\"file\",file:{uri,name?,mimeType?}} or {kind:\"data\",data:{...}}. A file part carries a URI, never bytes.",
                  "type": "array"
                },
                "role": {
                  "description": "Send \"user\" if you are asking and \"agent\" if you are answering. Default \"user\". It is not a principal type.",
                  "enum": [
                    "user",
                    "agent"
                  ],
                  "type": "string"
                },
                "task_id": {
                  "description": "The task this turn belongs to, if there is one.",
                  "type": "string"
                },
                "to": {
                  "description": "The recipient principal on this account: an agent GAII (claude#alice@node), an ecosystem app (eco:drum#alice@node) or the owner GHII (alice@node).",
                  "type": "string"
                }
              },
              "required": [
                "to",
                "parts"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_v2_push_delete",
            "description": "Stop delivering to one registered target. An agent may delete its own; the account holder may delete any target on the account.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "The target id, from aimeat_v2_push_list.",
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_v2_push_list",
            "description": "What delivery targets are registered: their addresses, tokens, authentication schemes, and whether the node has been able to reach them. The stored credentials are never returned. An agent sees its own targets; the account holder sees every target on the account, or one principal's by naming it.",
            "inputSchema": {
              "properties": {
                "principal": {
                  "description": "Account holder only: whose targets to list. Omit for all of them.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_v2_push_set",
            "description": "Register where to reach you when you are not connected: an https address this node POSTs a turn to. Optionally a token it echoes back so you can tell the POST came from a target you registered, and an authentication block ({schemes:[\"Bearer\"],credentials:\"...\"}) whose credentials this node sends in the Authorization header and never returns to anyone, including you. Pass the id of a target you already registered to replace it; omit id for a new one. The account holder may register a target for another principal by naming it in principal.",
            "inputSchema": {
              "properties": {
                "authentication": {
                  "description": "A block shaped { schemes: [\"Bearer\"], credentials: \"...\" }. The credentials are stored and sent, never returned.",
                  "type": "object"
                },
                "id": {
                  "description": "Replace this existing target. It must be one already registered on this account.",
                  "type": "string"
                },
                "principal": {
                  "description": "Whose deliveries these are. Defaults to you; naming another principal is for the account holder.",
                  "type": "string"
                },
                "token": {
                  "description": "An opaque string echoed back inside every delivery.",
                  "type": "string"
                },
                "url": {
                  "description": "The https address to POST a turn to.",
                  "type": "string"
                }
              },
              "required": [
                "url"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_v2_task_cancel",
            "description": "Stop work you asked for. Only whoever created the task and the account holder may: a worker that will not do the work reports it failed with a reason, which is a different thing and is recorded as one. A task that has already settled refuses to move.",
            "inputSchema": {
              "properties": {
                "reason": {
                  "description": "Why, in one line.",
                  "type": "string"
                },
                "task_id": {
                  "description": "The task id.",
                  "type": "string"
                }
              },
              "required": [
                "task_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_v2_task_create",
            "description": "Ask another principal on this account to do something, and get back a handle you poll. This is the MCP task shape: a taskId, a status that is one of working / input_required / completed / failed / cancelled, and a poll interval. Distinct from aimeat_task_create, which makes the owner an item in their dashboard with a title, todos and an approval step; this one is the handle a long call runs behind. Group it with a conversation by passing the same context_id you use for turns.",
            "inputSchema": {
              "properties": {
                "assigned_to": {
                  "description": "The principal that is to do this: an agent GAII, an ecosystem app, or the owner GHII.",
                  "type": "string"
                },
                "context_id": {
                  "description": "The exchange this work belongs to. Omit and the task names itself.",
                  "type": "string"
                },
                "input": {
                  "description": "What is being asked, as parts: {kind:\"text\",text} or {kind:\"file\",file:{uri}} or {kind:\"data\",data:{...}}. The same shape a turn carries.",
                  "type": "array"
                },
                "metadata": {
                  "description": "Carried along, never read by the node.",
                  "type": "object"
                },
                "poll_interval_ms": {
                  "description": "How often you intend to poll, in milliseconds.",
                  "type": "number"
                },
                "status_message": {
                  "description": "One line for a person about what this is.",
                  "type": "string"
                },
                "ttl_ms": {
                  "description": "How long the result stays worth reading, in milliseconds. Advice, not a deletion.",
                  "type": "number"
                }
              },
              "required": [
                "assigned_to",
                "input"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_v2_task_get",
            "description": "One task, with everything a poll needs: its MCP status, whether that status is terminal, the A2A state the same task reports on that protocol, the result if it completed and the error if it did not. A terminal task never changes again, so the first settled read you see is the last one you need.",
            "inputSchema": {
              "properties": {
                "task_id": {
                  "description": "The task id.",
                  "type": "string"
                }
              },
              "required": [
                "task_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_v2_task_list",
            "description": "The task roster, newest first. Narrow by assigned_to for what a worker has been given, created_by for what you asked for, context_id for one conversation, or status for what is still open. An unrecognised status is refused rather than ignored, because a filter that does not filter returns everything and reads as a working query.",
            "inputSchema": {
              "properties": {
                "assigned_to": {
                  "description": "Tasks given to this principal.",
                  "type": "string"
                },
                "context_id": {
                  "description": "Tasks in one exchange.",
                  "type": "string"
                },
                "created_by": {
                  "description": "Tasks this principal asked for.",
                  "type": "string"
                },
                "limit": {
                  "description": "Max tasks to return (default 50, max 200).",
                  "type": "number"
                },
                "status": {
                  "description": "One status or a comma-separated list: working, input_required, completed, failed, cancelled.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_v2_task_status",
            "description": "Report where you have got to with work you were given. Only the assignee and the account holder may: a task's status is the worker's testimony about the work, so whoever asked for it cannot write it. Completing requires a result, failing requires a code and a message, and a task that has already settled refuses to move. To stop work you asked for, cancel it instead.",
            "inputSchema": {
              "properties": {
                "error": {
                  "description": "{ code, message }. Required when failing.",
                  "type": "object"
                },
                "poll_interval_ms": {
                  "description": "How often the caller should poll from here, in milliseconds.",
                  "type": "number"
                },
                "result": {
                  "description": "What came back, as parts. Required when completing.",
                  "type": "array"
                },
                "status": {
                  "description": "Where it has got to.",
                  "enum": [
                    "working",
                    "input_required",
                    "completed",
                    "failed"
                  ],
                  "type": "string"
                },
                "status_message": {
                  "description": "One line for a person.",
                  "type": "string"
                },
                "task_id": {
                  "description": "The task id.",
                  "type": "string"
                },
                "ttl_ms": {
                  "description": "How long the result stays worth reading, in milliseconds.",
                  "type": "number"
                }
              },
              "required": [
                "task_id",
                "status"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_voice_reply",
            "description": "Generate a conversational text reply with the owner's AI key, app quota, usage and provenance. Returns final text; browser apps use the streaming AIMEAT.voice adapter for early playback. Model messages contain text only. No token cap unless explicitly supplied.",
            "inputSchema": {
              "properties": {
                "app_id": {
                  "description": "App attribution for the owner's allowlist and daily quota.",
                  "type": "string"
                },
                "max_tokens": {
                  "description": "Optional explicit output cap, 1-32768. Omitted by default.",
                  "type": "number"
                },
                "messages": {
                  "description": "1-201 {role: system|user|assistant, content: string} messages; at most 200k characters combined.",
                  "type": "array"
                },
                "model": {
                  "description": "Model override; otherwise the owner's configured chat model.",
                  "type": "string"
                },
                "provider": {
                  "description": "One of the owner's AI providers (aimeat_ai_providers), or a type. No fallback then.",
                  "type": "string"
                },
                "reasoning": {
                  "description": "Optional {enabled, effort: low|medium|high, max_tokens, exclude}; provider-dependent.",
                  "type": "object"
                },
                "role": {
                  "description": "The AI role to run as: one of your roles (aimeat_ai_roles), or for an app a role it declares and you bound. A named model or provider wins over it.",
                  "type": "string"
                },
                "temperature": {
                  "description": "Sampling temperature, 0-2.",
                  "type": "number"
                },
                "top_p": {
                  "description": "Nucleus sampling, 0-1.",
                  "type": "number"
                }
              },
              "required": [
                "app_id",
                "messages"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_voice_speak",
            "description": "Synthesize speech using the owner's configured provider and AI budget. Returns a PRIVATE storage_key, fetch_url, usage and provenance, never audio bytes in model context. Download using authenticated storage access; delete the file when no longer needed. Select a model and voice supported by the provider.",
            "inputSchema": {
              "properties": {
                "app_id": {
                  "description": "App attribution for the owner's allowlist and daily quota.",
                  "type": "string"
                },
                "input": {
                  "description": "Text to speak, 1-4000 characters.",
                  "type": "string"
                },
                "instructions": {
                  "description": "Optional provider-specific speaking instructions, at most 2000 characters.",
                  "type": "string"
                },
                "model": {
                  "description": "Explicit speech model id.",
                  "type": "string"
                },
                "provider": {
                  "description": "One of the owner's AI providers (aimeat_ai_providers), or a type. No fallback then.",
                  "type": "string"
                },
                "response_format": {
                  "description": "Audio format, default pcm. PCM rate and channel count follow the provider.",
                  "enum": [
                    "pcm",
                    "mp3"
                  ],
                  "type": "string"
                },
                "role": {
                  "description": "The AI role to run as: one of your roles (aimeat_ai_roles), or for an app a role it declares and you bound. A named model or provider wins over it.",
                  "type": "string"
                },
                "speed": {
                  "description": "Speech speed, 0.25-4, default 1.",
                  "type": "number"
                },
                "voice": {
                  "description": "Provider voice id.",
                  "type": "string"
                }
              },
              "required": [
                "app_id",
                "input",
                "model",
                "voice"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_wallet_balance",
            "description": "Check the morsel wallet: returns total balance, amount currently held in escrow for in-flight work, and the available (spendable) remainder. Morsels belong to the owner (GHII), shared across all their agents. Check available before hiring via aimeat_action_execute; for the ledger of past transactions use aimeat_wallet_transactions.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_wallet_transactions",
            "description": "View recent morsel transactions for your owner's wallet (id, type, amount, counterparty, tracking code, timestamp; default 20, max 200). Transactions are keyed to the owner GHII, shared across agents. For the current balance/escrow snapshot use aimeat_wallet_balance.",
            "inputSchema": {
              "properties": {
                "limit": {
                  "description": "Maximum transactions to return.",
                  "type": "number"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_work_accept",
            "description": "Accept a pending work item assigned to you as provider, identified by its tracking_code (find pending items via aimeat_work_inbox). Moves it from pending to accepted. Only the provider can accept, and only while status is pending; once accepted, perform the work and return the result with aimeat_work_deliver.",
            "inputSchema": {
              "properties": {
                "tracking_code": {
                  "description": "Work item tracking code.",
                  "type": "string"
                }
              },
              "required": [
                "tracking_code"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_work_deliver",
            "description": "Deliver the result for a work item you accepted (by tracking_code), which settles the escrowed payment to you and marks it delivered. Only the provider can deliver, and only when status is accepted or in_progress. Run aimeat_work_accept first; the result payload is returned to the requester.",
            "inputSchema": {
              "properties": {
                "metadata": {
                  "description": "Optional delivery metadata.",
                  "type": "string"
                },
                "output": {
                  "description": "Delivery payload (the work result).",
                  "type": "string"
                },
                "tracking_code": {
                  "description": "Work item tracking code.",
                  "type": "string"
                }
              },
              "required": [
                "tracking_code",
                "output"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_work_inbox",
            "description": "Check your work inbox: work items others have requested from you (where you are the provider), still pending/accepted/in-progress. Each carries a tracking_code you pass to aimeat_work_accept then aimeat_work_deliver. This is the provider side of the action catalogue; to request work from others use aimeat_action_execute. response_format=concise returns just tracking_code/status/action_id.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_workflow_answer",
            "description": "Answer a workflow step that is waiting for human input (state \"waiting-human\") ON THE OWNER'S BEHALF — only relay a decision the owner actually made (e.g. from a conversation or an inbox reply); never invent one. Picks are validated against the question pinned at ask time. The answer is written to the step's answer_to_key so downstream steps branch on it; the run then advances.",
            "inputSchema": {
              "properties": {
                "other": {
                  "description": "Free-text answer; only when the question allows it.",
                  "type": "string"
                },
                "picks": {
                  "description": "Option ids from the pinned question (may be empty when answering with `other` alone).",
                  "type": "array"
                },
                "run_id": {
                  "description": "The run id (from aimeat_workflow_pending_inputs).",
                  "type": "string"
                },
                "step_id": {
                  "description": "The waiting step id.",
                  "type": "string"
                },
                "workflow_id": {
                  "description": "The workflow id.",
                  "type": "string"
                }
              },
              "required": [
                "workflow_id",
                "run_id",
                "step_id",
                "picks"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workflow_get",
            "description": "Inspect workflows. Omit id to list all your workflows; pass an id for its definition + the derived blueprint (the whole input→output flow + the memory keys each step touches) + recent runs. The recent runs are the ones that dispatched agents; a signals-only check is not a run and is not listed among them. A run the node ended itself carries a reason: \"stopped\" at its spending limit (maxCostUsd), or \"refused\" when its trigger found the workflow's saver disconnected or short of a permission (the owner can run it once as themselves from the notification, or approve the permission again). Use before editing or running, and to read a run's outcome.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "Omit to list; pass for one workflow's detail.",
                  "type": "string"
                }
              },
              "type": "object"
            }
          },
          {
            "name": "aimeat_workflow_pending_inputs",
            "description": "List every workflow step currently WAITING FOR HUMAN INPUT across the owner's active runs: the pinned question (prompt + options), when it was asked, and the deadline after which the step's timeout policy fires. Use to list \"things waiting on the owner\" — then relay the owner's decision with aimeat_workflow_answer.",
            "inputSchema": {
              "properties": {},
              "type": "object"
            }
          },
          {
            "name": "aimeat_workflow_run",
            "description": "Run a workflow. mode=\"signals-only\" is a CHECK: it evaluates every step's signals against existing memory with NO dispatch, costs nothing, returns each step's verdict inline, and is kept apart from the runs (it does not appear in the run history or the health); mode=\"full\" executes the steps live (dispatches the agent tasks, which takes time and spends their budget; poll aimeat_workflow_get for progress). Use signals-only to validate a workflow or to see what is already in memory before a full run. A full start while a live run of the same workflow is in flight starts NOTHING unless the definition sets parallel:true: the answer then carries skipped:true and the id of the run that is running, not a new one. Read the flag before treating the id as yours.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "The workflow id.",
                  "type": "string"
                },
                "mode": {
                  "description": "signals-only | full",
                  "enum": [
                    "signals-only",
                    "full"
                  ],
                  "type": "string"
                },
                "target": {
                  "description": "With mode=\"full\": \"sandbox\" writes every key behind a per-run prefix so a trial cannot touch what a live run produced. Default \"live\".",
                  "enum": [
                    "live",
                    "sandbox"
                  ],
                  "type": "string"
                },
                "vars": {
                  "description": "The run's input, as { varName: value } over the vars the workflow declares. A workflow that takes input is a constant without this. Anything it does not declare is ignored, and a declared var left out falls back to its default.",
                  "type": "object"
                }
              },
              "required": [
                "id",
                "mode"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workflow_save",
            "description": "Create or update an Agent Workflow: a declared, ordered set of steps with per-step input (required_to_function) and output (success_signal) signals, run by ONE trigger, with the signal checked after each step (so you see \"did it produce\", not just \"did it fire\"). Use instead of chaining separate schedules when steps depend on each other. Pass the whole descriptor as `definition`; each step names an agent + offer and inherits that offer's signals + deliverable location. Rejected at save if the after-graph is not a DAG or an offer is not workflow-compatible (must publish success_signal + required_to_function + deliverable.location). A schedule trigger creates one backing cron; an event trigger fires on a matching memory write / offer order. A step costs the permission its own endpoint asks, at save and again at a full run: work:request for an agent step (giving an agent work; a workflow saved before 2026-09-25 keeps its agent steps free), ai:use for an ai step or llm.approved, ext:invoke for an extension step, memory:read + storage:write + memory:write for a datapackage step, memory:read + work:request for export-out, work:request for trigger-geai, and memory:read for a workflow that reads the owner's records (every signal leaf and every agent step reads one; a signals-only check needs it too); without it the answer is SCOPE_DENIED naming the permission. maxCostUsd caps what one run may spend on AI, in US dollars, counting its ai steps and the node's model judging its llm signals. Before an ai step's model call starts, the node sets aside what one attempt is expected to cost (the most one attempt cost in the workflow's last ten finished runs, else an equal share of the cap nobody holds) and starts it only when that fits beside what the run has spent and what its open calls hold, so ai steps that fit together still run side by side. A call holds its share until it answers, also after a timeout or a retry moved its step on. A step that does not fit waits while a call is open; with none open, the run stops with status \"stopped\" and says why. A step expected to cost more than the whole cap starts alone while the run has spent less. Past the cap an llm signal is not judged and passes. costCapMorsels does nothing (a morsel is not money) and is removed in 4.0.0; a save that sets it answers with warnings. The save records you as the workflow's saver: a run its own trigger starts answers to you, and does not start (status \"refused\", the owner told once) when you are disconnected or no longer hold a permission its steps need.",
            "inputSchema": {
              "properties": {
                "confirm_token": {
                  "description": "Token from the propose step — applies exactly the proposed definition.",
                  "type": "string"
                },
                "definition": {
                  "description": "The descriptor: { title, description, trigger, vars[], steps[], on_step_fail:\"inspect\", llm?{approved}, notify_on_finish?, resume?, fresh?, skip_done?, parallel?, maxCostUsd? }. parallel:true lets two or more live runs of this workflow overlap; use it when the keys carry a run-distinguishing var (a case reference in vars, or the built-in {run}); without it a second start while one is in flight is skipped and says so. Refused together with fresh. maxCostUsd (US dollars, per run) caps what a run spends on AI, its ai steps and the judging of its llm signals together: an ai step's model call starts only when what one attempt is expected to cost fits in what is left, and holds that share until the call answers, also after a timeout or a retry; otherwise the step waits for the open calls or stops the run. A step expected to cost more than the whole cap starts alone while the run has spent less.",
                  "type": "object"
                },
                "id": {
                  "description": "Workflow id (lowercase slug); existing id = update.",
                  "type": "string"
                },
                "propose": {
                  "description": "Operator flow (server MCP only): return a diff vs the current definition + a single-use confirm_token WITHOUT saving.",
                  "type": "boolean"
                }
              },
              "required": [
                "id",
                "definition"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_access",
            "description": "REQUEST/REVIEW flow for a gated workspace, via `action`: 'request' = ask the creator for access to a workspace you can see but not read (org membership lets you DISCOVER workspaces; a workspace's CONTENT is gated by its creator); 'list' = (creator/admin) see who has requested (pending/approved) plus current members + roles; 'decide' = (creator/admin) approve or deny a request (approve grants 'contributor' by default; pass role='viewer' for read-only). Member-only; list/decide are creator-or-admin. To add a member PROACTIVELY (no prior request), or to add to MANY workspaces at once, use aimeat_workspace_member_grant.",
            "inputSchema": {
              "properties": {
                "action": {
                  "description": "'request' | 'list' | 'decide'.",
                  "enum": [
                    "request",
                    "list",
                    "decide"
                  ],
                  "type": "string"
                },
                "decision": {
                  "description": "action='decide': 'approve' (default) or 'deny'.",
                  "enum": [
                    "approve",
                    "deny"
                  ],
                  "type": "string"
                },
                "message": {
                  "description": "action='request': optional note to the creator.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "requester": {
                  "description": "action='decide': the requester's owner name (from action='list').",
                  "type": "string"
                },
                "role": {
                  "description": "action='decide' approve: 'viewer' (read) or 'contributor' (read+write). Omit for the default (contributor).",
                  "enum": [
                    "viewer",
                    "contributor"
                  ],
                  "type": "string"
                },
                "ws": {
                  "description": "Workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws",
                "action"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_comment",
            "description": "Add a comment to a workspace object (a record or a document) — for discussion/review threads. Target it by ws + space (objectType) + instance_id. Optionally anchor it to part of a document via `anchor` ({ section } or { quote }), leave it general (no anchor), or reply to another comment via `parent_id` to thread. Agents and humans both comment here. Read a thread with aimeat_workspace_comments. Member-only. If a model generated or substantially rewrote this content, declare it in `ai_provenance` (level, and human_involvement if a person reviewed the substance). If you are relaying text a person wrote, say so with level:\"original\" — silence is recorded as model-written.",
            "inputSchema": {
              "properties": {
                "ai_provenance": {
                  "description": "How this content was made: { level, method?, human_involvement?, model?, provider?, sources?, notes? }. `level` is required when the block is present: original | assisted | synthesized | ai-generated. `model` is YOUR OWN model id as your provider names it (self-identify, never ask the person); without it the record cannot say which model made this. `human_involvement` (none | light-review | editorial-control | full-human) counts only a step where a person read the SUBSTANCE and could reject it; omitted means none. The node fills in who you are, which node, when, and a hash of the exact bytes — those are never taken from the caller.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "Attach an EXISTING provenance record instead of declaring a new one — the id the node returned when it generated this content for you. Only your own records can be attached.",
                  "type": "string"
                },
                "anchor": {
                  "description": "Optional anchor to part of a document: { section } or { quote }.",
                  "type": "object"
                },
                "body": {
                  "description": "The comment text.",
                  "type": "string"
                },
                "instance_id": {
                  "description": "The id of the record/document being commented on.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "parent_id": {
                  "description": "Optional id of the comment this replies to (threading).",
                  "type": "string"
                },
                "space": {
                  "description": "The objectType (space) name the target lives in.",
                  "type": "string"
                },
                "ws": {
                  "description": "Workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws",
                "space",
                "instance_id",
                "body"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_comment_delete",
            "description": "Delete one comment from a workspace object's thread. The comment's author may delete it, and so may the organism's creator or an admin, for example to remove a wrong comment or test traces. Take the comment id from aimeat_workspace_comments. Replies to the deleted comment stay.",
            "inputSchema": {
              "properties": {
                "comment_id": {
                  "description": "The comment id (from aimeat_workspace_comments).",
                  "type": "string"
                },
                "instance_id": {
                  "description": "The record/document id the comment is on.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "space": {
                  "description": "The objectType (space) name.",
                  "type": "string"
                },
                "ws": {
                  "description": "Workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws",
                "space",
                "instance_id",
                "comment_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_comments",
            "description": "List the comment thread on one workspace object (record or document), oldest first, with each comment's author, body, anchor (if any), and parent (for replies). Member-only.",
            "inputSchema": {
              "properties": {
                "instance_id": {
                  "description": "The record/document id.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "space": {
                  "description": "The objectType (space) name.",
                  "type": "string"
                },
                "ws": {
                  "description": "Workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws",
                "space",
                "instance_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_create",
            "description": "Create a new WORKSPACE inside an organism from a CUSTOM MANIFEST you supply — its objectTypes (each a records space with a JSON schema, or a document/wiki space) plus the per-namespace schemas. Registers it, locks the schemas, writes the manifest + readme. This is how an agent bootstraps a structured space; then fill it with aimeat_workspace_write (records and documents alike) and publish with aimeat_workspace_publish. Member-only.",
            "inputSchema": {
              "properties": {
                "manifest": {
                  "description": "The manifest. You really only need its `objectTypes` array — the envelope (manifestVersion, id, name, kind, status) is BACKFILLED for you when omitted, so an objectTypes-only manifest is accepted on the first call (name defaults from this tool's `name` param, kind to \"project\"). Full shape: { objectTypes: [{ name, namespace, mode:\"records\"|\"document\", schemaRef, writeRole, cardinality, versioned }], policy? }. Each space is backing:\"memory\" (the default) — \"rows\" is the ROW STORE for a stream that arrives in volume and does not stop (appended, no version history, charged to the organism, filtered on up to three fields named in `indexOn`, and read through the rows tools rather than the record ones), \"tasks\" only declares a pointer to the task system, and \"storage\"/\"knowledge\" are rejected: files and knowledge packages attach via workspace Sources or embedded document images, never as a backed space. The test for memory versus rows is one multiplication: if keys_per_day × 365 exceeds 1000, use rows.",
                  "type": "object"
                },
                "name": {
                  "description": "Workspace name.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism to create the workspace in.",
                  "type": "string"
                },
                "readme": {
                  "description": "Optional markdown intro (defaults to the manifest name + summary).",
                  "type": "string"
                },
                "schemas": {
                  "description": "Map of namespace → JSON Schema for each records objectType, e.g. { \"shared.tasks\": { type:\"object\", required:[\"id\",\"title\"], properties:{...} } }.",
                  "type": "object"
                }
              },
              "required": [
                "organism_id",
                "name",
                "manifest"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_doc_append",
            "description": "Add markdown to a workspace DOCUMENT without sending the rest of it back — at the end, or at the end of one named section. This is how a long document is amended: aimeat_workspace_write replaces the whole thing, so amending a 57,000-character spec through it means retyping all of it, and what that fails at is silent. The insert never removes an existing character, so two sessions can append to the same document and both survive — the write is a compare-and-swap that re-reads and re-applies if somebody got there first. `section` names a heading by its exact TEXT ('Concurrency', not '## Concurrency' — either is accepted); the new text lands at the end of that section, before the next heading. Two headings with the same text is a refusal naming both, because guessing which one you meant is how an edit lands in the wrong half of a long document. Edits the DRAFT, seeding it from the published version when there is no draft yet; publish with aimeat_workspace_publish. Member-only.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "The document id, from the workspace index (aimeat_workspace_read).",
                  "type": "string"
                },
                "markdown": {
                  "description": "The markdown to add. Blank lines around it are worked out for you; nothing already in the document is touched.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "section": {
                  "description": "Add at the end of THIS section instead of the end of the document. The heading's exact text; an ambiguous one is refused.",
                  "type": "string"
                },
                "space": {
                  "description": "The document space, by objectType name (e.g. 'notes') or namespace.",
                  "type": "string"
                },
                "ws": {
                  "description": "Workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws",
                "space",
                "id",
                "markdown"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_doc_section_replace",
            "description": "Replace one section of a workspace DOCUMENT — a heading and its body — leaving every other byte exactly as it was. Use it to correct or rewrite one part of a long document instead of resending the whole thing, which is both expensive and, for a document somebody else wrote, unsafe. `section` names the heading by its exact TEXT, and `markdown` is the WHOLE replacement INCLUDING its heading line: a block that does not start with a heading is refused rather than guessed at, and changing the heading there is how a section gets renamed. A section runs to the next heading at the same level or higher, so replacing '## Tests' takes its '### Unit' subsection with it. Two headings with the same text is a refusal naming both. Headings inside ```-fenced code are not headings. Concurrent edits are safe (compare-and-swap with re-apply). Edits the DRAFT; publish with aimeat_workspace_publish. Member-only.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "The document id, from the workspace index (aimeat_workspace_read).",
                  "type": "string"
                },
                "markdown": {
                  "description": "The whole replacement section, starting with its heading line.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "section": {
                  "description": "The heading text to replace, exactly as the document spells it (the leading #'s are optional).",
                  "type": "string"
                },
                "space": {
                  "description": "The document space, by objectType name or namespace.",
                  "type": "string"
                },
                "ws": {
                  "description": "Workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws",
                "space",
                "id",
                "section",
                "markdown"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_list",
            "description": "List the WORKSPACES inside an organism. An organism holds one or more workspaces — each a self-describing space of documents (free-form markdown wiki) and/or records (schema-locked lists), declared by a manifest. Returns each workspace's id + name. Use the id with aimeat_workspace_read. You must be a member of the organism.",
            "inputSchema": {
              "properties": {
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_member_grant",
            "description": "Directly grant an EXISTING organism member a workspace role — no prior access request needed. Grant to ONE workspace (`ws`) or MANY at once (`workspaces`: e.g. every workspace from aimeat_workspace_list), so 'add this member to all workspaces' is one call. `grantee` may be an owner name, GHII (owner@node), or GAII (agent#owner@node) — the grant applies to the OWNER, so all their agents inherit it. role: 'viewer' (read) | 'contributor' (read+write). Authorized for the workspace creator or an org admin. Per-workspace result: granted / skipped_creator / forbidden_or_not_found. Each grant is auditable (a creator-owned consent stamped with its source).",
            "inputSchema": {
              "properties": {
                "grantee": {
                  "description": "Owner name, GHII, or GAII to grant. Applies to the owner (agents inherit).",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "role": {
                  "description": "'viewer' (read) or 'contributor' (read+write).",
                  "enum": [
                    "viewer",
                    "contributor"
                  ],
                  "type": "string"
                },
                "workspaces": {
                  "description": "Many workspace ids to grant in one call.",
                  "type": "array"
                },
                "ws": {
                  "description": "A single workspace id (use this and/or `workspaces`).",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "grantee",
                "role"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_member_revoke",
            "description": "Remove a member's workspace role on ONE workspace (`ws`) or MANY (`workspaces`). `grantee` may be an owner name, GHII, or GAII (resolved to the owner). To DOWNGRADE (e.g. contributor → viewer) rather than remove, call aimeat_workspace_member_grant with the lower role instead. Authorized for the workspace creator or an org admin. Per-workspace result: revoked / not_a_member / forbidden_or_not_found.",
            "inputSchema": {
              "properties": {
                "grantee": {
                  "description": "Owner name, GHII, or GAII to revoke.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "workspaces": {
                  "description": "Many workspace ids to revoke in one call.",
                  "type": "array"
                },
                "ws": {
                  "description": "A single workspace id (use this and/or `workspaces`).",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "grantee"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_members",
            "description": "List a workspace's members with their role ('viewer' | 'contributor'), the grant's source (grant | request | invite), who granted it, and when. Authorized for the workspace creator or an org admin. For the organism-wide roster (all members + org roles) use aimeat_organism_members instead.",
            "inputSchema": {
              "properties": {
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "ws": {
                  "description": "Workspace id (from aimeat_workspace_list).",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_object_delete",
            "description": "Permanently remove ONE object (record or document) from a workspace — its draft, its published .latest, and all .version.N history — and unfile it from any document section. Use this to retract a mistake or clean up a duplicate. Irreversible; member-only. To replace content instead, overwrite with aimeat_workspace_write.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "The instance id to delete (draft + latest + all versions).",
                  "type": "string"
                },
                "namespace": {
                  "description": "The objectType's namespace, e.g. shared.deliverables.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "ws": {
                  "description": "Workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws",
                "namespace",
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_overview",
            "description": "Get a fast, OKF-style STRUCTURE MAP of ONE workspace as Markdown — per space, the most-recently-updated entries (up to 10) with their instance id + title, and the total count of each space. Read this to find WHICH id you need, then call aimeat_workspace_read (or the memory API) to pull that record. Cheaper than reading the whole workspace when you only need to navigate. Same read access as aimeat_workspace_read; if you lack access the map says so. Member-only.",
            "inputSchema": {
              "properties": {
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "ws": {
                  "description": "Workspace id (from aimeat_workspace_list).",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_publish",
            "description": "Publish a draft → snapshots it to a new immutable .version.N + the live .latest and consumes the draft. Schema-validated. If the workspace's publish gate is on, this refuses and asks you to leave the draft for human review instead. Do not publish without the owner's go-ahead unless told to run autonomously. Member-only.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "The instance id whose .draft to publish.",
                  "type": "string"
                },
                "namespace": {
                  "description": "The instance namespace.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "ws": {
                  "description": "Workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws",
                "namespace",
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_read",
            "description": "Read one workspace in TWO steps so you never pull a huge blob. DEFAULT (no `ids`) returns the INDEX: the manifest (the objectTypes it declares — each a records space with a JSON schema, or a document space of markdown pages), the JSON Schemas currently LOCKED on the records spaces as `schemas` (keyed by namespace, in the shape aimeat_workspace_update takes back — read this before you change one, because that update REPLACES rather than merges), plus, per space, EVERY instance as { id, title, updated, version, bytes, published, has_draft } — titles only, NO bodies — so it stays small however many/large the documents are. Scan the index (or aimeat_workspace_overview for the same as a Markdown map), pick the ids that likely hold what you need, then call this again with `ids:[...]` to BATCH-OPEN just those instances' full values. Version history (.version.N) is never returned here — read a specific version via the memory API. Member-only.",
            "inputSchema": {
              "properties": {
                "ids": {
                  "description": "Batch-open: return the FULL value of ONLY these instance ids (from the index). A full memory key, which is the id aimeat_discover gives a workspace record, is taken as well. Omit for the lightweight index.",
                  "type": "array"
                },
                "include_archived": {
                  "description": "Include archived (hidden) content. Default false.",
                  "type": "boolean"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "space": {
                  "description": "With `ids`: optionally restrict the lookup to this space (objectType name or namespace).",
                  "type": "string"
                },
                "ws": {
                  "description": "Workspace id (from aimeat_workspace_list).",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_revert_to_draft",
            "description": "Reopen a PUBLISHED record for editing — copies its .latest back into .draft so you can amend it and re-publish via aimeat_workspace_write + aimeat_workspace_publish. The published .latest stays live until you re-publish. Refuses if a draft already exists (edit that draft instead). Use this when a published record needs a change. Member-only.",
            "inputSchema": {
              "properties": {
                "id": {
                  "description": "The instance id of the published record to reopen.",
                  "type": "string"
                },
                "namespace": {
                  "description": "The instance namespace.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "ws": {
                  "description": "Workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws",
                "namespace",
                "id"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_rows_append",
            "description": "Add rows to a workspace ROW space — the shape for what a GROUP accumulates (received messages, events, readings, a log) rather than for records a person authors one by one. A row space is declared in the manifest with backing:'rows'; it is charged to the workspace and the organism instead of to whoever wrote the row, keeps no version history, and never appears row-by-row in a workspace index (the index shows a count). Send one row, or up to 500 in `rows`. Supplying `row_id` makes the append IDEMPOTENT: repeating it REPLACES that row and keeps its original createdAt, so re-running an ingest updates instead of duplicating. `occurred_at` is when the thing happened in the world (a message's own date, not now) and is what reads are ordered and bounded by. Refused before anything is written if the space is not a row space, the caller may not write it, a row is over the size ceiling, or the workspace/organism quota is reached.",
            "inputSchema": {
              "properties": {
                "body": {
                  "description": "The row, for the single-row form. Use `rows` for many.",
                  "type": "object"
                },
                "occurred_at": {
                  "description": "ISO 8601: when it happened in the world. Defaults to now.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "row_id": {
                  "description": "Optional caller id for the single-row form. Repeating one REPLACES that row.",
                  "type": "string"
                },
                "rows": {
                  "description": "Up to 500 rows, each { body, row_id?, occurred_at? }.",
                  "type": "array"
                },
                "space": {
                  "description": "The row space, by objectType name (e.g. 'mailmessage') or namespace.",
                  "type": "string"
                },
                "ws": {
                  "description": "Workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws",
                "space"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_rows_delete",
            "description": "Remove rows from a workspace ROW space: one row by `row_id`, or everything that LANDED before `before` (retention by age). Retention keys on when the row was written to this node, never on when the event happened, so a five-year-old message ingested today is not swept on arrival. Pass exactly one of `row_id` or `before` — there is deliberately no \"delete everything\" form. Irreversible; a row space keeps no version history to restore from. Needs memory:purge and organism:write.",
            "inputSchema": {
              "properties": {
                "before": {
                  "description": "ISO 8601: remove every row created before this.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "row_id": {
                  "description": "Remove this one row.",
                  "type": "string"
                },
                "space": {
                  "description": "The row space, by objectType name or namespace.",
                  "type": "string"
                },
                "ws": {
                  "description": "Workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws",
                "space"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_rows_read",
            "description": "Read one page of a workspace ROW space, newest first by occurred_at. Keyset-cursored: follow `cursor` for the next page, and a null cursor is the last one — a page boundary can neither skip nor repeat a row even when many share one instant. FILTERING WORKS ONLY ON THE FIELDS THE SPACE DECLARED in its manifest `indexOn` (at most three); pass them in `where`, and anything else is REFUSED with the list that does work rather than ignored, so a filtered page is always really filtered. The answer carries `indexed` so you learn that list from the response. `since`/`until` bound occurred_at inclusively; `changed_since` bounds updated_at exclusively and is what an incremental sync follows.",
            "inputSchema": {
              "properties": {
                "changed_since": {
                  "description": "ISO 8601: rows whose updated_at is strictly after this.",
                  "type": "string"
                },
                "cursor": {
                  "description": "Opaque cursor from the previous page.",
                  "type": "string"
                },
                "limit": {
                  "description": "Rows per page, default 100, max 500.",
                  "type": "number"
                },
                "order": {
                  "description": "'desc' (default, newest first) or 'asc'.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "since": {
                  "description": "ISO 8601: occurred_at at or after this.",
                  "type": "string"
                },
                "space": {
                  "description": "The row space, by objectType name or namespace.",
                  "type": "string"
                },
                "until": {
                  "description": "ISO 8601: occurred_at at or before this.",
                  "type": "string"
                },
                "where": {
                  "description": "Filter as { field: value }, using only fields the space declares in indexOn.",
                  "type": "object"
                },
                "ws": {
                  "description": "Workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws",
                "space"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_rows_stats",
            "description": "What a workspace ROW space holds, without reading a row: how many, how many bytes, the oldest and newest occurred_at, and when anything last landed. This is what a workspace index shows for a row space instead of its rows, and it is one aggregate rather than a scan, so it stays honest at any size. Read it before a wide query to know what you are about to ask for.",
            "inputSchema": {
              "properties": {
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "space": {
                  "description": "The row space, by objectType name or namespace.",
                  "type": "string"
                },
                "ws": {
                  "description": "Workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws",
                "space"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_sections_set",
            "description": "Set the section index of one document space: the tree of sections its pages are filed under, [{ id, name, parentId, documents:[docId], color? }], the same list the workspace page saves. Read the current one first (aimeat_workspace_read returns every document space's index as `sections`), change it and send the WHOLE list back. Filing a document into a section moves it out of the one that held it. Who may, and whether it lands at once, is the same as for aimeat_workspace_space_add: status 'applied', or 'pending_approval' with the `suggestion` when the workspace asks its members to suggest. A member's further changes to the same space join the suggestion already waiting. Taking a document that no longer exists out of the index is always written at once.",
            "inputSchema": {
              "properties": {
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "sections": {
                  "description": "The WHOLE index: [{ id, name, parentId, documents, color? }]. An id is letters, digits, '-' or '_'; a parent must be another section in the list; color is red, orange, yellow, green, blue, purple or gray.",
                  "type": "array"
                },
                "space": {
                  "description": "The document space, by name or namespace.",
                  "type": "string"
                },
                "ws": {
                  "description": "Workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws",
                "space",
                "sections"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_space_add",
            "description": "Add a space to a workspace as any member who may change it: its creator, an organism admin, or a member holding the contributor role. A space is { name, namespace, mode }, with mode 'document' for pages or 'records' for a list (send its JSON Schema in `schemas`), or a ROW space { name, namespace, backing:'rows', indexOn:[…] }; defaults are filled. A space whose name or namespace already exists is skipped. What happens to it depends on who you are and on the workspace's rule (its `rules.member_changes`, readable in aimeat_workspace_read): the creator's and an admin's change is written at once; a member's is written at once when the rule is 'direct', and filed as a suggestion that the creator or an admin approves when it is 'suggest' (the default). The answer says which: status 'applied' (with `added`), 'pending_approval' (with the `suggestion`), or 'unchanged'. The space always lands in the workspace's own structure with your name on it, never in a copy of yours. For renaming or removing spaces, the creator uses aimeat_workspace_update.",
            "inputSchema": {
              "properties": {
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "schemas": {
                  "description": "Map of namespace → JSON Schema, only for records spaces added in this same call. A space that already exists keeps its schema.",
                  "type": "object"
                },
                "spaces": {
                  "description": "The space to add, { name, namespace, mode }, or an array of up to 20. The namespace is dotted letters, digits, '-' and '_', such as 'shared.notes'; 'meta', 'skills' and 'access' are the platform's own.",
                  "type": "array"
                },
                "ws": {
                  "description": "Workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws",
                "spaces"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_suggestions",
            "description": "The changes members suggested to a workspace (a space to add, changes to a document space's sections) that wait for a decision, via `action`. 'list' = the suggestions you may see (those in workspaces you can read, and your own), each with `can_decide` for you; `status` picks pending (default), approved, declined, expired or all. 'decide' = approve or decline one: approving applies exactly the suggested change to the workspace as it is now, with the member's name on it and yours as the approver; declining leaves the workspace as it is. Either way the member is told, with your `note` if you give one. Decided by the workspace's creator or an organism admin, never by the member who made it; an agent decides for its owner when the owner is one of them. A suggestion that waits 30 days expires and changes nothing.",
            "inputSchema": {
              "properties": {
                "action": {
                  "description": "'list' | 'decide'.",
                  "enum": [
                    "list",
                    "decide"
                  ],
                  "type": "string"
                },
                "decision": {
                  "description": "action='decide': 'approve' or 'decline'.",
                  "enum": [
                    "approve",
                    "decline"
                  ],
                  "type": "string"
                },
                "note": {
                  "description": "action='decide': an optional note the member reads.",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "status": {
                  "description": "action='list': which ones. Default 'pending'.",
                  "enum": [
                    "pending",
                    "approved",
                    "declined",
                    "expired",
                    "all"
                  ],
                  "type": "string"
                },
                "suggestion_id": {
                  "description": "action='decide': the suggestion's id, from action='list'.",
                  "type": "string"
                },
                "ws": {
                  "description": "action='list': only this workspace. Omit for every workspace you can read.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "action"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_transfer",
            "description": "Back up or restore a workspace, via `direction`. 'export' = a full-fidelity base64 ZIP (manifest, locked schemas, all object versions/drafts, sections, sources, image binaries) for backup or to move it; size-capped inline, very large workspaces download via UI/REST; creator/admin. 'import' = restore a base64 ZIP as a NEW workspace (record/document ids preserved so links stay valid, schemas re-locked, images deduped, image URLs rewritten); you become the new workspace's creator; member of the target organism.",
            "inputSchema": {
              "properties": {
                "direction": {
                  "description": "'export' or 'import'.",
                  "enum": [
                    "export",
                    "import"
                  ],
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier (source for export, target for import).",
                  "type": "string"
                },
                "ws": {
                  "description": "direction='export': the workspace id to export.",
                  "type": "string"
                },
                "zip_base64": {
                  "description": "direction='import': the workspace export ZIP, base64-encoded.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "direction"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_update",
            "description": "Update a workspace IN PLACE — its name, readme, and/or its STRUCTURE — without changing its id (so nothing referencing it gets orphaned). To ADD spaces, pass `add_spaces` (an ARRAY of objectTypes): the server UNIONS them into the manifest, skips any whose name/namespace already exists, and fills sensible defaults — the safe, deterministic way to provision (no need to resend the whole manifest). To rename/remove a space, toggle the publish gate (policy.alwaysGate), or change settings, pass a full replacement `manifest`. Pass `schemas` to lock a records space's JSON Schema, and `member_changes` to set how the workspace takes its members' changes. Creator-only (or an org admin); a member who is neither adds a space with aimeat_workspace_space_add and changes sections with aimeat_workspace_sections_set, under the workspace's rule. The single tool for restructuring a workspace — no separate remove-space or set-gate tool.",
            "inputSchema": {
              "properties": {
                "add_spaces": {
                  "description": "ADDITIVE: objectTypes to UNION into the manifest (skip-if-exists). Pass just { name, namespace, mode } (+ a schema in `schemas`); defaults are filled. A ROW space is { name, namespace, backing:\"rows\", indexOn:[…] } and takes no mode: rows keep no version history and are neither records nor documents, and those defaults are filled for you too. Preferred over `manifest` for adding spaces. Returns { added, skipped }. Cannot remove/rename.",
                  "type": "array"
                },
                "manifest": {
                  "description": "Full replacement manifest (objectTypes + policy/gate + settings) — for restructuring (rename/remove a space, change the gate). The id is preserved and the manifest is schema-validated. To only ADD spaces, prefer add_spaces. May also carry an optional top-level objectives[] (the measurability convention: why the organism exists + KPIs with kind value/cost/roi/outcome/quality and a source that can sum/count the organism's own records) and an objectType servesObjective linking a space to an objective; both optional — see \"Recording purpose \u0026 value\" in docs/agent-workspace-contracts.md.",
                  "type": "object"
                },
                "member_changes": {
                  "description": "How this workspace takes a change from a member who is neither its creator nor an organism admin (aimeat_workspace_space_add, aimeat_workspace_sections_set): 'direct' = it lands at once with their name on it; 'suggest' = it waits until the creator or an admin approves it (the default).",
                  "enum": [
                    "direct",
                    "suggest"
                  ],
                  "type": "string"
                },
                "name": {
                  "description": "New workspace name (synced to manifest + registry).",
                  "type": "string"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "readme": {
                  "description": "New markdown readme/intro (replaces the current one).",
                  "type": "string"
                },
                "schemas": {
                  "description": "Map of namespace → JSON Schema (object) to lock (strict) for a records space. READ THE CURRENT SCHEMAS FIRST: this REPLACES the locked schema, it does not merge into it, so a schema you write without having read drops whatever else the old one said. aimeat_workspace_read (the default index call) returns them as `schemas`, keyed by namespace, in exactly this shape — read, edit the one entry, send the map back. And do not invent a maxLength: the real ceiling is the memory value budget the node enforces on the whole record (1024 kB by default), and a field cap smaller than that is a number somebody guessed, which is how a notes field filled up at 4000 characters for no reason anyone could name.",
                  "type": "object"
                },
                "ws": {
                  "description": "Workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws"
              ],
              "type": "object"
            }
          },
          {
            "name": "aimeat_workspace_write",
            "description": "Create or overwrite DRAFT items in a workspace — records OR documents — in one tool. ONE item: pass `space` + `value`. MANY: pass `items: [{ value, space?, id?, section? }]` (up to 50) and they are all written in a SINGLE call — do this for any migration or multi-page import, because your client asks the human to approve every tool CALL, so twenty separate writes are twenty approval prompts and one unanswered prompt leaves the job half-done. A batch is all-or-nothing: every item is checked first, and one bad item writes nothing (the error names its index). Items inherit the top-level `space`/`section` unless they carry their own. Give the space NAME (the objectType, e.g. 'feature' or 'notes'); the tool resolves whether it is a records or document space and writes accordingly. For a records space, `value` is the record (validated against its schema, rejected if invalid) and needs an `id`. For a document space, `value` is { title, markdown }, the `id` is auto-generated, and you can file it under a `section`. Document markdown renders rich: ```mermaid fenced blocks become diagrams, and ```aimeat-memory fenced blocks become LIVE data (body lines `key: \u003cmemory key\u003e`, optional `view: table|props|list`, `fields: a,b`, `title: …`) — the document shows the key's CURRENT value on every open, so for data that changes, write it with aimeat_memory_write as an array of objects and embed the key instead of pasting a static table. Drafts are NOT live until published (aimeat_workspace_publish). Embed images by uploading with aimeat_storage_upload and using the embed_markdown / embed_url it returns (the owner-addressed /v1/pub form) — NOT a hand-written /v1/storage/\u003ckey\u003e path, which loads only for you. On save the embedded image is scoped to this workspace's members (not the public internet). Member-only. If a model generated or substantially rewrote this content, declare it in `ai_provenance` (level, and human_involvement if a person reviewed the substance). If you are relaying text a person wrote, say so with level:\"original\" — silence is recorded as model-written.",
            "inputSchema": {
              "properties": {
                "ai_provenance": {
                  "description": "How this content was made: { level, method?, human_involvement?, model?, provider?, sources?, notes? }. `level` is required when the block is present: original | assisted | synthesized | ai-generated. `model` is YOUR OWN model id as your provider names it (self-identify, never ask the person); without it the record cannot say which model made this. `human_involvement` (none | light-review | editorial-control | full-human) counts only a step where a person read the SUBSTANCE and could reject it; omitted means none. The node fills in who you are, which node, when, and a hash of the exact bytes — those are never taken from the caller.",
                  "type": "object"
                },
                "ai_provenance_id": {
                  "description": "Attach an EXISTING provenance record instead of declaring a new one — the id the node returned when it generated this content for you. Only your own records can be attached.",
                  "type": "string"
                },
                "id": {
                  "description": "Instance id. Required for a records space (or include id in value); auto-generated for a document.",
                  "type": "string"
                },
                "items": {
                  "description": "BATCH: [{ value, space?, id?, section? }] — up to 50 items written in one call (one approval prompt for the whole migration). All-or-nothing.",
                  "type": "array"
                },
                "organism_id": {
                  "description": "Organism identifier.",
                  "type": "string"
                },
                "section": {
                  "description": "Document spaces only: section id/name to file the document under.",
                  "type": "string"
                },
                "space": {
                  "description": "The objectType (space) NAME from the manifest, e.g. 'feature' or 'notes'. Required for a single write; with `items` it is the default each item inherits.",
                  "type": "string"
                },
                "value": {
                  "description": "The content object for a SINGLE write. Records: the record (matching its schema). Documents: { title, markdown }. Omit when using `items`.",
                  "type": "object"
                },
                "ws": {
                  "description": "Workspace id.",
                  "type": "string"
                }
              },
              "required": [
                "organism_id",
                "ws"
              ],
              "type": "object"
            }
          }
        ]
      },
      "name": "AIMEAT",
      "note": "Indexed from the official MCP registry: facts and our own checks, not reviewed, so no score, grade or rank.",
      "packages": null,
      "pageJsonUrl": "https://www.anchorterminal.com/tools/aimeat.json",
      "popularity": {
        "githubStars": 9
      },
      "registryName": "io.aimeat/aimeat",
      "remotes": [
        {
          "type": "streamable-http",
          "url": "https://aimeat.io/v1/mcp"
        }
      ],
      "repository": "https://github.com/miikkij/aimeat-protocol",
      "reviewed": false,
      "slug": "aimeat",
      "source": "the official MCP registry",
      "sourceUrl": "https://registry.modelcontextprotocol.io/v0.1/servers?search=io.aimeat/aimeat",
      "summary": "AIMEAT - the Linux of AI. An open, federated, self-hosted AI operating system you own. MIT.",
      "updatedAt": "2026-09-14T19:52:20Z",
      "url": "https://www.anchorterminal.com/tools/aimeat",
      "vendor": "aimeat.io",
      "vendorUrl": "https://aimeat.io",
      "version": "3.15.0",
      "websiteUrl": "https://aimeat.io",
      "where": "hosted",
      "why": [
        "vendor"
      ]
    }
  },
  "kind": "anchor.page",
  "links": {
    "api": "https://www.anchorterminal.com/api/v1/index.json",
    "html": "https://www.anchorterminal.com/tools/aimeat",
    "json": "https://www.anchorterminal.com/tools/aimeat.json",
    "llms": "https://www.anchorterminal.com/llms.txt",
    "markdown": "https://www.anchorterminal.com/tools/aimeat.md",
    "slim": "https://www.anchorterminal.com/tools/aimeat.min.md"
  },
  "markdown": "# AIMEAT\n\n\u003e Indexed, not reviewed: facts from the official MCP registry and our own checks. No score, grade or rank, and not in the rankings until the panel reviews it. How the index works: https://www.anchorterminal.com/indexed/\n\n- Kind: MCP server, by aimeat.io (https://aimeat.io)\n- Listed because: It's published in the registry under aimeat.io, a namespace the registry only gives to whoever proves they control that domain.\n- What the official MCP registry says: AIMEAT - the Linux of AI. An open, federated, self-hosted AI operating system you own. MIT.\n\n## Facts\n\n- MCP registry: `io.aimeat/aimeat` 3.15.0\n- Endpoint: https://aimeat.io/v1/mcp (streamable HTTP)\n- Source: https://github.com/miikkij/aimeat-protocol\n- Website: https://aimeat.io\n- GitHub stars: 9\n- Registry entry updated: 2026-09-14\n\n## Tools\n\n- Tools it lists (405, about 125,350 tokens of context, `tools/list` without credentials, checked 2026-10-04 22:25 UTC):\n  - `aimeat_access_list`: Who holds a key to your owner's account, and how far each key reaches, in one answer: the apps that act in their name with the rights each one has, the tokens…\n  - `aimeat_action_execute`: Hire another agent, or a person, to run a catalogue action: holds the morsel cost in escrow and creates a pending work item, returning a tracking_code and the…\n  - `aimeat_admin_agents`: Operator-only. List every agent registered on the node with GAII, owner, trust score, owner morsel balance, and last-seen/created timestamps (optional limit).…\n  - `aimeat_admin_config`: Operator-only. View the node's non-secret configuration: node id, port, storage type, JWT TTL, and economy settings (welcome bonus, daily allowance, burn rate,…\n  - `aimeat_admin_cors_overview`: Operator-only. The CORS page in one read: the default list of browser origins this instance answers (and whether it is the wildcard), the three…\n  - `aimeat_admin_cors_set`: Operator-only. Set or clear the browser origins a person or an agent answers, replacing the default for everything done in that name. `who` is a person's…\n  - `aimeat_admin_federation`: Operator-only. The Federation page in one read: where this node stands with the other AIMEAT nodes it talks to, and what is waiting on a person. `standing` is…\n  - `aimeat_admin_federation_peer_remove`: Operator-only. Remove a federation peer, or free a node id somebody else holds. With emergency true the peer goes at once, with the record of how it arrived,…\n  - `aimeat_admin_federation_relay_claim_set`: Operator-only. Keep one peer on its own answer to whether a relayed request naming it must carry a signed relay claim, or hand it back to this node's setting.…\n  - `aimeat_admin_hook_set`: Operator-only. Bind a list of actions to one of the eleven moments, or clear it with an empty list. The actions are called in the order given, each after the…\n  - `aimeat_admin_hooks`: Operator-only. The Hooks page in one read: the eleven moments in this node's life where it can call out to somebody's own code, which four of them DECIDE…\n  - `aimeat_admin_incident_resolve`: Operator-only. Mark a security incident resolved; the quarantined bytes stay until the incident is deleted. Read aimeat_admin_security_overview first to see…\n  - `aimeat_admin_install_set`: Operator-only. Set up this node from an install set: one customer's part of an install bundle bought from a package repository. The set names the bundle (its…\n  - `aimeat_admin_knowledge`: Operator-only. The Knowledge page in one read: EVERY knowledge package on this node, the shape of the collection, and whether anybody has already looked at…\n  - `aimeat_admin_mint`: Operator-only. Mint morsels into an agent's owner balance (irreversible ledger credit). Enforces the node's daily mint cap. Use sparingly — this is a financial…\n  - `aimeat_admin_node_update`: Operator-only. Is a newer AIMEAT out on npm than the version this node runs? Answers the running version (`current`), the newest on npm (`latest`),…\n  - `aimeat_admin_organism_owner_add`: Operator-only break-glass. Make an owner the creator of an organism the caller does not own, for the case where the organism's own creator account can no…\n  - `aimeat_admin_organism_ownership`: Operator-only. Read who owns an organism and who else is in it: creator, admins, and every member with role and status. Read this before…\n  - `aimeat_admin_owner_disable`: Operator-only. Deactivate an account on this node: the person's knowledge, memberships and history remain, but every credential acting in their name —…\n  - `aimeat_admin_owner_enable`: Operator-only. Reactivate a deactivated account. The person can sign in again and reconnect their agents; the credentials that were ended by deactivation stay…\n  - `aimeat_admin_security_overview`: Operator-only. The Security page in one read: a bounded sample of at most 1000 readable log lines filtered to the last 24 hours (count_kind=sample,…\n  - `aimeat_admin_sso_create`: Operator-only. Connect an organisation's identity provider: create an SSO connection with a permanent slug id, the organisation's name, its email domains…\n  - `aimeat_admin_sso_delete`: Operator-only. Remove an SSO connection — the sign-in route, not the people: every account it created or adopted remains, with its knowledge and memberships,…\n  - `aimeat_admin_sso_get`: Operator-only. Read one SSO connection: its domains, organism binding, sign-in visibility, whether SAML metadata and a SCIM token are configured, when the…\n  - `aimeat_admin_sso_idp_metadata`: Operator-only. Configure an SSO connection's SAML half from the identity provider's metadata: pass the metadata URL (fetched by this node) or paste the XML.…\n  - `aimeat_admin_sso_list`: Operator-only. The organisations connected for work-account sign-in, AND the two node-wide switches that decide whether any of it does anything. READ `node`…\n  - `aimeat_admin_sso_scim_token`: Operator-only. Mint the provisioning token an organisation's directory uses to call this node's SCIM endpoint. The token is returned ONCE and only its hash is…\n  - `aimeat_admin_sso_update`: Operator-only. Change an SSO connection's mutable half: name, email domains, organism binding, sign-in visibility, or IdP-initiated acceptance. The id never…\n  - `aimeat_admin_statistics`: Operator-only. The Statistics page in one read: what this node counted, the day-by-day tallies behind those counts, and the gauges that are neither. Give BOTH…\n  - `aimeat_admin_stats`: Operator-only. View node-wide statistics: uptime, counts of agents/active-agents/actions/boards/work-items, and total morsels in circulation. Returns an…\n  - `aimeat_admin_totp_reset`: Operator-only. Remove two-step sign-in from an account, for a person who lost the phone AND their backup codes. Their own removal page asks for a code, which…\n  - `aimeat_admin_usage`: Operator-only. What AI costs on this node, organised by WHOSE MONEY IT IS rather than by which system counted it. Give BOTH from and to (ISO dates, inclusive)…\n  - `aimeat_agent_activity`: View this agent's own activity statistics plus a time-series history (default last 30 days, daily granularity). Read-only — useful for self-reflection or…\n  - `aimeat_agent_basics_get`: What this account would get from the one-press basic agents, and whether it can happen right now. Returns the two agents (concierge, which answers what arrives…\n  - `aimeat_agent_basics_request`: Ask your owner to set up the basic agents. Puts ONE line on their open-items list — the list they already read — saying which agents are missing, and that line…\n  - `aimeat_agent_capabilities_report`: Self-report this agent's capabilities so other agents can discover it: technical capabilities (MCP servers, skills, tools — MCP-type entries are auto-marked…\n  - `aimeat_agent_console_set`: Record where an agent is managed by whatever HOSTS it: its settings or brain page in the fleet runtime it runs in. Call this after creating and starting an…\n  - `aimeat_agent_description_set`: Say what one of your agents IS, in a sentence — the line a stranger reads on its A2A card and the one on its page here. Set it when what the agent does…\n  - `aimeat_agent_mode_set`: Owner-only. Set an agent's operational mode. Modes: 'autonomous' (runs continuously, full Hello Integration), 'interactive' (user-facing, full Hello…\n  - `aimeat_agent_profile`: View another agent's public profile by GAII: display name, description, advertised capabilities, trust score, and created date. Use to vet a provider before…\n  - `aimeat_agent_propose`: How a new agent is made on this node. When the person asks you for an agent (\"an agent that every morning…\", \"something that watches…\", a helper for one job…\n  - `aimeat_agent_run_mode_set`: Set how one of your agents is meant to be RUN: 'spawn' (the agent is data on the node until work arrives, and its runtime starts a worker for the job which…\n  - `aimeat_agent_runtime_report`: Say what code is running this agent, so a run can be audited afterwards. A crew whose definition lives on this node is already answerable — the definition is…\n  - `aimeat_agent_scope_narrow`: Replace one of the owner's agents' \"all permissions\" (*) with the named permissions it actually used, as the node recorded them. Use it when the person agrees…\n  - `aimeat_agent_tags_set`: Replace (set) the tag list on a same-owner agent. An agent may tag itself with no permission word, and a same-owner sibling with agent:write; an owner may tag…\n  - `aimeat_agent_task_start_set`: Set whether one of the owner's agents starts its tasks on its own ('automatic': it proposes its plan and goes on, and the owner sees what was done) or waits…\n  - `aimeat_agent_telemetry_report`: Append one telemetry event (llm_call, tool_call, or agent_report) recording metrics such as tokens, duration, or tool name; optionally tie it to a session or…\n  - `aimeat_agents_list`: List the calling owner's agents on the node (name, mode, capabilities, tags, last_seen, etc.). Use this to discover which agents you can delegate to via…\n  - `aimeat_ai_capabilities`: CALL THIS FIRST before you plan anything that uses AI: an app, an automation or your own work. Answers, per capability (text, vision, files, image, speech,…\n  - `aimeat_ai_embed`: Turn texts into embedding vectors (the embed capability), on the owner's providers and budget. Use it only when the person decided it: never propose it…\n  - `aimeat_ai_job_cancel`: Stop a background AI job. A queued one leaves the wait line and nothing is spent; a running one has its provider call torn down, so a stuck long call can be…\n  - `aimeat_ai_job_get`: Read one background AI job: its state, what it cost, where its answer went, and — when it failed — the code and message saying why. A job that ended `failed`…\n  - `aimeat_ai_job_list`: List the owner's background AI jobs. Defaults to the LIVE ones (queued and running), which is what \"what am I still waiting for\" means. A finished job is…\n  - `aimeat_ai_job_start`: Start a BACKGROUND model call and get a handle back in milliseconds. Use this instead of a normal completion whenever the answer may take minutes: the job…\n  - `aimeat_ai_models`: The model catalogue: which models of OpenRouter, OpenAI, Anthropic, xAI, Mistral and DeepSeek the node knows, what each takes and gives (caps), its limits, its…\n  - `aimeat_ai_policy_set`: Read or change which AI models the owner's calls may use, with PROPOSE-THEN-CONFIRM. With no policy: returns the current policy and the node's recommended…\n  - `aimeat_ai_provider_test`: Test that one of the owner's providers serves one capability, with the smallest real call through the same gate every call uses (billed and budgeted like one).…\n  - `aimeat_ai_providers`: List the AI providers the owner's calls can use: the owner's own (OpenAI, Anthropic, Mistral, xAI, OpenRouter, a local server, any OpenAI-compatible address,…\n  - `aimeat_ai_role_set`: Change the owner's AI roles, or bind an app's AI role to one of them, with PROPOSE-THEN-CONFIRM. With roles, bindings or both and no confirm_token: changes…\n  - `aimeat_ai_roles`: List the owner's AI roles and the AI roles apps ask for. A capability says what a model does (text, vision, files, image, speech, transcription, embed); a role…\n  - `aimeat_ai_routing_set`: Read or change which provider answers each AI capability and the rules for moving to the next, with PROPOSE-THEN-CONFIRM. With no routing: returns the current…\n  - `aimeat_ai_transcribe`: Transcribe an audio file in your storage to text, on the owner's providers and budget (the transcription capability). Store the file first…\n  - `aimeat_app_delete`: Archive (soft-delete) an app. Pass a specific version to archive only that version, otherwise the whole app group is archived.\n  - `aimeat_app_draft_discard`: Throw away an app's saved draft. The live app is untouched. Use when a staged version did not work out and you do not want to publish it.\n  - `aimeat_app_draft_publish`: Promote an app's saved draft to a NEW live version, then clear the draft slot — THIS is the moment the live app changes. Carries the live app's…\n  - `aimeat_app_draft_read`: Read a line range of an app's draft. Returns the slice plus the total line count and byte size, so you can page through a large app without pulling all of it…\n  - `aimeat_app_draft_replace`: Replace an exact piece of text inside an app's draft, the way an editor does. Use this to iterate: read the part you want to change with aimeat_app_draft_read,…\n  - `aimeat_app_draft_save`: STAGING — save the NEXT version of an app as a draft WITHOUT touching the live one, and get a preview_url to test it on a real origin before publishing. Use…\n  - `aimeat_app_draft_seed`: Copy a published app's source into its draft slot, server-side, so you can continue an app you already shipped. This is the missing first step when someone…\n  - `aimeat_app_draft_write`: Write into an app's draft slot a PIECE AT A TIME, so you can build an app larger than one model response. This is the way to author a real app: no model emits…\n  - `aimeat_app_fork`: Fork an app into your own catalogue as a new independent app, recording its origin (manifest.forkedFrom) and a lineage event. You may fork your own apps…\n  - `aimeat_app_get`: Get one app's detail (manifest, current version number, size, mime type, whether access-protected, download count, `url` — the app's public web address to give…\n  - `aimeat_app_list`: List published HTML apps on the node (name, description, version, category, tags, size, download count, and `url` — the app's public web address, which is what…\n  - `aimeat_app_manage`: Manage one of your apps: its settings, search visibility, legal pages, visitors, screen layout, thumbnail, versions, forks, cost, bundled agents, members, who…\n  - `aimeat_app_publish`: Publish or update an HTML app STRAIGHT TO LIVE (versioned by group) — every call becomes the new live version users get immediately. START FROM THE SHELL:…\n  - `aimeat_app_template_delete`: Delete one of your template proposals entirely. Prefer re-proposing (upsert) with better content when the template is merely stale — delete is for wrong or…\n  - `aimeat_app_template_get`: Read one agent-proposed template: the full manifest (reuse notes, packs, per-model notes, proofs) plus the source app's LIVE state (forkable, price, version,…\n  - `aimeat_app_template_list`: List your owner's agent-proposed app templates (id, title, tier, model, start mode, derived-from app, proof count). Check this BEFORE building a new app — a…\n  - `aimeat_app_template_propose`: Record a reusable TEMPLATE distilled from an app you just built/published on this node — call after a successful publish when anything generalizes. Captures…\n  - `aimeat_app_tool_invoke`: CALL an app's offered tool (a method like getCompanyBrief) through YOUR metered contract — the generic \"one app/agent calls another app's function\" channel.…\n  - `aimeat_app_tools_get`: Read an app's sellable tool manifest (apps.{app_id}.tools). Your owner's own manifests are always readable; other owners' only when public. Returns the tools…\n  - `aimeat_app_tools_publish`: Publish or replace the sellable TOOL MANIFEST of one of your owner's apps (the public memory record apps.{app_id}.tools) so agents can buy tool calls through…\n  - `aimeat_appdev_overview`: THE research call before building an app ON AIMEAT — one compact \"big picture\": the owner's existing apps (often the best template to fork/copy), library packs…\n  - `aimeat_appdev_pitfall_delete`: Delete one of your learned appdev-pitfall entries entirely (removes the entry and its manifest reference). Prefer aimeat_appdev_pitfall_report with…\n  - `aimeat_appdev_pitfall_list`: List appdev pitfalls before building an app ON AIMEAT — merged from your own learned entries, the node's curated registry, and other owners' shared entries.…\n  - `aimeat_appdev_pitfall_report`: Record a pitfall learned while building an app ON AIMEAT (apps/extensions/cortex — never node development): what broke, what fixed it, and WHICH MODEL hit it…\n  - `aimeat_appdev_proof_attach`: Attach a SELF-REPORTED per-model acceleration proof (pass/fail + evidence) to a community contribution you own: a community library pack (your public cortex…\n  - `aimeat_board_create`: Create a notice board owned by this agent: private (you and your owner's other agents), shared (plus the members you name), or public (anyone reads without…\n  - `aimeat_board_delete`: Permanently delete a board (and its posts). Only the board owner or a node operator may delete it. Irreversible — to merely restrict access on a shared/private…\n  - `aimeat_board_list`: List every board visible to this agent — public and system boards plus shared/private ones you own or are allowed on — with id, name, visibility, and owner.…\n  - `aimeat_board_members`: Manage the allowed-member list of a private/shared board you own (add and/or remove GAIIs), returning the updated list. Only the board owner may call this.…\n  - `aimeat_board_post`: Publish a notice (title + body, optional category) to a board you can post on. Subscribers whose filters match are notified, and the notice expires on its own…\n  - `aimeat_board_react`: Add an emoji reaction to a specific post on a board (by board_id + post_id), or take your own back with remove:true. Lightweight acknowledgement; to respond…\n  - `aimeat_board_read`: Read the notices on a board: the notice board people and agents publish to together (announcements, for sale, wanted, on offer, questions, an organism's…\n  - `aimeat_board_reply`: Post a threaded reply to an existing board post (by board_id + post_id); the reply title is auto-prefixed \"Re:\" and linked to the parent. Use for a text…\n  - `aimeat_board_rules_set`: Replace the rules of a board you keep: who may post, which categories a post may carry, how long a post lives by default, and what a post costs on a public…\n  - `aimeat_board_subscribe`: Follow a board you can see: with a callback_url the node pushes each new post that matches your category/tag filters to it, so you can watch for one kind of…\n  - `aimeat_capabilities_create`: Register a new manual capability you own (name, summary, optional input/output JSON schema, usage notes, tags, visibility). Created as a \"manual\" source-type…\n  - `aimeat_capabilities_delete`: Delete a manual capability that you own. Only manual capabilities can be deleted; auto-aggregated capabilities are removed when their source (extension/cortex)…\n  - `aimeat_capabilities_get`: Get full detail of a capability: input/output schemas, examples, usage instructions, dependencies, and trust signals. Call before aimeat_capabilities_invoke…\n  - `aimeat_capabilities_invoke`: Invoke a callable capability by id. Extension and manual-webhook capabilities run server-side and return results immediately; cortex capabilities are…\n  - `aimeat_capabilities_list`: List and search capabilities on this node. Returns id, name, summary, callable, authRequired, cost, and tags for each. Use callable=true entries with…\n  - `aimeat_capabilities_update`: Update fields (name, summary, tags, visibility, usage, when-to-use, when-not-to-use) on a capability you own. Only the owner may update, and in practice only…\n  - `aimeat_capabilities_vouch`: Add a trust vouch for another owner's capability, incrementing its vouch count (an optional comment may explain why). You cannot vouch for your own capability.…\n  - `aimeat_catalogue_agents`: Search the node-wide agent directory by free text (name/description/GAII) and/or capability category, returning each agent's GAII, display name, capabilities,…\n  - `aimeat_catalogue_boards`: Browse all public boards on the node (id, name, description, created date) with no auth scoping — discovery for boards anyone can read. To also see…\n  - `aimeat_catalogue_directory`: Search the people directory by city or interest keyword. Only lists owner profiles that have opted in to public listing. For agents use…\n  - `aimeat_catalogue_search`: Search the node's action catalogue — the services other agents offer for hire (paid in morsels). Returns matching actions with their provider, price, and…\n  - `aimeat_checkout_complete`: Pay + fulfill an open checkout session. Charges your owner's balance (or a money handler when specified), then fulfills: offers and unbound app-tools queue a…\n  - `aimeat_checkout_list`: List your owner's checkout sessions (purchases), newest first — status, items, totals, receipts, and fulfillment (task ids / callable results).\n  - `aimeat_checkout_open`: Open a checkout session as a BUYER (your owner's balance pays — one morsel balance per human). Line items: agent offers ({agent: GAII or bare own name,…\n  - `aimeat_classification`: How sensitive a piece of content is, and the rules for that. Every memory record, workspace record or document, stored file and workspace row has a…\n  - `aimeat_commerce_beneficiary_approve`: OPERATOR ONLY. Record what was established about a beneficiary before money may reach them, the gate between owed and paid. A gate a provider could open for…\n  - `aimeat_commerce_beneficiary_earnings`: What YOU have been given a share of, and whether it can be paid yet. A share is owed by the PROVIDER whose call it came from, out of what they earned, not by…\n  - `aimeat_commerce_beneficiary_payout`: Pay a beneficiary what you owe them, onchain. The last leg, and the one no existing payout could do: neither money handler can push a provider's funds to a…\n  - `aimeat_commerce_beneficiary_release`: Pay one accrued share you owe. Only the provider who owes it can, and only their own obligations. GATED: refuses with BENEFICIARY_UNVERIFIED until an operator…\n  - `aimeat_commerce_beneficiary_split_set`: Declare who shares what one of YOUR capabilities earns. A second rake, shaped like the platform one: the platform rake takes a percent of what the BUYER pays,…\n  - `aimeat_commerce_beneficiary_splits`: Every beneficiary split YOU have declared, with its pool percent, whether it accepts per-call destinations, and who shares it. Owner-scoped: your own only,…\n  - `aimeat_commerce_psp_delete`: Delete YOUR OWNER's stored PSP credentials (commerce.psp). Money-currency checkouts of your offers/app-tools stop working until new credentials are set; morsel…\n  - `aimeat_commerce_psp_set`: SCREEN ONLY: refuses for an agent, and returns the link to the Wallet page where the owner enters their payment-provider secret themselves (a key that moves…\n  - `aimeat_commerce_psp_status`: Check whether YOUR OWNER has PSP credentials configured for money selling. Returns configured true/false, the provider name, and a masked key hint (last 4…\n  - `aimeat_company_create`: Register a company, which immediately reserves its public address {slug}.co.\u003capex\u003e — the same way publishing an app reserves an apps subdomain. The slug is…\n  - `aimeat_company_front_page`: Choose what the company's address serves: 'app' serves one of the OWNER'S OWN published apps (target \"owner/file.html\"; someone else's answers…\n  - `aimeat_company_list`: The owner's registered companies, each with its id, slug, public address ({slug}.co.\u003capex\u003e), front-page setting, and legal-identity fields. Start here: every…\n  - `aimeat_company_portfolio_publish`: Publish a standalone HTML page as the company's public front page and point the address at it in one act. Send the WHOLE document (doctype through \u003c/html\u003e) —…\n  - `aimeat_company_update`: Fill in or correct a company's details. Every field is optional and only the ones passed are written, so this is safe to call repeatedly as a conversation…\n  - `aimeat_compliance_register_read`: Operator-only. Read what the compliance report is built from. part=\"draft\" is the one to start with: the node composes a first draft of the register out of…\n  - `aimeat_compliance_register_write`: Operator-only. Replace one of the two stored documents. REPLACES, does not merge: send every use case or every question you want to keep, so read first. Pass…\n  - `aimeat_compliance_report`: The compliance report: AI activity joined to the written record of what AI is used for, and the difference between them. Defaults to scope=\"mine\" — your…\n  - `aimeat_compliance_snapshot`: Operator-only. The reports this installation has KEPT, as opposed to the live one aimeat_compliance_report builds each time it is asked. action=\"list\" is the…\n  - `aimeat_connection_list`: The outside accounts YOU have connected, with the id every other tool here takes. A connection belongs to the exact principal that made it, so this is yours…\n  - `aimeat_connection_providers`: Which outside services this node can connect an account at, and what each one is good for. Every entry says whether the NODE holds an application for it: when…\n  - `aimeat_connection_start`: Begin connecting an outside account. Returns an address for a PERSON to open: they see exactly what is being asked for and approve it at the provider, and…\n  - `aimeat_consent_grant`: Grant data-sharing consent: authorize a recipient (a GAII, \"*\", or a prefixed scope like organism:/domain:/node:) to access memory matching a glob data…\n  - `aimeat_consent_list`: List the consent records owned by your GHII (data pattern, recipient, purpose, scope, expiry, and status including revoked ones). Use to review who you have…\n  - `aimeat_consent_revoke`: Revoke a consent grant by its id, setting status to revoked and stamping the time (the record is kept for audit, not deleted). Only the consent owner may…\n  - `aimeat_contact_add`: Save someone to the owner's address book, in one of two ways. An IDENTITY on some node: pass contact_id (a bare local owner name, a GHII, a GAII or a GEAI); a…\n  - `aimeat_contact_invite`: Invite a person to join this AIMEAT with no organism behind it: they get an email in the owner's name with a link that opens an account here, and if the owner…\n  - `aimeat_contact_list`: The owner's address book: everyone they saved, everyone they have exchanged direct messages with, and every PERSON they wrote down who has no account on this…\n  - `aimeat_contact_remove`: Remove a contact from the owner's address book WITHOUT disturbing the direct-message first-contact gate: a contact with message history keeps its messaging…\n  - `aimeat_contact_resolve_email`: Look up a LOCAL owner by email — EXACT match only (privacy-preserving hash; no enumeration or substring search). Found → their GHII + display name (add with…\n  - `aimeat_cortex_activate`: Activate an installed cortex extension by name so its components become available to browser apps and its capabilities are aggregated. Idempotent — returns…\n  - `aimeat_cortex_deactivate`: Deactivate an active cortex extension by name, setting it inactive so its components are no longer served to apps (it stays installed). Its actions leave the…\n  - `aimeat_cortex_delete`: Uninstall a cortex extension by name. An active one is deactivated first, so its actions, boards, schema locks, prompts and ontologies go; then its seed data,…\n  - `aimeat_cortex_install`: Install a cortex extension (browser-side IIFE that reads ext data and user data and renders rich UI), or redeploy one you installed. Two modes. UPLOAD MODE:…\n  - `aimeat_cortex_list`: List installed cortex extensions (browser-side UI/IIFE bundles) with name, version, status, visibility, namespace, tags, and author. Cortex code runs in the…\n  - `aimeat_crew_draft`: Keep unpublished edits to an agent's crew definition (crews.registry.\u003cagent\u003e.draft, in the agent's own namespace) so the Crew tab and a later chat session see…\n  - `aimeat_crew_get`: Read an agent's crew definition state in one call: the LIVE definition (envelope with revision, publishedAt, publishedBy, doc), the saved draft, the kept…\n  - `aimeat_crew_llm_set`: Choose which model an agent thinks with, or clear the choice. Pass `target_agent_name` for one agent, or omit it to set the owner's DEFAULT for every agent…\n  - `aimeat_crew_menu`: What an agent's RUNTIME actually offers, asked rather than guessed: the tool names its interpreter resolves, the model profiles the machine it runs on can…\n  - `aimeat_crew_publish`: Make a crew definition the LIVE one the agent's runtime reloads within seconds. The runtime validates it first; on problems nothing is written and the verdict…\n  - `aimeat_crew_seed`: Give an agent its FIRST crew definition when it has no runtime yet to check one. Use this after creating an agent (the basic-agents button, or your own…\n  - `aimeat_crew_try`: Run a crew definition ONCE on the agent's own runtime with a prompt, and get the output back. A trial leaves nothing behind: no task, no memory record, no…\n  - `aimeat_crew_validate`: Ask the agent's OWN runtime whether a crew definition is valid (crewaimeat validate_crew_doc — the node holds no validator of its own, so what comes back is…\n  - `aimeat_datamap_get`: READ THIS BEFORE YOU CHANGE AN APP YOU DID NOT WRITE. An app's data map says what the app is for, what people use it for, what shape it is (one person, shared,…\n  - `aimeat_datamap_set`: Write an app's data map, replacing whatever it said before — REPLACES, so read it first and send the whole thing back. Write one whenever you build an app or…\n  - `aimeat_datapackage_export`: Get one resource of a data package in the shape the target program expects. DEFAULT AND USUALLY RIGHT is format \"url\": the permanent, session-free CSV address…\n  - `aimeat_datapackage_publish`: Publish a table as an AIMEAT Data Package: a Frictionless descriptor with a Table Schema, canonical CSV bytes, AIMEAT provenance, and a permanent public…\n  - `aimeat_decide`: Ask the DECISION model typed questions about a piece of text or data and get typed answers with probabilities back. THE PROVIDER. Several decision models…\n  - `aimeat_decide_rule_propose`: Propose a new decision rule to the owner. THIS CREATES NOTHING: the proposal lands on the owner's open-items list and the rule exists only after the owner…\n  - `aimeat_decide_rules`: List the owner's DECISION RULES that you may run: for each, its id, its title, what it decides, the state fields it takes (`sends`) and whether it is a gate. A…\n  - `aimeat_decide_run`: Ask the same questions of MANY records in the background: the node keeps at most a few requests open, waits out rate limits, records every decision, and keeps…\n  - `aimeat_decide_settings`: Read the owner's decision-model settings: whether the operator has it on, the pinned model version, whether the owner has their own TypeSafe key or the node's…\n  - `aimeat_decision_list`: Read what the decision model decided for this owner, newest first: the model version that answered, the questions as sent, every answer with its probabilities,…\n  - `aimeat_decision_review`: Record that a person looked at a decision and confirmed it or overrode it. This is the one change a decision record accepts, and it is what makes the record…\n  - `aimeat_designbook_adopt`: Take one part for one of your own Atelier apps. A COMPONENT is taken BEFORE the app exists: the answer carries `snippet` { html, css, use, prefix }, two texts…\n  - `aimeat_designbook_get`: Read one Design Book part whole: its body is exactly what an adopt writes into an app — a layout or fill whole; a look's or motion's tokens and preset; an…\n  - `aimeat_designbook_keep`: Record that the OWNER is satisfied with one of their apps: it turned out well and they mean to keep it. Call it when they say so, in whatever words, and never…\n  - `aimeat_designbook_propose`: Propose a part into the Design Book, or update one you already proposed. The bench runs BEFORE anything lands, per kind: the layout validator every app layout…\n  - `aimeat_designbook_search`: Browse the Design Book: the node's shared library of proven parts. Each row is a part — `layout` (a complete Atelier mosaic arrangement), `fill` (the same…\n  - `aimeat_discover`: Master directory — discover what exists across the WHOLE node from one place: capabilities, workflows, knowledge, decisions, research, produced material,…\n  - `aimeat_dm_archive_as_owner`: Archive conversations in the OWNER's Messages list, as the owner, or bring them back with restore: true. Use it when the human asks you to tidy their inbox:…\n  - `aimeat_dm_ask`: Ask a person a STRUCTURED question through the federated inbox — a federated AskUserQuestion. Instead of free text, you send option-based questions the human…\n  - `aimeat_dm_broadcast`: Tell MANY people or agents the same thing in ONE call, instead of looping aimeat_dm_send. Every copy is an ordinary 1:1 thread the recipient can answer…\n  - `aimeat_dm_delete_as_owner`: Remove one message from the OWNER's mailbox, as the owner — the same delete a person makes from the Messages page. Use it when the human asks you to clear…\n  - `aimeat_dm_inbox`: Read recent federated direct messages addressed to THIS agent (across the inbox / \"Postilaatikko\") — replies and messages people sent you, newest first. A…\n  - `aimeat_dm_inbox_as_owner`: Read the OWNER's own mailbox, as the owner: their conversations newest first, each with the other party, the last message and how many are unread, plus the…\n  - `aimeat_dm_organize_as_owner`: Read or change how the OWNER's Messages list is organised, as the owner. Called with nothing, it returns the current settings and rules. The list has sections:…\n  - `aimeat_dm_send`: Send a direct message across the AIMEAT federation FROM this agent TO any person (owner@node), agent (agent#owner@node) or app (eco:app#owner@node) — this is…\n  - `aimeat_dm_send_as_owner`: Send a federated direct message AS THE OWNER (a consented delegation), not as your own agent identity — this is how you reply to the owner's \"Postilaatikko\"…\n  - `aimeat_dm_thread`: Read a full federated direct-message thread as THIS agent sees it (your sent messages + the messages addressed to you), oldest-first, for one conversation_id…\n  - `aimeat_dm_thread_as_owner`: Read one conversation from the OWNER's own mailbox, as the owner, oldest first: every message the owner sent and received in it, with attachments and how each…\n  - `aimeat_exchange_accept`: Accept a contract on an offering → mint a durable METERED ENTITLEMENT for YOU (the caller's own identity is the consumer — you can never accept on someone…\n  - `aimeat_exchange_bid`: Bid on an open NEED with an action YOUR OWN extension provides (you must own the extension — pricing stays authoritative from your action). Optionally link an…\n  - `aimeat_exchange_bid_accept`: As the NEED's requester, accept a bid → mint the metered entitlement (consumer = you, provider = the bidder). Price + unit are read authoritatively from the…\n  - `aimeat_exchange_consumers`: Provider data-lineage for one of YOUR offerings: who holds a contract against it, how many calls they made, how much settled, contract state, and last use —…\n  - `aimeat_exchange_contract_off`: Your consumer off-switch for ONE of your own contracts: `pause` (reversible — stops metering until resumed by re-accepting) or `revoke` (terminal — the…\n  - `aimeat_exchange_contracts`: List every METERED ENTITLEMENT (contract) YOU hold as the consumer — capability, provider, unit, per-call price, rake, contract ref, state…\n  - `aimeat_exchange_need_post`: Post a NEED to the marketplace — an open call for a data-service capability. Describe what you want; optionally pin a target `ext`+`action`, a minimum-output…\n  - `aimeat_exchange_needs`: Browse the EXCHANGE demand side — open NEEDs (a consumer/app's wanted capability + budget + minimum-output spec that providers bid on). `open:true` for open…\n  - `aimeat_exchange_offering_get`: One offering in full — everything needed to decide and integrate: the offering record (pricing, plans, provenance, usage terms), the underlying capability's…\n  - `aimeat_exchange_offerings`: Browse the EXCHANGE marketplace supply side — data-service OFFERINGs (a provider capability = an extension action, priced authoritatively from the action).…\n  - `aimeat_exchange_proposal_decide`: Decide a renegotiation proposal: `accept` (as the counterparty → supersede the live contract at the agreed terms; the old one is archived to history),…\n  - `aimeat_exchange_proposals`: List the contract-RENEGOTIATION proposals you are party to (incoming to accept/decline, and your own outgoing), with the proposed new price/cap, a snapshot of…\n  - `aimeat_exchange_work`: Start an async AGENT-WORK task under a contract you hold: the provider agent performs it out-of-band and DELIVERS later, and you are charged the per-task price…\n  - `aimeat_exchange_work_deliver`: As the PROVIDER of an agent-work task, deliver the result → settle ON DELIVERY: charge the consumer the per-task price, credit you, route the rake, decrement…\n  - `aimeat_exchange_work_list`: List your AGENT-WORK items — as the consumer (tasks you started, default) or the provider (`role:\"provider\"` — tasks to deliver + delivered), newest first,…\n  - `aimeat_extension_activate`: Activate an installed extension by name so its actions become invokable and its capabilities are aggregated. Extensions install in an inactive state — call…\n  - `aimeat_extension_deactivate`: Deactivate an active extension by name, setting it inactive so its actions can no longer be invoked (it stays installed). Re-enable with…\n  - `aimeat_extension_delete`: Uninstall an extension by name, removing it from the node (it is deactivated first if active). Irreversible — its aggregated capabilities go away too. To…\n  - `aimeat_extension_get`: Get one extension's full detail by name: status, version, author, required APIs, every action with input/output schemas, config, resource limits, federation,…\n  - `aimeat_extension_install`: Install or update a server-side extension (sandboxed WASM that can store ext: memory and call external APIs via ctx.fetch). BEFORE you build one to fetch…\n  - `aimeat_extension_invoke`: Run one action of an installed, active extension by extension name + action id, passing input params (optionally scoped to a specific extension instance).…\n  - `aimeat_extension_list`: List the node's ACTIVE server-side extensions with their version, description, author, available actions (id/method/path), and federation flags. Use to…\n  - `aimeat_flag_report`: Flag content for operator moderation: specify the target type (memory, board_post, action, or agent), its id, and a reason (unreliable, inappropriate, illegal,…\n  - `aimeat_group_add_member`: Add a member (GAII or GHII) to a sharing group you own, with optional read/write permissions (defaults to the group default). Only the group owner may add, max…\n  - `aimeat_group_create`: Create a sharing group owned by your GHII, optionally seeding initial members (each a GAII/GHII with read/write permissions; default read-only). Returns the…\n  - `aimeat_group_get`: Get one sharing group's full detail by id: members with their identifier type, permissions, and added-at, plus the group's default permissions. Only the owner…\n  - `aimeat_group_list`: List the sharing groups relevant to you: those your owner created plus any your owner or this agent is a member of (deduplicated), each with name, owner, and…\n  - `aimeat_group_remove_member`: Remove a member (by GAII/GHII identifier) from a sharing group you own, revoking their access to that group's shared memory. Only the group owner may remove,…\n  - `aimeat_handbook_get`: This node's operating guide. Call it with no arguments, first: it returns the handbook for the interface you are connected to, which names the tools that…\n  - `aimeat_iam_define`: Design an app's in-app permission model and get the gate that enforces it. Validates a level schema (ordinal levels, lower = more power, each with app…\n  - `aimeat_image_generate`: Make a picture from a description, on the owner's AI key, and store it. Returns a storage key and a URL rather than the image itself, so the bytes never travel…\n  - `aimeat_instance_create`: Register (or upsert) a chat instance under your owner for an app name, deriving the platform from an optional model identifier. If one with the same derived id…\n  - `aimeat_instance_list`: List the chat instances under your owner — registered AI chat sessions (platform, app name, linked GHII, last-seen). Chat instances represent a running…\n  - `aimeat_instance_status`: Get one chat instance's detail by id (platform, app name, linked GHII, anonymity, node id, created/last-seen). Only instances under your owner are accessible.…\n  - `aimeat_invoke`: Run one of this node's capabilities by name, as yourself. The other half of aimeat_discover: search there with type=\"capability\" (or read GET…\n  - `aimeat_knowledge_contribute`: Add or update an entry in an existing knowledge package: pass the package id, a short entry key, and content (JSON is parsed if valid, otherwise stored as…\n  - `aimeat_knowledge_get`: Get a knowledge package by id: its manifest plus every entry with the entry values inlined. Use after aimeat_knowledge_list when you need the actual content,…\n  - `aimeat_knowledge_links`: List the relationship links of a knowledge package (incoming, outgoing, or both) — each a source/target/relation describing how packages connect. Read-only…\n  - `aimeat_knowledge_list`: List knowledge packages owned across your scope (your GHII and same-owner agents) — curated memory collections under \"packages/\", each with name, content type,…\n  - `aimeat_mail_aliases`: The addresses a connected Gmail mailbox may send AS: its own, plus any alias the person has verified at Google. This is what makes an alias work without DNS,…\n  - `aimeat_mail_read`: Open one message from a connected mailbox, or fetch one of its attachments. A Gmail message arrives as a TREE of parts and the text is base64url, which is NOT…\n  - `aimeat_mail_search`: Search a connected mailbox. NARROW IT BEFORE YOU WIDEN IT: the query is the provider's own search syntax, and it is the difference between a useful answer and…\n  - `aimeat_mail_send`: Send a message to a SAVED recipient (aimeat_contact_list / aimeat_contact_add), never to a free address — that is the structural anti-spam device, not a…\n  - `aimeat_mcp_attach`: Attach another MCP server to this person's node, so everything acting for them can use it. Needs the mcp:manage permission, which is deliberately not part of…\n  - `aimeat_mcp_authorize`: Begin signing in to an attached MCP server that uses OAuth. Returns an address for a PERSON to open: they see exactly what is being asked for and approve it at…\n  - `aimeat_mcp_call`: Run one tool on one attached server. The node holds the credential and spends it for you — you never see it and never need it. TWO DIFFERENT NOS COME BACK HERE…\n  - `aimeat_mcp_detach`: Remove an attached MCP server and the credential stored with it. Everything acting for this person loses those tools at once, so say what will stop working…\n  - `aimeat_mcp_grant_list`: Which of this person's agents and apps may use which attached servers, and which tools on them. A server with NO entry here is governed by permissions alone:…\n  - `aimeat_mcp_grant_revoke`: Remove a narrowing. THIS DOES NOT REMOVE ACCESS: what the agent may do goes back to being decided by its permissions alone, which is usually MORE than the…\n  - `aimeat_mcp_grant_set`: Narrow one agent or app to named tools on one attached server, optionally with arguments already decided, a call ceiling and an end date. This is how 'my…\n  - `aimeat_mcp_list`: The other MCP servers this person has attached to their node, by the short name every other tool here takes. This is how you reach tools that are not on this…\n  - `aimeat_mcp_registry_list`: What THIS NODE offers everybody who has an account on it: the MCP servers its operator attached once, who may reach each one, and what a call costs. Operator…\n  - `aimeat_mcp_registry_set`: Decide who may use one of this node's own MCP servers, what a call costs them, how its tools are listed, and whether it is on at all. Operator only.…\n  - `aimeat_mcp_tools`: What one attached server can actually do: its tools, each with the arguments it takes. Read this before aimeat_mcp_call, because the names and the argument…\n  - `aimeat_mcp_update`: Change an attached server without removing it: switch it off and on again, or rename it on screen. Switching it off STOPS calls at once rather than marking it…\n  - `aimeat_memory_delete`: Delete one of your memory entries. It is NOT gone at once: it leaves every read immediately (by key, in lists, in searches) and stays takeable back for a grace…\n  - `aimeat_memory_hands`: How many hands have been on one memory key, and whose. A key gets rewritten and the value changes; who touched it was never written down anywhere until this…\n  - `aimeat_memory_list`: List memory entries for the calling agent (metadata only, not full values — use aimeat_memory_read for a value). Set owner_scope=true to also include the owner…\n  - `aimeat_memory_read`: Read one memory entry by its exact key for the calling agent. Use when you already know the key (from aimeat_memory_list or a prior write); for discovery use…\n  - `aimeat_memory_read_public`: Read a single public memory entry belonging to another agent or owner, by their GAII/GHII and the exact key. Only entries with public visibility are returned;…\n  - `aimeat_memory_restore`: Put back a memory entry you deleted, whole, as long as the grace window has not closed. Refused once the entry has been removed for good, which is the honest…\n  - `aimeat_memory_search`: Full-text search across this agent's own memory entries (optionally filtered by visibility). Returns a SNIPPET per hit (a short window around the match) +…\n  - `aimeat_memory_write`: Write (create or update) a memory entry for the calling agent. The value can be any JSON: string, number, boolean, object, or array. Visibility controls who…\n  - `aimeat_message_history`: Read the full message history for a conversation — both your messages and the owner's, oldest-first — so you have complete context, not just the unread items…\n  - `aimeat_message_inbox`: Fetch this agent's pending inbound messages from its owner (each with id, thread_id, sender, content, timestamp). Poll this to pick up new instructions or…\n  - `aimeat_message_send`: Send a message from this agent to its owner's conversation (markdown supported). Omit thread_id to start a new thread, or pass a thread_id from…\n  - `aimeat_notify`: Tell your OWN owner that something happened: a line in their header bell and, if they turned push on, a notification on their devices; a click opens `link`.…\n  - `aimeat_offer_price_set`: Set or clear the price of one offer on YOUR OWNER's agent (the agents.{name}.offers document): morsel price (integer) and/or money price (amount in 6-decimal…\n  - `aimeat_onboarding_confirm_directives_read`: Complete the \"read directives\" onboarding step by confirming you have read the AIMEAT handbook (fetch it first with aimeat_handbook_get). Pass confirmed=true…\n  - `aimeat_onboarding_confirm_skill_installed`: Complete the \"install skill\" onboarding step by confirming the local AIMEAT skill bundle is available, passing the platform and bundle version (use \"local\"…\n  - `aimeat_onboarding_declare_services`: Complete the optional \"declare services\" onboarding step by listing services this agent offers (name + optional description). An empty list is allowed. Marks…\n  - `aimeat_onboarding_identify_platform`: Complete the \"identify platform\" onboarding step by declaring which runtime you are (e.g. claude, openclaw, hermes, vscode, generic). Records the platform on…\n  - `aimeat_onboarding_status`: Check this agent's Hello Integration onboarding progress: which steps have passed, which are still pending, and a next_step hint pointing to the tool to call…\n  - `aimeat_operator_agent_configure`: Configure a same-owner agent with PROPOSE-THEN-CONFIRM. Without confirm_token nothing is applied: the tool returns the current state, the proposed state, a…\n  - `aimeat_operator_ai_config`: Inspect or change the owner's AI routing + daily budget with PROPOSE-THEN-CONFIRM. With no fields: returns the current safe view (daily_budget_usd, model,…\n  - `aimeat_organism_archive`: ARCHIVE or UNARCHIVE organism content (creator/admin only). Archived content becomes READ-ONLY and is hidden from normal operation — it drops out of overviews,…\n  - `aimeat_organism_create`: Create a new ORGANISM (a shared, governed container for people + agents): one place every AI the person connects and every person they invite reads and writes.…\n  - `aimeat_organism_export`: Export a whole organism (its settings + every workspace you can read) as one base64 ZIP backup. Organism creator or admin. Size-capped for inline use — very…\n  - `aimeat_organism_get`: Get one organism's full detail by id: description, type, visibility, join policy, capacity, linked board, creator/admins, interests/location, and active…\n  - `aimeat_organism_import`: Import an organism bundle (base64 ZIP from aimeat_organism_export) as a NEW organism — you become its creator, and every workspace inside is restored (ids…\n  - `aimeat_organism_invitation_cancel`: Withdraw a PENDING name invitation before it is accepted (creator/admin only). The invitee is notified that the invitation was withdrawn.\n  - `aimeat_organism_invitation_email_cancel`: Cancel a PENDING email invitation before it is used (creator/admin only). Invalidates the link so it can no longer be accepted.\n  - `aimeat_organism_invitation_respond`: Accept or decline an invitation to an organism that was extended to you. Accepting makes you an active member; declining removes the invitation.\n  - `aimeat_organism_invitation_update`: Edit a PENDING name invitation's organism role and/or workspace grants before the invitee accepts (creator/admin only). The invitee lands with the edited…\n  - `aimeat_organism_invitations`: List your own pending organism invitations across all organisms — each with a brief organism summary. Respond to one with aimeat_organism_invitation_respond.\n  - `aimeat_organism_invitations_email`: List the PENDING email invitations for an organism (creator/admin only) — each invitee email, organism role, workspace grants, and expiry. These are the…\n  - `aimeat_organism_invite`: Invite an owner to an organism by their bare owner name, optionally with an organism role (member/admin) and per-workspace grants applied when they accept.…\n  - `aimeat_organism_invite_email`: Invite a person who is NOT yet on this node into an organism by EMAIL. Creator/admin only. Sends a single-use, expiring link that lets the recipient register a…\n  - `aimeat_organism_join`: Join an organism (a managed group of agents). Returns joined immediately for open organisms, or pending_approval for approval-required ones. Invite-only…\n  - `aimeat_organism_leave`: Leave an organism you belong to. The creator cannot leave — they must delete the organism instead.\n  - `aimeat_organism_list`: List organisms (managed groups of agents) visible to you: all public ones plus any your owner belongs to, with name, type, visibility, join policy, and member…\n  - `aimeat_organism_member_add`: DIRECTLY add an already-registered local owner to an organism as an ACTIVE member — no invitation round-trip. Creator/admin only. Applies the organism role and…\n  - `aimeat_organism_member_remove`: Take a member off an organism: their membership goes, their agents drop off the organism, and their per-workspace grants are revoked, all in one step.…\n  - `aimeat_organism_members`: List the members of an organism (GHII, role, status, joined-at), optionally filtered by role or status (defaults to active). Visible only if the organism is…\n  - `aimeat_organism_overview`: Get a fast, OKF-style STRUCTURE MAP of a whole organism as Markdown — every workspace, its space breakdown (objectType → instance count), and totals. SHALLOW…\n  - `aimeat_organism_owner_add`: Make an existing active member a co-owner of an organism you own. ADDITIVE: you keep everything you had, and an organism can have several owners. That is the…\n  - `aimeat_organism_owner_remove`: Take an owner off an organism you own; they stay on as an admin. Any owner may remove any other. The LAST owner cannot be removed (LAST_OWNER) — an organism…\n  - `aimeat_organism_search`: Search the records + documents across an organism's workspaces by text (case-insensitive substring). Returns matches with the workspace, space (objectType),…\n  - `aimeat_organism_update`: Update an ORGANISM in place (creator/admin only): its name, description (the short tagline), interests, join policy, visibility, and/or its free-form README —…\n  - `aimeat_package_buy`: Buy a package this node sells, for your owner. This node reads the author's terms from the package repository for you; you never need an account there. action…\n  - `aimeat_package_check_updates`: Check your owner's installed packages against the nodes they came from, now. A newer version is pulled; a copy with auto_update on is updated (parts your owner…\n  - `aimeat_package_claim`: Operator-only, on the node that is to receive a package. A shop sold this node a package before it existed and gave a claim code (pkgc_…). Redeem it here: this…\n  - `aimeat_package_compose`: Make a package out of apps you already published, with the cortexes they load and your own skills bound to them. Names what the installing node must supply…\n  - `aimeat_package_compose_set`: Make a set to sell from apps you already published: one package per app (or its next version), and an install bundle that lists them, with the organism and…\n  - `aimeat_package_config_needs`: The settings a package of yours, or every package of an install bundle of yours, needs the customer to give before it works: the questions to ask before a…\n  - `aimeat_package_delete`: Archive one version of a component package.\n  - `aimeat_package_entitlements`: On a package repository: list, grant or revoke which customer nodes a private package of yours is served to. A grant with updates_until serves the node every…\n  - `aimeat_package_fork`: Fork a managed package install: it becomes your own editable copy in place, keeping every address, every record and every schedule, and it receives no further…\n  - `aimeat_package_get`: Get one component package by its group id.\n  - `aimeat_package_install`: Install a component package as your own copy. Each component is registered under your identity. With mode \"editable\" (the default) what you get is yours to…\n  - `aimeat_package_install_requests`: List your owner's package install requests, read one, or approve or decline one. You may approve a request only when you did not file it yourself and you hold…\n  - `aimeat_package_instance_set`: Change your owner's choices about one installed package copy: its label, and whether the daily update check updates it by itself (auto_update true) or tells…\n  - `aimeat_package_instances`: List your owner's installed package copies: each one's instance_id, package, version, whether it is managed (the package owns the code and layout) or editable,…\n  - `aimeat_package_list`: List component packages on this node. These are NOT the single-file web apps — for those use aimeat_app_list.\n  - `aimeat_package_offer`: On a package repository, for a package's author: the terms seller nodes sell it on. action \"get\" reads the offer; \"set\" appends new terms, changes the state,…\n  - `aimeat_package_publish`: Publish a component package: one or more components (app, extension, cortex, translation) that install together.\n  - `aimeat_package_pull`: Bring a package published on another node onto this one, verifying that node's signature and every component digest before anything is written.\n  - `aimeat_package_repository`: List what a package repository serves this node: its public packages and the private ones this node is entitled to, each with the version its entitlement…\n  - `aimeat_package_sale`: Operator-only, on a selling node (a shop's own AIMEAT). Sell a package repository's packages with no token: this node signs each request with its own key, and…\n  - `aimeat_package_sellers`: On a package repository: list, add or remove the nodes that sell your packages. A seller node (a shop's own AIMEAT, e.g. store.aimeat.io) then asks for a…\n  - `aimeat_package_status_set`: Move one package version between draft, published, beta and archived. Only the author may. A beta version is served only to the customer nodes whose…\n  - `aimeat_package_update`: Update a whole installed package to its latest version. Parts you have edited are left untouched and reported, never overwritten. A new version that writes…\n  - `aimeat_package_versions`: List one component package's version history.\n  - `aimeat_package_withdraw`: Withdraw a bad version of your package, with a reason. Nothing serves it again: not an install, not a pull, not a repository's customers. Every installed copy…\n  - `aimeat_portfolio_publish`: Publish this person's own welcome page — the page at their address, which is also their portfolio. Use it when they ask you to make their page, improve it, or…\n  - `aimeat_refinery_classes`: The class packs a mail refinery sorts messages into: receipt, invoice, order, booking, job, system, support, newsletter and personal. Each says what the…\n  - `aimeat_refinery_run`: Run one batch of a mail refinery: read the next page of mail from where the last batch stopped, classify each message, read the fields its class names from the…\n  - `aimeat_refinery_status`: How far a refinery batch is: running, done or failed; the step and the message it is on; the counts per queue; and the rows it filed, newest first. A failed…\n  - `aimeat_schedule_create`: Create a recurring schedule the AIMEAT server runs on a cron clock (survives your disconnect; the owner can pause/cancel it any time). FIRST, if a person asked…\n  - `aimeat_schedule_delete`: Cancel and remove one of your schedules. Already-spawned task occurrences are left intact; only future fires stop.\n  - `aimeat_schedule_list`: List the schedules you created (id, kind, cron, enabled, last/next run, run count). Use before updating or deleting one. With detail: true each schedule also…\n  - `aimeat_schedule_report_internal`: If you run your OWN recurring jobs outside AIMEAT (your own cron/heartbeat), report them here so the owner sees them in the scheduler. Pass your full current…\n  - `aimeat_schedule_trigger`: Run one of your schedules once, right now, without waiting for its cron. Use it immediately after creating a schedule: a job that has never run is unproven,…\n  - `aimeat_schedule_update`: Update one of your schedules: pause/resume (enabled=false/true), change the cron, timezone, display name, or prompt. A new prompt replaces an ai schedule's…\n  - `aimeat_secret_delete`: Remove one secret from your owner's vault by name. Anything that named it in a header stops working immediately and says so by name, so check…\n  - `aimeat_secret_list`: The named keys and passwords in your owner's vault: for each one its name, when it was first stored, when its value last changed, and which extensions have…\n  - `aimeat_secret_set`: Store a key or password in your owner's vault under a name, or replace what is there (same call either way — replacing keeps the date it was first stored). The…\n  - `aimeat_seo_announce`: Tell the search engines about the whole site now, through IndexNow: the node's pages and, by default, every findable application, sent as one batch per host…\n  - `aimeat_seo_status`: Whether this node can be found in a search engine, and what is still undone about it. One answer assembled from every setting that decides it: the discovery…\n  - `aimeat_share_create`: Let a sharing group read a key space of your owner's memory. The group says WHO, this says WHAT: give a key or a pattern (\"deliveries.abc.**\"), and every key…\n  - `aimeat_share_list`: List key-space shares in either direction: \"outgoing\" is what your owner has given away and to whom, \"incoming\" is what other people have shared with your…\n  - `aimeat_share_revoke`: Withdraw a key-space share by id. Reads stop at once and the records fall back to their own visibility; copies the reader already took are not recalled, which…\n  - `aimeat_skill_get`: Resolve one skill from the registry: manifest (name, description, version, file index) plus the file bodies (SKILL.md and any scripts/, references/, assets/).…\n  - `aimeat_skill_link`: Attach a skill to a same-owner agent by ref. Links store references, never copies — the agent's consumers (e.g. a crew runtime) resolve the ref to fresh…\n  - `aimeat_skill_list`: Browse the skills registry without loading bodies (progressive disclosure — manifests only). view=library (default) returns everything you can load right now…\n  - `aimeat_skill_publish`: Publish or update a skill in the skills registry — a SKILL.md pack (YAML frontmatter with name + description, markdown body = the expertise) plus optional…\n  - `aimeat_skill_unlink`: Detach a skill ref from a same-owner agent (default: yourself). The skill itself stays in the registry; only the agent attachment is removed. Returns the…\n  - `aimeat_skill_update`: Change who may read a skill without publishing it again: owner (you and your agents), members (every signed-in identity on this node) or public (readable from…\n  - `aimeat_storage_delete`: Delete one of your own stored files by key. Irreversible: a stored file has no version history behind it the way a memory record does, so what this removes is…\n  - `aimeat_storage_download`: Get a stored file by key, or by REFERENCE for a file you do not own. Storage holds binaries (images, video, large blobs), so by default this returns a HANDLE —…\n  - `aimeat_storage_upload`: Upload a binary file (image, document, etc.) to the agent's file storage, addressed by key. For files over ~1 KB prefer presigned-upload mode: omit data_base64…\n  - `aimeat_surface_layout_get`: Read how one of this node's pages is arranged, and what it could be arranged from. `surface` is 'portal' for the public front page, 'home' for the page members…\n  - `aimeat_surface_layout_set`: Arrange one of this node's pages: which blocks it shows, in what order, and the words between them. Send the WHOLE layout — this replaces what is there, it…\n  - `aimeat_task_complete`: Mark one of your ACTIVE or STALLED tasks as done, with an optional completion message and an optional deliverable_key naming the memory record you produced.…\n  - `aimeat_task_create`: Queue a task for one of your owner's agents (yourself or any same-owner agent). The owner sees it in their dashboard. Use this to ask another crew or worker to…\n  - `aimeat_task_decline`: Decline one of your QUEUED, ACTIVE or STALLED tasks because the request is not one you should take (off your topic, against your rules, outside what the owner…\n  - `aimeat_task_event`: Append a progress event (e.g. started, progress, verification, message) to one of your ACTIVE tasks, optionally carrying details/telemetry that update the…\n  - `aimeat_task_fail`: Mark one of your ACTIVE or STALLED tasks as failed, recording the reason. Sets status to failed, stamps completedAt, and appends a failed event so the owner…\n  - `aimeat_task_get`: Get the full detail of one task assigned to this agent: description, scope, rules, verification criteria, resources (including any attached FILES, each with a…\n  - `aimeat_task_list`: List the tasks assigned TO this agent (paginated; optional status filter such as queued, active, done, failed, declined). Each entry includes title, status,…\n  - `aimeat_task_propose_todos`: Propose TODOs for a queued task, a task that started on its own and has no plan yet (e.g. the Hello Integration test task), or re-propose after the owner has…\n  - `aimeat_task_request_changes`: Owner-only: ask an agent to revise its proposed TODO plan for a queued task. Marks the existing todos as outdated, flips the task status to…\n  - `aimeat_task_start`: Start a task that waits for the owner's OK, because the owner told you to (\"go ahead\", \"start it\"). Only on the owner's word, and only for another of their…\n  - `aimeat_task_todo`: Update the status of one TODO item within an ACTIVE task (pending, active, done, failed, skipped). Marking it done/failed/skipped also stamps a completion time…\n  - `aimeat_theme_component_css_set`: Style one component in one theme with CSS of your own, for example \"give the loud action a coral ground\": theme 'my-theme', component 'slab', css '.poster-slab…\n  - `aimeat_theme_font_save`: Add a face (font) to this server, so its themes and the Design Book can use it at once, or change or remove one you added. Give `family` (the name a style…\n  - `aimeat_theme_get`: Read one theme whole: every style with every colour in light and dark, its faces and mode, the theme's component CSS and theme CSS, the warnings each carries…\n  - `aimeat_theme_list`: List this server's themes: the look of every page of AIMEAT's own interface (the home, the chat, Settings \u0026 Controls, admin; published apps keep their own). A…\n  - `aimeat_theme_policy_set`: Decide who chooses the look of this server's own pages: `personalChoice` (true: people pick a theme and a style in the look picker; false: everybody sees the…\n  - `aimeat_theme_save`: Make or change one of this server's themes. Without `id` you make a new theme: a copy of `basedOn` (default 'aimeat') with its styles, CSS and choices. With…\n  - `aimeat_theme_style_save`: Make or change a style inside a theme: its colours in light and dark, its three faces and its mode. Without `style` you make a new style, a copy of `basedOn`…\n  - `aimeat_tools_find`: Your tool list starts small, and this node has many more tools. When the job needs one you do not see, say what you want to do and this finds the tools for it…\n  - `aimeat_ui_component_get`: Read one component of this node's own web interface whole: its data shape and every field, when to use it, its variants and the class or prop that selects…\n  - `aimeat_ui_component_list`: List the components this node's own web interface is built from: each one with a module (in /components/ with its own stylesheet, kind 'component') and each…\n  - `aimeat_usage_report`: Answer \"what did we actually use, and what did it cost\" for the owner behind this session: spend per model, per app, per agent, per day, plus which tools get…\n  - `aimeat_v2_message_list`: Read turns back, oldest first. Narrow by context_id for one exchange, by task_id for the turns of one task, by to/from for one party, or by since (an ISO…\n  - `aimeat_v2_message_send`: Send one turn to another principal on this same account: an agent, an ecosystem app, or the owner. A turn carries an ordered list of parts, so one send can say…\n  - `aimeat_v2_push_delete`: Stop delivering to one registered target. An agent may delete its own; the account holder may delete any target on the account.\n  - `aimeat_v2_push_list`: What delivery targets are registered: their addresses, tokens, authentication schemes, and whether the node has been able to reach them. The stored credentials…\n  - `aimeat_v2_push_set`: Register where to reach you when you are not connected: an https address this node POSTs a turn to. Optionally a token it echoes back so you can tell the POST…\n  - `aimeat_v2_task_cancel`: Stop work you asked for. Only whoever created the task and the account holder may: a worker that will not do the work reports it failed with a reason, which is…\n  - `aimeat_v2_task_create`: Ask another principal on this account to do something, and get back a handle you poll. This is the MCP task shape: a taskId, a status that is one of working /…\n  - `aimeat_v2_task_get`: One task, with everything a poll needs: its MCP status, whether that status is terminal, the A2A state the same task reports on that protocol, the result if it…\n  - `aimeat_v2_task_list`: The task roster, newest first. Narrow by assigned_to for what a worker has been given, created_by for what you asked for, context_id for one conversation, or…\n  - `aimeat_v2_task_status`: Report where you have got to with work you were given. Only the assignee and the account holder may: a task's status is the worker's testimony about the work,…\n  - `aimeat_voice_reply`: Generate a conversational text reply with the owner's AI key, app quota, usage and provenance. Returns final text; browser apps use the streaming AIMEAT.voice…\n  - `aimeat_voice_speak`: Synthesize speech using the owner's configured provider and AI budget. Returns a PRIVATE storage_key, fetch_url, usage and provenance, never audio bytes in…\n  - `aimeat_wallet_balance`: Check the morsel wallet: returns total balance, amount currently held in escrow for in-flight work, and the available (spendable) remainder. Morsels belong to…\n  - `aimeat_wallet_transactions`: View recent morsel transactions for your owner's wallet (id, type, amount, counterparty, tracking code, timestamp; default 20, max 200). Transactions are keyed…\n  - `aimeat_work_accept`: Accept a pending work item assigned to you as provider, identified by its tracking_code (find pending items via aimeat_work_inbox). Moves it from pending to…\n  - `aimeat_work_deliver`: Deliver the result for a work item you accepted (by tracking_code), which settles the escrowed payment to you and marks it delivered. Only the provider can…\n  - `aimeat_work_inbox`: Check your work inbox: work items others have requested from you (where you are the provider), still pending/accepted/in-progress. Each carries a tracking_code…\n  - `aimeat_workflow_answer`: Answer a workflow step that is waiting for human input (state \"waiting-human\") ON THE OWNER'S BEHALF — only relay a decision the owner actually made (e.g. from…\n  - `aimeat_workflow_get`: Inspect workflows. Omit id to list all your workflows; pass an id for its definition + the derived blueprint (the whole input→output flow + the memory keys…\n  - `aimeat_workflow_pending_inputs`: List every workflow step currently WAITING FOR HUMAN INPUT across the owner's active runs: the pinned question (prompt + options), when it was asked, and the…\n  - `aimeat_workflow_run`: Run a workflow. mode=\"signals-only\" is a CHECK: it evaluates every step's signals against existing memory with NO dispatch, costs nothing, returns each step's…\n  - `aimeat_workflow_save`: Create or update an Agent Workflow: a declared, ordered set of steps with per-step input (required_to_function) and output (success_signal) signals, run by ONE…\n  - `aimeat_workspace_access`: REQUEST/REVIEW flow for a gated workspace, via `action`: 'request' = ask the creator for access to a workspace you can see but not read (org membership lets…\n  - `aimeat_workspace_comment`: Add a comment to a workspace object (a record or a document) — for discussion/review threads. Target it by ws + space (objectType) + instance_id. Optionally…\n  - `aimeat_workspace_comment_delete`: Delete one comment from a workspace object's thread. The comment's author may delete it, and so may the organism's creator or an admin, for example to remove a…\n  - `aimeat_workspace_comments`: List the comment thread on one workspace object (record or document), oldest first, with each comment's author, body, anchor (if any), and parent (for…\n  - `aimeat_workspace_create`: Create a new WORKSPACE inside an organism from a CUSTOM MANIFEST you supply — its objectTypes (each a records space with a JSON schema, or a document/wiki…\n  - `aimeat_workspace_doc_append`: Add markdown to a workspace DOCUMENT without sending the rest of it back — at the end, or at the end of one named section. This is how a long document is…\n  - `aimeat_workspace_doc_section_replace`: Replace one section of a workspace DOCUMENT — a heading and its body — leaving every other byte exactly as it was. Use it to correct or rewrite one part of a…\n  - `aimeat_workspace_list`: List the WORKSPACES inside an organism. An organism holds one or more workspaces — each a self-describing space of documents (free-form markdown wiki) and/or…\n  - `aimeat_workspace_member_grant`: Directly grant an EXISTING organism member a workspace role — no prior access request needed. Grant to ONE workspace (`ws`) or MANY at once (`workspaces`: e.g.…\n  - `aimeat_workspace_member_revoke`: Remove a member's workspace role on ONE workspace (`ws`) or MANY (`workspaces`). `grantee` may be an owner name, GHII, or GAII (resolved to the owner). To…\n  - `aimeat_workspace_members`: List a workspace's members with their role ('viewer' | 'contributor'), the grant's source (grant | request | invite), who granted it, and when. Authorized for…\n  - `aimeat_workspace_object_delete`: Permanently remove ONE object (record or document) from a workspace — its draft, its published .latest, and all .version.N history — and unfile it from any…\n  - `aimeat_workspace_overview`: Get a fast, OKF-style STRUCTURE MAP of ONE workspace as Markdown — per space, the most-recently-updated entries (up to 10) with their instance id + title, and…\n  - `aimeat_workspace_publish`: Publish a draft → snapshots it to a new immutable .version.N + the live .latest and consumes the draft. Schema-validated. If the workspace's publish gate is…\n  - `aimeat_workspace_read`: Read one workspace in TWO steps so you never pull a huge blob. DEFAULT (no `ids`) returns the INDEX: the manifest (the objectTypes it declares — each a records…\n  - `aimeat_workspace_revert_to_draft`: Reopen a PUBLISHED record for editing — copies its .latest back into .draft so you can amend it and re-publish via aimeat_workspace_write +…\n  - `aimeat_workspace_rows_append`: Add rows to a workspace ROW space — the shape for what a GROUP accumulates (received messages, events, readings, a log) rather than for records a person…\n  - `aimeat_workspace_rows_delete`: Remove rows from a workspace ROW space: one row by `row_id`, or everything that LANDED before `before` (retention by age). Retention keys on when the row was…\n  - `aimeat_workspace_rows_read`: Read one page of a workspace ROW space, newest first by occurred_at. Keyset-cursored: follow `cursor` for the next page, and a null cursor is the last one — a…\n  - `aimeat_workspace_rows_stats`: What a workspace ROW space holds, without reading a row: how many, how many bytes, the oldest and newest occurred_at, and when anything last landed. This is…\n  - `aimeat_workspace_sections_set`: Set the section index of one document space: the tree of sections its pages are filed under, [{ id, name, parentId, documents:[docId], color? }], the same list…\n  - `aimeat_workspace_space_add`: Add a space to a workspace as any member who may change it: its creator, an organism admin, or a member holding the contributor role. A space is { name,…\n  - `aimeat_workspace_suggestions`: The changes members suggested to a workspace (a space to add, changes to a document space's sections) that wait for a decision, via `action`. 'list' = the…\n  - `aimeat_workspace_transfer`: Back up or restore a workspace, via `direction`. 'export' = a full-fidelity base64 ZIP (manifest, locked schemas, all object versions/drafts, sections,…\n  - `aimeat_workspace_update`: Update a workspace IN PLACE — its name, readme, and/or its STRUCTURE — without changing its id (so nothing referencing it gets orphaned). To ADD spaces, pass…\n  - `aimeat_workspace_write`: Create or overwrite DRAFT items in a workspace — records OR documents — in one tool. ONE item: pass `space` + `value`. MANY: pass `items: [{ value, space?,…\n- How its tools read to an agent (0 errors, 555 warnings, 3 notes, about 125,350 tokens; rules at https://www.anchorterminal.com/check.md; not part of the score):\n  - warn TC07 aimeat_admin_federation: the description is about 686 tokens\n  - warn TC07 aimeat_agent_propose: the description is about 521 tokens\n  - warn TC07 aimeat_app_manage: the description is about 2,736 tokens\n  - warn TC07 aimeat_app_tools_publish: the description is about 804 tokens\n  - warn TC07 aimeat_classification: the description is about 1,230 tokens\n  - warn TC07 aimeat_decide: the description is about 668 tokens\n  - warn TC07 aimeat_designbook_propose: the description is about 1,153 tokens\n  - warn TC07 aimeat_package_sale: the description is about 590 tokens\n  - warn TC07 aimeat_workflow_save: the description is about 640 tokens\n  - warn TC07 aimeat_workspace_write: the description is about 525 tokens\n  - warn TC13 aimeat_action_execute: input (object with no properties)\n  - warn TC13 aimeat_admin_cors_set: origins (array with no items)\n  - warn TC13 aimeat_admin_hook_set: actions (array with no items)\n  - warn TC13 aimeat_admin_install_set: install_set (object with no properties), secrets (object with no properties)\n  - warn TC13 aimeat_admin_sso_create: domains (array with no items)\n  - warn TC13 aimeat_admin_sso_update: domains (array with no items)\n  - warn TC13 aimeat_agent_capabilities_report: domain (array with no items), languages (array with no items), technical (array with no items)\n  - warn TC13 aimeat_agent_propose: crew_def (object with no properties), scopes (array with no items)\n  - warn TC13 aimeat_agent_tags_set: tags (array with no items)\n  - warn TC13 aimeat_agent_telemetry_report: data (object with no properties)\n  - warn TC13 aimeat_ai_embed: input (array with no items)\n  - warn TC13 aimeat_ai_job_start: input_keys (array with no items), on_done (object with no properties)\n  - warn TC13 aimeat_ai_policy_set: policy (object with no properties)\n  - warn TC13 aimeat_ai_role_set: bindings (object with no properties), roles (object with no properties)\n\n- JSON: https://www.anchorterminal.com/api/v1/tools/aimeat.json\n- Being indexed says nothing about quality, and nobody can pay for it. Ask for a review: https://www.anchorterminal.com/builders/#claiming\n",
  "meta": {
    "attribution": "Anchor Terminal (https://www.anchorterminal.com)",
    "docs": "https://www.anchorterminal.com/docs/",
    "generatedAt": "2026-10-05",
    "license": "CC-BY-4.0",
    "method": "https://www.anchorterminal.com/benchmark/",
    "methodology": "0.3",
    "openapi": "https://www.anchorterminal.com/openapi.json",
    "preview": false,
    "run": "2026-10-01",
    "runLabel": "October 2026 research run"
  },
  "page": {
    "breadcrumbs": [
      {
        "name": "Home",
        "url": "https://www.anchorterminal.com/"
      },
      {
        "name": "Terminal",
        "url": "https://www.anchorterminal.com/tools/"
      },
      {
        "name": "Indexed",
        "url": "https://www.anchorterminal.com/indexed/"
      },
      {
        "name": "AIMEAT",
        "url": ""
      }
    ],
    "description": "AIMEAT, an MCP server by aimeat.io, listed from the official MCP registry. Indexed, not reviewed: facts and our own checks, no score or ranking. AIMEAT - the Linux of AI. An open, federated, self-hosted AI operating system you own. MIT.",
    "facts": [
      "not reviewed",
      "not ranked",
      "facts only"
    ],
    "h1": "AIMEAT",
    "image": "https://www.anchorterminal.com/assets/og/indexed.png",
    "path": "/tools/aimeat",
    "published": "",
    "section": "indexed",
    "title": "AIMEAT: MCP server, indexed from the official MCP registry",
    "toc": null,
    "updated": "2026-10-05",
    "url": "https://www.anchorterminal.com/tools/aimeat"
  },
  "tokens": {
    "markdown": 20100,
    "slim": 20030
  },
  "version": 1
}
