docs(static-variables): add prompt-injection threat model and trust tiers#1035
Merged
dhruva-reddy merged 1 commit intodr/squads-passing-data-between-assistantsfrom Apr 29, 2026
Conversation
…iers Expands tools/static-variables-and-aliases.mdx with the security framing that customers building progressive-authentication flows need: - Lead with the naming distinction between function.parameters (LLM-facing JSON schema) and the top-level parameters array (server-merged, LLM-invisible). The dashboard surfaces both as similarly-named sections, which has bitten customers. - Document the full Liquid variable bag in three trust tiers: Tier 1 server-trusted (customer.*, phoneNumber.*, transport.*, call.*, assistant.*, time, assistantOverrides.variableValues set at call start), Tier 2 conversation-derived (messages, transcript, prompt -- not safe as a security boundary), Tier 3 LLM-derived (variableExtractionPlan aliases from non-trusted sources, handoff arguments, handoff schema extraction). - Five common failure modes with bad/good code pairs covering the patterns that defeat the security boundary (defining the trusted field in function.parameters; body-default leak; system-prompt forwarding; unsafe alias chains; mid-call bag mutation). - Worked example for caller-ID-based progressive authentication. - Tool-type support matrix, plus an explicit warning that legacy assistant.model.functions[] does NOT support static parameters. - Cross-link to /squads/passing-data-between-assistants for the three-approaches handoff guide; flag the squads guide's Approach 1 (function.parameters on handoff) as not-a-security-boundary for signaling-derived values. - Document the known limitation that destination.assistantOverrides .variableValues is not Liquid-resolved at handoff time. - Dashboard mental model: Parameters (JSON schema editor) vs Static Body Fields (key/value rows with Liquid). Surfaced by Mudflap asking how to do progressive auth without giving the LLM a path to forward a fake caller-ID. Skipped: workflow-extraction failure mode (workflows are deprecated). Skipped: test-writer / code-reviewer (docs-only PR, per write-pr rules).
Contributor
|
🌿 Preview your docs: https://vapi-preview-e8f5b949-7836-4efc-904b-e1bcd4516401.docs.buildwithfern.com |
roshan-vapi
approved these changes
Apr 29, 2026
3bbefdb
into
dr/squads-passing-data-between-assistants
6 checks passed
This was referenced Apr 29, 2026
dhruva-reddy
added a commit
that referenced
this pull request
Apr 29, 2026
…stic ≠ invisible (#1038) Two combined goals -- the previous PR #1035 was orphaned by an inverted merge order (parent #1033 squash-merged to main 25 seconds before child #1035 squash-merged into the parent's branch, so #1035's content was applied to a branch that was already obsolete and never propagated to main). This restores that hardening AND fixes wording the user flagged in review of the original page. Recovers from orphaned commit 3bbefdb the full PR #1035 hardening work: trust tiers (Tier 1 server-trusted, Tier 2 conversation-derived, Tier 3 LLM-derived), five common failure modes, prompt-injection threat-model framing, dashboard mental model, handoff-data-forwarding section, legacy assistant.model.functions[] footgun warning, the 'Static parameters as a security boundary' section, and the worked caller-ID example. Wording fixes applied on top of that recovery, eliminating language that conflated two different guarantees -- (1) static parameters are truly LLM-invisible (server-merged into the request body, never in the schema sent to the model) vs. (2) variableExtractionPlan aliases chain values across tools deterministically but the source response IS in the LLM's context (it was added to conversation history as a role: tool message). Specific changes: - Subtitle (line 3): split the two guarantees, no longer claims both are 'without LLM involvement' - Intro bullet (line 19): 'deterministically -- the next tool gets the correct value regardless of how the LLM behaves between calls' - Deterministic tool chaining intro (line 457): rewritten + new Warning callout explicitly stating 'Deterministic does not mean invisible' with the specific code-level claim that Tool A's response is added to the LLM's role:tool message history - Tips section: new bullet 'Aliases are a determinism primitive, not an invisibility primitive', flagging that hiding values from the model requires the tool server to omit them from the response body in the first place Skipped: test-writer / code-reviewer (docs-only PR).
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.
Description
Stacked on top of #1033 (
dr/squads-passing-data-between-assistants). Targets the static-variables-and-aliases page; the squads page in #1033 stays scoped to its own concern.Surfaced by an FDE conversation with Mudflap asking how to do progressive authentication on inbound calls without giving the LLM a path to forward a fake caller-ID. The current page documents the mechanics of static
parameterscorrectly but doesn't frame it as a security boundary, and doesn't address the failure modes that break that boundary in practice. This PR adds that framing.What changes in
fern/tools/static-variables-and-aliases.mdxfunction.parameters(LLM-facing JSON schema, model fills it) vs. top-levelparameters(server-merged, LLM never sees it). The dashboard surfaces both as similarly-named sections (just Parameters vs Static Body Fields), which is the most common cause of customers accidentally exposing trusted fields to the model.customer.*,phoneNumber.*,transport.*,call.*,assistant.*, time variables,assistantOverrides.variableValuesset at call start). Tier 2 (conversation-derived, not safe as a security boundary:messages,transcript,prompt). Tier 3 (LLM-derived, never trustworthy:variableExtractionPlanaliases from non-trusted sources, handoff arguments, handoff schema extraction).function.parameters; body-default leak; system-prompt forwarding; unsafe alias chains; mid-call bag mutation.assistant.model.functions[]does not support static parameters (the converter zeroes them out at request time, so customers on the deprecated shape have no orchestration-layer injection at all)./squads/passing-data-between-assistants(feat: add "Passing data between assistants" page to squads #1033). Documents thattool.parametersdoesn't exist on handoff and explains why it doesn't need to: call-level Liquid variables persist across handoffs; aliases from server-trusted sources persist viaallMessagesContext.variablesAdd;destination.assistantOverrides.variableValuesis merged at handoff time bypassing the LLM. Flags that feat: add "Passing data between assistants" page to squads #1033's Approach 1 (handoff arguments viafunction.parameters) is correct for LLM-derived values like sentiment/intent but is not a security boundary for signaling-derived values like caller-ID.destination.assistantOverrides.variableValuesare not currently resolved at handoff time (values spread verbatim into the bag).parametersfields, with a step-by-step for the caller-ID pattern.Skipped
Testing Steps
fern check-- 0 errors/squads/passing-data-between-assistantsresolves via the parent branch in this stack;/tools/code-tool,/tools/custom-tools,/tools/tool-rejection-plan,/api-reference/tools/createall resolve)#the-variable-bag,#forwarding-trusted-data-across-handoffs) so the cross-references inside the page resolveYOUR_API_KEY, etc.)Related
destination.assistantOverrides.variableValuesshould support Liquid template resolution at handoff time -- usability gap, not a security gap.