Load ``skill_name`` and run it as an agent with ``intent``. When the skill's frontmatter declares ``od.mode == "deck"`` and ``od.output_path_template`` is set, ``run_skill``: 1. Templates the path with the provided ``slug``. 2. Adds a "Write to: " line to the agent's inte
(
*,
skill_name: str,
intent: str,
kb_dir: Path,
model: str,
language: str = "en",
max_turns: int = MAX_TURNS,
seed: Optional[str] = None,
slug: Optional[str] = None,
extra_skill_roots: tuple[str | Path, ...] = (),
)
| 62 | |
| 63 | |
| 64 | async def run_skill( |
| 65 | *, |
| 66 | skill_name: str, |
| 67 | intent: str, |
| 68 | kb_dir: Path, |
| 69 | model: str, |
| 70 | language: str = "en", |
| 71 | max_turns: int = MAX_TURNS, |
| 72 | seed: Optional[str] = None, |
| 73 | slug: Optional[str] = None, |
| 74 | extra_skill_roots: tuple[str | Path, ...] = (), |
| 75 | ) -> SkillRunResult: |
| 76 | """Load ``skill_name`` and run it as an agent with ``intent``. |
| 77 | |
| 78 | When the skill's frontmatter declares ``od.mode == "deck"`` and |
| 79 | ``od.output_path_template`` is set, ``run_skill``: |
| 80 | |
| 81 | 1. Templates the path with the provided ``slug``. |
| 82 | 2. Adds a "Write to: <path>" line to the agent's intent so the |
| 83 | skill knows the expected destination. |
| 84 | 3. After the agent run, checks the file exists and (if the skill |
| 85 | declared ``od.deck_grammar``) runs ``validate_deck`` against it. |
| 86 | |
| 87 | Args: |
| 88 | skill_name: Name (frontmatter ``name:``) of the skill to invoke. |
| 89 | intent: Natural-language brief for what to produce. |
| 90 | kb_dir: KB root. Used both for skill discovery and for the |
| 91 | agent's wiki read-tools / write-file scoping. |
| 92 | model: LiteLLM-formatted model string from KB config. |
| 93 | language: Passed through to the underlying query agent for |
| 94 | answer-language consistency. |
| 95 | max_turns: Hard cap on agent loop iterations. |
| 96 | seed: Optional kick-off user message. Defaults to a short nudge |
| 97 | that points the agent at its own instructions. |
| 98 | slug: Required when the skill declares |
| 99 | ``od.output_path_template`` (it substitutes ``{slug}``). |
| 100 | Otherwise ignored. |
| 101 | extra_skill_roots: Additional directories to scan beyond the |
| 102 | built-in ``<kb>/skills``, ``~/.openkb/skills``, |
| 103 | ``~/.claude/skills``. |
| 104 | |
| 105 | Returns: |
| 106 | A :class:`SkillRunResult` carrying the resolved output path (if |
| 107 | any) and the validation result (for deck-mode skills). |
| 108 | |
| 109 | Raises: |
| 110 | SkillNotFoundError: if no skill with ``skill_name`` is found. |
| 111 | RuntimeError: on turn-cap, model error, or missing |
| 112 | output file after a templated-path run. |
| 113 | """ |
| 114 | skills = scan_local_skills(kb_dir, extra_roots=extra_skill_roots) |
| 115 | match = next((s for s in skills if s["name"] == skill_name), None) |
| 116 | if match is None: |
| 117 | available = ", ".join(sorted(s["name"] for s in skills)) or "(none)" |
| 118 | raise SkillNotFoundError( |
| 119 | f"Skill {skill_name!r} not found. Available: {available}. " |
| 120 | f"Drop a SKILL.md into ~/.openkb/skills/<name>/ or " |
| 121 | f"<kb>/skills/<name>/ and re-run." |