---
title: Summary templates
description: The Liquid template language behind the summaries Prefactor renders
  for span types and quality schemas — available data, control flow, filters,
  and failure behaviour.
editUrl: true
head: []
template: doc
sidebar:
  hidden: false
  attrs: {}
pagefind: true
draft: false
---

Any schema in an agent's [activity schema](/platform/concepts/activity-schema) can carry a template that renders a one-line summary of the data that schema describes. Span types use it for the summary on each span card in the [Activity tab](/admin-ui/agent-instance/activity); quality schemas use it for the summary on the instance [Quality tab](/admin-ui/agent-instance/quality). Templates are written in [Liquid](https://shopify.github.io/liquid/) and rendered server-side by Prefactor each time the summary is displayed. Nothing renders in your SDK or in the browser, so the same template produces the same summary everywhere it appears.

## Declaring a template

Templates are declared on the schema entry, not inside the JSON schema itself. Each span type in the agent schema carries a `template` field alongside its `params_schema` and `result_schema`; each quality schema carries one alongside its `schema`:

```json
{
  "name": "web_search",
  "params_schema": {
    "type": "object",
    "properties": { "query": { "type": "string" } }
  },
  "template": "Searched for {{query}} — {{results.size}} results"
}
```

A span type's template can reference both params and result fields; a quality schema's template references the fields of the recorded payload. The SDKs expose the same field — TypeScript as `template` on a span type or quality schema entry, Python as the `template` argument to `register_type` and `register_quality_schema`. Templates need this structured form: the flat `span_schemas` map of names to JSON schemas has no place for one. See [Schemas and result schemas](/sdks/concepts-schemas) and [Quality evaluations](/sdks/quality-evaluations) for the full declaration flow.

## Available data

What the template can see depends on the schema kind.

**Span types** render with the span's params and result fields merged into one flat namespace. When the same name exists in both, the result field wins. Given params:

```json
{ "query": "refund policy", "limit": 5 }
```

and result:

```json
{ "results": ["a", "b", "c"], "limit": 3 }
```

the template `Searched for "{{query}}" — returned {{results.size}} of {{limit}} requested` renders as `Searched for "refund policy" — returned 3 of 3 requested`, because the result's `limit` shadows the params' `limit`.

**Quality schemas** render with the recorded quality payload as the data — the same fields the quality schema declares, as in `Scored {{overall_score}}/100 ({{verdict}})`.

## Control flow

Templates support Liquid's standard control-flow tags:

- `{% if %}` with `{% elsif %}` and `{% else %}`, closed by `{% endif %}`
- `{% unless %}` ... `{% endunless %}`
- `{% case %}` with `{% when %}` and `{% else %}`, closed by `{% endcase %}`
- `{% for %}` ... `{% endfor %}`, with `limit:`, `offset:`, and `reversed` parameters

```
{% if verdict == "pass" %}Passed{% else %}Failed — {{notes}}{% endif %}
```

```
{% for item in results limit:3 reversed %}{{item}} {% endfor %}
```

The [Liquid documentation](https://shopify.github.io/liquid/) covers the full tag syntax.

## Filters

The standard Liquid filters are available — `default`, `upcase`, `downcase`, `capitalize`, `append`, `prepend`, `replace`, `join`, `split`, `map`, `first`, `last`, `date`, `plus`, `minus`, `round`, and the rest:

```
{{notes | default: "No notes recorded"}}
```

`default` earns its keep here: because unknown variables render as empty (see [Failure behaviour](#failure-behaviour)), it is the usual way to show something meaningful when a field is absent.

## Property access

- A field name on its own reads that field from the merged data: `{{query}}`.
- Dot access walks into nested objects, as deep as the data goes: `{{customer.email}}`.
- A field whose name itself contains a dot needs bracket notation with the quoted name — `{{["ai.model"]}}` at the top level, or `{{request["ai.model"]}}` inside a nested object. Writing `{{ai.model}}` looks for a `model` field inside `ai` and renders empty. The bracket form works anywhere a field is referenced, including conditions.
- Lists support `.first`, `.last`, `.size`, and integer indexes: `{{items[0]}}`.
- Dots and indexes chain together: `{{items[0].title}}`.
- Strings support `.size`, giving the length in characters.
- Objects support `.size`, giving the number of keys.

A missing key or an out-of-range index renders as empty rather than raising an error.

## Failure behaviour

| Situation | What renders |
| --- | --- |
| Unknown variable or missing field | Nothing — the reference renders as empty text. |
| Template does not parse | No summary is shown at all. |
| Error while rendering | The summary shows `Summary render failed: <message>`. |

Rendering never fails the request that asked for the summary — the worst case is the fallback message in place of the summary text.

## Redacted values

When a payload carries [sensitive](/platform/sensitive-data) values, a redacted field renders in templates as its redaction placeholder: `🔒` followed by the data-category labels, for example `🔒 personal_identifiers, contact_information`. A discarded value renders as `🔒 <labels> - discarded`.

Conditions on a redacted field therefore test the placeholder, not the original value. The placeholder is a non-empty string, so `{% if email %}` is true for a redacted email and `{{email}}` prints the placeholder. When a viewer reveals sensitive values in the web app, the summary re-renders with the real values; API callers get the same choice through the `redacted` parameter on span queries.

## Related

- [Activity schema](/platform/concepts/activity-schema) — where span types and quality schemas are declared.
- [Schemas and result schemas](/sdks/concepts-schemas) — declaring schemas from the SDKs.
- [Quality evaluations](/sdks/quality-evaluations) — quality schemas and their templates, end to end.
- [Sensitive data](/platform/sensitive-data) — how marked values are stored, redacted, and discarded.
- [Liquid template language](https://shopify.github.io/liquid/) — the full syntax reference.