gpfsagent/README.md
Laurence Horrocks-Barlow 0d75d73c23 Add Docker, bash launcher, and Linux-first README
Lets the project be served as a web app from a Linux host in one command:
- Dockerfile (python:3.12-slim + non-root user + streamlit healthcheck)
- docker-compose.yml with env_file, restart policy, configurable HOST_PORT,
  and an optional CA-bundle volume for self-signed GPFS GUIs
- .dockerignore to keep the image lean
- run.sh for native (non-Docker) runs: creates a venv on first use and
  launches either the Streamlit UI (default) or the REPL
- .gitattributes pins LF line endings on shell/yaml/py so scripts stay
  executable when checked out on Linux from a Windows host
- README rewritten with Linux/Docker quick starts in front, Windows behind

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 13:05:30 +01:00

121 lines
4.5 KiB
Markdown

# 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://<host>: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://<gui>/openapi/` — useful for
discovering endpoints your specific release ships.