# What Is the Elicitation Hook in Claude Code Harness?

> Discover the elicitation hook in Claude Code Harness. Learn how this two-stage system captures user input, logs requests, and prevents automation deadlocks for smoother Breezing sessions.

- Repository: [Chachamaru/claude-code-harness](https://github.com/Chachamaru127/claude-code-harness)
- Tags: deep-dive
- Published: 2026-05-28

---

**The elicitation hook is a two-stage interception system that captures every MCP server request for user input, logs it to a structured ledger, and prevents background automation deadlocks by automatically skipping UI prompts during Breezing sessions.**

The elicitation hook in [Chachamaru127/claude-code-harness](https://github.com/Chachamaru127/claude-code-harness) provides a robust, auditable mechanism for handling interactive prompts without breaking automated workflows. This hook pair intercepts structured input requests from the Claude Code server, records them permanently, and enforces policies that distinguish between interactive sessions and background workers.

## How the Elicitation Hook Works

The system operates as a **two-stage hook pair** registered in [`hooks/hooks.json`](https://github.com/Chachamaru127/claude-code-harness/blob/main/hooks/hooks.json). Each stage handles a distinct phase of the user-prompt lifecycle, creating a clean separation between request interception and response handling.

### Stage One: The Elicitation Handler

When the MCP server asks the user for structured input, the harness triggers [`scripts/hook-handlers/elicitation-handler.sh`](https://github.com/Chachamaru127/claude-code-harness/blob/main/scripts/hook-handlers/elicitation-handler.sh). This handler receives a JSON payload from STDIN describing the prompt request and performs three critical actions:

1. **Records the event** to `.claude/state/elicitation/events.jsonl` using the `elicitation-event.v1` schema defined in [`go/internal/hookhandler/elicitation_ledger.go`](https://github.com/Chachamaru127/claude-code-harness/blob/main/go/internal/hookhandler/elicitation_ledger.go)
2. **Emits a desktop notification** titled `Claude Code: elicitation` to alert the operator
3. **Checks for Breezing sessions** via the `HARNESS_BREEZING_SESSION_ID` environment variable

If a Breezing session is active, the handler immediately returns a denial JSON without showing UI, preventing background agents from hanging on interactive prompts.

```json
// Input payload read from STDIN
{
  "schema_version": "elicitation-event.v1",
  "event_kind": "elicitation",
  "elicitation_id": "req-001",
  "message": "Please confirm the target repository URL:",
  "source": "mcp",
  "timestamp": "2026-05-28T12:00:00Z"
}

```

```json
// Automatic denial during Breezing sessions
{
  "decision": "deny",
  "reason": "Breezing session: background agent cannot interact with elicitation UI"
}

```

### Stage Two: The Elicitation Result Handler

After the user provides input (or the request is skipped), [`scripts/hook-handlers/elicitation-result.sh`](https://github.com/Chachamaru127/claude-code-harness/blob/main/scripts/hook-handlers/elicitation-result.sh) receives the response payload. This lightweight handler appends a result entry to the same ledger and returns minimal approval JSON to the MCP server. No UI is displayed during this stage, ensuring minimal overhead for logging the outcome.

```json
// Result payload processed by elicitation-result.sh
{
  "schema_version": "elicitation-event.v1",
  "event_kind": "elicitation_result",
  "elicitation_id": "req-001",
  "result_status": "done",
  "message": "https://github.com/example/repo.git",
  "timestamp": "2026-05-28T12:01:13Z"
}

```

## Key Improvements to User Prompt Handling

The elicitation hook introduces five specific enhancements that make Claude Code operations more reliable and auditable.

### Structured Audit Ledger

Every request and response is persisted as an `elicitation-event.v1` record in `.claude/state/elicitation/events.jsonl`. This creates a permanent, queryable trail for debugging, compliance audits, and post-hoc analysis. The Go implementation in [`go/internal/hookhandler/elicitation_ledger.go`](https://github.com/Chachamaru127/claude-code-harness/blob/main/go/internal/hookhandler/elicitation_ledger.go) defines the schema and provides atomic write operations to prevent data corruption during concurrent access.

### Two-Layer Defense Architecture

By separating the request (`elicitation`) from the response (`elicitation-result`), the system enforces policy decisions **before** any UI is rendered. This prevents scenarios where background agents might stall waiting for user interaction that can never occur. The architecture is implemented in the hook registration at [`hooks/hooks.json`](https://github.com/Chachamaru127/claude-code-harness/blob/main/hooks/hooks.json) (lines 276-288), where each stage maps to its respective handler.

### Breezing Session Protection

The handler detects Breezing sessions—a special mode for background workers that cannot display UI—by checking for the `HARNESS_BREEZING_SESSION_ID` environment variable. When present, [`elicitation-handler.sh`](https://github.com/Chachamaru127/claude-code-harness/blob/main/elicitation-handler.sh) short-circuits immediately with a denial decision, avoiding deadlocks in parallel automation runs.

```bash

# From elicitation-handler.sh lines 123-132

if [[ -n "$HARNESS_BREEZING_SESSION_ID" ]]; then
  echo '{"decision":"deny","reason":"Breezing session: background agent cannot interact with elicitation UI"}'
  exit 0
fi

```

### Desktop Notification System

For interactive sessions, the hook emits a system notification titled **Claude Code: elicitation** (implemented at line 129-130 of [`elicitation-handler.sh`](https://github.com/Chachamaru127/claude-code-harness/blob/main/elicitation-handler.sh)). This alerts the operator precisely when the MCP server requires input, reducing the risk of missed prompts during long-running operations.

### Weak Supervision Cues

The ledger serves as input for [`scripts/build-weak-supervision-cues.sh`](https://github.com/Chachamaru127/claude-code-harness/blob/main/scripts/build-weak-supervision-cues.sh), which reads `.claude/state/elicitation/events.jsonl` to generate "weak-supervision cues." These cues provide automated scoring mechanisms and decision guidance for downstream agents, turning historical user interactions into training signals for future automation.

```bash

# Generate supervision cues from the elicitation ledger

./scripts/build-weak-supervision-cues.sh

# Output: Weak-supervision cues from local elicitation ledger: ...

```

## Core Files and Their Responsibilities

| File | Purpose |
|------|---------|
| [`scripts/hook-handlers/elicitation-handler.sh`](https://github.com/Chachamaru127/claude-code-harness/blob/main/scripts/hook-handlers/elicitation-handler.sh) | Captures incoming prompts, manages UI notifications, and enforces Breezing policies |
| [`scripts/hook-handlers/elicitation-result.sh`](https://github.com/Chachamaru127/claude-code-harness/blob/main/scripts/hook-handlers/elicitation-result.sh) | Logs user responses and returns minimal approval JSON to the MCP server |
| [`go/internal/hookhandler/elicitation_ledger.go`](https://github.com/Chachamaru127/claude-code-harness/blob/main/go/internal/hookhandler/elicitation_ledger.go) | Defines the `ElicitationEvent` struct and handles atomic ledger I/O operations |
| [`hooks/hooks.json`](https://github.com/Chachamaru127/claude-code-harness/blob/main/hooks/hooks.json) | Registers the `elicitation` and `elicitation-result` hook triggers with the harness binary |
| [`scripts/build-weak-supervision-cues.sh`](https://github.com/Chachamaru127/claude-code-harness/blob/main/scripts/build-weak-supervision-cues.sh) | Transforms ledger entries into weak-supervision signals for downstream automation |

## Summary

- The **elicitation hook** provides a two-stage interception system for MCP server prompts, consisting of [`elicitation-handler.sh`](https://github.com/Chachamaru127/claude-code-harness/blob/main/elicitation-handler.sh) for requests and [`elicitation-result.sh`](https://github.com/Chachamaru127/claude-code-harness/blob/main/elicitation-result.sh) for responses.
- It maintains an immutable audit trail in `.claude/state/elicitation/events.jsonl` using the `elicitation-event.v1` schema.
- **Breezing session detection** automatically denies UI requests during background worker execution, preventing automation deadlocks.
- Desktop notifications ensure operators never miss interactive prompts during active sessions.
- The ledger supports downstream **weak-supervision cue generation**, enabling automated systems to learn from historical user interactions.

## Frequently Asked Questions

### What triggers the elicitation hook in Claude Code Harness?

The hook triggers whenever the MCP (Claude Code server) attempts to request structured input from the user. This request flows through the harness binary, which consults [`hooks/hooks.json`](https://github.com/Chachamaru127/claude-code-harness/blob/main/hooks/hooks.json) and executes the appropriate handler based on the hook name—either `elicitation` for new requests or `elicitation-result` for completed responses. Both handlers receive JSON payloads via STDIN and must return valid JSON to STDOUT for the MCP server to continue.

### How does the elicitation hook prevent automation deadlocks?

The hook prevents deadlocks through **Breezing session detection** in [`elicitation-handler.sh`](https://github.com/Chachamaru127/claude-code-harness/blob/main/elicitation-handler.sh). When the environment variable `HARNESS_BREEZING_SESSION_ID` is set—indicating a background worker that cannot display UI—the handler immediately returns a denial JSON without spawning any interactive interface. This ensures parallel automation tasks continue execution rather than hanging indefinitely on user prompts.

### What is the elicitation-event.v1 schema?

The `elicitation-event.v1` schema is a standardized JSON structure defined in [`go/internal/hookhandler/elicitation_ledger.go`](https://github.com/Chachamaru127/claude-code-harness/blob/main/go/internal/hookhandler/elicitation_ledger.go) that records both prompt requests and user responses. Required fields include `schema_version`, `event_kind` (either "elicitation" or "elicitation_result"), `elicitation_id` for correlation, `message` content, and ISO 8601 timestamps. This schema ensures consistent, parseable records across the audit ledger.

### Where are elicitation events stored?

All events are appended to `.claude/state/elicitation/events.jsonl` in the project root. This newline-delimited JSON file serves as the permanent ledger for the elicitation hook system. The Go implementation in [`elicitation_ledger.go`](https://github.com/Chachamaru127/claude-code-harness/blob/main/elicitation_ledger.go) handles atomic writes to this location, while [`scripts/build-weak-supervision-cues.sh`](https://github.com/Chachamaru127/claude-code-harness/blob/main/scripts/build-weak-supervision-cues.sh) reads from it to generate downstream automation signals.