Claude Code routine API text is untrusted: pass Sume input as data

A routine's fire text arrives wrapped as untrusted data, and the saved prompt must opt in to use it. Sume's run input follows the same rule: data only.

5 min readSume
All posts

When you fire a Claude Code routine over its API, the text field reaches the session wrapped in a <routine-fire-payload> block that labels it as untrusted. So the saved prompt has to point at the payload explicitly, and anything you hand on to Sume should travel the same way: Sume Agent Completions and Format runs take caller data in input, which is written to a file and treated as data, never as instructions.

The wrapper is documented on Anthropic's routines page, read on 2026-10-03; Sume's side is in Agent Completions and Calling a Format.

What does the routine do with the fire text?

The text is freeform and not parsed: send JSON and the routine receives a literal string. Anyone holding the bearer token can send text, so the wrapper makes fire text from a leaked token arrive labeled as untrusted rather than as direct instructions. The consequence is practical. A prompt that says only "handle the alert" treats the payload as inert context. A prompt that says "investigate the alert described in the routine-fire-payload block" opts in.

The same page says the /fire endpoint ships under the experimental-cc-routine-2026-04-01 beta header and that request shapes and limits may change during the research preview.

How does Sume treat the same kind of data?

An Agent Completion takes the task as instruction or messages, and caller data as input, which is written whole to /workspace/inputs/sume-action-input.json while the prompt carries only a bounded pointer to it. Docs describe it as data, never instructions. A Format run follows the same split: input is a JSON object of at most 64 top-level keys and 2 MiB, and instruction is capped at 8000 characters with only the first part used as prompt text.

Keep the line in one place. Put what the agent should do in the instruction you wrote, and put what the alert said in input.

Where untrusted text should go (read 2026-10-03)
SurfaceInstructions live inUntrusted text goes in
Claude Code routineSaved routine prompttext, read through the payload block
Sume Agent Completioninstruction or messagesinput
Sume Format runFormat plus instructioninput

What does the hand-off look like?

This script takes an alert as a string, builds the fire body for the routine and the matching Sume body, and keeps the alert out of the instruction. It runs offline.

import json
alert_text = '{"id": "SEN-4521", "service": "checkout", "error": "timeout"}'
alert = json.loads(alert_text)
fire_body = {'text': alert_text}
completion_body = {
    'instruction': 'Summarize the alert in the input file in two sentences.',
    'input': alert,
    'generation_spend_cap_usd': 1,
}
assert 'SEN-4521' not in completion_body['instruction']
print(json.dumps(fire_body))
print(json.dumps(completion_body))

What does this not protect against?

Wrapping lowers the odds that injected text steers a run; it does not remove them. Give the routine the narrowest connectors and a spend cap on every Sume call, so a successful injection has little to spend or change.

Sources

Related posts

More in Agents

All Agents posts

Written by Sume