Tuning Personas, Keywords, and Strength Presets
A honeypot that looks wrong catches nothing. This recipe walks through the three knobs that decide whether hostile agents take the bait: the persona they think they're talking to, the keywords that trigger escalation, and the strength preset that sets the price of compliance.
Persona design
persona changes every engagement payload and the UI title on every runtime:
TokenTrap.init({ container: "#trap", persona: "Acme Support AI" });
PERSONA = "Acme Support AI" # worker wrangler.toml
tokentrap serve --persona "Acme Support AI" # python
Rules of thumb:
- Boring beats clever. "Internal AI Assistant", "Acme Support AI", "IT Helpdesk Bot". The persona should look like infrastructure that is supposed to exist.
- Match the page it lives on. A support widget on a support page. A docs assistant next to your API reference. Context mismatch makes agents (and their operators reading logs) suspicious.
- Never name the mechanism. Nothing about traps, tarpits, or tokens in the persona.
Turn 0's engagement payload asks visitors for three things - goal, background, output format. That structure reads as professional thoroughness for any plausible enterprise assistant, which is exactly why it extracts another attacker round-trip.
Detection keywords
The default list is 44 phrases covering classic jailbreaks (act as dan, do anything now, developer mode), system-prompt exfiltration probes (reveal your system prompt, print your system prompt), and special tokens (<|im_start|>, <<sys>>, [inst]). Matching is case-insensitive substring with whitespace collapsed first, so ignore previous instructions still fires.
Append to defaults
new TokenTrap({ injectionKeywords: ["engage hyperdrive", "company confidential protocol"] })
TrapConfig(extra_keywords=("engage hyperdrive",))
tokentrap serve --extra-keywords "engage hyperdrive,company confidential protocol"
Replace entirely
new TokenTrap({ injectionKeywords: ["my-list-only"], overrideInjectionKeywords: true })
Python: override_keywords=True / CLI --override-keywords.
Strategy notes:
- Appending is almost always right. The defaults are a decent baseline even when noisy.
- False positives only make the tarpit more aggressive - the desired failure mode. A legitimate user who types "jailbreak" in a support chat gets a compliance notice instead of an answer; on a pure trap page there are no legitimate users anyway.
- If the page doubles as a real assistant surface, prune aggressively instead:
override_keywords=Truewith a tight list keeps real users out of compliance envelopes while still catching the obvious probes. - Inspect what matched at runtime:
meta.matchedKeywordslists every trigger phrase found in the message. Mine those lists monthly to grow your own vocabulary.
Choosing a strength preset
| Strength | Turn-1 directive | Escalated directive | Personality |
|---|---|---|---|
| moderate | transcript x2 + 3,000 words | x6 + 8,000 words | polite deterrent |
| aggressive (default) | x3 + 4,000 words | x10 + 15,000 words | standard tarpit |
| maximum | x4 + 6,000 words | x16 + 25,000 words | scorched earth |
How to pick:
- aggressive everywhere by default. It's the tested middle: expensive enough to hurt, cheap enough that compliant agents don't hit context walls instantly and give up.
- maximum for pages where no legitimate traffic ever lands - canary pages, decoy subdomains, bait endpoints behind
/v1/. - moderate if you run a real assistant alongside the trap and want misdirected humans to suffer less.
Remember the escalation ladder means most sessions reach the escalated numbers quickly anyway: any detected injection jumps straight to max, and turn >= 2 escalates regardless. The preset mostly tunes how fast the early ladder climbs.
Changing presets mid-flight is one config value on all runtimes (trapStrength / TRAP_STRENGTH / --strength). The numeric table itself lives in STRENGTH_PRESETS - identical constants in TypeScript (src/types.ts) and Python (traps.py). Editing the numbers means editing both copies together, or the parity tests will fail, which is exactly what they're for.
Canary token hygiene
Covered deeply in the forensics recipe, but the tuning summary:
- Tokens rotate per turn across your list (
token[turn % len]) - more tokens means finer session fingerprinting. - Boring names (
audit-ref-7734) beat descriptive ones (canary-honeypot-tag). - Any inbound message containing a token = replayed trap output = automated pipeline confirmed (
canaryEchoed: truein logs,x-tokentrap-canary-echo: trueheader).
Verifying your tuning
After changing any knob, verify the trap end-to-end rather than trusting config:
- Open the deployed page.
- Send a benign message - expect the engagement payload (turn 0).
- Send a second benign message - expect a base-strength directive.
- Send a message containing one of your triggers - expect instant escalation to the preset maximum, R5 flag present, your keyword in
meta.matchedKeywords. - Check logs (
wrangler tail/ stdout JSON) show the same fields server-side.
Five minutes of clicking saves hours of wondering whether the env var actually applied.