> ## Documentation Index
> Fetch the complete documentation index at: https://docs.freeplay.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Prompt Bundling

> Bundle prompt templates into your deployment artifacts for increased resilience and release control.

Prompt Bundling enables you to fetch prompt templates once from the Freeplay server during your build process and then store them directly in the filesystem of your deployed artifact. You can then configure the Freeplay client to call prompt templates and model configuration directly from your code, rather than the Freeplay server.

## Advantages of Prompt Bundling

* Release Management Controls

  * This approach to deployment provides full control over what's running in production, since all prompt & model iterations managed in Freeplay get treated like any other part of your code.
  * Facilitates compliance obligations for peer review, use of established version control systems like GitHub, etc. A detailed guide on using prompt bundling with GitHub Actions is [here](/security-compliance/production-prompt-bundling-compliance-guard-rails).

* Increased Production Resilience

  * By decoupling the fetching of prompt templates from Freeplay, you ensure your application can keep serving requests if Freeplay is unavailable.
  * Unintended prompt changes cannot hurt production because prompts are only refreshed during your application build process.

* Reduced Latency
  * By reading the prompt template from your application filesystem instead of fetching it from Freeplay on each request, you can slightly reduce latency overhead.

## Disadvantages of Prompt Bundling

* Increased Cycle Time from Experimentation to Production

  * Requiring a build process to get new prompts into production, increasing cycle time between prompt updates and the deployment of those updates into production.

<Tip>
  Many Freeplay customers use a hybrid approach: server-side prompt management in lower environments (dev/staging) for rapid iteration, and prompt bundling in production for release control. See [Multi-Environment Configuration](#multi-environment-configuration) below.
</Tip>

## Implementation

Downloading of prompts is handled by the Freeplay Python SDK

### Install the Python SDK

Python will be used to download the prompts for all SDKs

<CodeGroup>
  ```bash theme={null}
  pip install freeplay
  ```
</CodeGroup>

### Download the Prompt Templates

<CodeGroup>
  ```bash theme={null}
  Usage: freeplay download [OPTIONS]

  Options:
  --project-id TEXT The Freeplay project ID. [required]
  --environment TEXT The environment from which the prompts will be pulled.
  [required]
  --output-dir TEXT The directory where the prompts will be saved.
  [required]
  --help Show this message and exit.

  ```
</CodeGroup>

<CodeGroup>
  ```bash theme={null}
  # Set necessary environment variables
  export FREEPLAY_API_KEY=$FREEPLAY_API_KEY
  export FREEPLAY_SUBDOMAIN=$FREEPLAY_SUBDOMAIN
  export FREEPLAY_PROJECT_ID=$FREEPLAY_PROJECT_ID

  # Run the command with your project and environment settings, specifying where you want the prompts to be placed.
  freeplay download --project-id=<your-project-id> --output-dir=my_freeplay_prompts --environment=prod
  ```
</CodeGroup>

### Download all Prompt Templates

To download all prompt templates in your account, you can use the `download-all` option for the API. This will download all prompts and store them by project id. For private projects, prompts will only be downloaded if the user has access to that project.

<CodeGroup>
  ```bash theme={null}
  # Set necessary environment variables
  export FREEPLAY_API_KEY=$FREEPLAY_API_KEY
  export FREEPLAY_SUBDOMAIN=$FREEPLAY_SUBDOMAIN

  # Run the command with your project and environment settings, specifying where you want the prompts to be placed.

  freeplay download-all --output-dir=my_freeplay_prompts --environment=prod

  ```
</CodeGroup>

### Point your Freeplay Client at your Prompt Directory

<CodeGroup>
  ```python python theme={null}
  from freeplay import Freeplay
  from freeplay.resources.prompts import FilesystemTemplateResolver
  from pathlib import Path

  # create a freeplay client link to local filesystem
  fpClientLocal = Freeplay(
      freeplay_api_key=freeplay_key,
      api_base=freeplay_api_base,
      template_resolver=FilesystemTemplateResolver(Path(freeplay_template_path))
  )
  ```

  ```typescript typescript theme={null}
  import Freeplay, { FilesystemTemplateResolver } from "freeplay";

  const fpClient = new Freeplay({
    freeplayApiKey: process.env["FREEPLAY_API_KEY"],
    baseUrl: process.env["FREEPLAY_URL"],
    templateResolver: new FilesystemTemplateResolver(templatePath),
  });
  ```

  ```java java theme={null}
  // create the client
  Path templateDir = Paths.get(outputDirectory);
  Freeplay localClient = new Freeplay(Config()
          .freeplayAPIKey(freeplayApiKey)
          .customerDomain(freeplaySubdomain)
          .templateResolver(new FilesystemTemplateResolver(templateDir))
          .providerConfigs(new ProviderConfigs(new AnthropicProviderConfig(anthropicApiKey)))
  );
  ```
</CodeGroup>

## Multi-Environment Configuration

A common pattern is to use different Freeplay client configurations for different environments. This approach gives you the best of both worlds:

* **Dev/Staging**: Fetch prompts from the Freeplay server for rapid iteration and experimentation
* **Production**: Use prompt bundling for resilience and release control

<CodeGroup>
  ```python python theme={null}
  from freeplay import Freeplay
  from freeplay.resources.prompts import FilesystemTemplateResolver
  from pathlib import Path
  import os

  def create_freeplay_client():
      """Create a Freeplay client configured for the current environment."""
      
      base_config = {
          "freeplay_api_key": os.environ["FREEPLAY_API_KEY"],
          "api_base": os.environ["FREEPLAY_URL"],
      }
      
      if os.environ.get("ENVIRONMENT") == "production":
          # Production: Use bundled prompts from filesystem
          return Freeplay(
              **base_config,
              template_resolver=FilesystemTemplateResolver(
                  Path(os.environ["FREEPLAY_TEMPLATE_PATH"])
              )
          )
      else:
          # Dev/Staging: Fetch prompts from Freeplay server
          return Freeplay(**base_config)

  fp_client = create_freeplay_client()
  ```

  ```typescript typescript theme={null}
  import Freeplay, { FilesystemTemplateResolver } from "freeplay";

  function createFreeplayClient(): Freeplay {
    const baseConfig = {
      freeplayApiKey: process.env.FREEPLAY_API_KEY!,
      baseUrl: process.env.FREEPLAY_URL!,
    };

    if (process.env.ENVIRONMENT === "production") {
      // Production: Use bundled prompts from filesystem
      return new Freeplay({
        ...baseConfig,
        templateResolver: new FilesystemTemplateResolver(
          process.env.FREEPLAY_TEMPLATE_PATH!
        ),
      });
    } else {
      // Dev/Staging: Fetch prompts from Freeplay server
      return new Freeplay(baseConfig);
    }
  }

  const fpClient = createFreeplayClient();
  ```

  ```java java theme={null}
  import ai.freeplay.client.thin.Freeplay;
  import ai.freeplay.client.thin.Config;
  import ai.freeplay.client.thin.resources.prompts.FilesystemTemplateResolver;
  import java.nio.file.Paths;

  public class FreeplayClientFactory {
      public static Freeplay create() {
          Config config = new Config()
              .freeplayAPIKey(System.getenv("FREEPLAY_API_KEY"))
              .customerDomain(System.getenv("FREEPLAY_SUBDOMAIN"));
          
          if ("production".equals(System.getenv("ENVIRONMENT"))) {
              // Production: Use bundled prompts from filesystem
              config.templateResolver(new FilesystemTemplateResolver(
                  Paths.get(System.getenv("FREEPLAY_TEMPLATE_PATH"))
              ));
          }
          // Dev/Staging: Uses default server-side resolution
          
          return new Freeplay(config);
      }
  }
  ```
</CodeGroup>

This pattern allows your team to iterate quickly on prompts in lower environments while maintaining strict control over what's deployed to production.

***

## What's Next

Learn how to use Mustache syntax for advanced prompt templating or move onto the next section on Evaluations.

* [Advanced Prompt Templating Using Mustache](/core-concepts/prompt-management/advanced-prompt-templating-using-mustache)
* [Evaluations](/core-concepts/evaluations/evaluations)
