Skip to main content

Conditional Templates

An agent's instructions are not a static string. They're a Handlebars template rendered fresh each turn. That means the prompt can react to what's happening right now: which page the user is on, whether a value is set, or what the last tool returned.

Conditionals in instructions​

Wrap prompt sections in {{#if}} so they appear only when they're relevant:

# ROLE
You help users manage their subscription.

{{#if on_billing_page}}
The user is on the billing page. Prefer actions they can see: {{available_actions}}.
{{/if}}

{{#unless account_verified}}
The account is unverified. Ask them to verify before making changes.
{{/unless}}

This keeps the base prompt lean and surfaces guidance exactly when it applies, rather than listing every case every turn.

Feeding in runtime state​

The variables come from your app via the Chat component's getMetadata. The dynamic_sections you return become template variables:

<Chat
agent={agent}
threadId="sub"
getMetadata={async () => ({
dynamic_sections: {
on_billing_page: location.pathname === '/billing',
account_verified: user.verified,
available_actions: 'upgrade, downgrade, cancel',
},
})}
/>

So the same agent definition renders differently depending on where the user is and what state your app is in. No separate agents per case.

Common built-in placeholders like {{task}} (the user's message) and {{{available_tools}}} are always available; see Agent Definition → Handlebars Templates for the full list.

Conditionals in workflows​

The same idea applies to workflows: a step's skip_if expression decides whether the step runs, interpolating {input.x}, {steps.step_id.x}, and {env.x}:

{ "id": "notify", "label": "Notify reviewer",
"kind": { "type": "reply", "message": "Ready for review" },
"skip_if": "{input.auto_publish}" }