Foxy Audit
Book a demo
← The manual

Configuration

Every setting the SDK reads, in one table: what it does, its default, an example, and when to change it.

Skip to the chapter
All chapters

What you'll learn

  • the two ways to give the SDK a setting, and which one wins;
  • every FOXY_* setting, in one table;
  • the settings you can only give in code;
  • how to keep your settings when you close the terminal;
  • recipes for common setups.

Two ways to give a setting

You can give most settings in two ways:

  1. In code, as an argument: FoxyClient(mode="block").
  2. In the environment, as an environment variable: FOXY_MODE=block.

When both are given, the code wins. When neither is given, the SDK uses the default. So the order is: argument, then environment variable, then default.

A setting the SDK cannot read, such as a misspelled value in the environment, falls back to its default, and your program starts as usual. Two things do stop a client from being made, with an error at once:

  • a mistake in code, such as a plain http:// address to another machine passed as endpoint;
  • with an API key set, a spool file in a folder your program cannot write to.

Every setting

Setting What it does Default Example When to change it
FOXY_API_KEY Your API key. With it, records are sent to Foxy Audit. none: records are not sent YOUR_API_KEY Always, to send records.
FOXY_BACKEND_URL Where records are sent. Give the base address, with no path after it. http://127.0.0.1:8000, a backend on this machine https://app.foxyaudit.tech Always, to use Foxy Audit's service.
FOXY_ALLOW_INSECURE Lets the key go over plain http:// to another machine. off 1 Almost never: only on a private test network.
FOXY_MODE What happens when a prompt check fires: observe, block or redact. observe block When you are ready to stop risky prompts. See Modes.
FOXY_RESPONSE_SCAN What happens when the answer check fires: observe, block or off. observe block For regulated data. See Response scanning.
FOXY_AUDIT_REQUIRED Makes a call fail when its record cannot be confirmed. It needs an API key: with none, nothing is sent, so an error is logged and it stays off. false true When a call must never go unconfirmed.
FOXY_COMMITMENT_KEY The key used to make your hashes. the key in the SDK's key file YOUR_COMMITMENT_KEY In a container or a serverless function, whose disk does not last. Keep the key in a secret store. See below.
FOXY_COMMITMENT_KEY_FILE Where the SDK keeps its own commitment key. commitment.key, next to the spool /data/foxy/commitment.key When the spool's folder is not where you keep a secret.
FOXY_SALT_SIDECAR Turns on salts, and names the file where they are kept. not set: no salts /var/lib/foxy/salts.jsonl For extra protection of short prompts. See The evidence model.
FOXY_SPOOL_PATH Where the spool file is. ~/.foxy-audit/spool.sqlite3 /data/foxy/spool.sqlite3 In a container, or on a shared server.
FOXY_SPOOL_MAX_ROWS How many records may wait, for each key and address. 0 means no limit. 100000 250000 Rarely. See The spool and delivery.
FOXY_SPOOL_RECEIPT_TTL How many seconds to keep delivery receipts in the spool. 0 keeps them for ever. 604800, which is 7 days 86400 Rarely, to keep the spool smaller.
FOXY_CLIENT_ID A fixed name for this installation in the ledger. Letters, digits and _ . : -, up to 128 characters. Any other name is logged as an error and not used. made up once for each key and address, and kept in the spool billing-service-1 When you want to recognise a machine in your records.
FOXY_SYSTEM_ID Which of your AI systems these records belong to. not set: no system an id that GET /v1/systems returns When your workspace lists more than one AI system.
FOXY_ORG_POLICY Whether to read your workspace's enforcement setting. on off On a machine with no internet, or when only your code should decide.
FOXY_ORG_POLICY_TTL Seconds between reads of the workspace setting. 300 60 Rarely.
FOXY_INJECTION_CLASSIFIER Turns the injection classifier on or off. The pattern rules always run. on off When very long prompts make it too slow. See below.
FOXY_OLD_API_KEY Your old key, for foxy spool rekey only. not set: the command asks for it YOUR_OLD_KEY When you move waiting records to a new key.

Case and spaces around the value do not matter, but the words do:

  • FOXY_AUDIT_REQUIRED is on for 1, true, yes or on, and off for 0, false, no, off or nothing. Any other value leaves it off, and says so in the log.
  • FOXY_ALLOW_INSECURE is off unless the value is 1, true or yes. Any other value, even on, leaves it off.
  • FOXY_ORG_POLICY and FOXY_INJECTION_CLASSIFIER are on unless the value is 0, false, no or off. Any other value leaves them on.

Your commitment key. Your hashes are made with a key of your own, which Foxy Audit never sees. If you set none, the SDK makes one when a client first starts with an API key. It keeps the key in a file called commitment.key, next to the spool, and only you can read it. Every program that shares the spool uses the same key.

Back that file up. foxy explain needs the key to prove a record later. Without it, you cannot prove which text a record's hashes came from. The chain still checks out without it.

In a container or a serverless function, the disk does not last, so a new key would be made at each start. There, set FOXY_COMMITMENT_KEY from your secret store, or mount the key file from a volume that lasts.

If the key file can be neither read nor made, the SDK uses your API key, and logs a warning. It also warns when FOXY_COMMITMENT_KEY is your API key, because Foxy Audit receives that key with every request.

With audit_required=True in your code, the SDK is strict about this. If the key file can be neither read nor made, the client does not start: it raises an error that says why and how to fix it. With FOXY_AUDIT_REQUIRED instead, the SDK logs an error and goes on with your API key.

Settings you give in code only

A few settings have no environment variable. You pass them to FoxyClient(...):

Argument What it does Default
on_event a function the SDK calls after each call, with a receipt none
timeout how many seconds a call waits for its record to be confirmed when audit_required is on (at least 1), and how long a read of your workspace's setting may take 5.0
desktop_ping whether to send signals to the optional desktop app True
udp_host, udp_port where the desktop app listens 127.0.0.1, 9999

The environment settings above can also be given in code, with the same names in lower case: api_key, endpoint (for the backend URL), mode, response_scan, audit_required, commitment_key, commitment_key_path (for the key file), salt_sidecar_path, spool_path, client_id, system_id and injection_classifier.

Five environment settings have no argument on FoxyClient: FOXY_ALLOW_INSECURE, FOXY_ORG_POLICY, FOXY_ORG_POLICY_TTL, FOXY_SPOOL_MAX_ROWS and FOXY_SPOOL_RECEIPT_TTL. They belong to whoever runs the machine, not to the code, so you set them in the environment. FOXY_OLD_API_KEY is read only by foxy spool rekey.

Step 1: Keep your settings

A setting you type in a terminal lasts until you close it. To keep it, put it where your program starts:

  • On a server, set it in the service's own settings, for example the environment section of a service file or a container's environment.
  • On your own computer, add the export lines to your shell's start-up file. On Windows, open Start and search for "Edit environment variables for your account".

Keep your API key out of your code and out of version control. Anyone who has it can write records into your ledger.

Step 2: See what the SDK is using

Python
from foxy_audit import FoxyClient

foxy = FoxyClient()
print(foxy.enabled, foxy.cfg.endpoint, foxy.cfg.mode)

What you should see, with nothing set:

False http://127.0.0.1:8000 observe

foxy.enabled is True when an API key is set, which means records will be sent. foxy.cfg holds every resolved setting. It is read-only. To change a setting, make a new client.

The backend address, in detail

The SDK sends your API key with every request, so it is careful about where the key goes:

  • An https:// address is fine, to any machine.
  • A plain http:// address is allowed only to this machine: 127.0.0.1, ::1, or localhost. A name that happens to point at this machine is not enough; write 127.0.0.1.
  • A plain http:// address to any other machine is refused, unless you set FOXY_ALLOW_INSECURE=1.
  • An address that two parts of Python would read in two different ways is always refused, even with FOXY_ALLOW_INSECURE.

Where the address came from changes what a refusal looks like:

Where you set it What happens when it is refused
FoxyClient(endpoint=...) in code an InsecureEndpointError straight away
--backend on a foxy command the command prints why, and exits 2
FOXY_BACKEND_URL one error in the log. Your program keeps running, records are kept in the spool for that address, and nothing is sent there. foxy doctor exits 2.

The SDK never follows a redirect when it sends your key. If your backend answers with a redirect, set the address to the place it redirects to.

Records are kept for the address they were made for. After you change the address, records made for the old one stay in the spool, and a notice in foxy doctor counts them. Move them to the new address with foxy spool rekey --from-backend <the old address>, with FOXY_OLD_API_KEY set to your key. See If your API key changes.

The response scan and regulated data

FOXY_RESPONSE_SCAN controls the check on the model's answers. It is observe by default, so it records findings and never stops an answer. For PHI and other regulated data, set block: then an answer the scan flags never reaches your code. The scan is a set of patterns, so an answer that does harm in a way no rule matches still gets through. What block costs is explained under Which to choose in Response scanning.

The injection classifier's cost

The classifier runs on your machine, before the model call, and its cost grows with the length of the prompt. Here is how long the whole prompt check took, measured on one development laptop on 2026-09-30, with Python 3.13, best of three:

Prompt length With the classifier With the classifier off
2 KB 7.8 ms 4.4 ms
8 KB 31.8 ms 16.3 ms
64 KB 259 ms 139 ms
256 KB 1,080 ms 592 ms

These numbers are from one machine on one day, so measure your own. There is no length limit, on purpose: a limit would give an attacker a place to hide. If your prompts are very long and speed matters more than this check, set FOXY_INJECTION_CLASSIFIER=off. The six pattern rules keep running.

The setting belongs to each client. check() and the foxy command read the environment variable.

Recipes

Trying it out, with no account: set nothing. Checks and hashes run on your machine, and nothing is sent.

Connected, for a first test:

Terminal
export FOXY_API_KEY="YOUR_API_KEY"
export FOXY_BACKEND_URL="https://app.foxyaudit.tech"

Regulated work, where every call must be recorded:

Terminal
export FOXY_API_KEY="YOUR_API_KEY"
export FOXY_BACKEND_URL="https://app.foxyaudit.tech"
export FOXY_MODE=block
export FOXY_RESPONSE_SCAN=block
export FOXY_AUDIT_REQUIRED=true

In a container: add a lasting volume, and point the spool at it.

Terminal
export FOXY_SPOOL_PATH=/data/foxy/spool.sqlite3

No internet, or only your code decides:

Terminal
export FOXY_ORG_POLICY=off

If it goes wrong

What you see Why What to do
Records are not sent, and no error FOXY_API_KEY is not set where the program runs Print foxy.enabled. Set the key in the program's own environment.
InsecureEndpointError A plain http:// address to another machine, in code Use https://.
An error in the log about FOXY_BACKEND_URL, and records waiting The same, set in the environment Fix the variable, and new records go out. The waiting ones were made for the old address: move them with foxy spool rekey --from-backend <the old address>.
A setting seems to be ignored An argument in code wins over the environment variable Remove the argument, or change it.
FOXY_AUDIT_REQUIRED=... is not a value the SDK reads, in the log A word other than 1, true, yes or on Use true.
ValueError when the client is made, saying audit_required=True needs an API key audit_required is on in code, and no key is set Set FOXY_API_KEY, or leave audit_required off.
An error in the log: FOXY_AUDIT_REQUIRED is on, but there is no API key The same, set in the environment Set FOXY_API_KEY. Until then nothing is recorded, and no call fails.
ValueError about client_id, or an error in the log about FOXY_CLIENT_ID The name has a character the backend refuses, or is over 128 characters Use letters, digits and _ . : -.
ValueError about system_id The id is not written exactly as GET /v1/systems returns it Copy the id from that answer. The decorator and the client shows how.
An error when the client is made With a key set, the spool file's folder cannot be written to Point FOXY_SPOOL_PATH at a folder your program can write.