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

# Create prompts

> Define a prompt's model, parameters, messages, and response format in the Braintrust UI, or define it in code and push with the bt CLI.

Create prompts directly in the Braintrust UI or define them in code and push them with the SDK. Once created, extend prompts with tools and MCP servers, test them in playgrounds, and improve them with Loop.

## Create a prompt

You can create a prompt in the UI or define it in code. Use the UI for quick, visual iteration, and use the SDK to version prompts alongside your application code and push them from your existing workflow.

<Tabs className="tabs-border">
  <Tab title="UI" icon="mouse-pointer-2">
    Create prompts directly in the Braintrust UI:

    1. Go to [**<Icon icon="message-circle" /> Prompts**](https://www.braintrust.dev/app/~/prompts) and click **+ Prompt**.

    2. Configure the prompt:
       * **Name**: Descriptive display name
       * **Slug**: Unique identifier for code references (remains constant across updates)
       * **Model and parameters**: Model selection, temperature, max tokens, etc.
       * **Messages**: System, user, assistant, or tool messages with text or images
       * **Templating syntax**: Mustache or Nunjucks for variable substitution
       * **Response format**: Freeform text, JSON object, or structured JSON schema
       * **Description**: Optional context about the prompt's purpose
       * **Tags**: Optional labels for organizing and filtering prompts
       * **Metadata**: Optional additional information

    3. Click **Save as custom prompt**.

    <Accordion title="Prompt caching for Anthropic and Bedrock models">
      When using Anthropic or AWS Bedrock (Converse API) models, a cache control button appears on each message for [Anthropic prompt caching](https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching). Click it to set a TTL of 5 minutes or 1 hour. When a message has multiple content blocks, you can set cache control on each block individually. Cache control settings are preserved when switching between Anthropic models and cleared when switching to a different provider.
    </Accordion>

    <Accordion title="Parameters for reasoning models">
      For reasoning models, the available parameters depend on the selected reasoning effort. GPT-5.1 and later expose a `temperature` setting only when **Reasoning effort** is `none`. Raising the reasoning effort removes the `temperature` setting. Older GPT-5 models (`gpt-5`, `gpt-5-mini`, `gpt-5-nano`) and GPT-5 Pro don't accept `temperature` at any reasoning effort.
    </Accordion>
  </Tab>

  <Tab title="SDK" icon="code">
    Define prompts in code, then push them to Braintrust with the [`bt` CLI](/docs/reference/cli/quickstart):

    <Steps>
      <Step title="Define the prompt in code">
        <CodeGroup dropdown>
          ```typescript title="summarizer.ts" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
          import * as braintrust from "braintrust";

          const project = braintrust.projects.create({
            name: "Summarizer",
          });

          export const summarizer = project.prompts.create({
            name: "Summarizer",
            slug: "summarizer",
            description: "Summarize text",
            tags: ["summarization"],
            model: "claude-sonnet-4-5-20250929",
            params: {
              temperature: 0.7,
              max_tokens: 1000,
              response_format: { type: "json_object" },
            },
            messages: [
              {
                role: "system",
                content: "You are a helpful assistant that can summarize text.",
              },
              {
                role: "user",
                content: "{{{text}}}",
              },
            ],
            metadata: { version: "1.0" },
          });
          ```

          ```python title="summarizer.py" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
          import braintrust

          project = braintrust.projects.create(name="Summarizer")

          summarizer = project.prompts.create(
              name="Summarizer",
              slug="summarizer",
              description="Summarize text",
              tags=["summarization"],
              model="claude-sonnet-4-5-20250929",
              params={
                  "temperature": 0.7,
                  "max_tokens": 1000,
                  "response_format": {"type": "json_object"},
              },
              messages=[
                  {"role": "system", "content": "You are a helpful assistant that can summarize text."},
                  {"role": "user", "content": "{{{text}}}"},
              ],
              metadata={"version": "1.0"},
          )
          ```
        </CodeGroup>

        <Accordion title="Assign an environment at creation time">
          To associate a prompt with a specific deployment environment in TypeScript, pass the `environments` field:

          <CodeGroup dropdown>
            ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
            export const summarizer = project.prompts.create({
              name: "Summarizer",
              slug: "summarizer",
              environments: ["production"],
              messages: [{ role: "user", content: "{{{text}}}" }],
            });
            ```
          </CodeGroup>

          Python `project.prompts.create(...)` does not expose an environment-assignment parameter, so use the UI or API if you need to associate environments from Python.

          See [Version prompts](/docs/evaluate/prompts/versions) for details on assigning versions to environments.
        </Accordion>
      </Step>

      <Step title="Push to Braintrust">
        <CodeGroup>
          ```bash TypeScript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
          bt functions push summarizer.ts
          ```

          ```bash Python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
          bt functions push summarizer.py
          ```
        </CodeGroup>
      </Step>
    </Steps>
  </Tab>
</Tabs>

To inject variables at runtime, use [Mustache or Nunjucks templating](/docs/evaluate/prompts/templating) in a prompt's messages.

## Add tools

[Tools](/docs/deploy/functions#deploy-tools) extend your prompt's capabilities by allowing the LLM to call functions during execution:

* Query external APIs or databases.
* Perform calculations or data transformations.
* Retrieve information from vector stores or search engines.
* Execute custom business logic.

<Tabs className="tabs-border">
  <Tab title="UI" icon="mouse-pointer-2">
    To add tools to a prompt in the UI:

    1. When creating or editing a prompt, click **+ Tool/MCP**.
    2. Select tool functions from your library or add raw tools as JSON.
    3. Click **Save tools**.
  </Tab>

  <Tab title="SDK" icon="code">
    To add tools to a prompt in code, use the `tools` parameter:

    <CodeGroup dropdown>
      ```typescript {21} theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
      import * as braintrust from "braintrust";

      const project = braintrust.projects.create({
        name: "RAG app",
      });

      export const docSearch = project.prompts.create({
        name: "Doc Search",
        slug: "document-search",
        model: "gpt-5-mini",
        messages: [
          {
            role: "system",
            content: "You are a helpful assistant that can answer questions about the Braintrust documentation.",
          },
          {
            role: "user",
            content: "{{{question}}}",
          },
        ],
        tools: [toolRAG],
      });
      ```

      ```python {19} theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
      import braintrust

      project = braintrust.projects.create(name="RAG app")

      doc_search = project.prompts.create(
          name="Doc Search",
          slug="document-search",
          model="gpt-5-mini",
          messages=[
              {
                  "role": "system",
                  "content": "You are a helpful assistant that can answer questions about the Braintrust documentation.",
              },
              {
                  "role": "user",
                  "content": "{{{question}}}",
              },
          ],
          tools=[tool_rag],
      )
      ```
    </CodeGroup>
  </Tab>
</Tabs>

When a prompt includes tools, your application code handles the tool calls returned at runtime. See [Handle tool calls](/docs/evaluate/prompts/use-in-code#handle-tool-calls).

## Add MCP servers

Use public [MCP (Model Context Protocol)](https://modelcontextprotocol.io/introduction) servers to give your prompts access to external tools and data:

* Evaluate complex tool-calling workflows.
* Experiment with external APIs and services.
* Reuse existing MCP integrations without building custom tools.

MCP servers must be public, support OAuth authentication, and use `http` or `https`. To protect against [server-side request forgery (SSRF)](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html), Braintrust validates the resolved target of each request.

<Note>
  MCP servers are a UI-only feature. They work in playgrounds and experiments but not when invoked via SDK.
</Note>

### Add to a prompt

To add an MCP server to a prompt:

1. When creating or editing a prompt, click **+ Tool/MCP**.
2. Enable any of the project's [configured MCP servers](#add-to-a-project).
3. To add a prompt-specific MCP server, click **Configure MCP servers**, then click **+ MCP server**:
   * Provide a name, the public URL of the server, and an optional description.
   * Click **Add server**.
   * Authenticate the MCP server in your browser.

For each MCP server, you'll see a list of available tools. Tools are enabled by default, but you can disable individual tools or click **Disable all**.

After testing a prompt-specific MCP server, you can promote it to a project-wide server by clicking **...** > **Save to project MCP servers**.

### Add to a project

Configure MCP servers at the project level so any prompt in the project can use them:

1. Go to **<Icon icon="settings-2" /> Settings** > [**<Icon icon="plug" /> MCP**](https://www.braintrust.dev/app/~/configuration/mcp).
2. Click **+ MCP server** and provide a name, the public URL of the server, and an optional description.
3. Click **Authenticate** to authenticate the MCP server in your browser.
4. Click **Save**.

## Test prompts

Playgrounds provide a no-code environment for rapid prompt iteration:

1. Create or select a prompt.
2. Add a dataset or enter test inputs.
3. Run the prompt and view results.
4. Adjust parameters or messages.
5. Compare different versions side-by-side.

See [Use playgrounds](/docs/evaluate/playgrounds) for details.

You can also test prompts by chatting directly with them from the prompt details page. Each chat interaction is automatically logged as a trace in your project's logs. To navigate back to the prompt from these traces, see [Navigate to trace origins](/docs/observe/examine-traces#navigate-to-trace-origins).

## Optimize with Loop

Use Loop to generate and improve prompts:

Example queries:

* "Generate a prompt for a chatbot that can answer questions about the product"
* "Add few-shot examples based on project logs"
* "Optimize this prompt to be friendlier and more engaging"
* "Improve this prompt based on the experiment results"

Loop analyzes your data and suggests improvements automatically.

## Best practices

Keep these guidelines in mind as you write and refine a prompt's messages:

**Start simple**: Begin with clear, direct instructions. Add complexity only when needed.

**Use few-shot examples**: Include 2-3 examples in your prompt to guide model behavior.

**Be specific**: Define exactly what you want, including format, tone, and constraints.

**Test with real data**: Use production logs to build test datasets that reflect actual usage.

**Iterate systematically**: Change one thing at a time and measure impact with experiments.

**Version everything**: Save prompt changes so you can track what works and roll back if needed.

## Next steps

* [Use templating](/docs/evaluate/prompts/templating) to inject runtime variables with Mustache or Nunjucks.
* [Use prompts in code](/docs/evaluate/prompts/use-in-code) to invoke prompts from your application.
* [Version prompts](/docs/evaluate/prompts/versions) to pin versions and assign them to environments.
* [Manage prompts](/docs/evaluate/prompts/manage) to duplicate prompts and customize the **Prompts** page.
* [Use playgrounds](/docs/evaluate/playgrounds) for rapid iteration.
* [Write scorers](/docs/evaluate/write-scorers) to evaluate prompt quality.
