# 2026-07-09 — Session execution, UX, and learning improvements **Status:** Done — 2026-07-11. Hard blocker and all major items verified: `pct_create` wired into `request_execution`, `ToolCallGroup` collapse + live status, `InlineApproval` blast radius, `http_get` tool, `session-review` skill. Two minor secondary items not implemented: `list_lxcs` CPU/mem enrichment, and a dedicated `get_tools_summary` tool (SOUL.md has general bulk-tool guidance instead). ## Goal Fix the hard blocker and UX issues found in the latest production Nomos session (`b9c5de7c-e0b5-424c-9149-9fd45b2e7011` — "deploy TypeType as an LXC on strong"). The user asked Nomos to deploy an LXC; Nomos gathered data, proposed a plan, but at the final step ("run all yourself") said it *couldn't* — `request_execution` has no `pct_create` action. The user's objective was not achieved. ## Session analysis 10 messages (5 user / 5 assistant), 150 tool calls, zero LXC created. | Msg | Role | Tool calls | Top tools | Summary | |-----|------|-----------|-----------|---------| | 0 | user | 0 | — | "deploy TypeType on strong as LXC" | | 1 | assistant | 40 | get_entity(20), search_knowledge(12) | Fleet scan, entity detail per host/LXC | | 2 | user | 0 | — | "it's github.com/Priveetee/TypeType, use tube.hubris.network" | | 3 | assistant | 2 | search_knowledge(2) | MCP has no web fetch tool → couldn't read GitHub | | 4 | user | 0 | — | "I think you can figure out those" | | 5 | assistant | 60 | search_knowledge(32), request_execution(14) | Built the plan, tried provisioning, failed silently | | 6 | user | 0 | — | "connect to strong media disk, no youtube login, proceed" | | 7 | assistant | 44 | search_knowledge(10), get_entity(10), request_execution(8) | Full deployment plan laid out | | 8 | user | 0 | — | "run all yourself" | | 9 | assistant | 4 | request_execution(4) | **"I can't run pct create — only pct_exec, systemctl, restart, apt_upgrade"** — failure | ## Findings ### 1. HARD BLOCKER: `pct_create` missing from `request_execution` `request_execution` (`internal/mcp/server.go:264-376`) supports `restart`, `systemctl`, `pct_exec`, `apt_upgrade`. The actuator has `ProvisionLXC()` (`internal/actuator/actuator.go:209`) that calls `pct create` via SSH, but it is only wired into the auto-act signal pipeline — Nomos has no way to invoke it through MCP. Nomos's final response laid out the exact `pct create` command the operator needs to run manually on the Proxmox host. That's a dead end for the user, who expected the agent to execute from chat. **Fix:** - Add `pct_create` action to `request_execution` handler. - Wire it to the existing `ProvisionLXC()` function. - Classification: `config_mutation` — requires operator approval. Once approved (from the Ops page or Matrix), the actuator picks it up and provisions the LXC with the step callback reporting progress. - Alternatively (for the "run from chat" expectation): add a chat-level approval flow — when Nomos proposes `request_execution` with `pct_create`, the frontend renders an inline "Approve" button in the chat bubble. Operator clicks → it runs. This is the UX the user described: "allow the agent to run things directly from the chat I'm in." ### 2. UI: ToolCallGroup expanded by default during streaming — no status animation `ToolCallGroup.svelte` uses `
` when `active=true`. During a streaming turn with 40+ tool calls, the collapsed group fills the viewport with raw JSON. The summary header shows only a static icon and "N tools" text. **What happens now:** - Streaming starts → group opens and stays open → all tool results visible as raw JSON. - When streaming ends → auto-collapses. No animation. - Header shows `WrenchIcon` pulsing OR `CheckIcon` OR `XIcon` — but no live running count, no per-tool status in the collapsed summary bar. **What should happen:** - Group starts **collapsed** by default. The summary header shows a live animated status: "⠋ Running get_lxc_state (caddy)… [2/40 done]" with the active tool name + a progress fraction, updating in real time. - When a tool completes, the header briefly reflects it ("✓ get_lxc_state (caddy)") before moving to the next. - Clicking the summary expands the group with a smooth animated open/close (replacing native `
` with bits-ui `Collapsible` + CSS transition). - On load from history (not streaming), always starts collapsed. **Fix:** - Replace `
` with bits-ui `Collapsible` component (already in `web/src/lib/components/ui/collapsible/`). - Add `animate-pulse` to the chevron icon during streaming (user sees motion). - Add a `statusText` derived that shows the in-progress tool name + count. - CSS animation: `Collapsible.Content` supports `forceMount` with transitions. ### 3. No web-fetch tool → Nomos can't read GitHub READMEs Msg 3: Nomos needed to inspect `github.com/Priveetee/TypeType` to understand the stack. It used `search_knowledge` (DB FTS), which returned nothing because the repo isn't in the DB. The agent had no way to fetch external URLs. The MCP has 27 tools (21 listed in AGENTS.md + 6 more added since), but none for HTTP/web fetching. Nomos can only query the DB or execute SSH commands on existing hosts. This forced the human to provide context that should have been machine-read. **Fix options (non-blocking):** - Add an `http_get` MCP tool that returns sanitized body text (strip scripts, truncate to 8KB). Rate-limited per-turn. - Or: add `web_fetch` as a first-class action in the MCP gateway itself, since the gateway container already makes outbound HTTP calls to OpenRouter. ### 4. Task: Bulk-tool awareness already in SOUL.md but not enough The SOUL.md already says "prefer `list_lxcs` over `get_lxc_state` for fleet-wide" (line 27-28). But msg 1 still made 40 calls. The issue: - `get_entity` was called 20 times (one per entity found by `list_entities`). `list_entities` already returns all entities; the agent wanted per-entity detail, which is redundant since `explain` or `get_state_snapshot` gives the same info in one call. **Fix (already planned in `2026-07-09-chat-sessions-improvements.md` finding 3):** - Enrich `list_lxcs` with CPU/memory utilization so the model doesn't feel it needs `get_lxc_state` per container. - Add `get_tools_summary` to SOUL.md preamble that lists each tool's intended use and warns about N+1 call patterns. ### 5. Skill gaps | Missing | Why | Where to add | |---------|-----|-------------| | `http_get` / `web_fetch` | Agent can't read external URLs | MCP tool in `internal/mcp/server.go` | | `session-review` skill | No way to learn from failed sessions | `.agents/skills/session-review/SKILL.md` | | `pct_create` action | Can't provision new LXCs from chat | `internal/mcp/server.go` + `internal/actuator/` | | `request_execution` approval from chat | Operator must switch to Ops page | Inline chat approval component | ## Implementation order 1. **Add `pct_create` to `request_execution`** (`internal/mcp/server.go`) — hard blocker, needed for the session's objective. 2. **ToolCallGroup: collapse by default + animated status header** (`web/src/lib/components/ToolCallGroup.svelte`) — immediate UX win, the user explicitly asked for this. 3. **Inline chat approval for `request_execution`** — renders an "Approve"/"Deny" button inside the chat when an execution is queued for approval. Lets the operator approve from the same chat. 4. **`session-review` local skill** — lives in `.agents/skills/`, loads when examining chat sessions for failure patterns. 5. **`http_get` MCP tool** — non-blocking but addresses a real gap seen in this session. ## Verification - Re-run the TypeType deploy prompt against the patched agent. Confirm: - Agent proposes plan as before (keep plan-proposal behavior). - When user says "run all", agent calls `request_execution(target=lxc:typetype, action=pct_create, params=)`. - Approval fires → operator sees inline approval in chat → approves → LXC created. - ToolCallGroup: start a session that triggers 5+ tool calls. Confirm: - Group starts collapsed. - Summary header shows animated status: tool name + count updating in real time. - Clicking expands smoothly. - On session reload (history), stays collapsed. - Load `session-review` skill and ask it to analyze the TypeType failure session; confirm it identifies the missing action as the root cause.