Skip to main content

Hook Health and Troubleshooting

Agent hooks can be installed and still fail when they run. Use the observed dispatch outcomes to find parsing, recording, and transport failures that a hook's shell guard may otherwise hide.

Availability

This page describes the session-scoped diagnostics introduced by Atomic PR #220. Use a CLI build containing that change.

# Installation, sessions, hook liveness, and outstanding failures
atomic agent status

# Machine-readable outcomes and failure details
atomic agent status --json

Understand the Report​

The human report shows the most recent successful dispatch and its age relative to the current time. A hook that fired but has never succeeded is distinguishable from one that worked and then failed. Outstanding failures are attributed to their sessions and parent sessions.

Outcomes are tracked per agent, session, and verb. A child's success cannot clear a parent's failure. A later successful dispatch of the same verb in the same session clears that session's current failure, while the operational log retains the earlier observations.

A successful dispatch may produce no new change when the working copy is unchanged. Inspect recorded changes to review the work itself.

Inspect JSON Outcomes​

FieldWhat it tells you
hook_healthPer-agent last_fired, last_ok, last_error, verbs_recorded, and failing_verbs
hook_sessionsPer-session rows with agent, session_id, parent_session_id, and health.verbs
hook_health_errorWhy the database-backed operational log could not be loaded
hook_errorsGrouped errors and recent entries from the bounded tail of the legacy plugin/git-shadow error log
silent_agentsInstalled agents with no successful dispatch in the available operational log

Each entry in health.verbs includes last_fired, outcome (ok or error), an optional failure detail, and an optional last_ok. Details are flattened and truncated for the report. An unassigned diagnostic has session_id: null.

With jq installed, inspect one session:

atomic agent status --json \
| jq '.hook_sessions[]? | select(.session_id == "ses_child")'

When there are no observations, the hook-health fields are omitted. A freshly installed hook may simply not have fired yet. If the service is unavailable and only pending observations can be read, hook_health_error explains the partial report and silent_agents is omitted.

Diagnose a Failure​

  1. Check the installation flags in atomic agent status.
  2. Inspect the affected session in hook_sessions and find the failing verb's detail. A malformed payload or service transport error can fail before recording starts.
  3. Correct the reported cause. If the integration is missing or its hook configuration is stale, refresh the integration.
  4. Trigger the same hook again and check that its session-level outcome becomes ok and last_ok advances.

Atomic also groups existing plugin and git-shadow errors from .atomic/hook-errors.log, collapsing repeated failures with differing session IDs or turn numbers into useful classes.

Concurrent Sessions and Correlation​

Native payloads identify the session. Integration bridges can preserve a parent_session_id in raw_json, or set ATOMIC_SESSION_ID and ATOMIC_PARENT_SESSION_ID for the hook process. Typed agent receive also accepts a top-level parent_session_id and forwards the caller-resolved parent on the service request. These fields keep parent/child attribution intact across process boundaries.

Malformed input without a usable session ID remains an unassigned diagnostic, so the failure is visible without being attributed to another session.

Logging and Service Outages​

Native hooks, typed receive, and the shared dispatch handler emit structured Rust tracing observations. The existing service layer appends them transactionally to .atomic/atomic.redb, with event-ID deduplication and session-indexed reads. Local mode runs the service handlers in-process; reactor mode calls the daemon. Concurrent hook processes retain independent events.

Status derives health from these local operational logs. They are independent of the running-turn provenance journal, allowing parsing failures and failures after a turn closes to remain recordable.

During a service outage, each observation is spooled to its own immutable file under .atomic/hook-log-pending/. Status can inspect pending observations while the service is unavailable. A successful append replays them into the database and removes their spool files after commit. Replayed events retain their IDs and original observation times, so retries do not duplicate events or make an older failure appear newer than a later recovery.

See Also​