feat: authorize keyword triggering instead of forcing it (addresses #88, #89) - #93
Merged
Merged
Conversation
Reframes keyword/effort triggering from 'force a workflow' to 'arm the tool and let the model decide', addressing #88 (over-triggering), #89 (triggered runs going idle instead of staying interactive), and cutting the always-on prompt (part of #65). - buildForcedWorkflowPrompt -> buildArmedWorkflowPrompt: the trigger now injects an authorize directive ('typing the word is explicit opt-in; if it's a request call workflow, if it's a question just answer -- the opt-in does not force a workflow') instead of 'You MUST / the ONLY acceptable action / Do NOT answer'. A lexical false-positive is no longer amplified into a forced wrong action. - #89 falls out of de-forcing: the idle was a downstream effect of the model being told to emit nothing but one bare background workflow call (which ends the turn). Handled in a normal turn, Pi stays interactive and the model can fold results inline. No change to the tool's background machinery. - Always-on prompt shrunk ~91% (6500 -> ~600 bytes): the ~20 'For workflow,' how-to lines moved off the always-on promptGuidelines into workflowHowToGuidelines(), injected into the message only on an armed turn; the always-on guideline is now a single gate line. Cuts self-priming and the always-on token cost, and stops churning the prompt-prefix cache. - byEffort path de-forced too, with an explicit conversational-turn escape. - Kept: keywordTriggerEnabled default ON (under authorize semantics the worst case is just an armed-turn directive), the #79 boundary regex, rainbow highlight, Backspace-to-disarm. README updated (force -> arm). 914 tests; always-on prompt budget ratcheted 6500 -> 650.
- Move the how-to mechanics from the per-armed-turn message into the workflow tool's static description, so the model has the manual on every arming path AND on off-keyword natural-language opt-ins, cacheably, not as per-turn priming (P2). Always-on promptGuidelines stays the single gate line. - buildArmedWorkflowPrompt now leads with the decision boundary, states the truthful opt-in reason per path (keyword vs standing-effort), and carries the #89 background/deliver-back reassurance so an ending turn reads as expected, not a stall (P1, P3). - /workflows run uses a distinct forcing directive (no question-escape) while avoiding the old MUST/ONLY language (P5). - Gate line gains task-shape positives, balancing the strong negative (P4). - Tests: trigger regression corpus (negatives/positives), gate-line R3, how-to now in tool description, armed-directive content, /workflows run forcing; honest prompt-budget ratchets (always-on ~766B, tool def grows to ~8.8KB as a MOVE, armed message drops ~6.8KB -> ~0.9KB; how-to trimming is #65, separate).
…ool default-active
The how-to now lives in the tool description, so a bare natural-language opt-in
('fan this out') sees the mechanics only if the host keeps the workflow tool in
its default active set. The arming paths add it on arm; document the dependency.
This was referenced Jul 18, 2026
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reframes keyword/effort triggering from force to authorize — the trigger arms the
workflowtool and lets the model decide, instead of rewriting the message into "You MUST / the ONLY acceptable action / Do NOT answer". Addresses #88 (over-triggering) and #89 (triggered runs going idle), and cuts self-priming (contributes to #65).What it does
buildArmedWorkflowPromptleads with the decision boundary (a question / trivial task / just talk → answer directly; a real decomposable request → callworkflow) and states the true opt-in reason per path (keyword vs standing-effort — no longer falsely claiming "you typed the trigger word" on the effort path). No MUST/ONLY/Do-NOT-answer.BACKGROUND_DELIVERY_REASSURANCEclause on all arm paths tells the model a background run legitimately ends the turn and its result auto-delivers back — "expected, not a stall" — and to usebackground:falseonly when the user is waiting inline. The idle was the model being told to emit one bare background call with no signal that turn-end is normal; this closes it.description(a static, cacheable part of the tool definition), removed from the armed message — so the mechanics are available on every path that calls the tool, including natural-language opt-ins ("fan this out") that don't trip the literal keyword, instead of only on keyword-armed turns./workflows runstays a force (explicit command → distinctbuildForcedWorkflowPrompt, no question-escape) but without the old hostile language.Honest sizing (a move, not a saving)
Trimming the how-to text itself is separate work (#65 / contract concision), not this change — no token saving on the definition is claimed.
Tests
Trigger regression corpus (negatives: URLs, camelCase, hyphens, filenames,
/workflows list; positives:run a workflow to…,workflow:, a CJK phrasing) at the lexical + directive layers; how-to-lives-in-description assertions; #89 reassurance present on all paths; decision-first ordering; per-path truthful reason;/workflows runforces without hostile language. 929 tests pass; tsc + biome clean.Addresses #88 and #89; reduces self-priming toward #65.