Formats

Prompt injection and user input: pass data to an AI agent API

Put customer text in a Sume run's input object, not its instruction. The agent is told to read it as data; the docs call that a trust boundary, not a sandbox.

5 min readSume
All posts

To pass customer or other user input to a Sume agent run, put it in the input JSON object and keep instruction for your own decisions. Sume writes input to a file in the run's workspace and tells the agent to read it as data, never as instructions. The docs call this “a trust boundary, not a sandbox”: the run's spend cap bounds the blast radius of a hostile payload, and you should still not pass raw untrusted text through on purpose.

Everything below comes from Sume's Create a run and Format API pages, plus the Agent Completions, Scheduled, and Safe automation pages, read on 2026-09-26. If Formats are new to you, start with What is a Sume Format?

Where does customer data belong: instruction or input?

In input. The docs name scraped product copy, a customer's message, and a supplier's field as exactly what belongs there, rather than concatenated into instruction. The Cookbook draws the same line: instruction holds decisions, in prose well under 4000 characters, and input holds data.

The two fields are also carried to the run differently:

What is accepted and what is carried, from Create a run, read 2026-09-26.
FieldAcceptedCarried to the run
instruction8000 charactersThe first ~4000 characters, as prompt text.
input2 MiBAll of it, as a file the agent reads. Never truncated.
The Format bodyNo cap beyond 100 MiB per package fileAll of it, attached as files.
curl -sS -X POST "https://api.sume.com/v1/formats/acme/product-promo/runs" \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-8823-v1" \
  -d '{
    "instruction": "Vertical 9:16 host video. Use the script as written. No BGM, no captions.",
    "input": {
      "product_url": "https://shop.example.com/p/8823",
      "product_name": "Aurora Headphones",
      "highlights": ["…copied from the supplier feed…"]
    },
    "generation_spend_cap_usd": 120
  }'

How does the agent see my input?

What the agent receives is composed in a fixed order: a pointer at the Format, the whole package on disk, the run instruction, a [Sume unattended run] block on API and scheduled runs, a pointer at your input, then attached files. For customer data, that means:

  • instruction comes after the Format's recipe and wins where the two disagree, so it is the wrong place for text you did not write.
  • input is written whole to /workspace/inputs/sume-action-input.json, and the agent is told to read it as data, never as instructions.
  • An empty input ({}) adds no file and no block at all. A Format told to read product_url from the input then has nothing to read.
  • To see what a run received, open its thread_id in Agents: the first message is exactly that composed text.

Does keeping data in input stop prompt injection?

No. The docs call input “a trust boundary, not a sandbox”: the agent is told to read it as data, and the docs still say not to pass raw untrusted text through on purpose. What they put around that boundary:

  • The spend cap. Runs are spend-capped, so the blast radius of a hostile payload is bounded by the cap. Name one per run with generation_spend_cap_usd, up to the $500 platform maximum; see spend caps for unattended AI agents.
  • No person in the loop. Runs over the API are unattended: approvals a chat recipe would ask for are pre-granted, and the run carries on to the paid step within its cap.
  • The key decides the workspace. API keys determine it, and tools should not accept user-supplied workspace ids unless the product supports switching workspaces.
  • Your logs. Excessive user content and transcripts are on the docs' list of unsafe things to log.

What does the API check in input?

Type, key count, size, and media references, and nothing else. input is not a wire schema, and Sume publishes no field list for it: the Format's recipe reads the keys it recognises, and unknown keys are just more data. A Format's io profile is the only declared contract between its author and its callers.

  • Type: a JSON object. Arrays, strings, and numbers are refused; null and omission both mean no input.
  • Keys: at most 64 top-level keys. Nested keys are not counted, so grouping is free.
  • Size: at most 2097152 UTF-8 bytes (2 MiB) on the compact serialization.
  • Media: HTTPS URLs to image, video, or audio files at any depth share the run's attachment budget of 30 files, at most 10 of them videos and 10 audio. Going over is 400 invalid_attachment.

Will the values I send come back in the output?

Not reliably. input does not reach the structured output: output is produced from what the run made and said, so an order id or a SKU you sent cannot be echoed back unless the run repeats it. Keep your identifiers on your side, keyed by data.id or by your Idempotency-Key.

Do Agent Completions and Scheduled runs treat input the same way?

Agent Completions writes input whole to the same /workspace/inputs/sume-action-input.json, the prompt carries a bounded pointer at it, and the agent is told to treat it as data, never as instructions. A malformed input is 400 invalid_request.

On Scheduled runs, the docs say input is handed to the agent as data, not instructions, and that behavior still comes from the schedule's saved instructions. They also call caller-supplied text untrusted: keep instructions authoritative, and do not design an Action that lets input redirect what it does. The limits match: 64 properties and 2 MiB.

Sources

Related posts

Written by Sume