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}" }