# Per-agent terminal: row taxonomy (as built) The per-agent web UI's live pane renders one row per `TermMsg` (`hive-agent/src/term_msg.rs`): `{icon?, level: debug|info|warn|error, summary, body?, body_format?: markdown|diff, coalesce_key?}`. Classification (icon, summary text, whether a tool call gets an expandable body) happens server-side, once — `term_msg.rs` + `stream_enrich.rs` — and both `GET /api/events/history` and `GET /api/events/stream` serve it identically as `TermEnvelope { ts, seq?, msgs: TermMsg[] }` frames (`hive-agent/src/web_ui/stream.rs`). The frontend renders a `TermMsg` close to as-is (`frontend/packages/agent/src/components/Row.tsx`): `level` picks the CSS colour (`terminal.css`'s `.live .level-*`), an empty `summary` + markdown `body` renders as a flat row with just the body (assistant text), and any other bodied row is an expandable `
`, opened by default according to the operator's expand-tool-output preference (`getExpandDetailsPref()`) — uniformly, no per-tool override. There's no separate client-side row model or classification step. ## Layout Every row is its own 2-column grid — icon column (`.row-glyph`, width from the `--row-icon-col` custom property) then content column (`.row-content`, or a markdown body's own `.md` class) — so an icon's left edge lands in the same place regardless of row kind. A `
` row grids its `` instead of itself (so the `
` body below
can stack full-width), using the exact same `grid-template-columns` value,
with the disclosure caret leading the summary text rather than the icon.
One shared column definition, not two independently-computed offsets
kept in sync by hand — see `terminal.css`'s own comment on the incident
that motivated the change.

## Levels

| Level | Colour | Roughly |
|---|---|---|
| `debug` | muted | thinking, coalesced ticks, ambient harness chatter |
| `info` | default fg | turn start/ok, assistant text, tool calls + results |
| `warn` | amber, left rule | stderr, an unrecognised event shape, API retries |
| `error` | red, left rule | turn failed, a tool result with `is_error: true` |

The settings menu's "hide debug output" toggle (`getHideDebugPref()`,
`@hive/shared/prefs.js`) skips `debug`-level rows entirely rather than
muting them further — client-side only, same live-read-no-reload shape
as the expand-tool-output preference above.

Per-tool icon + summary formatting (what a `Read`/`Edit`/`send` call's row
actually says) lives in `stream_enrich.rs`'s `fmt_tool_use()` family —
read that when you need the specifics, this doc doesn't duplicate it.

## Markdown

`frontend/packages/agent/src/lib/markdown.ts`'s `renderMarkdown()` runs
`marked.parse()` through DOMPurify into a `
`. Applied to any `TermMsg` with `body_format: "markdown"`. ## Dashboard side (not covered here) The main dashboard's message-flow pane is a different shape: broker messages render as `.msgrow` grid lines, not agent-terminal rows.