outputFormat controls two things: the instruction appended to the system prompt (what you're asking the model to produce), and the exact key(s) the step's result is returned under — which is what downstream steps reference with {{yourStep....}}. Every format also always includes tokensUsed and a usage object (inputTokens, outputTokens, totalTokens, model, provider, protocol, finishReason, and truncated — a boolean, true when the response was cut off by maxTokens, worth checking if output looks incomplete).

Shape per format

  • text{ response: string } — reference as {{step.response}}.
  • jsonflat, spread directly — { ...yourDeclaredFields }, no response wrapper. If you declared fields sender_name and topic, reference {{step.sender_name}} directly, not {{step.response.sender_name}}. If the model's output fails to parse as JSON, you get { _raw: "<the raw text>" } instead — check for _raw if you need to handle malformed output gracefully.
  • score{ score: number } (0-100, clamped).
  • category{ category: string } — matched against your declared categories by case-insensitive substring, not exact match; falls back to the raw trimmed text if nothing matches.
  • boolean{ decision: boolean } — true only for a response starting with "yes"/"true"/"1" (case-insensitive).
  • list{ items: string[] } — reference the whole thing as {{step}} (which resolves to the {items:[...]} object) or {{step.items}} directly.
  • image{ url: string } (no tokensUsed for the completion itself, since it's a direct DALL-E call, not a chat completion).
  • audio{ url: string } (an MP3 URL — the text is generated normally, then spoken via TTS).

json is flat — this trips people up

Every other format nests its result under one named key (response/score/category/decision/items). json is the one exception — your declared fields are spread directly onto the result object. Don't reference {{step.response.fieldName}} for a json-format step; it's {{step.fieldName}}.

Using a list output as a Loop source

An ai_call step with outputFormat: list produces exactly the same {items:[...]} shape as list_entities and a collection variable — so it works as a Loop step's source the same way. In the builder, add your ai_call step, set its Output format to List, then in a following Loop step's "Collection to iterate" field, select that ai_call step directly.

text
s1: ai_call   intent=generate  outputFormat=list
              contextFields=[{ label: topic, value: {{input.topic}} }]
              instructions="Generate 5 short blog post title ideas."
s2: loop      source={{s1}}  itemAs=title
      s2a: create_entity  entity=draft_post  fields=[{ title: {{title}} }, { status: draft }]