Skip to content

Commit f70e3e9

Browse files
refactor: separate sub-agent workflows, update model to Opus 4.6, remove hourly control loop
Addresses feedback from issue strands-agents#33 comment: 1. Remove hourly control loop (strands-control.yml) - Not needed for our use case. The Wednesday 10am cron is directly in strands-autonomous.yml — no AGENT_SCHEDULES machinery required. 2. Update model to Opus 4.6 with adaptive thinking and 1M context - Model: global.anthropic.claude-opus-4-6-v1 - Max tokens: 128,000 (was 64,000) - Thinking: adaptive (was fixed 8k budget) - Removed STRANDS_BUDGET_TOKENS constant - Matches strands-coder settings 3. Separate sub-agent workflows for isolated testing - strands-adversarial-test.yml — adversarial testing agent - strands-release-notes-agent.yml — release notes generation - strands-docs-gap.yml — documentation gap analysis - Each can be triggered independently via workflow_dispatch - Orchestrator dispatches to dedicated workflows 4. Bug fix: _get_all_tools() had dead code after return statement - Orchestrator tools were never actually loaded - Fixed to return after appending all tools Files: 6 modified, 3 new, 1 deleted
1 parent 6dd0021 commit f70e3e9

9 files changed

Lines changed: 569 additions & 413 deletions

File tree

strands-command/README.md

Lines changed: 67 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -544,20 +544,24 @@ The orchestrator module (`orchestrator.py`) enables agents to dispatch and coord
544544

545545
```mermaid
546546
graph TD
547-
A[Control Loop] -->|hourly check| B[Schedule Check]
548-
B -->|Wednesday 10am| C[Release Digest Agent]
549-
C -->|dispatch| D[Adversarial Tester]
550-
C -->|dispatch| E[Release Notes Generator]
551-
C -->|dispatch| F[Docs Gap Analyzer]
547+
A[strands-autonomous.yml] -->|"Wed 10am cron"| C[Release Digest Orchestrator]
548+
C -->|dispatch| D[strands-adversarial-test.yml]
549+
C -->|dispatch| E[strands-release-notes-agent.yml]
550+
C -->|dispatch| F[strands-docs-gap.yml]
552551
D -->|results| C
553552
E -->|results| C
554553
F -->|results| C
555554
C -->|create| G[Digest Issue]
556555
557556
style C fill:#f9f,stroke:#333,stroke-width:2px
558557
style G fill:#9f9,stroke:#333,stroke-width:2px
558+
style D fill:#fcc,stroke:#333
559+
style E fill:#ccf,stroke:#333
560+
style F fill:#cfc,stroke:#333
559561
```
560562

563+
Each sub-agent workflow can also be triggered independently via `workflow_dispatch` for isolated testing.
564+
561565
#### Self-Trigger Prevention
562566

563567
The orchestrator uses the same pattern as strands-coder to prevent infinite loops:
@@ -575,26 +579,12 @@ Copy the template workflows to your repository:
575579
```bash
576580
# From the devtools/strands-command/workflows/ directory
577581
cp strands-autonomous.yml your-repo/.github/workflows/
578-
cp strands-control.yml your-repo/.github/workflows/
582+
cp strands-adversarial-test.yml your-repo/.github/workflows/
583+
cp strands-release-notes-agent.yml your-repo/.github/workflows/
584+
cp strands-docs-gap.yml your-repo/.github/workflows/
579585
```
580586

581-
#### 2. Configure Repository Variables
582-
583-
Set the `AGENT_SCHEDULES` repository variable:
584-
585-
```json
586-
{
587-
"jobs": {
588-
"weekly_release_digest": {
589-
"enabled": true,
590-
"cron": "0 10 * * 3",
591-
"command": "release-digest",
592-
"workflow": "strands-autonomous.yml",
593-
"last_triggered": 0
594-
}
595-
}
596-
}
597-
```
587+
The Wednesday 10am schedule is configured directly in `strands-autonomous.yml` via cron — no additional schedule variables needed.
598588

599589
#### 3. Configure Secrets
600590

@@ -649,3 +639,57 @@ When running as an orchestrator agent, these tools are available:
649639
| `check_agents_status` | Check status of all dispatched sub-agents |
650640
| `wait_for_agents` | Wait for all sub-agents to complete (with timeout) |
651641
| `get_orchestrator_config` | View current orchestrator security configuration |
642+
643+
644+
### Autonomous Agent Capabilities
645+
646+
The Strands command system supports autonomous agent execution for:
647+
648+
- **Adversarial Testing**: Automated testing that actively tries to break code changes
649+
- **Release Digest**: Weekly orchestrated analysis combining adversarial testing, release notes, and documentation gap analysis
650+
651+
#### Workflow Architecture
652+
653+
Each agent type has its own dedicated workflow for **isolated testing and execution**:
654+
655+
| Workflow | Purpose | Trigger |
656+
|----------|---------|---------|
657+
| `strands-autonomous.yml` | Release digest orchestrator | Wednesday 10am UTC cron + manual |
658+
| `strands-adversarial-test.yml` | Adversarial testing agent | Dispatched by orchestrator + manual |
659+
| `strands-release-notes-agent.yml` | Release notes generation | Dispatched by orchestrator + manual |
660+
| `strands-docs-gap.yml` | Documentation gap analysis | Dispatched by orchestrator + manual |
661+
662+
#### Agent Orchestration
663+
664+
The orchestrator module (`orchestrator.py`) enables agents to dispatch and coordinate sub-agents via dedicated workflows:
665+
666+
```
667+
strands-autonomous.yml (Release Digest Orchestrator — Wed 10am)
668+
├── strands-adversarial-test.yml (isolated workflow)
669+
├── strands-release-notes-agent.yml (isolated workflow)
670+
└── strands-docs-gap.yml (isolated workflow)
671+
```
672+
673+
Each sub-agent runs in its own workflow, so you can:
674+
- **Test in isolation**: Trigger any sub-agent independently via `workflow_dispatch`
675+
- **Debug independently**: Check workflow run logs per agent type
676+
- **Customize timeouts**: Each workflow has its own `timeout-minutes`
677+
678+
Security limits:
679+
- Max concurrent sub-agents: 3 (configurable)
680+
- Per-agent timeout: 30 minutes
681+
- Max total sub-agents per run: 5
682+
- Rate limiting and cooldown between dispatches
683+
684+
#### Model Configuration
685+
686+
All agents use **Opus 4.6** with adaptive thinking and 1M context window:
687+
- Model: `global.anthropic.claude-opus-4-6-v1`
688+
- Max tokens: 128,000
689+
- Thinking: adaptive
690+
691+
#### Setup
692+
693+
1. Copy the workflow files to `.github/workflows/` in your repository
694+
2. Configure `PAT_TOKEN` secret with `workflow_dispatch` permission
695+
3. Configure orchestrator limits via repository variables (optional)

strands-command/agent-sops/task-release-digest.sop.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ Determine which sub-agents to dispatch based on the changes found.
6464
**Constraints:**
6565
- You MUST plan the following sub-agent tasks:
6666

67-
| Task | Agent Type | Input | Output |
68-
|------|-----------|-------|--------|
69-
| Adversarial Testing | `adversarial-test` | List of PRs with significant code changes | Findings report per PR |
70-
| Release Notes | `release-notes` | Base and head git references | Formatted release notes |
71-
| Documentation Gaps | `docs-gap` | List of PRs with new/changed APIs | Missing docs report |
67+
| Task | Agent Type | Workflow | Input | Output |
68+
|------|-----------|----------|-------|--------|
69+
| Adversarial Testing | `adversarial-test` | `strands-adversarial-test.yml` | List of PRs with significant code changes | Findings report per PR |
70+
| Release Notes | `release-notes` | `strands-release-notes-agent.yml` | Base and head git references | Formatted release notes |
71+
| Documentation Gaps | `docs-gap` | `strands-docs-gap.yml` | List of PRs with new/changed APIs | Missing docs report |
7272

7373
- You MUST skip adversarial testing if there are no code-changing PRs (only docs/CI/test changes)
7474
- You MUST skip documentation gap analysis if there are no API-changing PRs
@@ -80,10 +80,14 @@ Determine which sub-agents to dispatch based on the changes found.
8080
Dispatch sub-agents for parallel execution.
8181

8282
**Constraints:**
83-
- You MUST use the orchestrator module (`orchestrator.py`) to dispatch sub-agents
83+
- You MUST use the orchestrator module (`orchestrator.py`) to dispatch sub-agents to their **dedicated workflows** (each runs in isolation)
8484
- You MUST call the `dispatch_agent` function for each planned task
8585
- You MUST respect the concurrent agent limit — wait for slots before dispatching
8686
- You MUST wait the minimum cooldown between dispatches
87+
- You MUST dispatch each sub-agent to its dedicated workflow:
88+
- **Adversarial tester**`strands-adversarial-test.yml`
89+
- **Release notes**`strands-release-notes-agent.yml`
90+
- **Docs gap**`strands-docs-gap.yml`
8791
- You MUST pass appropriate inputs to each sub-agent:
8892
- **Adversarial tester**: PR numbers, branch references
8993
- **Release notes**: Base tag, head reference, repository
@@ -228,7 +232,7 @@ The orchestrator reads scheduling configuration from the `AGENT_SCHEDULES` repos
228232
"cron": "0 10 * * 3",
229233
"prompt": "Run the weekly release digest. Find all changes since the last release, dispatch adversarial testing and release notes sub-agents, and compile a comprehensive digest issue.",
230234
"system_prompt": "You are a Release Digest Orchestrator following the task-release-digest SOP.",
231-
"workflow": "strands-command.yml",
235+
"workflow": "strands-autonomous.yml" // orchestrator only,
232236
"tools": ""
233237
}
234238
}

strands-command/scripts/python/agent_runner.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@
5252
from notebook import notebook
5353
from str_replace_based_edit_tool import str_replace_based_edit_tool
5454

55-
# Strands configuration constants
56-
STRANDS_MODEL_ID = "global.anthropic.claude-opus-4-5-20251101-v1:0"
57-
STRANDS_MAX_TOKENS = 64000
58-
STRANDS_BUDGET_TOKENS = 8000
55+
# Strands configuration constants — matches strands-coder settings
56+
# Opus 4.6 with adaptive thinking and 1M context window
57+
STRANDS_MODEL_ID = "global.anthropic.claude-opus-4-6-v1"
58+
STRANDS_MAX_TOKENS = 128000
5959
STRANDS_REGION = "us-west-2"
6060

6161
# Default values for environment variables used only in this file
@@ -157,7 +157,7 @@ def _get_trace_attributes() -> dict:
157157
}
158158

159159
def _get_all_tools() -> list[Any]:
160-
return [
160+
tools = [
161161
# File editing
162162
str_replace_based_edit_tool,
163163

@@ -191,6 +191,8 @@ def _get_all_tools() -> list[Any]:
191191
# Add orchestrator tools if available
192192
if _ORCHESTRATOR_AVAILABLE:
193193
tools.extend([dispatch_agent, check_agents_status, wait_for_agents, get_orchestrator_config])
194+
195+
return tools
194196

195197

196198
def run_agent(query: str):
@@ -203,13 +205,10 @@ def run_agent(query: str):
203205
# Get tools and create model
204206
tools = _get_all_tools()
205207

206-
# Create Bedrock model with inlined configuration
208+
# Create Bedrock model — Opus 4.6 with adaptive thinking and 1M context
207209
additional_request_fields = {}
208-
additional_request_fields["anthropic_beta"] = ["interleaved-thinking-2025-05-14"]
209-
210210
additional_request_fields["thinking"] = {
211-
"type": "enabled",
212-
"budget_tokens": STRANDS_BUDGET_TOKENS
211+
"type": "adaptive",
213212
}
214213

215214
model = BedrockModel(

strands-command/scripts/python/orchestrator.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class AgentTask:
6464
completion_time: datetime | None = None
6565
result: str | None = None
6666
error: str | None = None
67-
workflow: str = "strands-command.yml"
67+
workflow: str = ""
6868

6969

7070
@dataclass
@@ -170,7 +170,7 @@ def dispatch_agent(
170170
agent_type: str,
171171
prompt: str,
172172
system_prompt: str = "",
173-
workflow: str = "strands-command.yml",
173+
workflow: str = "",
174174
extra_inputs: dict[str, str] | None = None,
175175
) -> AgentTask:
176176
"""Dispatch a sub-agent via workflow_dispatch.
@@ -179,7 +179,10 @@ def dispatch_agent(
179179
agent_type: Type of agent (e.g., "adversarial-test", "release-notes")
180180
prompt: Task prompt for the sub-agent
181181
system_prompt: System prompt override for the sub-agent
182-
workflow: Target workflow file (default: strands-command.yml)
182+
workflow: Target workflow file. Each sub-agent has a dedicated workflow:
183+
- strands-adversarial-test.yml
184+
- strands-release-notes-agent.yml
185+
- strands-docs-gap.yml
183186
extra_inputs: Additional workflow inputs
184187
185188
Returns:
@@ -468,7 +471,7 @@ def dispatch_agent(
468471
agent_type: str,
469472
prompt: str,
470473
system_prompt: str = "",
471-
workflow: str = "strands-command.yml",
474+
workflow: str = "",
472475
) -> str:
473476
"""Dispatch a sub-agent via GitHub Actions workflow_dispatch.
474477
@@ -482,7 +485,10 @@ def dispatch_agent(
482485
agent_type: Type of agent (e.g., "adversarial-test", "release-notes", "docs-gap")
483486
prompt: Task prompt for the sub-agent
484487
system_prompt: System prompt override (optional)
485-
workflow: Target workflow file (default: strands-command.yml).
488+
workflow: Target workflow file. Each sub-agent has a dedicated workflow:
489+
- strands-adversarial-test.yml
490+
- strands-release-notes-agent.yml
491+
- strands-docs-gap.yml.
486492
Use "owner/repo/workflow.yml" for cross-repo dispatch.
487493
488494
Returns:

0 commit comments

Comments
 (0)