Skip to content

Migrating from Promptfoo

EvalGuard is compatible with Promptfoo config files. Most migrations take under 5 minutes.

Quick Start

1. Point eval:local at your existing config

npx @evalguard/cli eval:local promptfooconfig.yaml

EvalGuard reads Promptfoo YAML configs directly. Standard assert types are mapped to EvalGuard scorers automatically — e.g. llm-rubric llm-grader, model-graded-factuality factuality, is-json json-valid, similar semantic-similarity.

eval:local calls the model on your machine, so set a provider key first — e.g. export OPENAI_API_KEY=… (or whichever provider your config targets). To smoke-test the wiring without a key, add --provider echo, which echoes each prompt back so scorers run offline.

2. Or convert to an explicit evalguard.config.json

npx @evalguard/cli import:promptfoo promptfooconfig.yaml

Writes a fully-converted evalguard.config.json you can review and commit, and prints a summary of any assertion types that need manual attention. The converted output looks like:

// evalguard.config.json (produced by import:promptfoo)
{
  "name": "Imported from Promptfoo",
  "providers": [{ "provider": "openai", "model": "gpt-4o-mini" }],
  "prompts": ["Answer: {{input}}"],
  "cases": [
    { "vars": { "input": "What is 2+2?" },
      "scorers": [{ "scorer": "contains", "value": "4" }] },
    { "vars": { "input": "Capital of France?" },
      "scorers": [{ "scorer": "icontains", "value": "Paris" }] }
  ]
}

Config Mapping

PromptfooEvalGuardNote
promptfooconfig.yamlevalguard.yamlSame YAML shape — eval:local reads Promptfoo configs directly
providers:model:Single model field instead of providers array (first provider is used)
tests:cases:Either spelling works
assert: [{ type: 'contains' }]scorers: ['contains']Per-test assertions become scorers — most types map automatically
assert: [{ type: 'llm-rubric' }]scorers: ['llm-grader']Assertion-type names are mapped to EvalGuard scorer names automatically
assert: [{ type: 'is-json' }]scorers: ['json-valid']model-graded-factuality → factuality, similar → semantic-similarity, etc.
npx promptfoo evalnpx @evalguard/cli eval:localSame workflow, different CLI
npx promptfoo generate redteamnpx @evalguard/cli scan:localBuilt-in red team with 300+ attack plugins

Most assert types map 1:1, but the names differ — EvalGuard handles the rename for you when you run eval:local or import:promptfoo.

Assertions that need manual handling

A handful of assertion types have no 1:1 EvalGuard scorer — the two that run arbitrary user code (javascript / python), plus perplexity-score, classifier, and moderation, which map to a deep-grader scorer instead. eval:local skips the unmapped ones with a warning (it never silently drops them) and import:promptfoolists them in its summary. Here's what to use instead:

Note: Promptfoo's bleu, rouge, and webhook assertions are not in this list — EvalGuard ships built-in bleu, rouge-n, and webhook scorers, so you can reference them directly in your config (e.g. scorers: ['bleu']) instead of rewriting them.

Promptfoo assertionEvalGuard equivalent
javascript / pythonWrite a custom scorer — see /docs/scorers/custom-function
perplexity-scoreEvalGuard scores via a deep-grader rubric instead — see `judge`
classifierUse a deep-grader scorer (e.g. `bias`, `toxicity`)
moderationUse `toxicity` + `pii_leak` deep graders combined

What you gain by switching

200+ built-in scorers (vs Promptfoo's ~45 assertions)
300+ red team attack plugins (vs 125)
Runtime firewall at 3.67ms p95 (measured)
Full observability with OpenTelemetry traces
AI-SPM (Security Posture Management)
FinOps cost tracking and optimization
CI/CD quality gates (exit code 1 on failure)
Python, JS, Go, and CLI SDKs

Ready to migrate?

Start with your existing Promptfoo config. No rewrite needed.