Claude Code Agent State vs Status: Why 'Waiting for Answer' Loses Context After an Hour
The article explains how Claude Code's agent view JSON fields state, status, and waitingFor differ in semantics and lifecycle, revealing that 'blocked' sessions waiting for user responses lose their waitingFor field after about an hour when the supervisor kills the process, unlike permission-prompt waits which keep the process alive.
Busy State Does Not Mean Process Is Busy
The state field in the JSON returned by claude agents --json takes values working, blocked, done, failed, stopped. The documentation defines working as "a turn is running, or the session is between two steps it drives itself," citing examples such as the gap between two /loop iterations or waiting for CI. It immediately adds that whether the process is actually busy must be read from status.
This sentence is itself an interface contract. working covers "the job isn't over and it's not waiting for you," not "something is burning CPU." Using state alone as a heartbeat or to judge "is it stuck" will mislead: a working session may have a completely idle process. status carries observational nature with values busy, waiting, idle, describing the process. But its presence condition is "the process is still alive," which leads to the second pitfall.
Two Kinds of 'Waiting' Are Not the Same
blockedmeans "the session is waiting for you": a question it asked, a permission or sandbox decision, an error only you can clear (e.g., expired login), or it hasn't received its first prompt yet. What it's waiting for is written in waitingFor, with values permission prompt, input needed, sandbox request, worker request, dialog open.
However, the documentation treats the two waits differently. In the supervisor process section, two rules appear side by side:
Sessions that are busy, stuck on a permission prompt or other dialog, or currently attached keep their process running.
Sessions that have finished a turn and are waiting for your next message — if unattached for about an hour — the supervisor stops the process to free resources. "A session that ended its turn with a question counts as waiting for your next message."
Combining these rules with field presence conditions yields an asymmetry: a session blocked on a permission prompt retains its process, and both status and waitingFor remain present. In contrast, a session that asked a question and is now waiting for your answer loses its process after roughly one hour; status and waitingFor disappear together — the record leaves only a lone state: blocked with no clue what it was waiting for.
This is the difference between "waiting for your answer" and "waiting for your approval," yet they share the same state word. If a scheduler uses blocked plus waitingFor to decide "who needs human intervention," a quiet failure appears: the sessions that need your reply are exactly the ones most likely to lose waitingFor.
A polling detail: the docs recommend polling with --all. Without it, output includes live sessions and background sessions that are still busy or blocked (even if the process has exited); completed background sessions only continue to appear with --all.
Those Texts Are Products, Not Logs
Two other text fields often mistaken as factual sources are also not observations.
One is the one-line summary per row in agent view. The docs state it is generated by a Haiku-class model to explain what the session is doing, what it needs, and what it produced without opening the transcript; the model rewrites it at turn end.
The other is done. Its definition: "the previous turn completed what you asked, and the session is ready for your next prompt" — a judgment about whether the intent was satisfied, and the docs explicitly say it is unrelated to process liveness.
A public issue records a case where state itself may drift. The reporter's state file showed state: "working", detail as the verbatim last sentence of the reply ("I'll go through the failures one by one."), tempo: "idle", with zero in-flight tasks and zero queued. Excerpt:
{
"state": "working",
"detail": "I'll go through the failures one by one.",
"tempo": "idle",
"inFlight": {"tasks": 0, "queued": 0}
}It stayed in this state until the next turn corrected it. The reporter reconstructed the turn-end judgment chain from the 2.1.296 distribution files: first run a regex; if it matches, skip the model judgment. One rule takes the last sentence of the reply, checks if it starts with Let me, I'll, Checking, etc., then checks an exclusion list; the exclusion list only matches against the last sentence, so a reply where the condition is in the previous sentence and the promise in the last sentence slips through. Note: this issue was still open at writing with no maintainer reply; the mechanism is the reporter's reproduction and inference, not official explanation.
Putting this together with the docs, the conclusion is not "this field is broken" but "the nature of such fields is judgment." working can mean "turn running," "between two steps," or "judgment on a sentence" — three sources compressed into one word, with no cheap way for the consumer to distinguish.
What To Do Then
The docs actually give a clear path: if you want the session to report progress in its own words, let it write its own file. Every background session has its own job directory, pointed to by the environment variable CLAUDE_JOB_DIR; the docs suggest writing under its tmp subdirectory (the session's own temp dir), not modifying state.json. In other words, the protocol has no "progress for external consumption" field; the channel that can prove progress must be built yourself.
On top of that, several trade-offs follow:
Don't drive irreversible actions with a single state. To let the "busy" signal support decisions like "kill, restart, upgrade a session," you must also watch status and accept that both may be absent.
Treat "waiting for your answer" and "waiting for your approval" as two distinct paths. The former drops waitingFor first, requiring you to copy the question to your side while the session is still alive; the latter keeps the process and the reason.
Don't rely solely on done for machine-judgable "task complete." It is a judgment about intent fulfillment, and the session's process may be long gone.
These points sum to one sentence: this JSON layer provides a readable session view, not a state machine with complete transition guarantees. It suits answering "should I look now?" but not "can this step automatically proceed?" The docs list status bar, scheduler, and supervisory session as supported uses, yet promise no field that won't disappear for any of them. The field's own lifetime is part of the design — you have to read it out first.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Architecture Development Notes
Focused on architecture design, technology trend analysis, and practical development experience sharing.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
