Labs · Prompt assembly
Drop in a preset, a card, a worldbook —
see how one prompt gets built.
“Why isn’t my preset working”, “the entry fired but never showed up”, “who decides the order” — the three unsolved cases of every tavern player, and they all trace back to assembly, where the tavern itself only shows you a collapsed JSON blob. Load any combination of preset, character card and worldbook here and replay the moment you hit send: every piece colored by origin, every lorebook entry accounted for, the token budget draining layer by layer. Ported function-by-function against SillyTavern 1.18. Runs entirely in your browser.
Preset
optionalDrop or pick a JSON
No preset = tavern's built-in default order (main → world info → card fields → history → PHI).Character card
optionalDrop or pick PNG / JSON / charx
Worldbook
optionalDrop or pick a JSON
Drop a preset, a card and a worldbook into the three slots above — all optional, whatever you load gets assembled.
Or start with the demo:
How do you inspect a real prompt without opening the tavern?
Drop your preset JSON, character card (PNG/JSON/charx) and worldbook JSON into the three slots above — all optional — and type the message you’d send. The result lists every message in send order; expand one to see which segments built it, which file and field each segment came from, and what the macros looked like before expansion. The overview strip up top draws the whole context window to scale — preset blocks, card fields, worldbook, history, each sized by its token share. Change any input and the assembly re-runs live.
Where this tool comes from
Assembly semantics were checked function by function against SillyTavern 1.18 source: prompt_order as the final message order, marker filling and end-appending of missing markers (preparePromptsForChatCompletion), card system_prompt replacing main (with {{original}} and forbid_overrides), order groups and role merging for @depth injections (populationInjectionPrompts), newest-first budget packing for history (populateChatHistory), all-or-nothing example blocks (populateDialogueExamples), and the eight worldbook positions with ascending-order joining (the tail of checkWorldInfo).
The activation engine is shared with this site's lorebook trigger simulator (aligned against the app-side activator pinned by 60+ unit tests); the macro engine is shared with the macro playground; token estimation uses the card checkup's convention. On top sit 85 golden self-tests for the assembly layer itself — trunk order, card overrides, injection depths, budget trimming, and structural invariants on real community files. Ported 2026-07.
What it can't do
The worldbook's own token budget isn't simulated (the tavern gives entries 25% of context by default and trims by priority when exceeded) — the page warns when activated entries pass that watermark, but shows everything injected. Regex scripts don't enter the assembly (that's the regex tester's job); sticky/cooldown are cross-turn state and get treated as stateless here.
Chat Completion track, normal generation only: group chats, continue/impersonate/quiet types, extension injections (summaries, vector memory) and the squash-system-messages toggle are out of scope. Tavern versions keep drifting — this page is pinned to 1.18 semantics; edge behavior follows whatever build you actually run.
Token counts are a character-ratio estimate (CJK ≈ 1.6 chars/token, Latin ≈ 4, plus 4 tokens of chat-format overhead per message), not the model's tokenizer — trim decisions near the budget edge may differ from a real run by a message or two.
FAQ
Why does my preset block seem to do nothing?
Four usual suspects, all flagged directly by this tool: ① the block is defined but never placed in prompt_order — per tavern semantics it's inert, and the inspector lists it under preset-block diagnosis; ② the block is disabled in the order; ③ it's set to absolute injection (injection_position=1), so it doesn't sit at its trunk position at all — it gets spliced into chat history N messages from the end; ④ your main block got silently replaced by the character card's system_prompt — that's default tavern behavior (prefer character prompt), and the inspector badges the replaced main as “card override”.
My worldbook entry fired — why is the content still missing from the prompt?
Firing and delivery are two different things, with four gates in between: the preset disabled the World Info marker (content dropped entirely); the marker isn't in the order at all (content gets appended to the very end of the prompt — real tavern behavior, rarely what anyone wants); an @depth entry got cut during token packing; or the order has no Chat History marker, so @depth injections have nowhere to land. This page gives every entry a verdict: where it went, or which gate stopped it.
Where exactly does an @depth injection land?
Count backwards from the newest message: depth 0 sits at the very end, depth 2 sits two chat messages up, and injected messages themselves don't count toward depth. Multiple injections at the same depth, order group and role merge into one message (preset blocks first, then worldbook/author's-note extensions); different order groups stay separate, higher numbers first. All of it replicates SillyTavern 1.18's injection code — and you can see every landing spot in the assembled result.
Will the simulation match a real send exactly?
The trunk semantics match: prompt-manager order, marker filling, card overrides of main/jailbreak, all worldbook injection positions (before/after/@depth/examples/author's-note/outlet), macro expansion, and the budget-packing order — each checked function by function against SillyTavern 1.18 source. A few layers are deliberately out of scope: the worldbook's own budget trimming (25% of context by default — you get a warning when activated entries exceed it), regex scripts, cross-turn sticky/cooldown, group chats, continue/impersonate generation types, and extension injections. Token counts are a character-ratio estimate, not a real tokenizer. Full list under “What it can't do”.
Are my preset and card uploaded?
No. Parsing, entry scanning and assembly all run in your browser — the page keeps working offline once loaded. That's why you can drop a whole novel-sized worldbook in: there's no server in the loop.