Fix Linter Errors Dynamically
This example demonstrates a more advanced Bosun workflow that dynamically identifies linter errors in your codebase and then spawns individual AI agents to fix each error. This showcases the power of combining run steps for command execution with for_each loops and agent steps for targeted, automated code remediation.
Workflow Definition (bosun.yaml)
name: fix-linter-errors-dynamically
description: Identifies linter errors and uses agents to fix them, then creates a PR.
inputs:
maxErrors:
type: Number
required: false
description: Limit how many erroring files to process.
steps:
- id: lint_errors
name: Run linter and get errors
run: |
# Simulate a linter command that outputs file paths with errors.
# In a real scenario, this would be your actual linter command (e.g., `eslint --format compact src/`).
# For this example, we'll just list some files that *would* have errors.
echo "src/components/BadComponent.tsx"
echo "src/utils/BrokenHelper.ts"
echo "src/pages/UnformattedPage.tsx"
# The output of this step will be a list of file paths, one per line.
- id: fix_lint_errors
name: Fix each linter error with an agent
for_each:
from: '{{ outputs.lint_errors | split(pat="\n") | filter(value) | slice(end=inputs.maxErrors) | json_encode() }}'
agent:
extends: Coding
instructions: "Apply automatic linting fixes to the file {{ for_each.value }}. Focus on common formatting issues and simple syntax corrections."
role: "You are a meticulous code formatter and linter expert."
constraints:
- "Use the project's standard linting rules (assume ESLint/Prettier are configured)."
- "Only apply fixes that do not change code logic."
- "Ensure the file remains syntactically correct and passes type checks."
- "Focus solely on the specified file: {{ for_each.value }}"
- "Do not make any unrelated changes."
- id: open_pr
name: Create a pull request for fixes
agent:
extends: Default
role: "You create pull requests for automated code fixes."
instructions: "Create a draft pull request for all lint fixes applied in this run."
toolboxes: [repository_read, dangerous]
tools:
- name: create_pull_request
extends: create_or_update_pull_request
with:
draft: true
starts_with: lint_errors
ends_with: open_pr
edges:
- from: lint_errors
to: fix_lint_errors
- from: fix_lint_errors
to: open_pr
How it Works
- Run Linter: The
lint_errorsrun step simulates executing a linter command. In a real-world scenario, you would replaceecho "..."with your actual linter command (for exampleeslint --format compact src/). The output is expected to be a list of file paths, one per line. - Iterate and Fix: The graph moves from
lint_errorstofix_lint_errors. Thisfor_eachstep takesoutputs.lint_errors, splits it into file paths, filters out empty strings, and iterates over each file. The optional numeric inputinputs.maxErrorslimits the workload.- For each file path, a new
Codingagent is spawned. - The agent's
instructionsdynamically include{{ for_each.value }}, telling it exactly which file to focus on. - The agent's
roleandconstraintsguide it to apply automatic linting fixes without altering code logic.
- For each file path, a new
- Create Pull Request: After the fan-out step completes, the graph continues to
open_pr, where aDefaultagent creates a draft pull request containing the accumulated fixes.
Replace the placeholder command
Swap the echo statements with your actual linter invocation—Bosun only needs a newline-delimited list of files to drive the loop.