`/fire` API `text` payload is enqueued as a user message but never dequeued by the routine — silent payload loss
Summary
When invoking a Claude Code cloud routine via the /fire API endpoint with body {"text": "..."}, the text value is enqueued as a second user message in the session's transcript queue, but the routine runs only the saved prompt (Turn 1) and then terminates without dequeuing the queued message. As a result the text payload is effectively invisible to the saved prompt unless the prompt explicitly reads the queue file from disk. The documented behavior is that text is "passed to the routine alongside its saved prompt," which readers reasonably interpret as "visible in-context during Turn 1" — but it isn't.
Environment
CLAUDE_CODE_VERSION: 2.1.42CLAUDE_CODE_ENTRYPOINT:remote_triggerCLAUDE_CODE_USE_CCR_V2:trueCLAUDE_CODE_REMOTE_ENVIRONMENT_TYPE:cloud_default- Beta header:
anthropic-beta: experimental-cc-routine-2026-04-01
Reproduction
- Create a routine via the web UI or API.
- Attach an API trigger; generate and save the per-routine bearer token.
- Write the saved prompt so it instructs Claude to print or act on whatever the caller sends as
text. - From any HTTP client, \
POST /v1/claude_code/routines/{id}/fire\with body \{"text": "hello-from-caller-42"}\and the required headers. - Open the resulting session. The saved prompt runs, but \
hello-from-caller-42\does not appear anywhere in Claude's in-context prompt; and no Turn 2 is processed even if the prompt explicitly waits for it.
Observed behavior
- The request returns 200 with a session URL.
- In the sandbox, the transcript JSONL at
/root/.claude/projects/-home-user/<sessionId>.jsonlcontains two"type":"queue-operation"entries: the saved prompt is enqueued + dequeued, and the caller'stextis enqueued shortly after (observed ~13 ms later, but up to ~2 s later in some runs) — but is never dequeued. - The session ends after Claude's response to Turn 1.
- Any saved prompt that tries to "search for the caller's text in visible context" finds nothing. Any saved prompt that says "wait for the next user message" stalls and the routine terminates with no further turns.
Expected behavior
One of:
- The routine auto-dequeues and processes the
textpayload as a second turn before the session ends, or - The
textis concatenated/appended to the saved prompt so it's visible during Turn 1, or - The docs at https://code.claude.com/docs/en/routines describe the actual delivery location (the queue JSONL file path) so callers can write saved prompts that read it directly.
Workaround
Saved prompt reads the queue file directly with a short polling loop:
\\\bash\
QUEUE_DIR=/root/.claude/projects/-home-user
for i in \$(seq 1 30); do
PAYLOAD=\$(grep -h '"operation":"enqueue"' "\$QUEUE_DIR"/*.jsonl 2>/dev/null \\
| python3 -c "import sys,json,re
for line in sys.stdin:
try:
c = json.loads(line).get('content','')
if re.search(r'github\\.com/[^/]+/[^/]+/pull/\\d+', c):
print(c); break
except Exception: pass")
[ -n "\$PAYLOAD" ] && break
sleep 0.5
done
\\
This works, but relies on an undocumented path and an internal JSONL schema — both of which are implementation details that could break at any time.
Impact
Any routine that needs dynamic per-invocation input (PR URL, alert body, deploy SHA, customer ID, etc.) is affected. The doc copy ("passed alongside its saved prompt") guides users toward saved prompts that assume the payload is in context; those routines silently do the wrong thing on every invocation until someone debugs the sandbox. The failure is quiet: the HTTP call returns 200, the session spawns, Claude produces a plausible-looking response, and the caller has no way to tell that their payload never reached the model.
Suggested fixes (any one would close this)
- Dequeue and process the
textmessage as Turn 2 before ending the session. - Append
textto the saved prompt content on the server side (e.g., as a delimited \## Caller input\section) before Turn 1 runs. - Update the docs to describe the actual delivery mechanism so callers can write correct saved prompts.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗