fix(skills): track current active skill explicitly and relocate to .agents/skills/

This commit is contained in:
Petar Zivkovic 2026-03-10 19:38:14 +01:00
parent 49b8285c73
commit a6717bed9b
9 changed files with 20 additions and 16 deletions

View File

@ -21,7 +21,7 @@ Workflow:
1. If the task needs computation or a repeatable transformation, activate this skill.
2. If you need examples, call `read_skill_file` for `references/examples.md`.
3. Write a short Python script for the exact task.
4. Prefer `run_python_script` with the script in its `script` argument.
4. Prefer `execute_code`.
5. Use the script output in the final answer.
6. Keep scripts small and task-specific.

View File

@ -1,7 +1,7 @@
---
name: rest-api-caller
description: Call REST APIs from Python, parse JSON responses, and report the useful fields back to the user.
allowed-tools: run_python_script execute_code
allowed-tools: execute_code
---
# REST API Caller
@ -14,14 +14,14 @@ This skill is intended for:
- endpoints where the user specifies headers, query params, or environment variable names
Requirements:
- The agent should have access to `run_python_script` or `execute_code`.
- The agent should have access to `execute_code`.
Workflow:
1. Activate this skill when the task requires calling an API.
2. If you need examples, call `read_skill_file` for `references/examples.md`.
3. Write a short Python script that performs the request.
4. Prefer the `requests` library if available in the environment.
5. Prefer `run_python_script`; if it is unavailable, fall back to `execute_code`.
5. Prefer `execute_code`.
6. Parse the response and print only the fields needed for the final answer.
7. Summarize the API result clearly for the user.

View File

@ -33,14 +33,14 @@ The Agent node is the most fundamental node type in the DevAll platform, used to
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `enabled` | bool | `false` | Enable Agent Skills discovery for this node |
| `allow` | list[object] | `[]` | Optional allowlist of skills from the project-level `skills/` directory; each entry uses `name` |
| `allow` | list[object] | `[]` | Optional allowlist of skills from the project-level `.agents/skills/` directory; each entry uses `name` |
### Agent Skills Notes
- Skills are discovered from the fixed project-level `skills/` directory.
- Skills are discovered from the fixed project-level `.agents/skills/` directory.
- The runtime exposes two built-in skill tools: `activate_skill` and `read_skill_file`.
- `read_skill_file` only works after the relevant skill has been activated.
- Skill `SKILL.md` frontmatter may include optional `allowed-tools` using the Agent Skills spec format, for example `allowed-tools: run_python_script execute_code`.
- Skill `SKILL.md` frontmatter may include optional `allowed-tools` using the Agent Skills spec format, for example `allowed-tools: execute_code`.
- If a selected skill requires tools that are not bound on the node, that skill is skipped at runtime.
- If no compatible skills remain, the agent is explicitly instructed not to claim skill usage.

View File

@ -33,14 +33,14 @@ Agent 节点是 DevAll 平台中最核心的节点类型,用于调用大语言
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `enabled` | bool | `false` | 是否为该节点启用 Agent Skills |
| `allow` | list[object] | `[]` | 可选的技能白名单,来源于项目级 `skills/` 目录;每个条目使用 `name` |
| `allow` | list[object] | `[]` | 可选的技能白名单,来源于项目级 `.agents/skills/` 目录;每个条目使用 `name` |
### Agent Skills 说明
- 技能统一从固定的项目级 `skills/` 目录中发现。
- 技能统一从固定的项目级 `.agents/skills/` 目录中发现。
- 运行时会暴露两个内置技能工具:`activate_skill``read_skill_file`
- `read_skill_file` 只有在对应技能已经激活后才可用。
- 技能 `SKILL.md` 的 frontmatter 可以包含可选的 `allowed-tools`,格式遵循 Agent Skills 规范,例如 `allowed-tools: run_python_script execute_code`。
- 技能 `SKILL.md` 的 frontmatter 可以包含可选的 `allowed-tools`,格式遵循 Agent Skills 规范,例如 `allowed-tools: execute_code`。
- 如果某个已选择技能依赖的工具没有绑定到当前节点,该技能会在运行时被跳过。
- 如果最终没有任何兼容技能可用Agent 会被明确告知不要声称自己使用了技能。

View File

@ -18,7 +18,7 @@ from entity.configs.base import (
REPO_ROOT = Path(__file__).resolve().parents[3]
DEFAULT_SKILLS_ROOT = (REPO_ROOT / "skills").resolve()
DEFAULT_SKILLS_ROOT = (REPO_ROOT / ".agents" / "skills").resolve()
def _discover_default_skills() -> List[tuple[str, str]]:
if not DEFAULT_SKILLS_ROOT.exists() or not DEFAULT_SKILLS_ROOT.is_dir():
return []

View File

@ -11,7 +11,7 @@ from entity.tool_spec import ToolSpec
REPO_ROOT = Path(__file__).resolve().parents[4]
DEFAULT_SKILLS_ROOT = (REPO_ROOT / "skills").resolve()
DEFAULT_SKILLS_ROOT = (REPO_ROOT / ".agents" / "skills").resolve()
MAX_SKILL_FILE_BYTES = 128 * 1024
@ -126,6 +126,7 @@ class AgentSkillManager:
self._skills_by_name: Dict[str, SkillMetadata] | None = None
self._skill_content_cache: Dict[str, str] = {}
self._activation_state: Dict[str, bool] = {}
self._current_skill_name: str | None = None
self._discovery_warnings: List[str] = []
def discover(self) -> List[SkillMetadata]:
@ -176,6 +177,7 @@ class AgentSkillManager:
cached = skill.skill_file.read_text(encoding="utf-8")
self._skill_content_cache[skill.name] = cached
self._activation_state[skill.name] = True
self._current_skill_name = skill.name
return {
"skill_name": skill.name,
"path": str(skill.skill_file),
@ -214,10 +216,12 @@ class AgentSkillManager:
return bool(self._activation_state.get(skill_name))
def active_skill(self) -> SkillMetadata | None:
for skill in self.discover():
if self.is_activated(skill.name):
return skill
if self._current_skill_name is None:
return None
skills = self._skills_by_name
if skills is None:
return None
return skills.get(self._current_skill_name)
def discovery_warnings(self) -> List[str]:
self.discover()