{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "colab-badge"
      },
      "source": [
        "<table align=\"left\">\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/google-gemma/cookbook/blob/main/apps/Gemma_4_HDP_Agentic_Security/Gemma_4_HDP_Agentic_Security.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Run in Google Colab</a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "byline"
      },
      "source": [
        "# Securing Gemma 4 Agentic Workflows with HDP\n",
        "\n",
        "**Author:** Asiri Dalugoda, Helixar Limited ([@asiridalugoda](https://github.com/asiridalugoda)) | [helixar.ai](https://helixar.ai)\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "gpu-instructions"
      },
      "source": [
        "## Before you begin\n",
        "\n",
        "This notebook requires a GPU runtime. To enable GPU in Colab:\n",
        "1. Go to **Runtime → Change runtime type**\n",
        "2. Set **Hardware accelerator** to **GPU** (T4 is sufficient for E4B)\n",
        "3. Click **Save**\n",
        "\n",
        "You will also need a **Hugging Face token** to download Gemma 4 (gated model):\n",
        "1. Go to [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens)\n",
        "2. Create a token with **Read** access\n",
        "3. Accept the Gemma 4 model license at [huggingface.co/google/gemma-4-E4B-it](https://huggingface.co/google/gemma-4-E4B-it)\n",
        "4. Run the cell below to authenticate"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "hf-login"
      },
      "outputs": [],
      "source": [
        "from huggingface_hub import notebook_login\n",
        "notebook_login()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "overview"
      },
      "source": [
        "# Securing Gemma 4 Agentic Workflows with HDP\n",
        "\n",
        "**Human Delegation Provenance (HDP)** is an open protocol that adds a cryptographic chain-of-custody to AI agent function calls — ensuring every tool invocation can be traced back to an authorized human principal.\n",
        "\n",
        "This notebook demonstrates how to integrate HDP with Gemma 4's native function-calling capability to:\n",
        "\n",
        "- **Verify** that Gemma 4's function calls were authorized by a human principal before execution\n",
        "- **Classify** actions by irreversibility (read-only → irreversible → physical actuation)\n",
        "- **Block** unauthorized or out-of-scope tool calls at the middleware layer\n",
        "- **Audit** every decision with a pre-execution log\n",
        "\n",
        "This is particularly relevant for Gemma 4 deployments on edge devices (Jetson Nano, Raspberry Pi) where the model may be directing physical actuators offline with no out-of-band authorization check.\n",
        "\n",
        "**References:**\n",
        "- HDP IETF draft: [draft-helixar-hdp-agentic-delegation-00](https://datatracker.ietf.org/doc/draft-helixar-hdp-agentic-delegation/)\n",
        "- HDP-P (physical AI agents): [DOI 10.5281/ZENODO.19332440](https://doi.org/10.5281/ZENODO.19332440)\n",
        "- Helixar: [helixar.ai](https://helixar.ai)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "b3600ee25c8e"
      },
      "source": [
        "## Setup"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "7a80251f52b3"
      },
      "outputs": [],
      "source": [
        "!pip install -q transformers torch cryptography"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ed80fe18f255"
      },
      "outputs": [],
      "source": [
        "# Download the middleware\n",
        "!wget -q https://raw.githubusercontent.com/google-gemma/cookbook/refs/heads/main/apps/Gemma_4_HDP_Agentic_Security/hdp_middleware.py\n",
        "\n",
        "from hdp_middleware import (\n",
        "    HDPDelegationToken,\n",
        "    HDPMiddleware,\n",
        "    IrreversibilityClass,\n",
        "    DEFAULT_TOOL_CLASS_MAP,\n",
        ")\n",
        "from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey\n",
        "import json"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "e88bdc7b7265"
      },
      "source": [
        "## 1. Load Gemma 4\n",
        "\n",
        "We use the 4B Effective model for this demo. For production agentic deployments, the 26B MoE or 31B Dense models are recommended."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "1e4e7779806d"
      },
      "outputs": [],
      "source": [
        "from transformers import pipeline\n",
        "\n",
        "# For edge/robotics use cases: swap to google/gemma-4-E2B-it\n",
        "MODEL_ID = \"google/gemma-4-E4B-it\"\n",
        "\n",
        "pipe = pipeline(\n",
        "    \"text-generation\",\n",
        "    model=MODEL_ID,\n",
        "    device_map=\"auto\",\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "d91e36cfb0b2"
      },
      "source": [
        "## 2. Define Tools\n",
        "\n",
        "Gemma 4 uses structured JSON function-calling. We define a tool set spanning different IrreversibilityClasses to demonstrate the middleware's classification behaviour."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "1becdb52e7f8"
      },
      "outputs": [],
      "source": [
        "TOOLS = [\n",
        "    {\n",
        "        \"name\": \"get_weather\",\n",
        "        \"description\": \"Get the current weather for a location.\",\n",
        "        \"parameters\": {\n",
        "            \"type\": \"object\",\n",
        "            \"properties\": {\n",
        "                \"location\": {\"type\": \"string\", \"description\": \"City name\"}\n",
        "            },\n",
        "            \"required\": [\"location\"]\n",
        "        }\n",
        "    },\n",
        "    {\n",
        "        \"name\": \"send_email\",\n",
        "        \"description\": \"Send an email to a recipient.\",\n",
        "        \"parameters\": {\n",
        "            \"type\": \"object\",\n",
        "            \"properties\": {\n",
        "                \"to\": {\"type\": \"string\"},\n",
        "                \"subject\": {\"type\": \"string\"},\n",
        "                \"body\": {\"type\": \"string\"}\n",
        "            },\n",
        "            \"required\": [\"to\", \"subject\", \"body\"]\n",
        "        }\n",
        "    },\n",
        "    {\n",
        "        \"name\": \"delete_file\",\n",
        "        \"description\": \"Permanently delete a file by path.\",\n",
        "        \"parameters\": {\n",
        "            \"type\": \"object\",\n",
        "            \"properties\": {\n",
        "                \"path\": {\"type\": \"string\"}\n",
        "            },\n",
        "            \"required\": [\"path\"]\n",
        "        }\n",
        "    },\n",
        "    {\n",
        "        \"name\": \"actuate_robot_arm\",\n",
        "        \"description\": \"Command a robot arm to move to a target position.\",\n",
        "        \"parameters\": {\n",
        "            \"type\": \"object\",\n",
        "            \"properties\": {\n",
        "                \"joint_angles\": {\"type\": \"array\", \"items\": {\"type\": \"number\"}},\n",
        "                \"force_limit_n\": {\"type\": \"number\"}\n",
        "            },\n",
        "            \"required\": [\"joint_angles\"]\n",
        "        }\n",
        "    }\n",
        "]\n",
        "\n",
        "# Tools indexed by name for lookup\n",
        "TOOL_REGISTRY = {t[\"name\"]: t for t in TOOLS}\n",
        "print(f\"Registered {len(TOOLS)} tools\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "722948b00a92"
      },
      "source": [
        "## 3. Issue an HDP Delegation Token\n",
        "\n",
        "The human principal generates an Ed25519 keypair and issues an HDT that specifies:\n",
        "- Which tools the agent is permitted to call\n",
        "- The maximum IrreversibilityClass the agent can act on\n",
        "- The token's lifetime"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "b0622c68dfa5"
      },
      "outputs": [],
      "source": [
        "# Human principal generates their signing keypair\n",
        "# In production: loaded from secure key storage (HSM, OS keychain, etc.)\n",
        "principal_private_key = Ed25519PrivateKey.generate()\n",
        "principal_public_key = principal_private_key.public_key()\n",
        "\n",
        "# Issue an HDT authorizing the Gemma 4 agent to call weather queries\n",
        "# and send emails (Class 0 and Class 2), but NOT delete files or actuate hardware\n",
        "token = HDPDelegationToken.issue(\n",
        "    principal_id=\"alice@example.com\",\n",
        "    agent_id=\"gemma4-agent-01\",\n",
        "    scope=[\"get_weather\", \"send_email\"],\n",
        "    max_class=IrreversibilityClass.CLASS_2,\n",
        "    ttl_seconds=3600,\n",
        "    private_key=principal_private_key,\n",
        ")\n",
        "\n",
        "print(json.dumps(token.to_dict(), indent=2))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "e206f950f4bc"
      },
      "source": [
        "## 4. Initialise the HDP Middleware\n",
        "\n",
        "The middleware takes the principal's **public key** only — it verifies but cannot issue tokens."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "e24676f528bf"
      },
      "outputs": [],
      "source": [
        "audit_log = []\n",
        "\n",
        "# Confirmation callback for Class 2 (irreversible) actions.\n",
        "# In production: this would invoke a push notification, SMS OTP,\n",
        "# or hardware confirmation device to the human principal.\n",
        "def require_human_confirmation(tool_name: str, parameters: dict) -> bool:\n",
        "    print(f\"\\n⚠️  Class 2 action requested: {tool_name}\")\n",
        "    print(f\"   Parameters: {json.dumps(parameters, indent=4)}\")\n",
        "    response = input(\"   Confirm? [y/N]: \").strip().lower()\n",
        "    return response == \"y\"\n",
        "\n",
        "middleware = HDPMiddleware(\n",
        "    public_key=principal_public_key,\n",
        "    tool_class_map=DEFAULT_TOOL_CLASS_MAP,\n",
        "    confirmation_callback=require_human_confirmation,\n",
        "    audit_log=audit_log,\n",
        ")\n",
        "\n",
        "print(\"HDP middleware initialised.\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "72d56542eba0"
      },
      "source": [
        "## 5. Gemma 4 Function Call → HDP Gate → Tool Execution\n",
        "\n",
        "This is the core integration pattern. Every function call Gemma 4 generates is passed through `middleware.gate()` before being forwarded to tool execution."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "da20bc191e71"
      },
      "outputs": [],
      "source": [
        "# Simulated Gemma 4 function call outputs\n",
        "# In production these come from parsing Gemma 4's structured JSON output\n",
        "gemma_function_calls = [\n",
        "    # ✅ Should ALLOW — Class 0, in scope\n",
        "    {\"name\": \"get_weather\", \"parameters\": {\"location\": \"Auckland\"}},\n",
        "\n",
        "    # ⚠️  Should CONFIRM then ALLOW — Class 2, in scope\n",
        "    {\"name\": \"send_email\", \"parameters\": {\n",
        "        \"to\": \"bob@example.com\",\n",
        "        \"subject\": \"Weekly report\",\n",
        "        \"body\": \"Please find attached.\"\n",
        "    }},\n",
        "\n",
        "    # ❌ Should BLOCK — Class 2, NOT in HDT scope\n",
        "    {\"name\": \"delete_file\", \"parameters\": {\"path\": \"/data/important.csv\"}},\n",
        "\n",
        "    # ❌ Should BLOCK — Class 3, physical actuation\n",
        "    {\"name\": \"actuate_robot_arm\", \"parameters\": {\n",
        "        \"joint_angles\": [0.0, -1.57, 0.0, -1.57, 0.0, 0.0],\n",
        "        \"force_limit_n\": 50.0\n",
        "    }},\n",
        "]\n",
        "\n",
        "print(\"=\" * 60)\n",
        "print(\"HDP VERIFICATION RESULTS\")\n",
        "print(\"=\" * 60)\n",
        "\n",
        "for call in gemma_function_calls:\n",
        "    result = middleware.gate(call, token)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "be0d0dd05bce"
      },
      "source": [
        "## 6. Audit Log\n",
        "\n",
        "Every decision is logged pre-execution. This is the HDP audit trail — a cryptographically linked record of what was authorized, by whom, and when."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "e6dbab6d88d1"
      },
      "outputs": [],
      "source": [
        "print(\"\\nAUDIT LOG\")\n",
        "print(\"-\" * 60)\n",
        "for i, entry in enumerate(audit_log):\n",
        "    status = \"✅ ALLOWED\" if entry.allowed else \"❌ BLOCKED\"\n",
        "    print(f\"{i+1}. {status} | {entry.tool_name} | {entry.action_class.name} | {entry.reason}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "bcadcb7040db"
      },
      "source": [
        "## 7. Token Expiry and Scope Violation Demo\n",
        "\n",
        "Demonstrate that expired tokens and out-of-scope calls are blocked regardless of the action class."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "deb2e3b6b20e"
      },
      "outputs": [],
      "source": [
        "import time\n",
        "\n",
        "# Issue a token that's already expired\n",
        "expired_token = HDPDelegationToken.issue(\n",
        "    principal_id=\"alice@example.com\",\n",
        "    agent_id=\"gemma4-agent-01\",\n",
        "    scope=[\"get_weather\"],\n",
        "    max_class=IrreversibilityClass.CLASS_0,\n",
        "    ttl_seconds=-1,   # expired immediately\n",
        "    private_key=principal_private_key,\n",
        ")\n",
        "\n",
        "print(\"Testing expired token:\")\n",
        "middleware.gate({\"name\": \"get_weather\", \"parameters\": {\"location\": \"Auckland\"}}, expired_token)\n",
        "\n",
        "print(\"\\nTesting call outside HDT scope:\")\n",
        "middleware.gate({\"name\": \"delete_file\", \"parameters\": {\"path\": \"/etc/passwd\"}}, token)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "b8f4acddb6fa"
      },
      "source": [
        "## 8. Edge / Robotics Deployment (HDP-P)\n",
        "\n",
        "For Gemma 4 E2B/E4B running on Jetson Nano or Raspberry Pi and directing physical actuators, use the HDP-P extension. The key additions are:\n",
        "\n",
        "- **Embodiment context** — bind the token to a specific hardware ID\n",
        "- **Policy attestation** — hash the deployed model weights into the token\n",
        "- **Fleet delegation constraints** — prevent lateral movement across robot fleet\n",
        "- **Pre-execution logging** — write audit records *before* actuator commands are issued\n",
        "\n",
        "See the [HDP-P specification](https://doi.org/10.5281/ZENODO.19332440) for the full EDT extension structure."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "fcf7b451d175"
      },
      "outputs": [],
      "source": [
        "# Minimal HDP-P Embodied Delegation Token (EDT) extension example\n",
        "# This shows how to attach physical constraints to an HDT\n",
        "\n",
        "hdp_p_extension = {\n",
        "    \"hdp-p\": {\n",
        "        \"version\": \"0.1\",\n",
        "        \"embodiment\": {\n",
        "            \"type\": \"mobile\",\n",
        "            \"platform\": \"raspberry-pi-5\",\n",
        "            \"hardware_id\": \"rpi-serial-XXXX\",   # TPM-attested in production\n",
        "            \"workspace\": \"lab-zone-a\"\n",
        "        },\n",
        "        \"action_scope\": {\n",
        "            \"permitted_actions\": [\"move_base\", \"read_sensor\"],\n",
        "            \"excluded_zones\": [\"human-workspace\"],\n",
        "            \"force_limit_n\": 10.0,\n",
        "            \"max_velocity_ms\": 0.5\n",
        "        },\n",
        "        \"irreversibility\": {\n",
        "            \"max_class\": 1,                       # Class 1 max for this token\n",
        "            \"class2_requires_confirmation\": True,\n",
        "            \"class3_prohibited\": True\n",
        "        },\n",
        "        \"policy_attestation\": {\n",
        "            \"policy_hash\": \"sha256:abc123...\",    # SHA-256 of deployed model weights\n",
        "            \"training_run_id\": \"gemma4-e2b-it\",\n",
        "            \"sim_validated\": True\n",
        "        },\n",
        "        \"delegation_scope\": {\n",
        "            \"fleet_delegation_permitted\": False,   # No lateral movement\n",
        "            \"max_delegation_depth\": 0\n",
        "        }\n",
        "    }\n",
        "}\n",
        "\n",
        "print(\"HDP-P EDT extension structure:\")\n",
        "print(json.dumps(hdp_p_extension, indent=2))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "b0af7c701dfc"
      },
      "source": [
        "## Summary\n",
        "\n",
        "| Layer | What it solves | Tool |\n",
        "|---|---|---|\n",
        "| Gemma 4 function calling | Model generates structured tool calls | `pipeline(\"text-generation\")` |\n",
        "| HDP middleware | Was this call authorized by a human? | `HDPMiddleware.gate()` |\n",
        "| HDP-P EDT extension | Is this physical action within delegated bounds? | `hdp_p_extension` |\n",
        "| Audit log | Pre-execution record of every decision | `audit_log` |\n",
        "\n",
        "The full HDP specification (IETF draft), HDP-P companion paper, TypeScript SDK, and Python bindings are available at:\n",
        "\n",
        "- **IETF draft:** https://datatracker.ietf.org/doc/draft-helixar-hdp-agentic-delegation/\n",
        "- **HDP-P paper:** https://doi.org/10.5281/ZENODO.19332440\n",
        "- **GitHub:** https://github.com/Helixar-AI\n",
        "- **Site:** https://helixar.ai"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "name": "Gemma_4_HDP_Agentic_Security.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
