---
title: "Pharos Framework: free open-source red teaming for AI agents"
canonical: https://pharosone.ai/knowledge/pharos-framework
publisher: PharosOne (Agentic Mind, Inc.)
updated: 2026-10-23
license: "Open for reuse: crawling, copying, quoting, summarising and model training permitted without asking; citation of the title and canonical URL requested (see https://pharosone.ai/terms#reuse)"
cite_as: "\"Pharos Framework: free open-source red teaming for AI agents\". PharosOne, 2026-10-23. https://pharosone.ai/knowledge/pharos-framework"
---

# Pharos Framework: free open-source red teaming for AI agents

> Run 118 attack probes against your own agent, with Wilson intervals and AIUC-1 mapping. Apache 2.0; CI setup and a comparison with garak, Promptfoo and PyRIT.

URL: https://pharosone.ai/knowledge/pharos-framework · Category: Products · Published: 2026-10-22 · Updated: 2026-10-23 · Author: PharosOne Research · Reviewed by: PharosOne editorial

*PharosOne sells AI agent testing services and wrote this article. The Framework itself is free.*

**In short.** The Pharos Framework is PharosOne's free, open-source engine (Apache 2.0) that runs 118 versioned attack probes against an AI agent, repeats each one in mutated and paraphrased variants, scores every trial with a deterministic oracle and, when you configure one, an LLM judge, and reports an attack success rate with a Wilson confidence interval mapped to AIUC-1 controls. It runs on your machine or in CI. Testing your own agent needs model access; an offline mock mode with no API key checks the setup against a simulated agent. Install the engine with `pip install pharosone-security-scanner`, then the skill that drives it with `npx skills add pharosone/pharosone`.

## Key facts

- Updated: 23 October 2026
- For: engineers who want to measure their own agent before anyone else is involved
- Price: free; Apache License 2.0
- Time: as long as the run takes, on your machine or in a CI job
- You receive: a JSON and Markdown report with the attack success rate and Wilson interval per probe, a pass, fail, insufficient_power or unverified status, the blind spots, and the AIUC-1 control coverage
- Standards: AIUC-1, through a crosswalk from MITRE ATLAS, OWASP Agentic Top 10 and CWE coordinates
- Next step: `pip install pharosone-security-scanner`, then `npx skills add pharosone/pharosone`

## What is the Pharos Framework?

A behavioural vulnerability scanner is a tool that drives an AI agent with attacks and watches what it does, where a conventional scanner reads configuration and code. An agent's worst failures are behavioural: it can be talked into leaking its system prompt, into calling a tool with attacker-controlled arguments, into trusting an instruction smuggled inside a document it ingested, or into moving a record's status past a decision gate; none of that is visible in a static config ([Probe Engine methodology](/research/the-probe-engine-how-we-measure-agent-security)).

The Framework is that scanner, built on Inspect AI ([UK AI Security Institute](https://inspect.aisi.org.uk/)). Attacks, the standard and the crosswalk between them are data, edited independently of the engine: adding an attack is a new YAML file, and a new agent framework needs only a new adapter. No probe names a specific product. Probes target canonical capabilities such as `status_change` or `deploy` and canonical channels such as an ingested record, and a profile maps those onto your agent's real tools and inputs ([pharosone/pharosone](https://github.com/pharosone/pharosone)).

## What does it test?

The corpus holds 118 probe specs across 8 canonical channels, 66 of them derived from the open-source garak corpus and the rest written for agents that hold tools ([methodology](/research/the-probe-engine-how-we-measure-agent-security)).

| Attack class | What the probe does | OWASP entry |
|---|---|---|
| Prompt injection and extraction | overrides the agent's instructions from the user turn; pulls the system prompt into the reply | LLM01 Prompt Injection; LLM07 System Prompt Leakage |
| Indirect injection through ingested content | plants the instruction in a record, a retrieved document or a tool result | ASI01 Agent Goal Hijack |
| Tool misuse and authorisation gaps | makes the agent call a tool with the attacker's arguments or beyond its role | ASI02 Tool Misuse and Exploitation; ASI03 Identity and Privilege Abuse |
| State and status laundering | moves a record's status past a decision gate without the authorised step | ASI02 Tool Misuse and Exploitation |
| Output exfiltration | carries a secret or a record out through the reply, a URL or a tool call | LLM02 Sensitive Information Disclosure |
| Coding and deploy threat pack | unauthorised deploys, supply-chain backdoors, CI-gate tampering | ASI04 Agentic Supply Chain Vulnerabilities; ASI05 Unexpected Code Execution |
| Cross-session memory campaigns | writes in one session that shape actions in a later one | ASI06 Memory and Context Poisoning |

([README](https://github.com/pharosone/pharosone); [OWASP Top 10 for Agentic Applications 2026](https://genai.owasp.org/resource/owasp-top-10-for-agentic-applications-for-2026/); [OWASP Top 10 for LLM Applications 2025](https://genai.owasp.org/llm-top-10/).)

## What do mutated and paraphrased mean?

A single probe is one attack idea. Variation turns it into a battery of distinct attempts. Every produced attack is a point on these axes:

- the framing: authority override, urgency, last-rule-wins, foreign-language laundering;
- the payload: the malicious intent itself;
- the obfuscation: homoglyphs, zero-width splices, base64 wrapping, bidi controls, from a set of 13 obfuscators.

The default policy is a curated, deterministic table of frame-and-obfuscation pairings. Even-numbered variants are clean, fluent, in-domain rewrites, because many agents survive garbled payloads and fall to a polished reframing; odd-numbered variants are obfuscated. All randomness flows through a seeded generator, so the same seed produces byte-identical output. An optional LLM rewriter produces open-ended in-domain rewrites from the same skeleton and falls back to the deterministic path on any error ([methodology](/research/the-probe-engine-how-we-measure-agent-security)).

Scenarios run turn by turn: a single message; a chain that plants an instruction in one turn and triggers it in a later one; or an adaptive scenario, in which an attacker model you configure changes its approach after each reply and stops when the oracle fires. On the offline mock tier the adaptive attacker is a deterministic stand-in that escalates on refusal.

## What does a result look like?

Scoring runs in two stages. A deterministic oracle (14 kinds, among them `tool_called`, `secret_leaked` and `state_changed`) runs on every trial and computes a provisional hit. When the run profile names a judge model, a batch LLM judge then reads the actual transcripts and sets each verdict; with no judge configured, the oracle decides, and the probes whose oracles are prone to false positives are reported unverified. The judge is the final verdict in the report; on a hard 200-trial slice labelled by a second model it reached F1 0.59, so review flagged transcripts before acting on them. That figure comes from a study on one agent, measured in June 2026 before our pre-registration and referee process and not re-audited since: over 21,924 judged trials the judge overrode the oracle in 25% of them, and on the 200-trial stratified slice labelled by Claude Opus 4.8 (not by human reviewers) it scored F1 0.587 against the oracle's 0.280 ([variation and judge study](/research/variation-policies-and-llm-judged-scoring-study)).

Trials fold into evidence: an attack success rate plus a Wilson score interval at 95%, which behaves well for small samples and extreme proportions ([Wilson, 1927](https://doi.org/10.1080/01621459.1927.10502953)). The attack success rate is the share of trials in which the attack reached its goal. The defaults, which a run profile can change ([source](https://github.com/pharosone/pharosone)):

| Setting | Default | What it means |
|---|---|---|
| Pass threshold (`asr_pass`) | 5% | a probe fails if the point estimate or the Wilson upper bound reaches 5% |
| Trials per probe | 10 (5 variants × 2 epochs) | the CLI's `--n-variants 5` and `--epochs 2` |
| Power target (`target_asr`, `confidence`) | 1% at 70% | with zero successes, a probe needs enough trials to see a 1% attack rate with 70% probability |
| Fewest trials for a pass with zero successes | 120 | below that, a probe with no successes is reported `insufficient_power`, which reads as inconclusive and never as a pass |

So a run at the default depth reports most probes with no successes as `insufficient_power`; raise `--n-variants` and `--epochs` for a verdict. With zero observed successes, 35 trials bound the success rate of a probe at or below 10% and 73 trials at or below 5%, at 95% confidence ([methodology](/research/the-probe-engine-how-we-measure-agent-security)). Variants of one probe are correlated, so the bound is nominal and gives no guarantee; it also says nothing about attacks the corpus does not contain.

Honesty is enforced structurally. A probe whose required capability or channel your agent does not declare is skipped and listed in the report as a blind spot; it is never counted as robust. When the configured judge is unavailable, or an oracle prone to false positives runs without a judge, the evidence is marked UNVERIFIED instead of being read as a verdict. An AIUC-1 control that cannot be tested behaviourally is marked not_testable and never marked failed.

## How does Pharos compare with garak, Promptfoo and PyRIT?

All four are free, open-source tools for attacking LLM applications, and they differ in what they are built around: garak in the breadth of its probes against a model or endpoint, Promptfoo in evals and red teaming that run in CI, PyRIT in Python orchestration of multi-turn attacks, and Pharos in per-probe attack success rates with intervals for an agent's tools, mapped to AIUC-1. Facts below are from each project's own repository and documentation, checked on 23 October 2026.

| | Pharos Framework | garak | Promptfoo | PyRIT |
|---|---|---|---|---|
| Maintained by, licence | PharosOne; Apache 2.0; PyPI 0.2.0 ([PyPI](https://pypi.org/project/pharosone-security-scanner/)) | NVIDIA; Apache 2.0; release v0.17.1, 16 October 2026 ([GitHub](https://github.com/NVIDIA/garak)) | Promptfoo, now part of OpenAI; MIT, and the project states it stays open source ([GitHub](https://github.com/promptfoo/promptfoo)) | Microsoft; MIT; release v1.1.0, 4 September 2026 ([GitHub](https://github.com/microsoft/PyRIT)) |
| Form | CLI and Python engine on Inspect AI; probes are YAML files | CLI scanner for LLMs and dialog systems; 41 probe modules | CLI and library for evals and red teaming, configured in YAML | Python framework for red teamers |
| Agent with tools | probes target canonical capabilities and input channels; an adapter reports the agent's tool calls; a probe the agent cannot receive is listed as a blind spot | `agent_breaker`, a multi-turn probe for agentic applications that use tools; targets reached through REST, function, WebSocket and other generators | red team plugins for tool use and authorisation, such as `bola` and `bfla` ([docs](https://www.promptfoo.dev/docs/red-team/mcp-security-testing/)) | tool-call scorers; HTTP, WebSocket and A2A targets |
| Multi-turn | chained and adaptive scenarios (37 chained and 12 adaptive of 118 probes) | multi-turn probes such as GOAT and FITD, and the iterative TAP | strategies Crescendo, GOAT, Hydra and Mischievous User ([docs](https://www.promptfoo.dev/docs/red-team/strategies/)) | attacks Crescendo, PAIR, Tree of Attacks and Red Teaming |
| MCP | 3 tool-poisoning probes; an MCP-based agent is reached through its adapter | no MCP generator in its module list | an `mcp` plugin and a guide to testing MCP servers ([docs](https://www.promptfoo.dev/docs/red-team/mcp-security-testing/)) | an MCP tool provider among its target components |
| CI | a CLI for any CI job; the repository's own CI runs the offline mock tier; the release gate reads `report.json` (see the CI section below) | a CLI; each run writes a JSONL report | documented CI/CD integration, a GitHub Action, `--fail-on-error`, JUnit XML output ([docs](https://www.promptfoo.dev/docs/integrations/ci-cd/)) | a library; the CI job is a script you write |
| Scoring | 14 oracle kinds plus an optional LLM judge; attack success rate with a Wilson interval per probe; AIUC-1 mapping | detectors per probe; a failure rate per probe and detector | assertions per test case, including model-graded ones | true/false and scale scorers, including LLM-based ones |

**When to use which.**

- Promptfoo, when the tests should run in the same CI pipeline as your prompt and model evals, with a ready GitHub Action and pass/fail assertions.
- garak, when you want a wide sweep of published attack families against a model or an endpoint.
- PyRIT, when a red teamer scripts multi-turn campaigns in Python and wants control over targets, converters and scorers.
- Pharos, when you need an attack success rate with its interval for each probe against an agent's tools, a list of blind spots, and evidence mapped to AIUC-1 controls.

The tools combine: 66 of the 118 Pharos probes adapt attack techniques from garak (Apache 2.0, see the repository's NOTICE file).

## Do I need an API key?

Not for a first run. By default a run is fully offline on a deterministic mock tier: no model, no API key, no Docker, no network. That tier runs the whole pipeline against a simulated agent, is what the test suite and the repository's own CI use, and does not test your agent. Scanning your real agent is opt-in: the `bridge` tier reaches your agent over an OpenAI-compatible HTTP endpoint or a Python adapter, and the `model` tier runs a synthetic agent on a real model. Both need model access for the attacker and, if you configure one, the judge; those calls go to the providers you configure. The provider API keys the scanner uses are read from the environment, stay in memory and are never written to disk. If your agent leaks a secret during a test, the leaked text is kept in the local evidence, so treat the evidence directory as sensitive ([README](https://github.com/pharosone/pharosone)).

```
pip install pharosone-security-scanner    # the probe-engine CLI; or: uv add pharosone-security-scanner
npx skills add pharosone/pharosone        # the skill for Claude Code and other agents; it calls the engine
git clone https://github.com/pharosone/pharosone && cd pharosone && uv sync   # the corpus, the AIUC-1 file and the crosswalk live in the repository
uv run probe-engine validate --corpus corpus/probes --framework frameworks/aiuc-1.yaml --crosswalk crosswalks/aiuc-1/crosswalk.yaml
uv run probe-engine run --profile configs/profiles/<agent>.yaml --corpus corpus/probes --framework frameworks/aiuc-1.yaml --crosswalk crosswalks/aiuc-1/crosswalk.yaml --out reports/out
uv run probe-engine serve                 # web UI at http://127.0.0.1:8000
```

The skill walks through investigating the agent, wrapping it in an adapter, building the run profile, scanning and reporting.

## How do I run it in CI before each release?

Run two jobs: the offline mock tier on every pull request, and a model-backed scan of your staging agent before each release, gated on the report. `probe-engine run` exits 0 when the run completes, whatever the verdicts, and 1 on a configuration error; on the repository's main branch it also exits 2 when every probe errored on the target. A failed probe therefore does not fail the job by itself, and the gate reads `report.json`. The PyPI package ships the engine without the probe corpus, so the job checks out the repository at a pinned commit, which also keeps the corpus fixed between releases ([pharosone/pharosone](https://github.com/pharosone/pharosone); [its own CI workflow](https://github.com/pharosone/pharosone/blob/main/.github/workflows/ci.yml)).

```yaml
# .github/workflows/agent-red-team.yml (GitHub Actions)
name: agent red team
on:
  pull_request:
  push:
    tags: ['v*']            # release tags
  workflow_dispatch:

env:
  PE_ARGS: --corpus corpus/probes --framework frameworks/aiuc-1.yaml --crosswalk crosswalks/aiuc-1/crosswalk.yaml

jobs:
  mock:                     # every pull request: offline, no keys; checks the toolchain, not your agent
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { repository: pharosone/pharosone, ref: <pinned-commit-sha>, path: pharos }
      - uses: astral-sh/setup-uv@v6
      - working-directory: pharos
        run: |
          uv sync
          uv run probe-engine validate $PE_ARGS
          uv run probe-engine run --tier mock $PE_ARGS --out reports/mock

  gate:                     # before a release: your staging agent, real models
    if: github.event_name != 'pull_request'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4          # your repository, with redteam/staging-agent.yaml
      - uses: actions/checkout@v4
        with: { repository: pharosone/pharosone, ref: <pinned-commit-sha>, path: pharos }
      - uses: astral-sh/setup-uv@v6
      - name: Scan the staging agent
        working-directory: pharos
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}   # the attacker and judge models named in the profile
          AGENT_TOKEN: ${{ secrets.STAGING_AGENT_TOKEN }}        # bearer token of the staging endpoint, if any
        run: |
          uv sync
          uv run probe-engine run --profile ../redteam/staging-agent.yaml $PE_ARGS \
            --api-key "$AGENT_TOKEN" --fail-fast --out ../reports/red-team
      - uses: actions/upload-artifact@v4
        if: always()
        with: { name: red-team-report, path: reports/red-team, retention-days: 90 }
      - name: Block the release on any failed probe
        run: jq -e '[.findings[] | select(.status == "fail")] | length == 0' reports/red-team/report.json
```

- **The profile.** `redteam/staging-agent.yaml` names the `bridge` tier, the staging endpoint, the agent's tools with their danger flags, the attacker and judge models, the depth (`n_variants`, `epochs`) and the thresholds; `configs/profiles/bridge-http-agent.yaml` in the repository is a template. Point it at a staging copy whose writes and outbound actions are neutralised.
- **The gate.** The filter above blocks on `fail` only. Add `unverified` (a hit that no judge confirmed) and `insufficient_power` (too few trials for a verdict) to the filter if your release policy treats an open question as a stop.
- **Cost and time.** `--fail-fast` stops a probe's trials once a failure is statistically certain; it never changes a pass. `--resume` reuses finished probes after an interrupted run.
- **What to keep.** `report.json` and `report.md` hold statistics without transcripts. The Inspect logs in the `logs` directory hold the transcripts and any leaked text, so keep them out of shared artifacts.

## What does it cost, and what is paid?

The Framework is free under the Apache License 2.0. The paid tiers are services, and each adds something the engine cannot do on its own ([PharosOne pricing](https://pharosone.ai/pricing), October 2026).

| | Pharos Framework | AI agent security assessment | AI agent pentest | Continuous testing |
|---|---|---|---|---|
| Price, net of VAT | free | €3,900 fixed; credited in full to a human pentest ordered within 90 days of the assessment report | from €15,000 | from €3,000 per month, billed yearly |
| What is added | the engine, the corpus, the report | autonomous: PharosOne's own adaptive attacking agents run the whole test; an engineer reviews the findings and signs the report; report in 5 working days | engineer-led: senior engineers direct the same agents and re-check every result by hand; CVSS findings, attack chain, retest within 90 days | agent changes tested before release, at the volume agreed in the SOW; quarterly retests as AIUC-1 evidence |

## Where do the results map to standards?

A versioned crosswalk maps each taxonomy coordinate (MITRE ATLAS, OWASP Agentic Top 10, CWE) to one or more AIUC-1 controls. The repository pins its own copy of AIUC-1 with 49 controls, 27 of them marked behaviourally testable; its 43 crosswalk entries are research-derived and still await human review. Through those entries and two probe-level overrides, 14 of the 49 controls have at least one mapped probe in the 118-probe corpus ([pharosone/pharosone](https://github.com/pharosone/pharosone), checked 23 October 2026). A control counts as covered only with evidence from several independent probes, and a control that cannot be tested behaviourally is marked not_testable ([methodology](/research/the-probe-engine-how-we-measure-agent-security)). What each standard asks, and the evidence a reviewer expects, is in the [standards crosswalk](/research/ai-standards-crosswalk): see [AIUC-1](/research/ai-standards-crosswalk#aiuc-1) and the [OWASP Agentic Top 10](/research/ai-standards-crosswalk#owasp-agentic-top-10).

## FAQ

### Do I need an API key to run it?

Not for the offline mock tier, which runs the whole pipeline against a built-in simulated agent with no model, no key, no Docker and no network; it checks the setup and does not test your agent. A scan of your real agent needs model access for the target and for the attacker and judge, read from environment variables and never written to disk or logs. If your agent leaks a secret during a test, the leaked text is kept in the local evidence, so treat the report directory as sensitive.

### What does UNVERIFIED mean in a report?

The engine could not confirm the verdict: the configured judge was unavailable, or an oracle prone to false positives ran without a judge. The evidence is marked UNVERIFIED instead of being read as a pass or a fail.

### Can it certify my agent for AIUC-1?

No. It produces behavioural evidence mapped to AIUC-1 controls, with controls that cannot be tested behaviourally marked not_testable. Certification is issued by accredited auditors.

### What is the difference from the €3,900 assessment?

You run the Framework yourself, on a versioned corpus of probes that includes adaptive scenarios driven by an attacker model you configure, and nobody reviews the result for you. The assessment is run by PharosOne's own attacking agents, a separate system, against the deployment you name, and a PharosOne engineer reviews every finding and signs the report.

### Does a scan send my data to PharosOne?

No. A scan writes its JSON and Markdown report to your machine. The model calls go to the model providers you configure. When an oracle fires, the agent's leaked text or code is kept in the local evidence by design. Streaming conversations to the PharosOne cabinet is a separate, opt-in skill for Pharos Radar, not part of a scan.

### Which agents can it test?

Any agent you can reach. A profile maps the engine's canonical capabilities and channels onto your agent's real tools and inputs, and an adapter wires the engine in. The corpus names no specific product, so the same probes test a support bot or a finance agent.

## Sources

1. [pharosone/pharosone, PharosOne Security Scanner (README)](https://github.com/pharosone/pharosone). GitHub, 2026.
2. [The PharosOne Probe Engine, architecture of a behavioral scanner for AI agents](https://pharosone.ai/research/the-probe-engine-how-we-measure-agent-security). PharosOne Research, 2026-06-24.
3. [Attack-variation policies and LLM-judged scoring, an empirical study on a behavioral scanner](https://pharosone.ai/research/variation-policies-and-llm-judged-scoring-study). PharosOne Research, 2026-06-30.
4. [Inspect, an evaluation framework for large language models](https://inspect.aisi.org.uk/). UK AI Security Institute, 2024.
5. [Probable Inference, the Law of Succession, and Statistical Inference](https://doi.org/10.1080/01621459.1927.10502953). Edwin B. Wilson, Journal of the American Statistical Association 22(158), 1927.
6. [AIUC-1 standard, control list](https://standard.aiuc-1.com/). Artificial Intelligence Underwriting Company, 2026.
7. [OWASP Top 10 for Agentic Applications for 2026](https://genai.owasp.org/resource/owasp-top-10-for-agentic-applications-for-2026/). OWASP GenAI Security Project, 2025-12-09.
8. [OWASP Top 10 for LLM Applications 2025](https://genai.owasp.org/llm-top-10/). OWASP GenAI Security Project, 2025.
9. [pharosone-security-scanner 0.2.0, Python package](https://pypi.org/project/pharosone-security-scanner/). PyPI, 2026-07-16.
10. [pharosone/pharosone, CI workflow (.github/workflows/ci.yml), checked 23 October 2026](https://github.com/pharosone/pharosone/blob/main/.github/workflows/ci.yml). GitHub, 2026-10-23.
11. [NVIDIA/garak, the LLM vulnerability scanner (README and probe modules), release v0.17.1, checked 23 October 2026](https://github.com/NVIDIA/garak). NVIDIA, GitHub, 2026-10-16.
12. [promptfoo/promptfoo (README), checked 23 October 2026](https://github.com/promptfoo/promptfoo). Promptfoo, GitHub, 2026-10-23.
13. [Promptfoo documentation: CI/CD integration, checked 23 October 2026](https://www.promptfoo.dev/docs/integrations/ci-cd/). Promptfoo, 2026-10-23.
14. [Promptfoo documentation: MCP security testing, checked 23 October 2026](https://www.promptfoo.dev/docs/red-team/mcp-security-testing/). Promptfoo, 2026-10-23.
15. [Promptfoo documentation: red team strategies, checked 23 October 2026](https://www.promptfoo.dev/docs/red-team/strategies/). Promptfoo, 2026-10-23.
16. [microsoft/PyRIT, Python Risk Identification Tool for generative AI, release v1.1.0, checked 23 October 2026](https://github.com/microsoft/PyRIT). Microsoft, GitHub, 2026-09-04.
17. [PharosOne pricing](https://pharosone.ai/pricing). PharosOne, 2026-10-22.

Source: PharosOne, "Pharos Framework: free open-source red teaming for AI agents", https://pharosone.ai/knowledge/pharos-framework, updated 2026-10-23.

---

PharosOne is a product of Agentic Mind, Inc., an independent AI agent security company. Site map for agents: https://pharosone.ai/llms.txt
