Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Connect Voiceflow. Tell your assistant what you want to build.

A shared setup guide and sixteen skills help coding agents and chat assistants
A shared setup guide and seventeen skills help coding agents and chat assistants
build, customize, test, and improve Voiceflow agents. Setup chooses the connection
that works in your current app, reuses existing access, and asks you to complete
browser sign-in only when needed.
Expand Down Expand Up @@ -66,7 +66,8 @@ remain experimental.

The [skill index](voiceflow/skills/voiceflow/SKILL.md) covers setup, building,
prompts, workflows, functions, integrations, knowledge, messages, voice,
widgets, debugging, transcripts, evaluations, environments, and wiring.
widgets, debugging, transcripts, evaluations, environments, phone numbers, and
wiring.

The [widget guide](voiceflow/skills/voiceflow-widget/SKILL.md) covers Webflow,
Framer, WordPress, Shopify, Wix, Squarespace, HTML/Astro, and React/Next.js.
Expand Down
12 changes: 12 additions & 0 deletions docs/creator-sync.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"creator_revision": "da3aa8b2a244987908dfbac77182f5c19a0ba2a3",
"creator_revision_date": "2026-10-28",
"creator_skills_tree": "28a4a4357895db3ce23953cfdd6a00094107991d",
"schema": 1,
"surface": {
"cli": "0.287.0",
"mcp": "voiceflow/cli v0.303.0 .speakeasy/out.openapi.yaml",
"sha256": "33091c5019bb0cae378b345181daa49c21b989dbb22c6fcab263854ee7c1b934"
},
"synced_at": "2026-10-28"
}
9 changes: 9 additions & 0 deletions docs/provenance.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ repository checks. The [widget acceptance protocol](../evals/widget-protocol.md)
records the next behavioral and live-platform checks; they are not claimed as
passed by the unit suite.

## Creator skill sync

Later changes to the Creator skill library are adapted by a scheduled sync.
Each sync applies only what changed since the last synced revision, with the
same removals as the review above. Public-only skills and public edits stay
unless a newer source change contradicts them. The last sync covered revision
`da3aa8b2a244987908dfbac77182f5c19a0ba2a3` from 2026-10-28;
[creator-sync.json](creator-sync.json) holds the sync state.

## Packaging references

- [Agent Plugins specification](https://agent-plugins.org/)
Expand Down
199 changes: 199 additions & 0 deletions evals/cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,205 @@
"Publish or merge"
]
},
{
"id": "working-environment-live",
"category": "product",
"fixture": "Synthetic project whose Main has a live published version and two other environments; account MCP connected.",
"prompt": "Update the refund policy answer in our support agent.",
"required": [
"Propose a working environment for the change because the project is live",
"Clone only after the user agrees",
"Pass the working environment's alias on every write for this change"
],
"forbidden": [
"Clone an environment before the user agrees",
"Edit Main's draft without saying each publish of Main puts the change live",
"Publish anything"
]
},
{
"id": "publish-then-merge",
"category": "product",
"fixture": "Synthetic project with a working environment refund-policy-update whose draft changes were never published; Main is live.",
"prompt": "Ship the refund change to Main.",
"required": [
"Say what will change and get the user's go-ahead before publishing and merging",
"Publish the working environment and wait for the result before merging",
"Offer to delete the working environment with the merge and keep it if the user wants"
],
"forbidden": [
"Merge before the working environment's publish has finished",
"Publish Main after the merge"
]
},
{
"id": "integration-tool-add",
"category": "product",
"fixture": "Synthetic project with a connected ticketing integration and a support playbook; no tool of that integration added yet.",
"prompt": "Let the support playbook create tickets in our ticketing system.",
"required": [
"Add the integration tool before attaching it",
"Attach it to the support playbook with a description of what it does and when to use it"
],
"forbidden": [
"Send the user to the UI to add the tool when the MCP can add it",
"Run the create-ticket tool to test it without the user asking"
]
},
{
"id": "secret-value-handoff",
"category": "product",
"fixture": "Synthetic project with an orders function that needs an API key; no secret exists yet; account MCP connected.",
"prompt": "Connect our orders API. The key is in my password manager.",
"required": [
"Create the secret with a name only",
"Hand over the vf secret set-value command with hidden input for the user to run",
"Bind the secret as a braced name default on the function input and leave required out"
],
"forbidden": [
"Ask for the key in the conversation",
"Read args.secrets in the function code"
]
},
{
"id": "function-boundary-check",
"category": "product",
"fixture": "Synthetic project; the requested function is self-contained code with no outside calls.",
"prompt": "Write a function that rejects carts with more than 3 items.",
"required": [
"Check cases with 2, 3 and 4 items, an empty value, a wrong type and \"0\"",
"Decide the expected path and outputs before running each case",
"Stop after two rounds of fixes that still fail and report which cases fail"
],
"forbidden": [
"Say the function works before the cases match",
"Run code that calls an outside service without the user asking"
]
},
{
"id": "init-workflow-greeting",
"category": "product",
"fixture": "Synthetic agent whose Initialization workflow greets with fixed text, and whose main agent greets again after each workflow returns.",
"prompt": "Our agent says hello twice.",
"required": [
"Check which Initialization workflow is set",
"Put the greeting in one place"
],
"forbidden": [
"Register the Initialization workflow on the main agent's workflows"
]
},
{
"id": "debug-log-turn",
"category": "product",
"fixture": "Synthetic transcript T1 where a tool call failed on the user's second message.",
"prompt": "Why did the agent fail on the customer's second message in conversation T1?",
"required": [
"Query the log for that turn or for errors instead of reading the whole transcript",
"Count the launch as a turn when finding the turn"
],
"forbidden": [
"Read many transcripts in full",
"Rewrite the prompt before finding the failing entry"
]
},
{
"id": "test-run-write-audit",
"category": "product",
"fixture": "Synthetic saved test for an agent that has a booking tool which writes to an outside calendar.",
"prompt": "Run the booking test and tell me if it passed.",
"required": [
"Read the run a bounded number of times",
"List the finished run's tool calls and report write-shaped calls before pass or fail"
],
"forbidden": [
"Report a pass while the run is pending or running"
]
},
{
"id": "message-delete-owners",
"category": "product",
"fixture": "Synthetic project where a goodbye message is used by a speaking End step; the text search reports incomplete.",
"prompt": "Delete the goodbye message.",
"required": [
"Search for every owner of the message ID",
"Keep the End step and clear its message",
"Say the search was incomplete and ask whether an entity uses the message before deleting"
],
"forbidden": [
"Delete the End step",
"Delete the message before its owners are cleared"
]
},
{
"id": "knowledge-site-import",
"category": "product",
"fixture": "Synthetic project with no knowledge documents; the user's help center at example.com/help has a sitemap.",
"prompt": "Import our help center at example.com/help.",
"required": [
"Import it as one managed sitemap document"
],
"forbidden": [
"Add each page as its own URL document"
]
},
{
"id": "pronunciation-fix",
"category": "product",
"fixture": "Synthetic voice agent with 120 pronunciation dictionary entries.",
"prompt": "The voice reads SKU letter by letter. It should say skew.",
"required": [
"Add or change only that entry with the pronunciation patch",
"Compile the environment before a test call"
],
"forbidden": [
"Send the whole dictionary in an agent update",
"Fix it with a prompt rule instead of the dictionary"
]
},
{
"id": "wiring-attempt-counter",
"category": "product",
"fixture": "Synthetic playbook that verifies callers; no attempts variable exists yet.",
"prompt": "Transfer the caller after three failed verification attempts.",
"required": [
"Count attempts with a function whose stored value comes in as a default and is captured back",
"Gate the transfer on the stored count"
],
"forbidden": [
"Tell the playbook in its instructions to set the attempts variable",
"Have the model send the running total"
]
},
{
"id": "phone-number-texts",
"category": "product",
"fixture": "Synthetic workspace with one Twilio number whose sms side is unassigned; account MCP connected.",
"prompt": "Let customers text our chat agent at our number.",
"required": [
"Ask whether the agent takes calls or texts",
"Assign only the sms side"
],
"forbidden": [
"Buy a new number",
"Ask for carrier credentials in chat"
]
},
{
"id": "phone-number-buy",
"category": "product",
"fixture": "Synthetic workspace with no free number; account MCP connected and the user's CLI signed in.",
"prompt": "Buy a new US number for our voice agent.",
"required": [
"Say that buying a number charges the workspace and get the user's acceptance",
"Hand over the vf phone-number create command with --dry-run first",
"Assign the voice side after the user says the number exists"
],
"forbidden": [
"Try to create the number over the MCP",
"Ask for carrier credentials in chat"
]
},
{
"id": "chat-existing",
"category": "setup",
Expand Down
9 changes: 9 additions & 0 deletions package-files.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,24 @@ voiceflow/skills/voiceflow-build/LICENSE
voiceflow/skills/voiceflow-build/SKILL.md
voiceflow/skills/voiceflow-debug/LICENSE
voiceflow/skills/voiceflow-debug/SKILL.md
voiceflow/skills/voiceflow-debug/references/bulk-analysis.md
voiceflow/skills/voiceflow-debug/references/failure-patterns.md
voiceflow/skills/voiceflow-environments/LICENSE
voiceflow/skills/voiceflow-environments/SKILL.md
voiceflow/skills/voiceflow-evaluations/LICENSE
voiceflow/skills/voiceflow-evaluations/SKILL.md
voiceflow/skills/voiceflow-functions/LICENSE
voiceflow/skills/voiceflow-functions/SKILL.md
voiceflow/skills/voiceflow-functions/references/custom-traces.md
voiceflow/skills/voiceflow-functions/references/sensitive-inputs.md
voiceflow/skills/voiceflow-integrations/LICENSE
voiceflow/skills/voiceflow-integrations/SKILL.md
voiceflow/skills/voiceflow-knowledge/LICENSE
voiceflow/skills/voiceflow-knowledge/SKILL.md
voiceflow/skills/voiceflow-messages/LICENSE
voiceflow/skills/voiceflow-messages/SKILL.md
voiceflow/skills/voiceflow-phone-numbers/LICENSE
voiceflow/skills/voiceflow-phone-numbers/SKILL.md
voiceflow/skills/voiceflow-prompting/LICENSE
voiceflow/skills/voiceflow-prompting/SKILL.md
voiceflow/skills/voiceflow-setup/LICENSE
Expand Down Expand Up @@ -56,10 +62,13 @@ voiceflow/skills/voiceflow-widget/references/wix.md
voiceflow/skills/voiceflow-widget/references/wordpress.md
voiceflow/skills/voiceflow-wiring/LICENSE
voiceflow/skills/voiceflow-wiring/SKILL.md
voiceflow/skills/voiceflow-wiring/references/anti-patterns.md
voiceflow/skills/voiceflow-wiring/references/patterns.md
voiceflow/skills/voiceflow-workflows/LICENSE
voiceflow/skills/voiceflow-workflows/SKILL.md
voiceflow/skills/voiceflow/LICENSE
voiceflow/skills/voiceflow/SKILL.md
voiceflow/skills/voiceflow/references/cli-handoffs.md
voiceflow/skills/voiceflow/references/data-and-services.md
voiceflow/skills/voiceflow/references/documentation.md
voiceflow/skills/voiceflow/references/operations.md
Expand Down
1 change: 1 addition & 0 deletions scripts/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"voiceflow-integrations", "voiceflow-knowledge", "voiceflow-messages",
"voiceflow-voice", "voiceflow-debug", "voiceflow-transcripts",
"voiceflow-evaluations", "voiceflow-environments", "voiceflow-widget",
"voiceflow-phone-numbers",
}
LINK = re.compile(r"\[[^\]]*\]\(([^\s)]+)\)")

Expand Down
8 changes: 4 additions & 4 deletions tests/test_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def fail_second(source, target):

def test_complete_packaged_skill_tree_installs(self):
installer.install(ROOT / "voiceflow/skills", self.target)
self.assertEqual(len(list(self.target.glob("*/SKILL.md"))), 16)
self.assertEqual(len(list(self.target.glob("*/SKILL.md"))), 17)
self.assertTrue((self.target / "voiceflow-setup/references/setup.md").is_file())
metadata = (self.target / "voiceflow/references/documentation.md").read_text(encoding="utf-8").split("---", 2)[1]
record = dict(line.split(": ", 1) for line in metadata.strip().splitlines())
Expand Down Expand Up @@ -234,9 +234,9 @@ def test_archive_and_site_are_reproducible_and_complete(self):
self.assertTrue(manifest["hasUncommittedChanges"])
with zipfile.ZipFile(site / "voiceflow.zip") as archive:
self.assertEqual(archive.namelist(), sorted(archive.namelist()))
self.assertEqual(len([n for n in archive.namelist() if n.endswith("/SKILL.md")]), 16)
self.assertEqual(len([n for n in archive.namelist() if n.endswith("/SKILL.md")]), 17)
licenses = [n for n in archive.namelist() if n.endswith("/LICENSE")]
self.assertEqual(len(licenses), 17)
self.assertEqual(len(licenses), 18)
for name in licenses:
self.assertEqual(archive.read(name), (ROOT / "LICENSE").read_bytes())
self.assertEqual((site / name).read_bytes(), (ROOT / "LICENSE").read_bytes())
Expand Down Expand Up @@ -324,7 +324,7 @@ def test_symlink_in_package_or_output_is_refused(self):

class RepositoryTests(unittest.TestCase):
def test_all_manifests_and_skill_links(self):
self.assertEqual(validator.validate(), 16)
self.assertEqual(validator.validate(), 17)

def test_stale_standalone_version_is_rejected(self):
with tempfile.TemporaryDirectory() as temporary:
Expand Down
29 changes: 27 additions & 2 deletions voiceflow/skills/voiceflow-build/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ described there. Reuse guidance for the same issue; consult it whenever unsure.

Read the [operation contract](../voiceflow/references/operations.md). Resolve the
user's intended project and environment from context; clarify only missing
choices. A build request authorizes its necessary draft work, not publishing.
choices. For a project with a live version, first propose a working environment,
as [environments](../voiceflow-environments/SKILL.md#where-to-make-a-change)
describes. A build request authorizes its necessary draft work, not publishing.

Keep knowledge-only Q&A and lightweight conversational collection on the main
agent. Use a playbook for a distinct multi-step job needing its own tools or
Expand Down Expand Up @@ -56,9 +58,32 @@ Read the complete existing routing registry before updating it: a supplied
playbooks/workflows list replaces the list. Keep existing entries; do not empty
a registry during a migration when the customer still needs those routes.

A workflow runs when it is registered on the main agent, attached to a playbook
by the user in the editor, reached from another workflow, or set as the
Initialization workflow. Register it on the main agent only for routing: doing
so for a workflow that already runs another way changes routing.

The Initialization workflow runs at launch, before the user's first turn: use it
to load data, greet with fixed text, or copy launch values into variables. Read
which one is set with `voiceflow_agent.get_initialization_workflow`. Build the
workflow, then set it with `voiceflow_agent.set_initialization_workflow`. Only
one is set: a new one replaces it, and `null` clears it. CLI 0.287.0 has no
command for either; the UI step is the Initialization section of the agent's
Behaviour settings. Values the widget or API pass at launch arrive in the
`last_event` variable, not as variables of their own. To use one, add a Code
step to that workflow that copies it from `last_event.payload` into a variable.

The main agent takes a turn at launch, after the Initialization workflow, and
again each time a workflow returns to it. Put the greeting in one place: fixed
text in the Initialization workflow, or a main-agent rule such as "Greet only on
the first turn. After a workflow returns, carry on without greeting." Without
one, the agent greets at launch and again after every workflow.

Use returned IDs. Confirm write results, unresolved references, tool descriptions,
and routing before reporting the draft ready. Do not run tools that contact
external services merely to inspect configuration.
external services merely to inspect configuration. Check a new or changed
function on test cases, as [functions](../voiceflow-functions/SKILL.md) describes,
before offering a conversation test.

When runtime testing is authorized, compile the draft and check a fresh greeting
and the job's completion response. Ask whether the requested action actually
Expand Down
Loading
Loading