Skip to content

Agent Attention Prompts

Status: Open — design proposal

The biggest hidden cost of running AI coding agents today is idle wall-clock. Agents finish work, hit a confirmation prompt, run into an ambiguous decision, or stop on a long-running command and silently wait for the operator to come back to the terminal. The operator, meanwhile, is heads-down on something else — reviewing a PR, in a meeting, on another machine — with no signal that anything wants their attention.

Every minute the agent waits is a minute of compounding throughput loss across however many agents the operator is running in parallel. The point of jackin’ is to make running many agents safe and convenient; “many agents” is only a real win if the operator can stay in flow and only context-switch when an agent actually needs them.

This roadmap item proposes agent attention prompts: an opt-in, per-workspace, per-role notification channel that fires a host-side OS notification when an agent inside a jackin’ container is waiting on operator input, with optional escalation to sound and a click action that focuses the right terminal tab.

The end state, from the operator’s seat:

  1. A passive notification, on the host, when an agent stops to wait. macOS Notification Center / Linux desktop notification / Windows toast. Title names the workspace, role, and (optionally) the question the agent is asking. No visible jackin window required — the operator can be anywhere on the host.
  2. Optional escalation. When the operator has set a per-workspace policy “if I don’t respond in N seconds, start playing a sound”, jackin’ escalates from a silent toast to an audible cue. Configurable per workspace and per role; off by default.
  3. Click-to-focus. Clicking the notification opens or focuses the terminal tab the agent is running in. The Desktop Agent Hub v1 should wire this for Ghostty first; kitty, iTerm2, WezTerm, gnome-terminal, and other adapters are later additions once the Ghostty contract is solid. Operators don’t have to remember which window the agent is in.
  4. Per-workspace mute. Operators in deep-focus mode can mute notifications for a workspace temporarily without losing the launch-time policy.
  5. Per-axis toggle. Notify on idle waiting, on agent finished work, on sensitive-mount confirmation requested, etc. — operators choose which classes of attention prompts they care about.

How the agent expresses “I’m waiting”

Section titled “How the agent expresses “I’m waiting””

The agent inside the container needs a way to tell jackin’ “I’m idle on operator input.” Three sources, in priority order:

  1. An MCP server jackin’ auto-registers in every agent session. Each agent runtime jackin’ supports (Claude Code, Codex; Amp forthcoming) integrates MCP servers via its own config. jackin’ already wires tirith and shellfirm for the Claude runtime via docker/runtime/entrypoint.sh; the equivalent registration for Codex / Amp is part of this proposal’s scope. The new jackin-attention MCP server adds two tools the agent can call:

    • attention.waiting(reason: string, urgency?: low | normal | high) — declare the agent is waiting for operator input.
    • attention.resolved() — clear the waiting state when the operator responds.

    The agent runtime’s tool-use loop already calls these tools when the runtime decides it’s hit a confirmation or an open-ended ambiguity; jackin’ bundles the MCP server, registers it at launch, and never asks the operator to wire it manually.

  2. Inferred from the agent’s PTY activity. Even without explicit MCP calls, jackin’ can detect “the agent stopped emitting output and is sitting on a prompt” by watching the container’s TTY (no output for N seconds while the process is S+ foreground). This catches the long tail of confirmation flows the agent runtime hasn’t instrumented yet.

  3. Inferred from the agent’s exit code / state file. When the agent runtime writes a state file or exits with a “waiting for input” code, jackin’ reads it.

Path 1 is the primary, path 2 the fallback, path 3 a future hook for runtimes that publish their own state.

The pieces:

  • jackin-attention MCP server. Static binary baked into the construct image. Registered automatically in each agent’s MCP config at container launch — extending the registration pattern docker/runtime/entrypoint.sh uses today for the Claude runtime’s tirith / shellfirm to every supported runtime. When the agent calls attention.waiting, the MCP server pushes the event over the existing per-container control channel (the same bind-mount or pipe used for daemon ↔ container coordination — see jackin daemon for the channel design).
  • The jackin daemon dispatches the host-side notification. Per the jackin daemon plug-in surface, this feature is one adapter that listens for attention events from any running container and translates them to OS-native notifications:
    • macOS — osascript -e 'display notification …' or the UserNotifications framework via a small Swift helper. Sound escalation via afplay / NSSound.
    • Linux — notify-send (libnotify) or the org.freedesktop.Notifications D-Bus API. Sound via paplay / aplay.
    • Windows — out of scope for the first phase; revisit when jackin’ supports Windows hosts.
  • Click-to-focus adapter. The notification carries an action that, when activated, runs a host-side command to focus the right terminal tab. The first Desktop slice should implement Ghostty only, matching the Jackin Desktop Agent Hub v1 launch contract. Other terminal emulators get a notification without click focus until their adapters are deliberately added.

The configuration knobs (managed through jackin console → workspace editor → a new Notifications tab, parallel to the existing General / Mounts / Roles / Secrets / Auth tabs):

KnobDefaultWhat it does
attention.enabledtrueMaster switch for this workspace.
attention.urgency_filternormal+highWhich urgency levels notify (low/normal/high).
attention.sound_escalation_afteroffIf unset, silent forever. Set to a duration (e.g. 60s, 5m) to start playing sound after that wait.
attention.click_actionfocus_tabWhat clicking the notification does (focus_tab / none).
attention.mute_untilunsetTemporary mute set from the TUI (m on the workspace row); auto-clears at the named timestamp.

Every knob is configurable globally, per workspace, and per (workspace × role × agent), with the same most-specific-wins resolution rule the rest of jackin’ already uses.

Same answer as live auth sync: this feature can’t run from a CLI that exits between commands. The daemon adapter:

  • Subscribes to the per-container control channels for attention events.
  • Tracks per-event timers (sound-escalation deadlines).
  • Holds the per-workspace mute state.
  • Talks to the OS notification API.
  • Receives click events back from the OS and runs the focus-tab action.

The lifecycle, install, and security posture this needs are the same ones the jackin daemon item is decided. This feature is an adapter against that daemon; it does not introduce its own long-running shape.

  • Tool surface. Just attention.waiting / attention.resolved? Or a richer set (attention.progress(message) for “I’m still working, here’s what I’m doing”)?
  • Auto-resolve vs explicit resolve. Does the next tool call from the agent count as “operator unblocked the agent” (auto-resolve), or does the agent have to call attention.resolved explicitly?
  • Urgency taxonomy. low / normal / high is a starting point; do we need an error level for crashes vs interactive for confirmations? The smaller the taxonomy, the better.
  • PTY-idle threshold. How many seconds of TTY silence before jackin’ assumes the agent is waiting? Too short = false positives every time an agent is thinking; too long = operator waits longer than necessary. Configurable per workspace?
  • False-positive backoff. When the operator confirms a notification was a false positive (clicks “this wasn’t really waiting”), the daemon should debounce that container for a while.
  • Detection. The v1 contract is Ghostty-first. What if the operator switches terminals after launch, closes Ghostty, or starts a session outside the Desktop launcher? The click action should degrade gracefully to a notification with no click action.
  • Adapter scope. Ghostty is the first supported adapter. Other terminals are explicitly deferred until the Desktop Agent Hub proves the product shape.
  • Multiple agents waiting at once. Five agents idle in five containers — five notifications? One grouped notification? A digest the operator can drill into?
  • Notification fatigue. What’s the rate-limit policy? After N notifications in M seconds, fall back to a digest?
  • Remote operator. When jackin’ grows to support remote agents (Kubernetes phase, see the Why jackin’ page), notifications need to reach the operator wherever they are. Out of scope for v1; revisit when remote-agent work lands.

A minimal cut to validate the shape:

  1. jackin-attention MCP server, baked into construct, auto-registered for every agent runtime jackin’ supports (Claude Code first, Codex / Amp as part of the same phase to close the runtime-coverage gap left by today’s Claude-only tirith / shellfirm registration).
  2. The two-tool surface attention.waiting / attention.resolved.
  3. Daemon adapter listening on the per-container control channel, dispatching macOS Notification Center notifications.
  4. Click action wired for Ghostty first; other terminals get the notification with no click action and a one-line “open this terminal manually” hint.
  5. Notifications tab in jackin console workspace editor — enable / mute / sound-escalation duration. No per-role overrides in v1.
  6. Linux notify-send adapter as part of the same phase (it’s small and operators on Linux deserve parity from day one).

Not in phase 1: PTY-idle inference fallback, sound files beyond a single default, urgency-based sound differentiation, cross-terminal click-to-focus matrix, Windows support.

Concretely: an operator running four agents in parallel today loses ~20–30% of total work time to “I didn’t notice the agent was waiting.” Even a 50% reduction in idle-wait time pays for the implementation effort within a few weeks of operator usage, and that’s before counting the qualitative win of staying in flow on the work the operator actually came to do.

The bet of jackin’ is that running many agents safely and conveniently changes how operators work. Attention prompts are the difference between “I have ten agents running, but I have to babysit them” and “I have ten agents running, and they ping me when they need me.”