DEV Community

Cover image for How to Test LLM Applications: The Complete Guide to Promptfoo (2026)
Preecha
Preecha

Posted on

How to Test LLM Applications: The Complete Guide to Promptfoo (2026)

TL;DR

Promptfoo is an open-source LLM evaluation and red-teaming framework for systematically testing AI applications. It supports 90+ model providers, includes 67+ security attack plugins, and runs locally by default for privacy. Install it with npm install -g promptfoo, then create a starter suite with promptfoo init --example getting-started.

Try Apidog today

Introduction

An AI-powered customer support chatbot can appear reliable during development, then fail in production when users discover prompt-injection paths, bypass safety controls, or trigger inconsistent answers.

Manual testing does not provide enough coverage for LLM applications. You need repeatable tests that detect regressions, compare models, validate structured outputs, and probe for security weaknesses before deployment.

Promptfoo provides that workflow. It lets you:

  • Evaluate prompts across multiple models
  • Define automated assertions for quality, latency, and cost
  • Run red-team scans for common LLM vulnerabilities
  • Track regressions in CI/CD
  • Compare model quality using the same test suite

This guide uses promptfoo version 0.121.2 and focuses on setting up practical evaluations, security scans, and CI checks.

If you also validate the APIs behind your LLM application, Apidog can complement promptfoo: use promptfoo for LLM evaluation and Apidog for API design, testing, and documentation.

What Is Promptfoo?

Promptfoo is a command-line tool and Node.js library for evaluating and red-teaming LLM applications.

Image

Traditional tests often depend on deterministic outputs. LLMs are probabilistic: the same input may produce slightly different responses across runs. Promptfoo addresses this with evaluation methods that do not require exact string matches:

  • Semantic assertions that validate meaning
  • LLM-graded assertions for subjective quality checks
  • Multi-model comparisons across providers
  • Security plugins that generate adversarial inputs
  • Latency and cost assertions for operational constraints

Promptfoo runs locally by default. Prompts and test data remain in your environment unless you explicitly use cloud features.

Problems Promptfoo Solves

Manual LLM testing creates recurring issues:

  • No regression detection: Model, prompt, or dependency changes can silently degrade behavior.
  • Coverage gaps: A few manually written prompts rarely cover edge cases or adversarial inputs.
  • No measurable baseline: Teams cannot objectively compare models, prompts, latency, or cost.

Promptfoo replaces ad hoc checks with repeatable evaluation suites. Define your test cases once, version them with your code, and run them locally or in CI.

Common Use Cases

Teams use promptfoo for:

  • Customer support chatbots that need consistent answers
  • Content-generation workflows that need brand and style checks
  • Healthcare and fintech workflows with compliance constraints
  • Security-sensitive applications that must resist prompt injection and data leakage
  • Model-selection experiments across hosted and local models

Promptfoo has 1.6 million npm downloads and is used in production by companies serving more than 10 million end users. In March 2026, Promptfoo joined OpenAI while remaining open source and MIT licensed.

Getting Started: Run Your First Eval

You can install promptfoo globally or run it with npx.

1. Install Promptfoo

# Global install
npm install -g promptfoo

# Or run without a global install
npx promptfoo@latest

# macOS
brew install promptfoo

# Python
pip install promptfoo
Enter fullscreen mode Exit fullscreen mode

Set provider API keys as environment variables:

export OPENAI_API_KEY=sk-abc123
export ANTHROPIC_API_KEY=sk-ant-xxx
Enter fullscreen mode Exit fullscreen mode

2. Create an Example Project

Initialize the starter evaluation:

promptfoo init --example getting-started
cd getting-started
Enter fullscreen mode Exit fullscreen mode

This creates a promptfooconfig.yaml file with example prompts, providers, and test cases.

3. Run the Evaluation

promptfoo eval
Enter fullscreen mode Exit fullscreen mode

Open the results UI:

promptfoo view
Enter fullscreen mode Exit fullscreen mode

The UI runs at http://localhost:3000 and shows outputs from each provider alongside assertion results.

Create a Practical Eval Suite

A promptfoo suite is defined in promptfooconfig.yaml.

description: "My First Eval Suite"

prompts:
  - prompts/greeting.txt
  - prompts/farewell.txt

providers:
  - openai:gpt-4o
  - anthropic:claude-sonnet-4-5

tests:
  - vars:
      input: "Hello"
    assert:
      - type: contains
        value: "Hi"
      - type: latency
        threshold: 3000
Enter fullscreen mode Exit fullscreen mode

The main sections are:

  • prompts: Prompt files or inline prompts to evaluate
  • providers: Models to run against
  • tests: Variables and assertions for each scenario

Keep this configuration in version control. Add test cases whenever you fix a production issue so it does not regress later.

Core Features

1. Automated Evaluations

Automated evaluations run your prompts against selected models and validate the output using assertions.

Useful Assertion Types

Assertion Purpose
contains Output includes a substring
equals Output matches an exact string
regex Output matches a regular expression
json-schema Output has a valid JSON structure
javascript Custom JavaScript pass/fail check
python Custom Python assertion
llm-rubric LLM grades the output against a rubric
similar Semantic similarity score
latency Response stays under a time threshold
cost Request stays under a cost threshold

For deterministic requirements, use checks such as contains, regex, or json-schema. For subjective requirements such as tone or helpfulness, use an LLM rubric.

Example: Test Quality, Length, Latency, and Cost

tests:
  - vars:
      question: "What is the capital of France?"
    assert:
      - type: contains
        value: "Paris"
      - type: javascript
        value: output.length < 100
      - type: latency
        threshold: 2000
      - type: cost
        threshold: 0.001
Enter fullscreen mode Exit fullscreen mode

This test verifies that the answer:

  1. Mentions Paris
  2. Is shorter than 100 characters
  3. Responds in under two seconds
  4. Costs less than $0.001

Use LLM-Graded Evaluations for Subjective Criteria

Use llm-rubric when exact matching is too restrictive:

assert:
  - type: llm-rubric
    value: "Response should be helpful, harmless, and honest"
Enter fullscreen mode Exit fullscreen mode

The grader model evaluates the output against the rubric. Use a lower-cost model for grading when appropriate to reduce evaluation cost.

2. Red Teaming and Security Testing

Promptfoo includes a red-team module that generates adversarial inputs and evaluates how your application responds.

Image

Attack Categories

Category What It Tests
Prompt Injection Direct, indirect, and context-injection attacks
Jailbreaks DAN, persona switching, and role-play bypasses
Data Exfiltration SSRF, system prompt extraction, and prompt leakage
Harmful Content Hate speech, dangerous activities, and self-harm requests
Compliance PII leakage, HIPAA violations, and financial data exposure
Audio/Visual Audio injection and image-based attacks

Run a Red-Team Scan

Create a red-team configuration:

promptfoo redteam init
Enter fullscreen mode Exit fullscreen mode

Run the scan:

promptfoo redteam run
Enter fullscreen mode Exit fullscreen mode

Generate a report:

promptfoo redteam report [directory]
Enter fullscreen mode Exit fullscreen mode

The redteam run workflow:

  1. Generates attack probes tailored to your application.
  2. Sends probes to your target.
  3. Scores the resulting vulnerabilities.

Review Critical and High findings before deployment. After implementing mitigations, rerun the scan and keep the exploit cases as regression tests.

Example output:

Vulnerability Summary:
- Critical: 2 (PII leakage, prompt extraction)
- High: 5 (jailbreaks, injection attacks)
- Medium: 12 (bias, inconsistent responses)
- Low: 23 (minor policy violations)
Enter fullscreen mode Exit fullscreen mode

3. Scan Pull Requests

Promptfoo can scan pull requests for LLM-related security issues.

# .github/workflows/promptfoo-scan.yml
name: Promptfoo Code Scan

on: [pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: promptfoo/promptfoo/code-scan-action@main
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
Enter fullscreen mode Exit fullscreen mode

This can identify issues such as:

  • Hardcoded API keys in configuration
  • Insecure prompt patterns
  • Missing input validation
  • Potential prompt-injection vectors

4. Compare Models with the Same Test Cases

Define multiple providers, then run one evaluation suite:

providers:
  - openai:gpt-4o
  - anthropic:claude-sonnet-4-5
Enter fullscreen mode Exit fullscreen mode

Run and inspect results:

promptfoo eval
promptfoo view
Enter fullscreen mode Exit fullscreen mode

The UI lets you compare:

  • Pass/fail rate by provider
  • Cost per request
  • Average latency
  • Qualitative differences in model responses

Use this data to choose models based on your actual workload instead of general benchmarks.

Supported Providers

Promptfoo supports more than 90 LLM providers, including hosted APIs and local models.

Provider Examples
OpenAI GPT-4, GPT-4o, GPT-4o-mini, o1, o3
Anthropic Claude 3.5/3.7/4.5/4.6 and thinking models
Google Gemini 1.5/2.0 and Vertex AI
Microsoft Azure OpenAI and Phi
Amazon Bedrock, including Claude, Llama, and Titan
Meta Llama 3, 3.1, and 3.2 through supported providers
Ollama Local Llama, Mistral, Phi, and other models

Create a Custom Provider

If your model is not directly supported, create a provider in Python or JavaScript.

Python Provider

# custom_provider.py
from typing import Any

class CustomProvider:
    async def call_api(self, prompt: str, options: dict, context: dict) -> dict:
        response = await my_async_api.generate(prompt)

        return {
            "output": response.text,
            "tokenUsage": {
                "total": response.usage.total_tokens,
                "prompt": response.usage.prompt_tokens,
                "completion": response.usage.completion_tokens
            }
        }
Enter fullscreen mode Exit fullscreen mode

JavaScript Provider

// customProvider.js
export default class CustomProvider {
  async callApi(prompt) {
    return {
      output: await myApi.generate(prompt),
      tokenUsage: {
        total: 50,
        prompt: 20,
        completion: 30,
      },
    };
  }
}
Enter fullscreen mode Exit fullscreen mode

Register a custom provider in your configuration:

providers:
  - id: file://custom_provider.py
    config:
      api_key: ${MY_API_KEY}
Enter fullscreen mode Exit fullscreen mode

Essential CLI Commands

# Run evaluations
promptfoo eval -c promptfooconfig.yaml

# Open the local results UI
promptfoo view

# Share results online
promptfoo share

# Initialize and run red-team testing
promptfoo redteam init
promptfoo redteam run

# Create or validate configuration
promptfoo init
promptfoo validate [config]

# Manage saved results
promptfoo list
promptfoo show <id>
promptfoo delete <id>
promptfoo export <id>

# Manage cache and retry runs
promptfoo cache clear
promptfoo retry <id>
Enter fullscreen mode Exit fullscreen mode

Useful Flags

--no-cache              Disable caching and force fresh results
--max-concurrency <n>   Limit parallel API calls
--output <file>         Write results to a JSON file
--verbose               Enable debug logging
--env-file <path>       Load environment variables from a file
--filter <pattern>      Run matching test cases only
Enter fullscreen mode Exit fullscreen mode

Example:

promptfoo eval \
  -c promptfooconfig.yaml \
  --no-cache \
  --max-concurrency 3 \
  --output results.json \
  --env-file .env
Enter fullscreen mode Exit fullscreen mode

This runs fresh evaluations, limits concurrency to three requests, writes JSON results, and loads credentials from .env.

Add Promptfoo to CI/CD

Run evaluations on every push and pull request to block regressions before deployment.

name: LLM Tests

on: [push, pull_request]

jobs:
  eval:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: "22"

      - run: npm install -g promptfoo

      - run: promptfoo eval -c promptfooconfig.yaml
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
Enter fullscreen mode Exit fullscreen mode

Add a Quality Gate

Set a minimum pass rate in promptfooconfig.yaml:

commandLineOptions:
  threshold: 0.8
Enter fullscreen mode Exit fullscreen mode

This fails the CI job if fewer than 80% of assertions pass.

Cache Results in GitHub Actions

Cache repeated evaluation results to reduce API calls and speed up unchanged runs:

- uses: actions/cache@v4
  with:
    path: ~/.cache/promptfoo
    key: ${{ runner.os }}-promptfoo-${{ hashFiles('promptfooconfig.yaml') }}
Enter fullscreen mode Exit fullscreen mode

Review Results in the Web UI

Start the local UI:

promptfoo view
Enter fullscreen mode Exit fullscreen mode

The UI includes:

  • An evaluation matrix for side-by-side output comparison
  • Filters for provider, test case, and pass/fail status
  • Diff views between runs
  • Shareable result links
  • Live evaluation updates

The UI runs on localhost:3000 by default. It uses CSRF protections based on Sec-Fetch-Site and Origin headers.

Do not expose the local server to untrusted networks. For team access, use promptfoo share or self-host with authentication.

Cache and Database Locations

Cache

Platform Location
macOS/Linux ~/.cache/promptfoo
Windows %LOCALAPPDATA%\promptfoo

The cache stores evaluation results. Use --no-cache during prompt development when you need fresh model responses.

Database

Promptfoo stores historical evaluation runs in SQLite:

~/.promptfoo/promptfoo.db
Enter fullscreen mode Exit fullscreen mode

Keep this database if you need historical comparisons and trend analysis.

Security Model

Promptfoo uses a trust-by-configuration model.

Trusted Inputs

Treat these as code. Only load them from trusted repositories and sources:

  • promptfooconfig.yaml
  • Custom JavaScript, Python, or Ruby assertions
  • Provider configurations
  • Transform functions

Untrusted Inputs

These are treated as data and should not execute code:

  • Prompt text
  • Test variables
  • Model outputs
  • Remote content fetched during evaluations

Hardening Checklist

For higher-security environments:

  • Run promptfoo in a container or VM with minimal privileges.
  • Use dedicated, least-privileged API keys.
  • Do not place secrets in prompts or config files.
  • Restrict network egress for third-party code.
  • Do not expose the local web server to untrusted networks.

Optimize Evaluation Performance

Use these techniques while iterating:

  • Keep caching enabled for repeated runs.
  • Set --max-concurrency according to provider rate limits.
  • Use --filter to run only relevant test cases during development.
  • Test with smaller datasets before running a full suite.
  • Use --repeat with subsets when tuning prompts.

For larger suites with thousands of cases:

  • Use the scheduler in src/scheduler/ for distributed runs.
  • Use remote generation when you need to offload compute.
  • Export results to Google Sheets for team visibility.

Create Custom Assertions

Use custom assertions for domain-specific checks.

// assertions/customCheck.js
export default function customCheck(output, context) {
  const pass = output.includes("expected");

  return {
    pass,
    score: pass ? 1 : 0,
    reason: pass ? "Output matched" : "Missing expected content",
  };
}
Enter fullscreen mode Exit fullscreen mode

Reference it in your configuration:

assert:
  - type: file://assertions/customCheck.js
Enter fullscreen mode Exit fullscreen mode

Use the MCP Server

Promptfoo includes a Model Context Protocol (MCP) server for AI assistants such as Claude Code.

promptfoo mcp
Enter fullscreen mode Exit fullscreen mode

This enables agents to:

  • Run evaluations from chat
  • Access red-team capabilities
  • Query stored results
  • Generate test cases

Example Implementation Patterns

Customer Support Chatbot

A support chatbot evaluation suite might include:

  • 500 tests for common support questions
  • GPT-4 and Claude comparisons
  • Red-team probes for PII leakage and jailbreaks
  • CI quality gates that block failed deployments

The goal is to turn production issues into repeatable test cases.

Content Generation Pipeline

For AI-generated marketing content:

  • Use llm-rubric checks for tone and style.
  • Add latency thresholds for interactive workflows.
  • Add cost assertions for budget control.
  • Compare models to find the best quality-to-cost ratio.

Healthcare Application

For a health-focused application:

  • Run red-team scans for HIPAA-related risks.
  • Add custom assertions for domain-specific requirements.
  • Keep evaluations local when handling sensitive data.
  • Preserve historical results for audit evidence.

Conclusion

Promptfoo provides a repeatable testing workflow for LLM applications. Instead of relying on manual prompt checks, you can automate quality evaluation, security testing, model comparison, and regression detection.

Start with this workflow:

  1. Install promptfoo:
   npm install -g promptfoo
Enter fullscreen mode Exit fullscreen mode
  1. Create an example suite:
   promptfoo init --example getting-started
Enter fullscreen mode Exit fullscreen mode
  1. Add assertions for correctness, latency, cost, and structured output.

  2. Run red-team scans before deployment.

  3. Add a CI threshold to block regressions.

  4. Compare providers using the same test suite before selecting a production model.

If you also work with APIs, use Apidog alongside promptfoo: Apidog handles API design, testing, and documentation, while promptfoo focuses on LLM evaluation.

FAQ

What is promptfoo used for?

Promptfoo tests and evaluates LLM applications. It runs automated prompt tests, compares outputs across models, and performs red-team security assessments.

Is promptfoo free?

Yes. Promptfoo is open source and MIT licensed for personal and commercial use. Cloud features and enterprise support may require paid plans.

How do I install promptfoo?

Install it globally:

npm install -g promptfoo
Enter fullscreen mode Exit fullscreen mode

You can also run it with npx promptfoo@latest, install it through Homebrew on macOS, or use pip install promptfoo.

What models does promptfoo support?

Promptfoo supports 90+ providers, including OpenAI, Anthropic, Google, Azure OpenAI, Amazon Bedrock, and local models through Ollama.

How do I run a red-team scan?

Initialize a red-team configuration, run it, then generate a report:

promptfoo redteam init
promptfoo redteam run
promptfoo redteam report
Enter fullscreen mode Exit fullscreen mode

Can I use promptfoo in CI/CD?

Yes. Install promptfoo in your pipeline and run:

promptfoo eval -c promptfooconfig.yaml
Enter fullscreen mode Exit fullscreen mode

Set a threshold in the configuration to fail CI when the pass rate is too low.

Does promptfoo send data to external servers?

Promptfoo runs locally by default. Prompts and test data remain on your machine unless you explicitly use cloud features.

How do I compare models with promptfoo?

List multiple providers in promptfooconfig.yaml, run promptfoo eval, then open the comparison UI:


bash
promptfoo view
Enter fullscreen mode Exit fullscreen mode

Top comments (0)