# gpfs-agent Agentic chat front-end for the IBM Storage Scale (GPFS) REST API v3, driven by Claude with tool-use. Read-only by default; writes and destructive operations are gated behind explicit env flags. Ships with both a terminal REPL and a pure-Python web UI (Streamlit). Runs natively or in Docker. ## Quick start ### 1. Configure ```bash cp .env.example .env # edit .env: ANTHROPIC_API_KEY, GPFS_API_BASE, GPFS_USERNAME, GPFS_PASSWORD ``` ### 2a. Docker (recommended for Linux) ```bash docker compose up -d --build # open http://:8501 ``` Stop / view / update: ```bash docker compose logs -f docker compose pull && docker compose up -d docker compose down ``` Override the host port with `HOST_PORT=9000 docker compose up -d`. If your GPFS GUI uses a private CA, drop the cert into `./certs/ca.pem` and uncomment the volume + `GPFS_CA_BUNDLE` lines in `docker-compose.yml`. ### 2b. Native Linux (no Docker) ```bash ./run.sh # web UI on 0.0.0.0:8501 ./run.sh cli # terminal REPL HOST=127.0.0.1 PORT=8080 ./run.sh # bind override ``` `run.sh` creates a `.venv` on first run and installs dependencies. ### 2c. Windows (PowerShell) ```powershell python -m venv .venv .\.venv\Scripts\Activate.ps1 pip install -r requirements.txt streamlit run gpfs_agent\web.py # web UI python -m gpfs_agent # REPL ``` ## Web UI The Streamlit app lives at `/` on the configured port. It shows: - A chat panel (uses Claude with tool-use against the GPFS REST API) - A sidebar with model, API base, mode, the live system prompt, and a tool-call log (last 25 calls with status, reason and payload) - A "Reset conversation" button - When `GPFS_ALLOW_WRITES=true`: a session-scoped *"Auto-approve mutations"* checkbox. Mutating calls are denied unless this is on. REPL commands: `/reset`, `/system`, `/quit`. ## How the guardrails work Everything is configured in `.env`: | Variable | Effect | | -------------------------- | ---------------------------------------------------------------------- | | `GPFS_ALLOW_WRITES` | When `false` (default) the model is given a tool that only accepts `GET`. | | `GPFS_ALLOW_DESTRUCTIVE` | When `false` (default) `DELETE` is stripped even if writes are on. | | `GPFS_CONFIRM_MUTATIONS` | When `true` (default) every `POST/PUT/DELETE` is gated by a confirm step. | | `GPFS_PATH_ALLOW` / `_DENY`| Optional regexes applied to the request path. | | `GPFS_INSTRUCTIONS` | Free-text instructions appended to the system prompt. | | `GPFS_INSTRUCTIONS_FILE` | Path to a file with longer instructions; merged with `GPFS_INSTRUCTIONS`. | Guardrails are enforced in three layers: 1. **Tool schema** — the `method` enum given to the model is built from `cfg.allowed_methods`, so it cannot ask for `DELETE` when disabled. 2. **Dispatcher** — `tools.py` re-checks method and allow/deny regex and triggers the confirm hook before any mutating HTTP call. 3. **System prompt** — `agent.py` injects natural-language guardrails plus a curated v3 endpoint reference (see `endpoints.py`) so the agent has accurate context without having to guess. ## Project layout ``` gpfs_agent/ ├── __init__.py ├── __main__.py # python -m gpfs_agent (REPL) ├── agent.py # Anthropic tool-use loop ├── cli.py # Rich REPL ├── config.py # .env loading & validation ├── endpoints.py # curated /scalemgmt/v3 reference (in-context) ├── gpfs_client.py # httpx wrapper around the GPFS REST API ├── tools.py # Tool schemas + guarded dispatcher └── web.py # Streamlit chat app Dockerfile # python:3.12-slim + streamlit docker-compose.yml # one-command deploy run.sh # bash helper for native Linux ``` ## Notes on the GPFS REST API - `GPFS_API_BASE` should include the version prefix, e.g. `https://gui:46443/scalemgmt/v3`. v3 is the current native REST API on Storage Scale 5.2.x / 6.0.x; the typical port is 443 (CNSA / container deploys) or 46443 (native install). - Auth is HTTP Basic against a Storage Scale GUI user. Use an account scoped to the operations you intend to allow. - For self-signed lab gear, set `GPFS_VERIFY_TLS=false` or point `GPFS_CA_BUNDLE` at a PEM file (mount as a volume when running in Docker). - The interactive Swagger UI lives at `https:///openapi/` — useful for discovering endpoints your specific release ships.