Contents
Developers
Step config format
๐ Overview
The step_config.json file stores step-specific agent configurations (LLM models, tool selections, execution settings) separate from the main plan structure. This separation allows plan.json to focus on workflow structure while step_config.json manages execution details.
Key Benefits:
- Separation of concerns: Plan structure vs execution configuration
- Consistent format: Object format with
stepsarray (both frontend and backend) - Backward compatibility: Legacy array format supported during migration
๐ Key Files & Locations
| Component | File Path | Key Functions |
|---|---|---|
| Frontend Parser | usePlanData.ts |
normalizeStepConfigFile(), saveStepConfig() |
| Backend Parser | source | ParseStepConfigContent(), ReadStepConfigs(), WriteStepConfigs() |
| Type Definitions | stepConfigMatching.ts |
StepConfig, AgentConfigs |
| Backend Types | source | AgentConfigs struct definition |
๐ File Locations
The step_config.json file can exist in two locations (with priority):
Run-specific config (highest priority):
{workspacePath}/runs/{runFolder}/planning/step_config.json- Used when a specific run folder is selected
- Allows different configs for different execution runs
Default config (fallback):
{workspacePath}/planning/step_config.json- Used when no run folder is selected or run-specific config doesn't exist
- Shared across all runs
Source: view on GitHub
The backend automatically checks run-specific config first, then falls back to default config.
๐ Format Structure
Object Format (Only Supported Format)
Both frontend and backend read and write only the object format with steps field:
{
"steps": [
{
"id": "step-id-here",
"title": "Optional step title",
"agent_configs": {
"selected_servers": ["server1", "server2"],
"selected_tools": ["server1:tool1", "server1:tool2", "server2:*"],
"enabled_custom_tools": ["workspace_browser:agent_browser"],
"execution_llm": {
"provider": "openai",
"model_id": "gpt-4o"
},
"use_code_execution_mode": true,
"disable_validation": false,
"llm_validation_mode": "skip",
"learnings_access": "read-write",
"learning_objective": "Capture target-system selectors, auth flow quirks, and session-expiry signals",
"enable_context_offloading": true,
"enable_prerequisite_detection": true,
"prerequisite_rules": [
{
"depends_on_step": "step-0",
"description": "If login session is missing or expired, go back to step 0"
}
]
}
}
]
}
Field Structure
| Field | Required | Type | Description |
|---|---|---|---|
steps |
โ | array |
Root array containing step configurations |
steps[].id |
โ | string |
Stable step ID from plan.json |
steps[].title |
โ | string |
Step title for reference/display only |
steps[].agent_configs |
โ | object |
Nested configuration object |
๐ Implementation Details
Frontend Implementation
File: usePlanData.ts
Read:
function normalizeStepConfigFile(rawContent: unknown): StepConfig[] {
// Handles object format: { "steps": [...] }
if (rawContent && typeof rawContent === 'object' && !Array.isArray(rawContent)) {
const obj = rawContent as Record<string, unknown>
if ('steps' in obj && Array.isArray(obj.steps)) {
return obj.steps as StepConfig[]
}
}
// Legacy array format support (with warning)
if (Array.isArray(rawContent)) {
return rawContent as StepConfig[]
}
return []
}
Write:
const content = JSON.stringify({ steps: stepConfigs }, null, 2)
await agentApi.updatePlannerFile(stepConfigPath, content, `Updated step config for step ${stepId}`)
Backend Implementation
Source: view on GitHub
Read:
type StepConfigFile struct {
Steps []StepConfig `json:"steps"`
}
func ParseStepConfigContent(content string) ([]StepConfig, error) {
var file StepConfigFile
if err := json.Unmarshal([]byte(content), &file); err != nil {
return nil, err
}
return file.Steps, nil
}
Write:
file := StepConfigFile{Steps: configs}
content, err := json.MarshalIndent(file, "", " ")
โ๏ธ Configuration Fields
Source: view on GitHub โ AgentConfigs struct
LLM Configuration
| Field | Type | Default | Purpose |
|---|---|---|---|
execution_llm |
object |
Preset default | LLM config for execution agent ({ provider: string, model_id: string }) |
validation_llm |
object |
Preset default | LLM config for validation agent |
Turn Limits
Per-step and workflow-default turn-limit properties are retired. Legacy execution_max_turns values are ignored on load and omitted from typed config saves; execution uses the shared runtime limit.
Tool & Server Configuration
| Field | Type | Default | Purpose |
|---|---|---|---|
selected_servers |
string[] |
[] |
MCP servers to use for this step (subset of preset servers) |
selected_tools |
string[] |
[] |
Specific tools (format: "server:tool" or "server:*" for all tools) |
enabled_custom_tools |
string[] |
[] |
Optional additions in "category:tool" or "category:*" format. Execution agents automatically receive workspace_advanced plus human_feedback, notify_user, and create_human_input_request. Name any additional human_tools entry explicitly. Legacy human_tools:* is normalized to the same three-tool baseline. |
enabled_custom_tool_categories |
string[] |
[] |
Legacy format: Tool categories (e.g., ["workspace_tools", "human_tools"]) - deprecated, use enabled_custom_tools instead |
Validation Configuration
| Field | Type | Default | Purpose |
|---|---|---|---|
disable_validation |
boolean |
true (nil = disabled) |
LLM validation control: nil/true = disabled (auto-approve), false = enabled. Pre-validation always runs if schema exists. |
llm_validation_mode |
"skip"|"auto"|"always" |
"skip" |
Validation strategy: "skip" (trust pre-validation), "auto" (skip after 3 successes), "always" (standard) |
Learning Configuration
| Field | Type | Default | Purpose |
|---|---|---|---|
learnings_access |
"read"|"read-write"|"none" |
"read" (auto-migrated from learning_objective if unset) |
Primary gate for the global learnings store. "read" โ step sees learnings/_global/SKILL.md in its prompt; "read-write" โ step also contributes (requires non-empty learning_objective); "none" โ step neither reads nor contributes. Mirrors knowledgebase_access. |
learning_objective |
string |
"" |
Extraction instruction for the post-step learning agent โ describes what patterns/selectors/recipes should land in SKILL.md. Required when learnings_access="read-write"; the validator rejects the combination of write access with an empty objective. |
Execution Mode Configuration
| Field | Type | Default | Purpose |
|---|---|---|---|
use_code_execution_mode |
boolean |
Preset default (nil = use preset) | Step-level code execution mode override (nil = use preset default, true/false = override) |
enable_context_offloading |
boolean |
true (nil = enabled) |
Enable/disable context offloading virtual tools |
Prerequisite Detection Configuration
| Field | Type | Default | Purpose |
|---|---|---|---|
enable_prerequisite_detection |
boolean |
false |
Enable prerequisite failure detection for this step |
prerequisite_rules |
array |
[] |
Array of prerequisite rules, each with depends_on_step (string) and description (string) |
๐ ๏ธ Common Issues & Solutions
| Issue | Cause | Solution |
|---|---|---|
"steps" field not found |
File uses legacy array format | Use normalizeStepConfigFile() to handle both formats (frontend) or ensure backend uses object format |
Step ID mismatch |
Step ID doesn't match plan.json | Ensure step IDs are stable and match plan.json exactly |
agent_configs is null |
Step has no configuration | This is valid - step will use preset defaults |
Parse error |
Invalid JSON structure | Verify file uses object format: { "steps": [...] } |
Config not found |
Run-specific config missing | Backend automatically falls back to default config in {workspacePath}/planning/step_config.json |
enabled_custom_tool_categories ignored |
Using legacy format | Migrate to unified enabled_custom_tools format: "category:tool" or "category:*" |
๐ For LLMs: Quick Reference
Constraints:
- โ
Allowed: Object format
{ "steps": [...] } - โ
Allowed: Empty
stepsarray[] - โ
Allowed: Missing
agent_configs(uses defaults) - โ Forbidden: Root-level array format (legacy, deprecated)
- โ Forbidden: Missing
idfield in step config
Example:
{
"steps": [
{
"id": "step-1",
"agent_configs": {
"selected_servers": ["aws"],
"execution_llm": {
"provider": "openai",
"model_id": "gpt-4o"
}
}
}
]
}
File Operations:
- Read: Always parse object format, extract
stepsarray - Write: Always write object format:
JSON.stringify({ steps: stepConfigs }, null, 2) - Update: Find step by
id, updateagent_configs, save entire file - Config Priority: Run-specific config (
runs/{runFolder}/planning/step_config.json) takes precedence over default config (planning/step_config.json)
Field Notes:
- All boolean fields use
nil(undefined) to mean "use default/preset value" enabled_custom_toolsuses unified format:"category:tool"or"category:*". Current categories includeworkspace_advanced,workspace_tools,workspace_browser, andhuman_tools; useexecute_shell_command/diff_patch_workspace_filefor file access instead of legacy basic workspace tool names.learning_detail_levelaccepts"exact","general", or"none"(default:"exact")
๐ Related Documentation
- Workflow Docs - Overall workflow architecture
- Learn Code and Code Execution Modes - Scripted execution configuration and flow
- Step Config Matching - Type definitions and matching logic