Skip to content

Added the ability to escape Jinja variables in recipes to include them in prompts#6975

Merged
jh-block merged 1 commit intoblock:mainfrom
peterwilli:fix/jinja-recipe-escape
Feb 5, 2026
Merged

Added the ability to escape Jinja variables in recipes to include them in prompts#6975
jh-block merged 1 commit intoblock:mainfrom
peterwilli:fix/jinja-recipe-escape

Conversation

@peterwilli
Copy link
Contributor

@peterwilli peterwilli commented Feb 5, 2026

Summary

Currently, it is impossible to escape variables in recipes. This makes it impossible to create recipes that create other recipes (recipeception anyone?)

Why is this important?

Well, I have this recipe (note: I escaped the triple backticks otherwise github messes up the formatting):

id: recipe-creator
version: 1.0.0
title: "Recipe Creator"
description: "Specialized subagent for creating new Goose recipes"
instructions: |
  You are a recipe creation assistant. Your job is to help users create new Goose recipes in the proper YAML format.

  **Important**: The prompt template uses simple parameter substitution only (e.g., `{{'{{param_key}}'}}`). 
  You **cannot** use Jinja2, conditionals, loops, or filters. Only straight parameter replacement works.

  **Important**: When defining parameters, all optional variables **must** have default values. This ensures the recipe works even when optional parameters are not provided.

  When creating a recipe, you should:
  1. Ask clarifying questions to understand the recipe's purpose
  2. Determine the appropriate name, id, and description
  3. Identify required vs optional parameters
  4. **Ensure all optional parameters have default values** - this is required!
  5. Write clear instructions for what the subagent should do
  6. Use parameters in the prompt template with `{{'{{parameter_key}}'}}` syntax

  Default extensions available:
  - `developer`: file editing, shell commands, code analysis
  - `todo`: task management
  - `subagent`: delegation to other agents
  - `apps`: create HTML/CSS/JS applications

  **Always output the example format** at the end of your response so the user sees exactly what the recipe looks like.

activities:
  - Create new recipe definitions
  - Define appropriate parameters
  - Write clear instructions and prompts
  - Suggest suitable extensions
  - Save recipe to specified location
extensions:
  - type: builtin
    name: developer
    display_name: Developer
    timeout: 300
    bundled: true
  - type: builtin
    name: text_editor
    display_name: Text Editor
    timeout: 300
    bundled: true
parameters:
  - key: output_path
    input_type: string
    requirement: required
    description: "Path to save the recipe file (project-level: ./recipes/, global: ~/.config/goose/recipes/)"
  - key: recipe_name
    input_type: string
    requirement: optional
    default: "my-recipe"
    description: "Name/ID for the new recipe"
  - key: purpose
    input_type: string
    requirement: optional
    default: "task automation"
    description: "What this recipe should accomplish"
  - key: extensions
    input_type: string
    requirement: optional
    description: "Comma-separated list of extensions needed (developer, todo, apps, etc.)"
    default: "developer"

prompt: |
  Create a new Goose recipe based on the following:

  Recipe Name: {{recipe_name}}
  Purpose: {{purpose}}
  Required Extensions: {{extensions}}
  Output Path: {{output_path}}

  Use this exact format (keep all keys, adapt values as needed):

  ``yaml
  id: {{recipe_name}}
  version: 1.0.0
  title: "Human-Readable Title"
  description: "Clear description of what this recipe does"
  instructions: |
    You are a specialized subagent for [purpose].

    Your responsibilities include:
    - [Task 1]
    - [Task 2]
    - [Task 3]

    Guidelines:
    - [Guideline 1]
    - [Guideline 2]

  activities:
    - [Activity 1]
    - [Activity 2]
  extensions:
    - type: builtin
      name: developer
      display_name: Developer
      timeout: 300
      bundled: true
  parameters:
    - key: param_name
      input_type: string
      requirement: optional
      description: "Parameter description"
  prompt: |
    [Your prompt template here using {{'{{param_name}}'}} for parameter substitution]
  ``

  Save the recipe to: {{output_path}}

  **After saving the recipe, validate it by running:**
  ``
  goose recipe validate {{output_path}}
  ``
  If validation fails, fix any errors and save again until validation passes.

Without this PR, it is impossible to use this. So this opens the door to much much more use-cases for recipes! I made sure it follows original escaping behaviour of Jinja, see: https://tedboy.github.io/jinja2/templ7.html

Type of Change

  • Feature
  • Bug fix
  • Refactor / Code quality
  • Performance improvement
  • Documentation
  • Tests
  • Security fix
  • Build / Release
  • Other (specify below)

AI Assistance

  • This PR was created or reviewed with AI assistance

Testing

Related Issues

Relates to #ISSUE_ID
Discussion: LINK (if any)

Screenshots/Demos (for UX changes)

(see example recipe)

…m in prompts

Signed-off-by: Peter Willemsen <peter@codebuffet.co>
Copy link
Collaborator

@jh-block jh-block left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@jh-block jh-block added this pull request to the merge queue Feb 5, 2026
Merged via the queue into block:main with commit e701350 Feb 5, 2026
17 checks passed
tlongwell-block added a commit that referenced this pull request Feb 5, 2026
* origin/main:
  fix: detect context length errors in GCP Vertex AI provider (#6976)
  Added the ability to escape Jinja variables in recipes to include them in prompts (#6975)
  Bug Fix: bump pctx (#6967)
  fix(acp): fixtures now raise content mismatch errors (#6912)
  custom provider form minor improvements (#6966)
  Fix 'Edit In Place' feature appending instead of editing messages (#6955)
  docs: change RPI slash commands (#6963)
kuccello pushed a commit to kuccello/goose that referenced this pull request Feb 7, 2026
…m in prompts (block#6975)

Signed-off-by: Peter Willemsen <peter@codebuffet.co>
Tyler-Hardin pushed a commit to Tyler-Hardin/goose that referenced this pull request Feb 11, 2026
…m in prompts (block#6975)

Signed-off-by: Peter Willemsen <peter@codebuffet.co>
Tyler-Hardin pushed a commit to Tyler-Hardin/goose that referenced this pull request Feb 11, 2026
…m in prompts (block#6975)

Signed-off-by: Peter Willemsen <peter@codebuffet.co>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants