AI Knowledge & Logic

Custom System Prompt Sections

Add your own computed section to the bot's system prompt with Python. Use it for per-conversation context the bot should always have — loyalty tier, cart state, or what the customer picked on your website.

Most of what the bot knows is either static (your business description, tone, rules) or fetched on demand when it decides to call an action. A prompt section is for the third case: context that changes per conversation and that the bot should have before it decides anything.

It is Python you write once per business. It runs on every reply, and whatever it returns is appended to the system prompt as an extra section.


When you need one

You don't need one if:

  • The context is the same for every conversation — put it in the business description or bot rules
  • The bot only occasionally needs the data — a custom action it can call is cheaper

You need one when:

  • The bot should always know something specific to this customer or conversation (their plan, their cart, the page they came from)
  • Waiting for the bot to decide to look something up is already too late
  • You want to steer the whole reply, not answer one question

Writing it

Set it under Settings → Advanced → System Prompt Sections. Define build_prompt_sections(context):

def build_prompt_sections(context):
    topic = context["conversation"]["metadata"].get("chat-widget:help_topic")

    if not topic:
        return None

    return {
        "title": "Selected help topic",
        "content": (
            f'The customer picked "{topic}" on the website before opening the '
            "chat. Treat that as what they are here for."
        ),
    }

It is not a custom action: the model never calls it, so it has no name, no description and no arguments. There is exactly one per business.

Return values:

ReturnResult
A stringAdded as the section body
{"title": ..., "content": ...}One titled block
A list of blocks or stringsSeveral blocks, each under its own #### heading, inside the one section
None or ""Nothing added this turn

Blocks with empty content are dropped. Everything lands under a single ### Custom instructions heading in the prompt.


What it receives

The same context and helpers as any other Python here — see Python Context for the full reference. Two things are worth calling out:

  • context["conversation"]["metadata"] holds conversation metadata, including anything the chat widget attached through custom JavaScript or custom data. Read it from there rather than calling get_conversation_metadata() — no HTTP round-trip.
  • context["customer"] and context["conversation"]["messages"] let you branch on who is asking and what has been said so far.

It fails open, on purpose

This runs inside every reply, so it is never allowed to block one. If your code raises, returns something unusable, or takes longer than a few seconds, the section is dropped and the bot answers without it. Nothing is retried and the customer sees no error.

Two consequences:

  • Keep it fast. Prefer context over network calls. A slow lookup eats the same budget the bot's own reply needs.
  • All your blocks share one failure domain. If you return three blocks and the code raises while building the third, none of them make it. Guard anything risky inside the function so the rest survives.

Repeated failures raise an internal alert, and each build shows up in the response debug data with its size and duration, so you can see whether the section was present for a given reply.

On this page