Using falsepass from an agent#
falsepass is built to be driven by a coding agent as much as by a person. Every command is non-interactive, writes its results to files, and has a machine-readable form. There are three ways in, from most to least structured.
1. MCP server#
falsepass mcp serves the commands as tools over stdio. Any MCP client can start it
without installing anything first:
uvx --from "falsepass[mcp]" falsepass mcp
For Claude Code:
claude mcp add falsepass -- uvx --from "falsepass[mcp]" falsepass mcp
For clients configured with JSON (Cursor, Claude Desktop, and others):
{
"mcpServers": {
"falsepass": {
"command": "uvx",
"args": ["--from", "falsepass[mcp]", "falsepass", "mcp"]
}
}
}
| Tool | Arguments | Returns |
|---|---|---|
falsepass_scan |
path |
static hints for a source folder or file; nothing is installed |
falsepass_init |
target (Hub id, local folder, Inspect task, HUD folder); optional name, version, framework, task, answers, extra, manual, force |
{"name": ..., "folder": ..., "framework": ..., "env": {...}, "next": ...}: name is what the other tools take |
falsepass_audit |
env, n (tasks, default 25), search (mutation budget), wait (seconds, default 45) |
the results digest below with "status": "finished", or "status": "running" if the audit needs longer |
falsepass_audit_status |
env, wait |
the same, for an audit already started: results, or "running" with the latest progress lines |
falsepass_results |
env |
the digest of the last run (progress instead while one is running) |
falsepass_completion |
env, completion_id |
the full text of one completion; the digest shows only its start and end |
falsepass_repro |
env, probe (e.g. ["P5"]) |
where the stand-alone repro script was written |
falsepass_discover |
days, limit |
recently maintained Hub environments and what each needs |
Every tool takes workdir; audits are created in workdir/audits/<name>/.
An audit installs the environment before it probes it, so it can take several minutes,
longer than many clients allow for one tool call. It therefore runs in the background:
falsepass_audit waits up to wait seconds and either returns the results or
{"status": "running", "elapsed_s": ..., "log_tail": [...]}. Call
falsepass_audit_status with the same env until it finishes. Calling
falsepass_audit again while one is running doesn't start a second audit. The job is
recorded in audits/<env>/job.json, its output in audits/<env>/job.log.
When something goes wrong (no such audit, a failed install, a dataset that needs a
login), the tool returns an MCP error whose text says what happened and what to try
next, so a client sees isError and the reason without reading server logs. Names are
forgiving: arc_easy finds the audit init named arc-easy.
For a HUD environment, pass reference answers with answers: a JSON file holding either
an object from task slug to answer ({"add-2-3": "5"}) or a list in task order. Without
it only the answer-free probes run. Adding answers to an existing audit takes
force: true. uv must be
on the PATH: each audit installs the environment in its own throw-away virtualenv.
2. Agent skill#
skills/falsepass/SKILL.md is the whole audit procedure in
the Agent Skills format: run, read the numbers, confirm a lead before claiming it, decide
defect or design, and write it up for the maintainer. Copy the folder into the agent's
skills directory (for Claude Code, ~/.claude/skills/) and ask the agent to audit an
environment.
3. Plain CLI#
falsepass init owner/environment # or ./folder, task.py, inspect_evals/<task>, a HUD folder
falsepass audit environment --fail-on 'ceiling>0.1' # exit 1 when the condition is met
falsepass results environment --json # compact digest, small enough for a context window
falsepass scan path/to/source --json # static pre-scan only
The digest from results --json and from the MCP audit tools (abridged):
{
"environment": "owner/env",
"headline": {"false_pass_ceiling": 1.0, "false_pass_via": "P5 shotgun/all_in_one_slot",
"lazy_policy_reward": 0.0, "false_fail_rate": 0.108, "scoring_errors": 0},
"failing": [{"probe": "P5", "variant": "all_in_one_slot", "runs": 10, "failed": 10,
"completion": "start of the completion … [316 chars] … its end, where the answer is",
"completion_id": "da79bcea66a8"}],
"static_hints": ["..."],
"note": "Leads, not findings: ..."
}
All fields are described in Output files.
Games, simulations and tool tasks#
Automatic mode needs a reference answer it can write into a reply. A game, a
customer-service simulation or a tool task has none: the reward depends on what the model
does over several turns. There, an audit ends "status": "inconclusive" (the reference
and an empty reply earned about the same) or, for tool tasks, runs only the generic tool
policies. The digest then lists only facts_that_hold: rows built without the answer,
such as "an empty reply earned 1.0 on 20 of 20 tasks", which are true either way.
The next step is to write policies, which takes a capable agent a few minutes per environment:
falsepass init owner/environment --policies --force # adds adapter.py: a policy skeleton
A policy is a function from the conversation so far (a list of {"role", "content"}
dicts) to the next assistant message, either a string or
{"content": ..., "tool_calls": [{"name": ..., "arguments": {...}}]}. With
Policy(name, act, wants_tools=True) it also gets the tool schemas. Each policy runs
through the environment's own rollout loop and rubric. Fill in:
solver(example): a policy that does the task properly (it may read the row's answer). It should earn full reward; setmax_rewardto what it earns.gives_up(example): plays honestly without solving. It should earn nothing.exploits(example): policies that never use the answer. The skeleton starts from the ready-made ones infalsepass.policies, each of which found a real hole:after_the_end(wrong, say)(answer wrong, then repeat what the environment gives away),keeps_talking(first)(carry on after "game over"),never_acts(). Adapt their messages to the environment's format.special_number_scripts(example): one message sequence the environment accepts;policies.special_numbers()turns it into variants withnan,inf,-1,1e999and-0in place of its numbers (ids such as#1234are left alone). A limit written asamount > LIMITis false for NaN.
Then run falsepass audit <env> as usual. Each policy's episode (what it said, and the
whole conversation) is kept: falsepass_completion shows it, and falsepass repro
replays the policy's turns as a fixed script, so a lead found by a policy is reproduced
without falsepass.
Reading the output#
false_pass_ceilingnear the maximum: some known-bad completion was paid.failingsays which probe and variant.lazy_policy_rewardabove zero: one fixed strategy that never uses the answer earns that much on average. On a closed answer set (yes/no, A–J), subtract what one fixed label earns under any correct grader.false_fail_rate: correct answers refused. Some of it is deliberate strictness.static_hintswithverdict: confirmed: the line that most likely causes a failure.
Rules worth giving your agent#
The output is a list of leads. Before an agent reports anything:
- Read the whole completion if the preview isn't enough:
falsepass_completion(orfalsepass results <env> --completion <id>). - Reproduce it:
falsepass repro <env> --probe P5writes a script that depends only on the environment's own packages. Run it twice from a clean virtualenv. - Find the line in the reward code that causes it.
- Decide whether it is a defect or a design choice. A grader that is exploitable on purpose, or strictness the prompt asks for, is not a bug.
- Measure how many of the environment's own tasks it affects. The audit samples 25 tasks by default; the repro script is the place to extend it to the full dataset.
Don't let an agent call an environment broken on the strength of a probe table, and don't let it file issues on other people's repositories without a person agreeing.
Text versions#
Every page on this site is also published as Markdown (link at the bottom of each page),
and llms.txt / llms-full.txt
index all of them.