Files
temp/docs/reference/actors_schema.md
T
aditya 411bc3325f docs(actor): add comprehensive actor schema reference documentation
Add complete reference documentation for actor YAML schema:

Documentation Sections:
- Actor types overview (LLM, TOOL, GRAPH)
- Complete field definitions for all models
- Tool node semantics (references vs inline definitions)
- Graph constraints and topology rules
- Comprehensive validation rules with examples
- Error messages with causes and fixes

Field Definitions:
- Top-level actor fields (name, type, model, etc.)
- ToolParameter and ToolDefinition fields
- MemoryConfig and ContextConfigSchema fields
- ContextView enum (strategist, executor, reviewer, full)

Graph Documentation:
- Node types (AGENT, TOOL, CONDITIONAL, SUBGRAPH)
- Edge definition and conditional routing
- RouteDefinition structure
- Cycle detection explanation

Validation Rules:
1. Unique node IDs
2. Entry node existence
3. Exit nodes existence
4. Edge reference validity
5. Acyclic graph requirement
6. Node reachability

Examples:
- Simple LLM actor
- LLM with inline tools
- Simple graph workflow
- Complex graph with conditionals
- Error examples with fixes

Part 6 of C1.schema implementation (Actor YAML Schema Models).
2026-02-17 13:26:15 +00:00

1041 lines
21 KiB
Markdown

# Actor YAML Schema Reference
## Overview
Actors are the v3 replacement for v2's reactive stream configurations, providing a simpler, more declarative way to define AI agent behaviors. An actor defines what an agent can do, how it processes information, and how it interacts with tools and other actors.
**Module:** `cleveragents.actor.schema`
**Schema Version:** 1.0
## Table of Contents
- [Actor Types](#actor-types)
- [Field Definitions](#field-definitions)
- [Tool Node Semantics](#tool-node-semantics)
- [Graph Constraints](#graph-constraints)
- [Validation Rules](#validation-rules)
- [Error Messages](#error-messages)
- [Examples](#examples)
---
## Actor Types
Actors come in three types, each serving different purposes:
### LLM Actor
**Type:** `llm`
**Purpose:** Single LLM agent with system prompt and optional tools
**Use Case:** Simple conversational agents, code reviewers, assistants
**Required Fields:**
- `name` - Namespaced actor name
- `type: llm`
- `model` - LLM model identifier (e.g., "gpt-4", "claude-3-opus")
**Optional Fields:**
- `system_prompt` - System prompt defining agent behavior
- `tools` - List of tool references or inline definitions
- `context_view` - Role-based context filtering
- `memory` - Conversation history settings
- `context` - File inclusion settings
**Example:**
```yaml
name: assistants/code_reviewer
type: llm
model: gpt-4
system_prompt: "You are an expert code reviewer..."
```
### TOOL Actor
**Type:** `tool`
**Purpose:** Collection of callable tools without LLM interaction
**Use Case:** Utility tool bundles, shared tool libraries
**Required Fields:**
- `name` - Namespaced actor name
- `type: tool`
- `tools` - At least one tool (reference or inline definition)
**Optional Fields:**
- None (tools-only actors don't need LLM configuration)
**Example:**
```yaml
name: utilities/file_ops
type: tool
tools:
- files/read_file
- files/write_file
```
### GRAPH Actor
**Type:** `graph`
**Purpose:** Multi-node workflow with conditional routing
**Use Case:** Complex workflows, multi-step processes, agentic loops
**Required Fields:**
- `name` - Namespaced actor name
- `type: graph`
- `model` - LLM model for agent nodes
- `route` - Complete graph topology definition
**Optional Fields:**
- `system_prompt` - Default prompt for graph-level agents
- `tools` - Tools available to all agent nodes
- `context_view` - Context filtering for the entire graph
- `memory` - Memory settings for the graph
- `context` - Context settings
**Example:**
```yaml
name: workflows/test_driven_dev
type: graph
model: gpt-4
route:
nodes: [...]
edges: [...]
entry_node: planner
exit_nodes: [review]
```
---
## Field Definitions
### Top-Level Fields
#### `name` (required)
**Type:** `str`
**Format:** `namespace/actor_name`
**Description:** Unique identifier for the actor in namespaced format
**Validation:**
- Must contain exactly one forward slash (`/`)
- Namespace and name must not be empty
- Should use snake_case for both parts
**Valid:**
- `assistants/code_reviewer`
- `workflows/test_driven_dev`
- `utilities/file_operations`
**Invalid:**
- `code_reviewer` (missing namespace)
- `assistants/code/reviewer` (too many slashes)
- `assistants/` (empty name)
#### `type` (required)
**Type:** `ActorType` enum
**Values:** `llm`, `tool`, `graph`
**Description:** Determines actor execution behavior and compilation target
#### `description` (required)
**Type:** `str`
**Description:** Human-readable description of what the actor does
**Best Practices:**
- Start with a verb ("Reviews code...", "Processes documents...")
- Keep under 200 characters
- Be specific about the actor's purpose
#### `version` (optional)
**Type:** `str`
**Default:** `"1.0"`
**Description:** Schema version for backward compatibility
#### `model` (conditional)
**Type:** `str`
**Required for:** `llm`, `graph` actors
**Optional for:** `tool` actors (not used)
**Description:** LLM model identifier
**Common Values:**
- OpenAI: `gpt-4`, `gpt-4-turbo`, `gpt-3.5-turbo`
- Anthropic: `claude-3-opus`, `claude-3-sonnet`, `claude-3-haiku`
- Open source: `mistral-large`, `llama-3-70b`
#### `system_prompt` (optional)
**Type:** `str`
**Description:** System prompt defining agent behavior and guidelines
**Best Practices:**
- Use multi-line YAML strings (`|`) for readability
- Include role definition ("You are an expert...")
- List specific tasks and constraints
- Provide output format guidance
#### `tools` (optional/required)
**Type:** `list[str | ToolDefinition]`
**Required for:** `tool` actors
**Optional for:** `llm`, `graph` actors
**Description:** Tools available to the actor
**Tool Reference Format:**
```yaml
tools:
- namespace/tool_name # Reference to existing tool
```
**Inline Tool Definition:**
```yaml
tools:
- name: utils/count_lines
description: Count lines in a file
parameters:
- name: file_path
type: str
required: true
code: |
def count_lines(file_path: str) -> int:
with open(file_path, 'r') as f:
return len(f.readlines())
```
---
### Tool Definition Fields
#### ToolParameter
**Fields:**
- `name` (str, required): Parameter name (must be valid Python identifier)
- `type` (str, required): Python type annotation (e.g., `str`, `int`, `list[str]`)
- `description` (str, required): Parameter description
- `required` (bool, default=True): Whether parameter is required
- `default` (any, optional): Default value for optional parameters
**Example:**
```yaml
parameters:
- name: input_file
type: str
description: Path to input file
required: true
- name: encoding
type: str
description: File encoding
required: false
default: utf-8
```
#### ToolDefinition
**Fields:**
- `name` (str, required): Tool name in `namespace/name` format
- `description` (str, required): What the tool does
- `parameters` (list, optional): List of ToolParameter objects
- `code` (str, required): Python code implementing the tool
**Validation:**
- Tool name must follow `namespace/name` format
- Code must be valid Python
- Parameter names must be valid identifiers
---
### Memory Configuration
#### MemoryConfig
**Fields:**
- `enabled` (bool, default=True): Enable conversation memory
- `max_messages` (int, optional): Maximum messages to retain (None = unlimited)
- `max_tokens` (int, optional): Maximum tokens in history (None = unlimited)
- `summarize_old` (bool, default=False): Summarize old messages to save tokens
**Example:**
```yaml
memory:
enabled: true
max_messages: 50
max_tokens: 4000
summarize_old: false
```
**Use Cases:**
- Short conversations: `max_messages: 10-20`
- Medium conversations: `max_messages: 50`, `max_tokens: 4000-8000`
- Long workflows: `summarize_old: true`, `max_tokens: 16000`
---
### Context Configuration
#### ContextConfigSchema
**Fields:**
- `include_files` (list[str]): Specific files to include in context
- `include_dirs` (list[str]): Directories to include in context
- `exclude_patterns` (list[str]): Glob patterns to exclude
- `max_context_tokens` (int, optional): Maximum context window size
**Example:**
```yaml
context:
include_files:
- README.md
- pyproject.toml
include_dirs:
- src/
- tests/
exclude_patterns:
- "**/__pycache__/**"
- "*.pyc"
- "**/.git/**"
max_context_tokens: 8000
```
#### ContextView
**Type:** enum
**Values:** `strategist`, `executor`, `reviewer`, `full`
**Description:** Role-based context filtering
**Context Views:**
- **strategist**: High-level planning view
- Project structure
- Goals and constraints
- Architecture decisions
- No implementation details
- **executor**: Implementation view
- Source code
- File contents
- Specific tasks
- Implementation details
- **reviewer**: Validation view
- Changes and diffs
- Test results
- Code quality metrics
- Review feedback
- **full**: Complete view (use sparingly)
- All available context
- Can exceed token limits
- Only for critical decision points
---
## Tool Node Semantics
### Tool References
Tool references point to existing tools in the tool registry. Use references when:
- The tool is shared across multiple actors
- The tool is complex and tested separately
- The tool requires specific dependencies
**Format:** `namespace/tool_name`
**Example:**
```yaml
tools:
- files/read_file
- testing/run_pytest
- analysis/extract_entities
```
### Inline Tool Definitions
Inline tools are defined directly in the actor YAML. Use inline tools when:
- The tool is actor-specific
- The tool is simple (< 50 lines of code)
- The tool doesn't require external dependencies
**Best Practices:**
1. Keep inline tools simple and focused
2. Include proper error handling
3. Add docstrings to the function
4. Use type hints for all parameters
5. Validate inputs before processing
**Example:**
```yaml
tools:
- name: utils/count_words
description: Count words in a text file
parameters:
- name: file_path
type: str
description: Path to text file
required: true
code: |
def count_words(file_path: str) -> dict:
"""Count words in a file and return statistics."""
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
words = content.split()
return {
"word_count": len(words),
"char_count": len(content),
"line_count": content.count('\n') + 1
}
except FileNotFoundError:
return {"error": f"File not found: {file_path}"}
except Exception as e:
return {"error": str(e)}
```
---
## Graph Constraints
### Graph Topology
A graph actor's `route` field defines the complete workflow topology.
#### RouteDefinition
**Fields:**
- `nodes` (list[NodeDefinition], required): All nodes in the graph
- `edges` (list[EdgeDefinition], required): Connections between nodes
- `entry_node` (str, required): Starting node ID
- `exit_nodes` (list[str], required): Terminal node IDs
### Node Types
#### AGENT Node
**Type:** `agent`
**Purpose:** LLM-powered decision making and content generation
**Configuration:**
```yaml
- id: planner
type: agent
name: Task Planner
description: Plans tasks based on requirements
config:
model: gpt-4 # Can override graph-level model
prompt: "You are a task planning expert..."
tools:
- files/read_file
- analysis/extract_requirements
```
#### TOOL Node
**Type:** `tool`
**Purpose:** Execute specific tools or functions
**Configuration:**
```yaml
- id: run_tests
type: tool
name: Test Runner
description: Executes pytest test suite
config:
tool_name: testing/run_pytest
parameters:
verbose: true
coverage: true
```
#### CONDITIONAL Node
**Type:** `conditional`
**Purpose:** Route execution based on conditions
**Configuration:**
```yaml
- id: check_results
type: conditional
name: Result Checker
description: Routes based on test results
config:
conditions:
- check: "state.get('tests_passed') == True"
route_to: code_review
- check: "state.get('tests_passed') == False"
route_to: fix_errors
```
**Conditional Expressions:**
- Access state with `state.get('key')`
- Use Python comparison operators (`==`, `!=`, `<`, `>`, `<=`, `>=`)
- Combine with boolean operators (`and`, `or`, `not`)
- Conditions are evaluated in order; first match wins
#### SUBGRAPH Node
**Type:** `subgraph`
**Purpose:** Embed another actor as a nested workflow
**Configuration:**
```yaml
- id: code_review
type: subgraph
name: Code Reviewer
description: Runs full code review workflow
config:
actor_path: actors/code_reviewer.yaml
```
**Subgraph Rules:**
- Subgraph actors can be of any type (llm, tool, graph)
- State is passed to and from the subgraph
- Subgraphs enable workflow composition and reuse
- Maximum nesting depth: 5 levels
### Edge Definition
**Fields:**
- `from_node` (str, required): Source node ID
- `to_node` (str, required): Target node ID
- `condition` (str, optional): Conditional routing expression
- `priority` (int, default=0): Edge priority (higher = evaluated first)
**Example:**
```yaml
edges:
# Unconditional edge
- from_node: planner
to_node: executor
# Conditional edge
- from_node: executor
to_node: retry
condition: "state.get('retry_count', 0) < 3"
priority: 10
# Default edge (lower priority)
- from_node: executor
to_node: escalate
priority: 1
```
---
## Validation Rules
### Graph Validation
The schema automatically validates graph topology when loading YAML files.
#### 1. Unique Node IDs
**Rule:** All node IDs must be unique within a graph.
**Valid:**
```yaml
nodes:
- id: planner
- id: executor
- id: reviewer
```
**Invalid:**
```yaml
nodes:
- id: planner
- id: executor
- id: planner # ❌ Duplicate ID
```
**Error:**
```
ValueError: Duplicate node IDs found: {'planner'}
```
#### 2. Entry Node Exists
**Rule:** The `entry_node` must reference a valid node ID.
**Valid:**
```yaml
nodes:
- id: start
- id: process
entry_node: start # ✅ 'start' exists
```
**Invalid:**
```yaml
nodes:
- id: start
- id: process
entry_node: init # ❌ 'init' doesn't exist
```
**Error:**
```
ValueError: Entry node 'init' not found in nodes
```
#### 3. Exit Nodes Exist
**Rule:** All `exit_nodes` must reference valid node IDs.
**Valid:**
```yaml
nodes:
- id: start
- id: end1
- id: end2
exit_nodes:
- end1
- end2
```
**Invalid:**
```yaml
nodes:
- id: start
- id: end1
exit_nodes:
- end1
- finish # ❌ 'finish' doesn't exist
```
**Error:**
```
ValueError: Exit node 'finish' not found in nodes
```
#### 4. Edge References Valid
**Rule:** All edge `from_node` and `to_node` must reference valid node IDs.
**Valid:**
```yaml
nodes:
- id: a
- id: b
edges:
- from_node: a
to_node: b
```
**Invalid:**
```yaml
nodes:
- id: a
- id: b
edges:
- from_node: a
to_node: c # ❌ 'c' doesn't exist
```
**Error:**
```
ValueError: Edge to_node 'c' not found in nodes
```
#### 5. No Cycles
**Rule:** Graphs must be acyclic (no circular dependencies).
**Valid (Linear):**
```yaml
edges:
- from_node: a
to_node: b
- from_node: b
to_node: c
```
**Valid (Branching):**
```yaml
edges:
- from_node: a
to_node: b
- from_node: a
to_node: c
- from_node: b
to_node: d
- from_node: c
to_node: d
```
**Invalid (Cycle):**
```yaml
edges:
- from_node: a
to_node: b
- from_node: b
to_node: c
- from_node: c
to_node: a # ❌ Cycle: a → b → c → a
```
**Error:**
```
ValueError: Graph contains cycles involving nodes: ['a']
```
**Note:** Conditional edges with retry logic can appear cyclic but are validated at runtime.
#### 6. All Nodes Reachable
**Rule:** All nodes must be reachable from the entry node.
**Valid:**
```yaml
entry_node: start
edges:
- from_node: start
to_node: process
- from_node: process
to_node: end
```
**Invalid:**
```yaml
entry_node: start
nodes:
- id: start
- id: process
- id: orphan # ❌ Not reachable from 'start'
edges:
- from_node: start
to_node: process
```
**Error:**
```
ValueError: Unreachable nodes detected: {'orphan'}
```
---
## Error Messages
### Common Validation Errors
#### NameError: Invalid Actor Name
**Cause:** Actor name doesn't follow `namespace/name` format
**Example:**
```yaml
name: code_reviewer # ❌ Missing namespace
```
**Error:**
```
ValueError: Actor name must be namespaced (namespace/name): code_reviewer
```
**Fix:**
```yaml
name: assistants/code_reviewer # ✅
```
#### TypeError: Missing Required Field
**Cause:** LLM or GRAPH actor missing `model` field
**Example:**
```yaml
name: assistants/helper
type: llm
# ❌ Missing model field
```
**Error:**
```
ValueError: LLM actors require 'model' field
```
**Fix:**
```yaml
name: assistants/helper
type: llm
model: gpt-4 # ✅
```
#### ValueError: Empty Tools List
**Cause:** TOOL actor with no tools defined
**Example:**
```yaml
name: utilities/helpers
type: tool
tools: [] # ❌ Empty list
```
**Error:**
```
ValueError: TOOL actors require at least one tool
```
**Fix:**
```yaml
name: utilities/helpers
type: tool
tools:
- files/read_file # ✅
```
#### ValueError: Missing Route
**Cause:** GRAPH actor without route definition
**Example:**
```yaml
name: workflows/process
type: graph
model: gpt-4
# ❌ Missing route field
```
**Error:**
```
ValueError: GRAPH actors require 'route' field
```
**Fix:**
```yaml
name: workflows/process
type: graph
model: gpt-4
route: # ✅
nodes: [...]
edges: [...]
entry_node: start
exit_nodes: [end]
```
---
## Examples
### Example 1: Simple LLM Actor
```yaml
name: assistants/code_reviewer
type: llm
description: Reviews Python code for best practices
version: "1.0"
model: gpt-4
system_prompt: |
You are an expert Python code reviewer.
Review code for:
- PEP 8 compliance
- Design patterns
- Potential bugs
- Performance issues
context_view: reviewer
memory:
enabled: true
max_messages: 20
```
### Example 2: LLM with Inline Tools
```yaml
name: assistants/file_analyzer
type: llm
description: Analyzes files and generates reports
version: "1.0"
model: gpt-4-turbo
system_prompt: "Analyze files and provide insights..."
tools:
- files/read_file # Tool reference
- name: utils/count_lines # Inline tool
description: Count lines in a file
parameters:
- name: file_path
type: str
required: true
code: |
def count_lines(file_path: str) -> int:
with open(file_path, 'r') as f:
return len(f.readlines())
```
### Example 3: Simple Graph Workflow
```yaml
name: workflows/doc_processor
type: graph
description: Processes documents through multiple stages
version: "1.0"
model: gpt-3.5-turbo
route:
nodes:
- id: extract
type: tool
name: Text Extractor
description: Extracts text from documents
config:
tool_name: documents/extract_text
- id: analyze
type: agent
name: Analyzer
description: Analyzes content
config:
model: gpt-3.5-turbo
prompt: "Analyze the document content..."
- id: summarize
type: agent
name: Summarizer
description: Creates summary
config:
model: gpt-3.5-turbo
prompt: "Summarize in 3-5 bullet points..."
edges:
- from_node: extract
to_node: analyze
- from_node: analyze
to_node: summarize
entry_node: extract
exit_nodes:
- summarize
```
### Example 4: Complex Graph with Conditionals
```yaml
name: workflows/ci_pipeline
type: graph
description: CI/CD pipeline with test and deploy stages
version: "1.0"
model: gpt-4
route:
nodes:
- id: build
type: tool
name: Builder
description: Builds the project
config:
tool_name: ci/build
- id: test
type: tool
name: Test Runner
description: Runs test suite
config:
tool_name: ci/run_tests
- id: check_tests
type: conditional
name: Test Result Checker
description: Check if tests passed
config:
conditions:
- check: "state.get('tests_passed') == True"
route_to: deploy
- check: "state.get('tests_passed') == False"
route_to: notify_failure
- id: deploy
type: tool
name: Deployer
description: Deploys to production
config:
tool_name: ci/deploy
- id: notify_failure
type: tool
name: Notifier
description: Sends failure notification
config:
tool_name: notifications/send_alert
edges:
- from_node: build
to_node: test
- from_node: test
to_node: check_tests
# Conditional routing handled by check_tests node
entry_node: build
exit_nodes:
- deploy
- notify_failure
```
---
## Usage
### Loading Actor Configuration
```python
from cleveragents.actor.schema import ActorConfigSchema
# Load from YAML file
actor = ActorConfigSchema.from_yaml_file("actors/code_reviewer.yaml")
# Access fields
print(actor.name) # assistants/code_reviewer
print(actor.type) # ActorType.LLM
print(actor.model) # gpt-4
# Validate graph (automatic on load)
if actor.type == ActorType.GRAPH:
# Validation already done:
# - All nodes have unique IDs
# - Entry/exit nodes exist
# - All edges reference valid nodes
# - No cycles detected
# - All nodes reachable
pass
```
### Saving Actor Configuration
```python
# Create actor programmatically
actor = ActorConfigSchema(
name="assistants/helper",
type=ActorType.LLM,
description="A helpful assistant",
model="gpt-4",
system_prompt="You are a helpful assistant."
)
# Save to YAML file
actor.to_yaml_file("actors/helper.yaml")
```
---
## See Also
- [ADR-010: Actor and Agent Architecture](../adr/ADR-010-actor-and-agent-architecture.md)
- [ADR-011: Tool System](../adr/ADR-011-tool-system.md)
- [Tool Schema Reference](../schema/tool.schema.yaml)
- [Action Schema Reference](../schema/action.schema.yaml)