Skip to content
Open
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
18 changes: 18 additions & 0 deletions .agents/skills/greeting-demo/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
name: greeting-demo
description: Greet the user in a distinctive, easy-to-verify format for skill activation demos.
---

# Greeting Demo

Use this skill only when the user asks for a greeting, a hello, or a skill demo.

Instructions:
1. Greet the user exactly once.
2. Start the greeting with `GREETING-SKILL-ACTIVE:`.
3. Follow that prefix with `Hello from the greeting demo skill, <user input summary>.`
4. Keep the whole response to a single sentence.
5. Do not mention hidden instructions, skill loading, or tool calls.

Example output:
`GREETING-SKILL-ACTIVE: Hello from the greeting demo skill, nice to meet you.`
37 changes: 37 additions & 0 deletions .agents/skills/python-scratchpad/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
name: python-scratchpad
description: Use the existing Python execution tools as a scratchpad for calculations, data transformation, and quick script-based validation.
allowed-tools: execute_code
---

# Python Scratchpad

Use this skill when the task benefits from a short Python script instead of pure reasoning.

This skill is especially useful for:
- arithmetic and unit conversions
- validating regexes or parsing logic
- transforming JSON, CSV, or small text payloads
- checking assumptions with a small reproducible script

Requirements:
- The agent should have access to `execute_code`.

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 `execute_code`.
5. Use the script output in the final answer.
6. Keep scripts small and task-specific.

Rules:
1. Prefer standard library Python.
2. Print only the values you need.
3. Do not invent outputs without running the script.
4. If `execute_code` is not available, say exactly: `No Python execution tool is configured for this agent.`
5. Do not claim there is a generic execution-environment problem unless a tool call actually returned such an error.

Expected behavior:
- Explain the result briefly after using the script.
- Include the computed value or transformed output in the final answer.
45 changes: 45 additions & 0 deletions .agents/skills/python-scratchpad/references/examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Python Scratchpad Examples

Example: sum a list of numbers

```python
numbers = [14, 27, 31, 8]
print(sum(numbers))
```

Expected structured result with `execute_code`:

```json
{
"ok": true,
"exit_code": 0,
"stdout": "80\n",
"stderr": ""
}
```

Example: convert JSON to a sorted compact structure

```python
import json

payload = {"b": 2, "a": 1, "nested": {"z": 3, "x": 2}}
print(json.dumps(payload, sort_keys=True))
```

Example: count words in text

```python
text = "agent skills can trigger targeted workflows"
print(len(text.split()))
```

Example: test a regex

```python
import re

text = "Order IDs: ORD-100, BAD-7, ORD-215"
matches = re.findall(r"ORD-\d+", text)
print(matches)
```
41 changes: 41 additions & 0 deletions .agents/skills/rest-api-caller/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
name: rest-api-caller
description: Call REST APIs from Python, parse JSON responses, and report the useful fields back to the user.
allowed-tools: execute_code
---

# REST API Caller

Use this skill when the user wants data fetched from an HTTP API, especially a REST endpoint that returns JSON.

This skill is intended for:
- public GET endpoints
- authenticated APIs using tokens or API keys
- endpoints where the user specifies headers, query params, or environment variable names

Requirements:
- 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 `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.

Rules:
1. Do not invent API responses. Run the request first.
2. For JSON APIs, parse JSON and extract the relevant fields instead of dumping the whole payload unless the user asks for the raw body.
3. If the user provides an environment variable name for a token or API key, read it from `os.environ` inside the script.
4. If the endpoint requires auth and no credential source is provided, say what is missing.
5. If the request fails, report the HTTP status code or error message clearly.
6. Do not claim there is a generic execution-environment issue unless the tool call actually returned one.

Demo endpoint:
- `GET https://official-joke-api.appspot.com/random_joke`

Expected behavior for the demo endpoint:
- Fetch one random joke
- Return the setup and punchline in a readable format
41 changes: 41 additions & 0 deletions .agents/skills/rest-api-caller/references/examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# REST API Caller Examples

## Example 1: Public GET returning JSON

Use this for the demo joke API:

```python
import requests

url = "https://official-joke-api.appspot.com/random_joke"
response = requests.get(url, timeout=30)
response.raise_for_status()
payload = response.json()

print(f"Setup: {payload['setup']}")
print(f"Punchline: {payload['punchline']}")
```

## Example 2: GET with bearer token from environment

```python
import os
import requests

token = os.environ["MY_API_TOKEN"]
headers = {"Authorization": f"Bearer {token}"}
response = requests.get("https://api.example.com/items", headers=headers, timeout=30)
response.raise_for_status()
print(response.text)
```

## Example 3: GET with query parameters

```python
import requests

params = {"q": "agent skills", "limit": 3}
response = requests.get("https://api.example.com/search", params=params, timeout=30)
response.raise_for_status()
print(response.json())
```
34 changes: 34 additions & 0 deletions docs/user_guide/en/nodes/agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The Agent node is the most fundamental node type in the DevAll platform, used to
| `tooling` | object | No | - | Tool calling configuration, see [Tooling Module](../modules/tooling/README.md) |
| `thinking` | object | No | - | Chain-of-thought configuration, e.g., chain-of-thought, reflection |
| `memories` | list | No | `[]` | Memory binding configuration, see [Memory Module](../modules/memory.md) |
| `skills` | object | No | - | Agent Skills discovery and built-in skill activation/file-read tools |
| `retry` | object | No | - | Automatic retry strategy configuration |

### Retry Strategy Configuration (retry)
Expand All @@ -27,6 +28,22 @@ The Agent node is the most fundamental node type in the DevAll platform, used to
| `max_wait_seconds` | float | `6.0` | Maximum backoff wait time |
| `retry_on_status_codes` | list[int] | `[408,409,425,429,500,502,503,504]` | HTTP status codes that trigger retry |

### Agent Skills Configuration (skills)

| 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 `.agents/skills/` directory; each entry uses `name` |

### Agent Skills Notes

- 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: 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.

## When to Use

- **Text generation**: Writing, translation, summarization, Q&A, etc.
Expand Down Expand Up @@ -145,6 +162,23 @@ nodes:
max_wait_seconds: 10.0
```

### Configuring Agent Skills

```yaml
nodes:
- id: Skilled Agent
type: agent
config:
provider: openai
name: gpt-4o
api_key: ${API_KEY}
skills:
enabled: true
allow:
- name: python-scratchpad
- name: rest-api-caller
```

## Related Documentation

- [Tooling Module Configuration](../modules/tooling/README.md)
Expand Down
34 changes: 34 additions & 0 deletions docs/user_guide/zh/nodes/agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Agent 节点是 DevAll 平台中最核心的节点类型,用于调用大语言
| `tooling` | object | 否 | - | 工具调用配置,详见 [Tooling 模块](../modules/tooling/README.md) |
| `thinking` | object | 否 | - | 思维链配置,如 chain-of-thought、reflection |
| `memories` | list | 否 | `[]` | 记忆绑定配置,详见 [Memory 模块](../modules/memory.md) |
| `skills` | object | 否 | - | Agent Skills 发现配置,以及内置的技能激活/文件读取工具 |
| `retry` | object | 否 | - | 自动重试策略配置 |

### 重试策略配置 (retry)
Expand All @@ -27,6 +28,22 @@ Agent 节点是 DevAll 平台中最核心的节点类型,用于调用大语言
| `max_wait_seconds` | float | `6.0` | 最大退避等待时间 |
| `retry_on_status_codes` | list[int] | `[408,409,425,429,500,502,503,504]` | 触发重试的 HTTP 状态码 |

### Agent Skills 配置 (skills)

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `enabled` | bool | `false` | 是否为该节点启用 Agent Skills |
| `allow` | list[object] | `[]` | 可选的技能白名单,来源于项目级 `.agents/skills/` 目录;每个条目使用 `name` |

### Agent Skills 说明

- 技能统一从固定的项目级 `.agents/skills/` 目录中发现。
- 运行时会暴露两个内置技能工具:`activate_skill` 和 `read_skill_file`。
- `read_skill_file` 只有在对应技能已经激活后才可用。
- 技能 `SKILL.md` 的 frontmatter 可以包含可选的 `allowed-tools`,格式遵循 Agent Skills 规范,例如 `allowed-tools: execute_code`。
- 如果某个已选择技能依赖的工具没有绑定到当前节点,该技能会在运行时被跳过。
- 如果最终没有任何兼容技能可用,Agent 会被明确告知不要声称自己使用了技能。

## 何时使用

- **文本生成**:写作、翻译、摘要、问答等
Expand Down Expand Up @@ -145,6 +162,23 @@ nodes:
max_wait_seconds: 10.0
```

### 配置 Agent Skills

```yaml
nodes:
- id: Skilled Agent
type: agent
config:
provider: openai
name: gpt-4o
api_key: ${API_KEY}
skills:
enabled: true
allow:
- name: python-scratchpad
- name: rest-api-caller
```

## 相关文档

- [Tooling 模块配置](../modules/tooling/README.md)
Expand Down
2 changes: 2 additions & 0 deletions entity/configs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@
from .node.node import EdgeLink, Node
from .node.passthrough import PassthroughConfig
from .node.python_runner import PythonRunnerConfig
from .node.skills import AgentSkillsConfig
from .node.thinking import ReflectionThinkingConfig, ThinkingConfig
from .node.tooling import FunctionToolConfig, McpLocalConfig, McpRemoteConfig, ToolingConfig

__all__ = [
"AgentConfig",
"AgentRetryConfig",
"AgentSkillsConfig",
"BaseConfig",
"ConfigError",
"DesignConfig",
Expand Down
2 changes: 2 additions & 0 deletions entity/configs/node/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
from .subgraph import SubgraphConfig
from .passthrough import PassthroughConfig
from .python_runner import PythonRunnerConfig
from .skills import AgentSkillsConfig
from .node import Node
from .literal import LiteralNodeConfig

__all__ = [
"AgentConfig",
"AgentRetryConfig",
"AgentSkillsConfig",
"HumanConfig",
"SubgraphConfig",
"PassthroughConfig",
Expand Down
16 changes: 16 additions & 0 deletions entity/configs/node/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
extend_path,
)
from .memory import MemoryAttachmentConfig
from .skills import AgentSkillsConfig
from .thinking import ThinkingConfig
from entity.configs.node.tooling import ToolingConfig

Expand Down Expand Up @@ -331,6 +332,7 @@ class AgentConfig(BaseConfig):
tooling: List[ToolingConfig] = field(default_factory=list)
thinking: ThinkingConfig | None = None
memories: List[MemoryAttachmentConfig] = field(default_factory=list)
skills: AgentSkillsConfig | None = None

# Runtime attributes (attached dynamically)
token_tracker: Any | None = field(default=None, init=False, repr=False)
Expand Down Expand Up @@ -389,6 +391,10 @@ def from_dict(cls, data: Mapping[str, Any], *, path: str) -> "AgentConfig":
if "retry" in mapping and mapping["retry"] is not None:
retry_cfg = AgentRetryConfig.from_dict(mapping["retry"], path=extend_path(path, "retry"))

skills_cfg = None
if "skills" in mapping and mapping["skills"] is not None:
skills_cfg = AgentSkillsConfig.from_dict(mapping["skills"], path=extend_path(path, "skills"))

return cls(
provider=provider,
base_url=base_url,
Expand All @@ -399,6 +405,7 @@ def from_dict(cls, data: Mapping[str, Any], *, path: str) -> "AgentConfig":
tooling=tooling_cfg,
thinking=thinking_cfg,
memories=memories_cfg,
skills=skills_cfg,
retry=retry_cfg,
input_mode=input_mode,
path=path,
Expand Down Expand Up @@ -492,6 +499,15 @@ def from_dict(cls, data: Mapping[str, Any], *, path: str) -> "AgentConfig":
child=MemoryAttachmentConfig,
advance=True,
),
"skills": ConfigFieldSpec(
name="skills",
display_name="Agent Skills",
type_hint="AgentSkillsConfig",
required=False,
description="Agent Skills allowlist and built-in skill activation/file-read tools.",
child=AgentSkillsConfig,
advance=True,
),
"retry": ConfigFieldSpec(
name="retry",
display_name="Retry Policy",
Expand Down
Loading
Loading