- DELETE infrastructure-monitoring.prose.md (redundant — proxmox-monitor already deployed this) - FIX infrastructure-control.prose.md: remove /grafana/ nginx route (reverted Jul 2, broke gpu-fleet) - FIX infrastructure-update.prose.md: wrong CT IDs (122→112 Tanko, 123→114 Mumuni, .19→storepve Zulip) - FIX infrastructure-update.prose.md: Strix Halo :8080→router health check (firewalled to .116 only) - FIX proxmox-monitor.prose.md: stale /grafana/ URLs→:3001 (post-revert cleanup) - ADD disk-gc-threat-response.prose.md: verified run (2026-07-04, reclaimed 35.67GB from kagentz) - ADD infrastructure-update.prose.md, pi-approval-architecture.prose.md, zulip-approval-fix.prose.md, zulip-self-heal.prose.md - UPDATE hermes-config, litellm-health/self-heal, pm2-self-heal, zulip-* contracts - ADD runs/20260704-005804-51f9a9 (disk-gc-threat-response run artifacts) All contracts verified against live PVE API, nginx config, and firewall state.
108 lines
4.7 KiB
Markdown
108 lines
4.7 KiB
Markdown
---
|
|
kind: architecture
|
|
name: pi-approval-architecture
|
|
description: >
|
|
Documents pi's approval model vs Hermes, what commands are available,
|
|
and the architectural constraints that prevent mid-turn tool approval in pi.
|
|
Updated with /approve and /deny stub commands for cross-agent UX consistency.
|
|
agent: abiba
|
|
version: 1.0.0
|
|
---
|
|
|
|
# Pi Approval Architecture
|
|
|
|
## TL;DR
|
|
|
|
| Feature | Hermes | Pi (Abiba) |
|
|
|---------|--------|------------|
|
|
| `/approve` command | ✅ Full — unblocks agent | ✅ Stub — acknowledges, no blocking |
|
|
| `/deny` command | ✅ Full — blocks agent | ✅ Stub — acknowledges, no blocking |
|
|
| Dangerous command detection | ✅ 40+ patterns + Tirith | ❌ None (LLM judgment only) |
|
|
| Mid-turn tool approval | ✅ Agent thread blocks on Event | ❌ No hook in agent loop |
|
|
| Smart approval (aux LLM) | ✅ `approvals.mode: smart` | ❌ N/A |
|
|
| Yolo mode | ✅ `/yolo`, `approvals.mode: off` | ❌ N/A |
|
|
| Permanent allowlist | ✅ `command_allowlist` + `shell-hooks` | ❌ N/A |
|
|
| Session-scoped approval | ✅ `approve_session()` | ❌ N/A |
|
|
| Approval timeout | ✅ 60s default, configurable | ❌ N/A |
|
|
|
|
## Why Pi Can't Do Mid-Turn Approval
|
|
|
|
Pi's agent loop is **418 lines** of TypeScript. It's deliberately minimal:
|
|
|
|
```
|
|
LLM decides → calls tool → tool executes immediately → output goes to LLM → repeats
|
|
```
|
|
|
|
There is no middleware between "LLM decides to call bash" and "bash executes."
|
|
The extension system (`injectIntoSession`) feeds messages IN but doesn't intercept
|
|
tool calls mid-turn.
|
|
|
|
Hermes has a full approval pipeline:
|
|
```
|
|
LLM decides → check_all_command_guards() → if dangerous → notify_cb → block thread
|
|
→ user responds /approve → resolve_gateway_approval() → Event.set() → unblock
|
|
```
|
|
|
|
This pipeline is deeply integrated into Hermes' gateway, tool executor, and
|
|
session management. Replicating it in pi would require rewriting the core agent
|
|
loop — violating pi's design constraint of minimal core.
|
|
|
|
## What Pi HAS: `/approve` and `/deny` Stubs
|
|
|
|
Added to prevent `/approve` and `/deny` from being forwarded to the LLM as
|
|
garbled input. When a user types these commands to Abiba:
|
|
|
|
- **`/approve`** → "Pi doesn't have pending approvals. Commands execute immediately."
|
|
- **`/approve session`** → Same response
|
|
- **`/deny`** → Same response + "For Hermes agents (Tanko, Mumuni), these work with their built-in approval system."
|
|
|
|
This keeps the UX consistent across agents — users can type `/approve` anywhere
|
|
without getting confused by LLM responses.
|
|
|
|
## Pi's Full Command Set (Hermes Parity)
|
|
|
|
| Command | Handler | Description | Hermes Equivalent |
|
|
|---------|---------|-------------|-------------------|
|
|
| `/status` | System | PM2 processes, containers, session info | `/status` |
|
|
| `/retry` | Session | Re-injects last user message | `/retry` |
|
|
| `/continue` | Session | Continues truncated response | `/continue` |
|
|
| `/new [topic]` | Session | Clears conversation context | `/new` |
|
|
| `/stop` | Control | Interrupts current LLM processing | `/stop` |
|
|
| `/model [name]` | Info | Show current model, list available | `/model` |
|
|
| `/compact` | Session | Requests context compaction | `/compact` |
|
|
| `/yolo` | Stub | Pi has no approval system — accepted for UX | `/yolo` |
|
|
| `/verbose` | Stub | Verbosity controlled by prompt, not toggle | `/verbose` |
|
|
| `/approve` | Stub | Pi executes immediately — no approvals | `/approve` |
|
|
| `/deny` | Stub | Pi executes immediately — no approvals | `/deny` |
|
|
| `/help [cmd]` | Info | Shows command help | `/help` |
|
|
|
|
## What Pi COULD Add (Without Core Changes)
|
|
|
|
These would work within pi's current architecture:
|
|
|
|
1. **Pre-message dangerous command scan**: Before forwarding an agent response to
|
|
Zulip, scan the text for dangerous bash commands and add a warning banner.
|
|
Doesn't prevent execution but alerts user.
|
|
|
|
2. **User-facing approval prompt injection**: When user asks pi to do something
|
|
dangerous (detected via regex on user input), pi could respond with a
|
|
confirmation request before proceeding. This works because it's at the
|
|
message level, not mid-turn.
|
|
|
|
3. **Response rate-limiting**: If pi generates many bash commands rapidly,
|
|
throttle and ask for confirmation. Works within the extension's send path.
|
|
|
|
## Files
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `/root/.pi/agent/extensions/zulip/index.js` | Pi Zulip extension with command system |
|
|
| `/root/prose-contracts/zulip-approval-fix.prose.md` | Hermes Zulip approval fix |
|
|
| `/root/prose-contracts/pi-approval-architecture.prose.md` | This document |
|
|
|
|
## Related
|
|
|
|
- Hermes `tools/approval.py` — Full approval pipeline (dangerous patterns, Tirith, smart mode)
|
|
- Hermes `gateway/slash_commands.py:_handle_approve_command` — Slash command handler
|
|
- Hermes Zulip adapter fix — HTML stripping for command detection
|