chore: import upstream snapshot with attribution
Validate YAML Workflows / Validate YAML Configuration Files (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:37:51 +08:00
commit d0e4308def
614 changed files with 74458 additions and 0 deletions
+186
View File
@@ -0,0 +1,186 @@
# Agent Node
The Agent node is the most fundamental node type in the DevAll platform, used to invoke Large Language Models (LLMs) for text generation, conversation, reasoning, and other tasks. It supports multiple model providers (OpenAI, Gemini, etc.) and can be configured with advanced features like tool calling, chain-of-thought, and memory.
## Configuration
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `provider` | string | Yes | `openai` | Model provider name, e.g., `openai`, `gemini` |
| `name` | string | Yes | - | Model name, e.g., `gpt-4o`, `gemini-2.0-flash-001` |
| `role` | text | No | - | System prompt |
| `base_url` | string | No | Provider default | API endpoint URL, supports `${VAR}` placeholders |
| `api_key` | string | No | - | API key, recommend using environment variable `${API_KEY}` |
| `params` | dict | No | `{}` | Model call parameters (temperature, top_p, etc.) |
| `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)
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `enabled` | bool | `true` | Whether to enable automatic retry |
| `max_attempts` | int | `5` | Maximum number of attempts (including first attempt) |
| `min_wait_seconds` | float | `1.0` | Minimum backoff wait time |
| `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.
- **Intelligent conversation**: Multi-turn dialogue, customer service bots
- **Tool calling**: Enable the model to call external APIs or execute functions
- **Complex reasoning**: Use with thinking configuration for deep thought
- **Knowledge retrieval**: Use with memories to implement RAG patterns
## Examples
### Basic Configuration
```yaml
nodes:
- id: Writer
type: agent
config:
provider: openai
base_url: ${BASE_URL}
api_key: ${API_KEY}
name: gpt-4o
role: |
You are a professional technical documentation writer. Please answer questions in clear and concise language.
params:
temperature: 0.7
max_tokens: 2000
```
### Configuring Tool Calling
```yaml
nodes:
- id: Assistant
type: agent
config:
provider: openai
name: gpt-4o
api_key: ${API_KEY}
tooling:
type: function # Tool type: function, mcp_remote, mcp_local
config:
tools: # List of function tools from functions/function_calling/ directory
- name: describe_available_files
- name: load_file
timeout: 20 # Optional: execution timeout (seconds)
```
### Configuring MCP Tools (Remote HTTP)
```yaml
nodes:
- id: MCP Agent
type: agent
config:
provider: openai
name: gpt-4o
api_key: ${API_KEY}
tooling:
type: mcp_remote
config:
server: http://localhost:8080/mcp # MCP server endpoint
headers: # Optional: custom request headers
Authorization: Bearer ${MCP_TOKEN}
timeout: 30 # Optional: request timeout (seconds)
```
### Configuring MCP Tools (Local stdio)
```yaml
nodes:
- id: Local MCP Agent
type: agent
config:
provider: openai
name: gpt-4o
api_key: ${API_KEY}
tooling:
type: mcp_local
config:
command: uvx # Launch command
args: ["mcp-server-sqlite", "--db-path", "data.db"]
cwd: ${WORKSPACE} # Optional, usually not needed
env: # Optional, usually not needed
DEBUG: "true"
startup_timeout: 10 # Optional: startup timeout (seconds)
```
### Gemini Multimodal Configuration
```yaml
nodes:
- id: Vision Agent
type: agent
config:
provider: gemini
base_url: https://generativelanguage.googleapis.com
api_key: ${GEMINI_API_KEY}
name: gemini-2.5-flash-image
role: You need to generate corresponding image content based on user input.
```
### Configuring Retry Strategy
```yaml
nodes:
- id: Robust Agent
type: agent
config:
provider: openai
name: gpt-4o
api_key: ${API_KEY}
retry: # Retry is enabled by default, you can customize it
enabled: true
max_attempts: 3
min_wait_seconds: 2.0
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)
- [Memory Module Configuration](../modules/memory.md)
- [Workflow Authoring Guide](../workflow_authoring.md)
+114
View File
@@ -0,0 +1,114 @@
# Human Node
The Human node is used to introduce human interaction during workflow execution, allowing users to view the current state and provide input through the Web UI. This node blocks workflow execution until the user submits a response.
## Configuration
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `description` | text | No | - | Task description displayed to the user, explaining the operation that requires human completion |
## Core Concepts
### Blocking Wait Mechanism
When the workflow reaches a Human node:
1. The workflow pauses, waiting for human input
2. The Web UI displays the current context and task description
3. The user enters a response in the interface
4. The workflow continues execution, passing the user input to downstream nodes
### Web UI Interaction
- Human nodes are presented as a conversation in the Launch interface
- Users can view previous execution history
- Supports attachment uploads (e.g., files, images)
## When to Use
- **Review and confirmation**: Have humans review LLM output before continuing
- **Modification suggestions**: Collect user suggestions for modifying generated content
- **Critical decisions**: Points where human judgment is needed to continue
- **Data supplementation**: When additional information from the user is needed
- **Quality control**: Introduce human quality checks at critical nodes
## Examples
### Basic Configuration
```yaml
nodes:
- id: Human Reviewer
type: human
config:
description: Please review the above content. If satisfied, enter ACCEPT; otherwise, enter your modification suggestions.
```
### Human-Machine Collaboration Loop
```yaml
nodes:
- id: Article Writer
type: agent
config:
provider: openai
name: gpt-4o
api_key: ${API_KEY}
role: You are a professional writer who writes articles based on user requirements.
- id: Human Reviewer
type: human
config:
description: |
Please review the article:
- If satisfied with the result, enter ACCEPT to end the process
- Otherwise, enter modification suggestions to continue iterating
edges:
- from: Article Writer
to: Human Reviewer
- from: Human Reviewer
to: Article Writer
condition:
type: keyword
config:
none: [ACCEPT]
case_sensitive: false
```
### Multi-Stage Review
```yaml
nodes:
- id: Draft Generator
type: agent
config:
provider: openai
name: gpt-4o
- id: Content Review
type: human
config:
description: Please review content accuracy. Enter APPROVED or modification suggestions.
- id: Final Reviewer
type: human
config:
description: Final confirmation. Enter PUBLISH to publish or REJECT to reject.
edges:
- from: Draft Generator
to: Content Review
- from: Content Review
to: Final Reviewer
condition:
type: keyword
config:
any: [APPROVED]
```
## Best Practices
- Clearly explain expected operations and keywords in the `description`
- Use conditional edges with keywords to implement flow control
- Consider adding timeout mechanisms to avoid infinite workflow waiting
+140
View File
@@ -0,0 +1,140 @@
# Literal Node
The Literal node is used to output fixed text content. When the node is triggered, it ignores all inputs and directly outputs a predefined message.
## Configuration
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `content` | text | Yes | - | Fixed text content to output, cannot be empty |
| `role` | string | No | `user` | Message role: `user` or `assistant` |
## Core Concepts
### Fixed Output
Characteristics of the Literal node:
- **Ignores input**: Regardless of what upstream content is passed in, it does not affect the output
- **Fixed content**: Outputs the same `content` every time it executes
- **Role marking**: Output message carries the specified role identifier
### Message Role
- `user`: Indicates this is a message sent by the user
- `assistant`: Indicates this is a message sent by the assistant (AI)
The role setting affects how downstream nodes process the message.
## When to Use
- **Fixed prompt injection**: Inject fixed instructions or context into the workflow
- **Testing and debugging**: Use fixed input to test downstream nodes
- **Default responses**: Return fixed messages under specific conditions
- **Process initialization**: Serve as the starting point of a workflow to provide initial content
## Examples
### Basic Usage
```yaml
nodes:
- id: Welcome Message
type: literal
config:
content: |
Welcome to the intelligent assistant! Please describe your needs.
role: assistant
```
### Injecting Fixed Context
```yaml
nodes:
- id: Context Injector
type: literal
config:
content: |
Please note the following rules:
1. Answers must be concise and clear
2. Reply in English
3. If uncertain, please state so
role: user
- id: Assistant
type: agent
config:
provider: openai
name: gpt-4o
edges:
- from: Context Injector
to: Assistant
```
### Fixed Responses in Conditional Branches
```yaml
nodes:
- id: Classifier
type: agent
config:
provider: openai
name: gpt-4o
role: Determine user intent, reply with KNOWN or UNKNOWN
- id: Known Response
type: literal
config:
content: I can help you complete this task.
role: assistant
- id: Unknown Response
type: literal
config:
content: Sorry, I cannot understand your request. Please describe it in a different way.
role: assistant
edges:
- from: Classifier
to: Known Response
condition:
type: keyword
config:
any: [KNOWN]
- from: Classifier
to: Unknown Response
condition:
type: keyword
config:
any: [UNKNOWN]
```
### Testing Purposes
```yaml
nodes:
- id: Test Input
type: literal
config:
content: |
This is a test text for verifying downstream processing logic.
Contains multiple lines.
role: user
- id: Processor
type: python
config:
timeout_seconds: 30
edges:
- from: Test Input
to: Processor
start: [Test Input]
```
## Notes
- The `content` field cannot be an empty string
- Use YAML multi-line string syntax `|` for writing long text
- Choose the correct `role` to ensure downstream nodes process the message correctly
+153
View File
@@ -0,0 +1,153 @@
# Loop Counter Node
The Loop Counter node is a loop control node used to limit the number of iterations of a loop in a workflow. Through a counting mechanism, it suppresses output before reaching the preset limit, and only releases the message to trigger outgoing edges when the limit is reached, thereby terminating the loop.
## Configuration
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `max_iterations` | int | Yes | `10` | Maximum number of loop iterations, must be ≥ 1 |
| `reset_on_emit` | bool | No | `true` | Whether to reset the counter after reaching the limit |
| `message` | text | No | - | Message content to send to downstream when limit is reached |
## Core Concepts
### How It Works
The Loop Counter node maintains an internal counter with the following behavior:
1. **Each time it is triggered**: Counter +1
2. **Counter < `max_iterations`**: **No output is produced**, outgoing edges are not triggered
3. **Counter = `max_iterations`**: Output message is produced, triggering outgoing edges
This "suppress-release" mechanism allows the Loop Counter to precisely control when a loop terminates.
### Topological Structure Requirements
The Loop Counter node has special placement requirements in the graph structure:
```
┌──────────────────────────────────────┐
▼ │
Agent ──► Human ─────► Loop Counter ──┬──┘
▲ │ │
└─────────┘ ▼
End Node (outside loop)
```
> **Important**: Since Loop Counter **produces no output until the limit is reached**:
> - **Human must connect to both Agent and Loop Counter**: This way the "continue loop" edge is handled by Human → Agent, while Loop Counter only handles counting
> - **Loop Counter must connect to Agent (inside loop)**: So it's recognized as an in-loop node, avoiding premature loop termination
> - **Loop Counter must connect to End Node (outside loop)**: When the limit is reached, trigger the out-of-loop node to terminate the entire loop execution
### Counter State
- Counter state persists throughout the entire workflow execution
- When `reset_on_emit: true`, the counter resets to 0 after reaching the limit
- When `reset_on_emit: false`, the counter continues accumulating after reaching the limit, outputting on every subsequent trigger
## When to Use
- **Preventing infinite loops**: Set a safety limit for human-machine interaction loops
- **Iteration control**: Limit the maximum number of self-improvement iterations for an Agent
- **Timeout protection**: Serve as a "circuit breaker" for process execution
## Examples
### Basic Usage
```yaml
nodes:
- id: Iteration Guard
type: loop_counter
config:
max_iterations: 5
reset_on_emit: true
message: Maximum iteration count reached, process terminated.
```
### Human-Machine Interaction Loop Protection
This is the most typical use case for Loop Counter:
```yaml
graph:
id: review_loop
description: Review loop with iteration limit
nodes:
- id: Writer
type: agent
config:
provider: openai
name: gpt-4o
role: Improve articles based on user feedback
- id: Reviewer
type: human
config:
description: |
Review the article, enter ACCEPT to accept or provide modification suggestions.
- id: Loop Guard
type: loop_counter
config:
max_iterations: 3
message: Maximum modification count (3 times) reached, process automatically ended.
- id: Final Output
type: passthrough
config: {}
edges:
# Main loop: Writer -> Reviewer
- from: Writer
to: Reviewer
# Condition 1: User enters ACCEPT -> End
- from: Reviewer
to: Final Output
condition:
type: keyword
config:
any: [ACCEPT]
# Condition 2: User enters modification suggestions -> Trigger both Writer to continue loop AND Loop Guard to count
- from: Reviewer
to: Writer
condition:
type: keyword
config:
none: [ACCEPT]
- from: Reviewer
to: Loop Guard
condition:
type: keyword
config:
none: [ACCEPT]
# Loop Guard connects to Writer (keeps it inside the loop)
- from: Loop Guard
to: Writer
# When Loop Guard reaches limit: Trigger Final Output to end the process
- from: Loop Guard
to: Final Output
start: [Writer]
end: [Final Output]
```
**Execution Flow Explanation**:
1. User first enters modification suggestions → Triggers both Writer (continue loop) and Loop Guard (count 1, no output)
2. User enters modification suggestions again → Triggers both Writer (continue loop) and Loop Guard (count 2, no output)
3. User enters modification suggestions for the third time → Writer continues execution, Loop Guard count 3 reaches limit, outputs message triggering Final Output, terminating the loop
4. Or at any time user enters ACCEPT → Goes directly to Final Output to end
## Notes
- `max_iterations` must be a positive integer (≥ 1)
- Loop Counter **produces no output until the limit is reached**, outgoing edges will not trigger
- Ensure Loop Counter connects to both in-loop and out-of-loop nodes
- The `message` field is optional, default message is `"Loop limit reached (N)"`
+159
View File
@@ -0,0 +1,159 @@
# Loop Timer Node
The Loop Timer node is a loop control node used to limit the duration of a loop in a workflow. Through a time-tracking mechanism, it suppresses output before reaching the preset time limit, and only releases the message to trigger outgoing edges when the time limit is reached, thereby terminating the loop.
## Configuration
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `max_duration` | float | Yes | `60.0` | Maximum loop duration, must be > 0 |
| `duration_unit` | string | Yes | `"seconds"` | Time unit: "seconds", "minutes", or "hours" |
| `reset_on_emit` | bool | No | `true` | Whether to reset the timer after reaching the limit |
| `message` | text | No | - | Message content to send to downstream when time limit is reached |
## Core Concepts
### How It Works
The Loop Timer node maintains an internal timer with the following behavior:
1. **On first trigger**: Timer starts tracking elapsed time
2. **Elapsed time < `max_duration`**: **No output is produced**, outgoing edges are not triggered
3. **Elapsed time >= `max_duration`**: Output message is produced, triggering outgoing edges
This "suppress-release" mechanism allows the Loop Timer to precisely control when a loop terminates based on time rather than iteration count.
### Topological Structure Requirements
The Loop Timer node has special placement requirements in the graph structure:
```
┌──────────────────────────────────────┐
▼ │
Agent ──► Human ─────► Loop Timer ──┬──┘
▲ │ │
└─────────┘ ▼
End Node (outside loop)
```
> **Important**: Since Loop Timer **produces no output until the time limit is reached**:
> - **Human must connect to both Agent and Loop Timer**: This way the "continue loop" edge is handled by Human → Agent, while Loop Timer only handles time tracking
> - **Loop Timer must connect to Agent (inside loop)**: So it's recognized as an in-loop node, avoiding premature loop termination
> - **Loop Timer must connect to End Node (outside loop)**: When the time limit is reached, trigger the out-of-loop node to terminate the entire loop execution
### Timer State
- Timer state persists throughout the entire workflow execution
- Timer starts on the first trigger to the Loop Timer node
- When `reset_on_emit: true`, the timer resets after reaching the limit
- When `reset_on_emit: false`, the timer continues running after reaching the limit, outputting on every subsequent trigger
## When to Use
- **Time-based constraints**: Enforce time limits for loops (e.g., "review must complete within 5 minutes")
- **Timeout protection**: Serve as a "circuit breaker" to prevent runaway processes
- **Variable iteration time**: When each loop iteration takes unpredictable time, but total duration must be bounded
## Examples
### Basic Usage
```yaml
nodes:
- id: Time Guard
type: loop_timer
config:
max_duration: 5
duration_unit: minutes
reset_on_emit: true
message: Time limit reached (5 minutes), process terminated.
```
### Time-Limited Review Loop
This is the most typical use case for Loop Timer:
```yaml
graph:
id: timed_review_loop
description: Review loop with 5-minute time limit
nodes:
- id: Writer
type: agent
config:
provider: openai
name: gpt-4o
role: Improve articles based on user feedback
- id: Reviewer
type: human
config:
description: |
Review the article, enter ACCEPT to accept or provide modification suggestions.
- id: Loop Gate
type: loop_timer
config:
max_duration: 5
duration_unit: minutes
message: Time limit (5 minutes) reached, process automatically ended.
- id: Final Output
type: passthrough
config: {}
edges:
# Main loop: Writer -> Reviewer
- from: Writer
to: Reviewer
# Condition 1: User enters ACCEPT -> End
- from: Reviewer
to: Final Output
condition:
type: keyword
config:
any: [ACCEPT]
# Condition 2: User enters modification suggestions -> Trigger both Writer to continue loop AND Loop Gate to track time
- from: Reviewer
to: Writer
condition:
type: keyword
config:
none: [ACCEPT]
- from: Reviewer
to: Loop Gate
condition:
type: keyword
config:
none: [ACCEPT]
# Loop Gate connects to Writer (keeps it inside the loop)
- from: Loop Gate
to: Writer
# When Loop Gate reaches time limit: Trigger Final Output to end the process
- from: Loop Gate
to: Final Output
start: [Writer]
end: [Final Output]
```
**Execution Flow Explanation**:
1. User first enters modification suggestions → Triggers both Writer (continue loop) and Loop Gate (track time, no output)
2. User enters modification suggestions again → Triggers both Writer (continue loop) and Loop Gate (track time, no output)
3. After 5 minutes of elapsed time → Loop Gate outputs message triggering Final Output, terminating the loop
4. Or at any time user enters ACCEPT → Goes directly to Final Output to end
## Notes
- `max_duration` must be a positive number (> 0)
- `duration_unit` must be one of: "seconds", "minutes", "hours"
- Loop Timer **produces no output until the time limit is reached**, outgoing edges will not trigger
- Ensure Loop Timer connects to both in-loop and out-of-loop nodes
- The `message` field is optional, default message is `"Time limit reached (N units)"`
- Timer starts on the first trigger to the Loop Timer node
+206
View File
@@ -0,0 +1,206 @@
# Passthrough Node
The Passthrough node is the simplest node type. It performs no operations and passes received messages to downstream nodes. By default, it only passes the **last message**. It is primarily used for graph structure "wire management" optimization and context control.
## Configuration
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `only_last_message` | bool | No | `true` | Whether to pass only the last message. Set to `false` to pass all messages. |
### Basic Configuration
```yaml
config: {} # Uses default configuration, only passes the last message
```
### Pass All Messages
```yaml
config:
only_last_message: false # Pass all received messages
```
## Core Concepts
### Pass-through Behavior
- Receives all messages passed from upstream
- **By default, only passes the last message** (`only_last_message: true`)
- When `only_last_message: false`, passes all messages
- Does not perform any content processing or transformation
### Graph Structure Optimization
The core value of the Passthrough node is not in data processing, but in **graph structure optimization** ("wire management"):
- Makes complex edge connections clearer
- Centrally manages outgoing edge configurations (such as `keep_message`)
- Serves as a logical dividing point, improving workflow readability
## Key Uses
### 1. As an Entry Node to Preserve Initial Context
Using Passthrough as the workflow entry node, combined with the `keep_message: true` edge configuration, ensures that the user's initial task is always preserved in the context and won't be overwritten by subsequent node outputs:
```yaml
nodes:
- id: Task Keeper
type: passthrough
config: {}
- id: Worker A
type: agent
config:
provider: openai
name: gpt-4o
- id: Worker B
type: agent
config:
provider: openai
name: gpt-4o
edges:
# Distribute tasks from entry, preserving original message
- from: Task Keeper
to: Worker A
keep_message: true # Preserve initial task context
- from: Task Keeper
to: Worker B
keep_message: true
start: [Task Keeper]
```
**Effect**: Both Worker A and Worker B can see the user's original input, not just the output from the previous node.
### 2. Filtering Redundant Output in Loops
In workflows containing loops, nodes within the loop may produce a large amount of intermediate output. Passing all outputs to subsequent nodes would cause context bloat. Using a Passthrough node allows you to **pass only the final result of the loop**:
```yaml
nodes:
- id: Iterative Improver
type: agent
config:
provider: openai
name: gpt-4o
role: Continuously improve output based on feedback
- id: Evaluator
type: agent
config:
provider: openai
name: gpt-4o
role: |
Evaluate output quality, reply GOOD or provide improvement suggestions
- id: Result Filter
type: passthrough
config: {}
- id: Final Processor
type: agent
config:
provider: openai
name: gpt-4o
role: Post-process the final result
edges:
- from: Iterative Improver
to: Evaluator
# Loop: Return to improvement node when evaluation fails
- from: Evaluator
to: Iterative Improver
condition:
type: keyword
config:
none: [GOOD]
# Loop ends: Filter through Passthrough, only pass the last message
- from: Evaluator
to: Result Filter
condition:
type: keyword
config:
any: [GOOD]
- from: Result Filter
to: Final Processor
start: [Iterative Improver]
end: [Final Processor]
```
**Effect**: Regardless of how many loop iterations occur, `Final Processor` will only receive the last output from `Evaluator` (the one indicating quality passed), not all intermediate results.
## Other Uses
- **Placeholder**: Reserve node positions during design phase
- **Conditional branching**: Implement routing logic with conditional edges
- **Debugging observation point**: Insert nodes for easy observation in the workflow
## Examples
### Basic Usage
```yaml
nodes:
- id: Router
type: passthrough
config: {}
```
### Conditional Routing
```yaml
nodes:
- id: Classifier
type: agent
config:
provider: openai
name: gpt-4o
role: |
Classify input content, reply TECHNICAL or BUSINESS
- id: Router
type: passthrough
config: {}
- id: Tech Handler
type: agent
config:
provider: openai
name: gpt-4o
- id: Biz Handler
type: agent
config:
provider: openai
name: gpt-4o
edges:
- from: Classifier
to: Router
- from: Router
to: Tech Handler
condition:
type: keyword
config:
any: [TECHNICAL]
- from: Router
to: Biz Handler
condition:
type: keyword
config:
any: [BUSINESS]
```
## Best Practices
- Use meaningful node IDs that describe their topological role (e.g., `Task Keeper`, `Result Filter`)
- When used as an entry node, configure outgoing edges with `keep_message: true` to preserve context
- Use after loops to filter out redundant intermediate output
+89
View File
@@ -0,0 +1,89 @@
# Python Node
The Python node is used to execute Python scripts or inline code within workflows, implementing custom data processing, API calls, file operations, and other logic. Scripts are executed in the shared `code_workspace/` directory and can access workflow context data.
## Configuration
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `interpreter` | string | No | Current Python | Python interpreter path |
| `args` | list[str] | No | `[]` | Startup arguments appended to the interpreter |
| `env` | dict[str, str] | No | `{}` | Additional environment variables, overrides system defaults |
| `timeout_seconds` | int | No | `60` | Script execution timeout (seconds) |
| `encoding` | string | No | `utf-8` | Encoding for parsing stdout/stderr |
## Core Concepts
### Code Workspace
Python scripts are executed within the `code_workspace/` directory:
- Scripts can read and write files in this directory
- Multiple Python nodes share the same workspace
- The workspace persists for the duration of a single workflow execution
### Input/Output
- **Input**: Outputs from upstream nodes are passed as environment variables or standard input
- **Output**: The script's stdout output will be passed as a Message to downstream nodes
## When to Use
- **Data processing**: Parse JSON/XML, data transformation, formatting
- **API calls**: Call third-party services, fetch external data
- **File operations**: Read/write files, generate reports
- **Complex calculations**: Mathematical operations, algorithm implementations
- **Glue logic**: Custom logic connecting different nodes
## Examples
### Basic Configuration
```yaml
nodes:
- id: Data Processor
type: python
config:
timeout_seconds: 120
env:
key: value
```
### Specifying Interpreter and Arguments
```yaml
nodes:
- id: Script Runner
type: python
config:
interpreter: /usr/bin/python3.11
timeout_seconds: 300
encoding: utf-8
```
### Typical Workflow Example
```yaml
nodes:
- id: LLM Generator
type: agent
config:
provider: openai
name: gpt-4o
api_key: ${API_KEY}
role: You need to generate executable Python code based on user input. The code should be wrapped in ```python ```.
- id: Result Parser
type: python
config:
timeout_seconds: 30
edges:
- from: LLM Generator
to: Result Parser
```
## Notes
- Ensure script files are placed in the `code_workspace/` directory
- Long-running scripts should have an appropriately increased `timeout_seconds`
- Use `env` to pass additional environment variables, accessible in scripts via `os.getenv`
+138
View File
@@ -0,0 +1,138 @@
# Subgraph Node
The Subgraph node allows embedding another workflow graph into the current workflow, enabling process reuse and modular design. Subgraphs can come from external YAML files or be defined inline in the configuration.
## Configuration
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `type` | string | Yes | - | Subgraph source type: `file` or `config` |
| `config` | object | Yes | - | Contains different configurations depending on `type` |
### File Type Configuration
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `path` | string | Yes | Subgraph file path (relative to `yaml_instance/` or absolute path) |
### Config Type Configuration
Inline definition of the complete subgraph structure, containing the same fields as the top-level `graph`:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `id` | string | Yes | Subgraph identifier |
| `description` | string | No | Subgraph description |
| `log_level` | string | No | Log level (DEBUG/INFO) |
| `nodes` | list | Yes | Node list |
| `edges` | list | No | Edge list |
| `start` | list | No | Entry node list |
| `end` | list | No | Exit node list |
| `memory` | list | No | Memory definitions specific to the subgraph |
## Core Concepts
### Modular Reuse
Extract commonly used process fragments into independent YAML files that can be reused by multiple workflows:
- Example: Package an "article polishing" process as a subgraph
- Different main workflows can call this subgraph
### Variable Inheritance
Subgraphs inherit `vars` variable definitions from the parent graph, supporting cross-level variable passing.
### Execution Isolation
Subgraphs execute as independent units with their own:
- Node namespace
- Log level configuration
- Memory definitions (optional)
## When to Use
- **Process reuse**: Multiple workflows sharing the same sub-processes
- **Modular design**: Breaking complex processes into manageable smaller units
- **Team collaboration**: Different teams maintaining different subgraph modules
## Examples
### Referencing External File
```yaml
nodes:
- id: Review Process
type: subgraph
config:
type: file
config:
path: common/review_flow.yaml
```
### Inline Subgraph Definition
```yaml
nodes:
- id: Translation Unit
type: subgraph
config:
type: config
config:
id: translation_subgraph
description: Multi-language translation subprocess
nodes:
- id: Translator
type: agent
config:
provider: openai
name: gpt-4o
role: You are a professional translator who translates content to the target language.
- id: Proofreader
type: agent
config:
provider: openai
name: gpt-4o
role: You are a proofreading expert who checks and polishes translated content.
edges:
- from: Translator
to: Proofreader
start: [Translator]
end: [Proofreader]
```
### Combining Multiple Subgraphs
```yaml
nodes:
- id: Input Handler
type: agent
config:
provider: openai
name: gpt-4o
- id: Analysis Module
type: subgraph
config:
type: file
config:
path: modules/analysis.yaml
- id: Report Module
type: subgraph
config:
type: file
config:
path: modules/report_gen.yaml
edges:
- from: Input Handler
to: Analysis Module
- from: Analysis Module
to: Report Module
```
## Notes
- Subgraph file paths support relative paths (based on `yaml_instance/`) and absolute paths
- Avoid circular nesting (A references B, B references A)
- The subgraph's `start` and `end` nodes determine how data flows in and out, which decides how the subgraph processes messages from the parent graph and which node's final output is returned to the parent graph