skip to content

Branching Search

Widening the search into parallel lines finds more and multiplies the query bill per root prompt, while pruning discards the odd line that would have got through. Interviewers ask where you set both.

on this pageshow

explore

questions

4

A branching jailbreak search expands each surviving candidate prompt into b children, prunes each level back to at most w survivors, and repeats for d levels from one seed behaviour. Roughly how many candidate prompts reach the model under test per seed, and how does that count change if you remove the width cap?

level: middleimportance: must knowfreq 46%

answer

  1. width cap turns b^d into w*b*d
  2. cut w before d
  3. candidates != calls, multiply per-node
  4. level 1 costs only b
  5. token bill grows with conversation carry-over

basics

~20 s

With the width cap you send about w times b candidates per level, so roughly w times b times d prompts per seed behaviour, linear in depth. Remove the cap and every child branches again, so the count grows like b to the power of d. The cap is what keeps a deep search affordable.

solid answer

~50 s

The width cap turns exponential expansion into linear expansion. Each level you hold at most **w** survivors, expand each into **b** children, and score them, so a level costs about **w·b** candidate prompts sent to the model under test; over **d** levels that is roughly **w·b·d** (the first level costs only **b**). Drop the cap and every child of every child survives, so the tree is **b^d** — at b=4, d=6 that is thousands of queries for a single seed behaviour, against a metered endpoint, per seed. The practical consequence: **width is the expensive knob, depth is the cheap one** once a cap is in place. If the query bill is too high, cut **w** first — it scales the per-level cost directly — then **b**, then **d**. And remember the candidate count is not the call count: each candidate typically costs an attacker generation and a scoring call as well as the target query, so multiply by that per-node constant before comparing against a query allowance.

go deeper

for a junior

Knows that keeping several candidate prompts alive costs more than refining one, and that there is a cap on how many are kept.

for a middle

Derives wbd with the cap and b^d without it, and knows candidates must be multiplied by per-node calls to get an API bill.

for a senior

Sizes w, b and d against a real query allowance across all seed behaviours, and accounts for retries and per-token conversation carry-over.

for a principal

Treats width, depth and seed count as one allocation problem against an engagement budget and sets the instrumentation that proves where the queries went.

### What the loop is actually doing A branching attacker-model jailbreak search maintains a **frontier**: the set of candidate prompts still alive at the current level. One level runs four steps. 1. An **attacker model** — a separate LLM whose job is to rewrite prompts, never to answer them — is asked to produce **b** variants of each surviving candidate. That count, **b**, is the *branching factor*, and it is set by whatever argument your loop passes to the attacker call. 2. Each variant is sent to the **target**: the model under test. 3. A **scorer** (a judge model, or a rule over the response text) rates each response for how close it came to the behaviour under test. 4. The level's children are ranked by that score and all but the top **w** are deleted. **w** is the *width cap*, also called beam width, and it is enforced at this prune step and nowhere else. Repeat for **d** levels. Published tree-search jailbreak methods are built on exactly this skeleton; the parameter names differ between implementations, the arithmetic does not. Note that step 4 is the only thing in the loop that bounds anything. Delete it and the frontier is simply whatever the attacker produced, which is a full tree. ### The arithmetic ``` level 1 b candidates (one root, nothing to prune yet) levels 2..d w * b candidates each total ~ b + (d-1)*w*b ~ w*b*d (linear in depth) no width cap b + b^2 + ... + b^d ~ b^d (exponential in depth) ``` At b=4 and d=6 the uncapped tree is about 5,460 candidates for **one** seed behaviour; with w=5 it is 104. Same depth, roughly one fiftieth of the traffic. That is the whole reason the cap exists. ### What it costs Candidates are not calls. Each candidate that survives to be evaluated typically costs three model calls — one attacker generation, one target query, one scorer call — so 104 candidates is around 312 calls for one seed. Across 200 seed behaviours that is roughly 62,000 calls. Money is usually the least interesting of the three costs: at a blended cent per call that is a few hundred dollars. Wall clock is what actually decides whether the run fits the engagement — at four requests in flight and three seconds per call, 62,000 calls is about thirteen hours, and that is before any retry. Engineer time is the third: someone has to triage every candidate the scorer flagged. ### Where the number misleads - **Candidate count read as query count.** A report saying "we sent 10,000 prompts" is describing candidates, and the endpoint saw roughly three times that in calls. Size against the allowance in *calls*, not candidates. - **Calls grow linearly, tokens can grow quadratically.** If each level re-sends the accumulated conversation as context, the level-6 prompt carries six turns. Calls stay at w*b*d while the token bill grows with depth squared, so a dashboard reading "60% of query allowance used" can sit beside a token spend already past budget. - **Depth is not coverage.** "We ran a depth-6 search" sounds exhaustive. With w=5 you visited 104 of about 5,460 reachable nodes — under two percent. Depth describes the longest line you explored, not how much of the space you saw. - **Averages hide a blown cap.** A common implementation bug prunes each *parent's* children to w instead of pruning the whole *level* to w. That restores exponential growth, and a mean query count across seeds will not show it — only the per-seed maximum will. - **A per-node constant measured on a well-guarded target is optimistic.** Candidates that get refused early may short-circuit before scoring, pulling the mean below three calls; carry that constant to a weaker target and the estimate is low. ### What to check Assert the frontier size after every prune inside the loop rather than trusting the config value. Instrument queries and candidates **per seed and per level**, with a terminal reason for each seed. Reconcile the run's own call counter against the provider's usage figures for the same window; a gap is retries you are not counting. If the target is priced per token, plot tokens per level — a rising line is conversation carry-over. And do the sizing sum before you start: seeds x w x b x d x calls-per-node against the allowance. If nobody did that arithmetic, the run's size is an accident rather than a decision.

  • Why does the first level cost only b candidates rather than w*b?
    There is one root, so it expands into b children; the cap only starts binding from the second level, once you have w survivors each expanding.
  • You must cut the per-seed bill in half with the least loss of search quality. Which knob?
    Usually w, halving the frontier: it halves every level's cost while leaving the depth of the deepest line untouched. Cutting d instead removes exactly the long refinement chains that produce late hits.
  • When does call count understate the real bill?
    When the target is priced per token and each level re-sends the accumulated conversation, so tokens grow roughly quadratically in depth while calls grow linearly.

Width is lanes and depth is miles: adding a lane costs you material along the entire road, while adding a mile costs you one mile. That is why halving w halves the whole bill and halving d only removes the last few levels.

saying these in an interview costs you the question

  • Says depth is the expensive knob and width is cheap — it is the other way round once a cap exists.
  • Quotes a candidate count as if it were the API call count, ignoring attacker and scoring calls.
  • Cannot say what happens without a width cap (b^d) and treats all tree searches as linear.
  • Sizes the search by wall-clock only and never converts to queries or tokens against the endpoint's price.

context

open as a page

In a branching jailbreak search, candidate prompts are checked for whether they still pursue the behaviour under test, and ones judged to have drifted off-topic are discarded before they are ever sent to the model under test. Why is that off-topic pruning step there, and what does it cost you?

level: middleimportance: should knowfreq 38%

basics

~20 s

It stops the attacker model wandering into prompts that no longer ask for the behaviour you are testing, so the queries you pay for buy relevant attempts. The cost is false pruning: an oblique, apparently unrelated framing is often exactly what slips past a filter, and a strict on-topic check kills it one turn early.

open as a page

A branching attacker-model jailbreak search runs against a metered chat endpoint with a fixed query allowance. It exhausts the allowance while only the first third of your seed behaviours have been searched at all; the rest were never attempted. How do you diagnose that, and what do you change?

level: seniorimportance: should knowfreq 33%

basics

~20 s

The allowance is global and the search walks seeds one at a time, so early seeds spend everything. Confirm it by counting queries per seed and per level. Fix it by dividing the allowance into a per-seed cap, capping frontier width, and stopping a seed early once it hits or clearly stalls.

open as a page

You have a fixed number of queries against the model under test for an engagement and around two hundred seed behaviours to search with a branching attacker-model loop. How do you decide between a shallow wide pass over all of them and a deep search on a chosen few, and what makes that decision defensible to the team reading the report?

level: principalimportance: should knowfreq 24%

basics

~20 s

Run shallow across everything first, then spend the remainder deep on the behaviours that showed partial movement. Wide answers which behaviours are reachable at all and gives an honest coverage denominator; deep answers how hard a specific one is. Decide by which claim the report has to support, and write the split down beforehand.

open as a page