Skip to content

v3 Skill facade#396

Merged
Shackless merged 30 commits into
developfrom
feat/skill-facade-v3-api
Jun 16, 2026
Merged

v3 Skill facade#396
Shackless merged 30 commits into
developfrom
feat/skill-facade-v3-api

Conversation

@Shackless

@Shackless Shackless commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Linked Issues

#364 #395

Summary

Introduce a new and clearer facade layer for Skills allowing us to control and error-handle what Skills can and can’t do.

Skills v3 API — Migration Guide for Skill Developers

v3 makes the skill ↔ runtime boundary explicit. Your skill now talks to the runtime only through self.wingman (a controlled facade with feature namespaces) and keeps its own concerns on self. Full reference + complete mapping table: MIGRATING-TO-V3.md.

Mandatory (or your skill won't load)

Add api_version: 3 to your default_config.yaml. Skills without it are shown as "Incompatible (legacy)" and are skipped at boot (the app still starts).

The 5 breaking changes

  1. Declare api_version: 3 in the manifest.
  2. No work at import/module-load time — the catalog import-probes your module. Do setup in __init__ / validate() / prepare().
  3. No raw LLM calls. self.llm_call(...) is gone → use self.wingman.ai.generate(...) (capped), self.wingman.ai.converse(...), or the free local model self.wingman.local_ai.generate(...) / .summarize(...).
  4. Config is read-only. self.wingman.config reads live values; writes raise FacadeError. Change things through capabilities (self.wingman.tts.set_voice(...), self.wingman.commands.*, self.wingman.audio.set_output_device(...)). Runtime TTS-provider switching is removed.
  5. No raw runtime access. audio_player, the registries (tool_skills / mcp_registry / skill_registry), messages, secret_keeper, tower are gone → use the feature namespaces.

Most common renames

v2 (removed) v3
await self.llm_call(msgs) await self.wingman.ai.generate(prompt, system=..., messages=...)
await self.wingman.play_to_user(t, no_interrupt=True) await self.wingman.tts.speak(t, interrupt=False)
self.wingman.get_conversation_history() self.wingman.conversation.history()
await self.wingman.add_assistant_message(c) await self.wingman.conversation.add_assistant(c)
await self.retrieve_secret(name, errors) await self.wingman.secrets.retrieve(name, errors)
self.threaded_execution(fn, *a) self.wingman.run_in_thread(fn, *a)
await self.local_ai.support(...) await self.wingman.local_ai.generate(...)
memory (self.local_ai.remember_fact, …) self.wingman.memory.* (remember / recall / context / …)
await self.wingman.registry.invoke(name, args) await self.wingman.tools.invoke(name, args) → returns a ToolResult (not a 4-tuple)
await self.wingman.generate_image(p) await self.wingman.ai.generate_image(p)
self.printr.print(...) self.log.info/warning/error(...)

Removed members fail loudly: touching e.g. self.wingman.llm_call raises a FacadeError naming the replacement and pointing to this guide — so migration is largely "follow the error messages."

Gotchas worth knowing

  • tts.speak's interrupt is keyword-only and inverted from the old no_interrupt (play_to_user(t, True)tts.speak(t, interrupt=False)).
  • ai.generate(...) returns a string (not a completion object) and is token-capped when conversation condensation is on — pre-summarize bulk text with the free self.wingman.local_ai.summarize(...).
  • tools.invoke(...) returns a ToolResult with .response / .instant_response / .skill / .label.
  • Threaded TTS: you can't pass tts.speak's keyword-only args through run_in_thread; wrap it in a small async def helper (see the guide).

Migrating with a coding agent?

Point it at MIGRATING-TO-V3.md and say "migrate this skill to the v3 Skill API using this guide." That's exactly how every bundled skill in this PR was ported.

Verify

  1. Boot Wingman and confirm your skill shows no incompatibility badge.
  2. Exercise each capability path your skill uses (speak, audio, LLM, commands, secrets, tools).

Shackless added 30 commits June 16, 2026 15:15
…readed_execution/llm_call, private secret_keeper, read-only settings, add self.log)
…sitional interrupt, source_type/logo, helper threading)
…n->run_in_thread, conversation.add_assistant
…_changer/file_manager/image_generation/spotify/thinking_sound to v3 facade
…Error on removed v2 members; drop dead imports
…io.set_output_device (drop HTTP hack + backend_port)
@Shackless Shackless force-pushed the feat/skill-facade-v3-api branch from db08705 to 4265ec0 Compare June 16, 2026 13:15
@Shackless Shackless merged commit 3bba41e into develop Jun 16, 2026
1 check passed
@Shackless Shackless deleted the feat/skill-facade-v3-api branch June 16, 2026 13:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant