Skip to main content
This guide teaches you how to write effective objectives and guardrails - the two tools that give your PAL structure and safety during conversations. Objectives are goals your PAL works through in order, like collecting a user’s name or confirming an appointment. Guardrails are safety rules that run in the background the entire time, like “don’t give medical advice.”
Create objectives with the Create Objectives API and guardrails with the Create Guardrail API. For full parameter details, see the Objectives and Guardrails docs.

How the System Works

Behind the scenes, two LLMs work together:
  1. The conversational AI talks to the user. It receives your objective_prompt in its system prompt, along with instructions to guide the user toward completing the objective.
  2. The evaluator watches the conversation in the background. It periodically checks whether each objective has been met and extracts any output variables you defined.
Your objective prompts drive both of these - they shape how the AI steers the conversation and how the evaluator tracks progress. This is why clarity and specificity matter so much.

What the Conversational AI Sees

  • Your objective_prompt (describing what to accomplish)
  • Instructions to actively engage with the user and gather the needed information
  • Progress on variable collection (what’s been collected, what’s still missing)
  • Guardrail prompts (if any)

What the Evaluator Does

For each active objective, the evaluator:
  1. Reads your objective prompt
  2. Analyzes the full conversation history
  3. Extracts the variables you defined (for info collection objectives)
  4. Decides if the objective is complete or incomplete (for condition checks)
  5. Chooses which branch to follow (for conditional objectives)
The evaluator can only see the conversation transcript. It can’t check your database, look up account tiers, or access anything outside the conversation.

Adding Objectives and Guardrails to a PAL

After creating your objectives or guardrails, attach them when creating a PAL:
Or add them to an existing PAL by editing it:

Writing Objectives

An objective has a prompt that describes the goal and, optionally, a list of variables to extract from the conversation. A good objective prompt follows this pattern: describe what information to collect or what condition to check for.

Collecting Information

The most common type of objective. You describe what information you want, and the system pulls it from the conversation.
Tips:
  • Keep the prompt short and specific.
  • Make sure the prompt matches the variables. If you ask for “the user’s name” but list ["first_name", "last_name", "email", "phone"], the system won’t know what to do with the extras.
  • Don’t combine unrelated things. “User’s email and favorite color” should be two separate objectives.

Checking a Condition

Sometimes you just need to verify something happened - no variables needed. Set output_variables to an empty list [].
Tips:
  • Be specific. “User seems happy” won’t work - the system can’t measure feelings. “User has confirmed they are satisfied” is concrete.
  • Only check things that have already happened. “User will receive a confirmation email” can’t be evaluated. “User has acknowledged they will receive a confirmation email” can.

Using the Camera (Visual Objectives)

If your PAL uses a camera or screen share, you can write objectives that check what’s visible. Set "modality": "visual".
Tips:
  • Focus on things that are clearly visible - large text, obvious objects, clear gestures.
  • Don’t expect the system to read tiny text or make expert judgments from a video feed.

Output Variables

Naming

Good variable names are clear and specific:

Break Information into Small Pieces

Split variables into the smallest useful units: Good - each piece is separate:
Bad - everything lumped together:
Smaller pieces are easier to validate, easier to use in your code, and make it possible to handle partial information (e.g., the user gives their city but not their zip code).

Variables Are Always Strings

The system returns all values as strings, even numbers and dates:
If you need separate fields (like year, month, day), use separate variables. Convert or validate the string in your own application code.

What Happens When Information is Missing

If the user doesn’t provide a value, the system returns "NOTFOUND". You don’t need to handle this in your prompt - it happens automatically. Don’t do this:
Do this instead:
Handle what happens with NOTFOUND in your own application code.

Requesting a Specific Format

You can ask for values in a particular format. The system will try to convert, but being explicit helps:

Branching: Making Conversations Dynamic

You can send the conversation down different paths based on what the user says using next_conditional_objectives.
If there’s only one next step (no branching needed), use next_required_objective instead:
Tips for branching:
  • Always include a catch-all branch like "general_questions": "for anything not covered above" so the conversation never gets stuck.
  • Keep conditions simple and non-overlapping. If two branches could both be true, the system won’t know which to pick.
  • Write conditions as positive statements. "if the user is a new patient" is clearer than "if the user is NOT a returning patient".
  • Stick to 2–5 branches. More than that gets unreliable.
  • Conditions must be based on what was said in the conversation - the system can’t look up account info or check a database.

Writing Guardrails

Guardrails are safety checks that run silently in the background for the entire conversation. When one is violated, it triggers a webhook so you can take action. Each guardrail has a prompt describing the violation to watch for:
Guardrails can also be visual - for example, checking the camera feed:
Tips:
  • Keep guardrail prompts short and direct.
  • Describe the specific violation, not a general vibe. “User is being inappropriate” is too broad. “User is using profanity or threatening language” is specific enough to detect.
  • Don’t use guardrails to drive conversation flow - that’s what objectives are for.

When to Use a Guardrail vs. an Objective

Best Practices

Start simple

Begin with straightforward objectives and add complexity as needed. Get a basic flow working first, then add branching, then add guardrails.

One goal per objective

Don’t combine unrelated tasks. “Get user’s email and verify they’re 18+” should be two objectives, not one.

Use descriptive names

Objective names should explain what they do at a glance. get_shipping_address and verify_insurance_coverage are good. step1 and check_thing are not.

Think about how people actually talk

Write prompts based on how users naturally express things: Good:
Bad:

Plan for different phrasings

The LLM is good at understanding variations. A prompt like "Get the user's preferred contact method (email, phone, or text message)" will correctly handle “email me,” “I prefer phone calls,” “text is best,” and “reach out via email.”

The system remembers the whole conversation

The evaluator sees all messages, not just the latest one. So an objective like "User has confirmed that the address previously provided is correct" will work - the system will look back to find the address.

Keep system prompts short

If your system prompt is over ~500 words, objective evaluations become less reliable. Keep the system prompt focused on PAL and tone. Put the detailed workflow logic in your objectives.

Use manual confirmation for important decisions

For critical actions like authorizing a payment, set "confirmation_mode": "manual" so the system waits for explicit confirmation instead of deciding on its own.

Common Mistakes

Writing behavioral instructions instead of goals

The prompt should describe what to accomplish, not how to behave while doing it.

Checking things that haven’t happened yet

The system can only look at the conversation so far - not the future.

Relying on data outside the conversation

The system can only read the transcript. It can’t check your database.

Cramming too much into one objective

If you need a lot of info, break it into smaller objectives. Users don’t provide 15 fields in one message.

Being vague

The more specific your prompt, the more consistent the results.

Prompt doesn’t match the variables

If your prompt says “Get the user’s name” but output_variables lists ["first_name", "last_name", "email", "phone"], the system won’t know what to do with the extras. Don’t make separate objectives for first name, last name, and email. Group related fields together - users often provide them all at once.

Using negative conditions for branching

"if condition A is true" is clearer than "if NOT condition B and NOT condition C". Positive conditions are less error-prone.

Overloading the system prompt

A 2,000-word system prompt that covers every scenario dilutes the objective evaluations. Keep the system prompt lean and put workflow logic in the objectives.

Testing Your Prompts

Before launch

  1. Try it yourself. Have a conversation with your PAL and check whether the right values get extracted.
  2. Test edge cases. What happens if the user gives partial info? Changes their answer? Gives everything in one long sentence? Refuses to answer?

After launch

  1. Track NOTFOUND rates for each variable. High rates mean your prompt may be unclear or asking for something users don’t naturally provide.
  2. Identify stuck objectives - objectives that never complete may have prompts that are too strict.
  3. Monitor correction rates. If the system frequently extracts wrong values, the prompt needs to be more specific.
  4. Review guardrail webhooks. Lots of false positives means the guardrail prompt is too broad.

A/B testing

Try different prompt wordings and measure completion rates. For example:
  • Version A: "Get the user's email address"
  • Version B: "Extract the user's email address if they provide one"
Measure which has fewer NOTFOUND results and faster completion.

Example: Healthcare Intake

A complete patient intake workflow with objectives and guardrails:
Guardrails for this PAL:

Example: Customer Support Triage

A support workflow that routes customers to the right path:
Guardrails for this PAL:

Example: Visual Identity Verification

A workflow that uses the camera to verify a user’s identity:
Guardrails for this PAL:

Example: Restaurant Reservation

A simple reservation flow with dietary restriction branching:
Guardrails for this PAL: