Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/strands-command.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ on:

jobs:
authorization-check:
if: startsWith(github.event.comment.body, '/strands') || github.event_name == 'workflow_dispatch'
# Exclude '/strands-ts' so strands-ts-command.yml handles it (the '/strands'
# prefix would otherwise match and fire both workflows on one comment).
if: (startsWith(github.event.comment.body, '/strands') && !startsWith(github.event.comment.body, '/strands-ts')) || github.event_name == 'workflow_dispatch'
name: Check access
permissions: read-all
runs-on: ubuntu-latest
Expand Down Expand Up @@ -79,7 +81,7 @@ jobs:
write_permission: 'false'

finalize:
if: always() && (startsWith(github.event.comment.body, '/strands') || github.event_name == 'workflow_dispatch')
if: always() && ((startsWith(github.event.comment.body, '/strands') && !startsWith(github.event.comment.body, '/strands-ts')) || github.event_name == 'workflow_dispatch')
needs: [setup-and-process, execute-readonly-agent]
permissions:
contents: write
Expand Down
98 changes: 98 additions & 0 deletions .github/workflows/strands-ts-command.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Multi-agent TypeScript PR reviewer, triggered by `/strands-ts <command>`.
# Mirrors strands-command.yml (the Python /strands handler) but invokes the
# strands-ts actions. Runs ALONGSIDE /strands; nothing is replaced.
#
# BLOCKED BY: strands-agents/devtools#68 — the strands-ts-* actions referenced
# below only exist on devtools@main AFTER that PR merges. Do not merge this
# until #68 is merged, or the runner/finalize steps will 404.
name: Strands-TS Command Handler

on:
issue_comment:
types: [created]

# No workflow-level write perms: the read/write split is enforced per job so
# the agent job never holds a write-capable token.
permissions: {}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: There's no concurrency group. Because this workflow introduces a strands-running label lifecycle (mark-runningclear-running), two /strands-ts comments on the same PR will race: clear-running from the first run can remove the label while the second run is still executing, and you'll also get duplicate concurrent reviews.

Suggestion: Add a per-PR concurrency group so a new invocation supersedes an in-flight one, e.g.:

concurrency:
  group: strands-ts-${{ github.event.issue.number }}
  cancel-in-progress: true


jobs:
authorization-check:
if: ${{ github.event.issue.pull_request && startsWith(github.event.comment.body, '/strands-ts') }}
name: Check access
permissions:
contents: read
runs-on: ubuntu-latest
outputs:
approval-env: ${{ steps.auth.outputs.approval-env }}
steps:
- name: Check Authorization
id: auth
uses: strands-agents/devtools/authorization-check@main
with:
username: ${{ github.event.comment.user.login || 'invalid' }}
allowed-roles: 'triage,write,admin'

mark-running:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: mark-running depends only on authorization-check and has no environment gate, while execute-readonly-agent does (environment: ${{ needs.authorization-check.outputs.approval-env }}). For users routed through a manual-approval environment, the strands-running label is applied before the approval is granted, so a PR can show "running" while actually pending/never-approved.

Suggestion: Consider gating mark-running on the same approval-env so the label only appears once the run is actually approved to proceed.

needs: [authorization-check]
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- name: Add strands-running label
env:
GH_TOKEN: ${{ github.token }}
PR_NUM: ${{ github.event.issue.number }}
run: gh pr edit "$PR_NUM" --repo "${{ github.repository }}" --add-label strands-running || true

execute-readonly-agent:
needs: [authorization-check, mark-running]
environment: ${{ needs.authorization-check.outputs.approval-env }}
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: read
pull-requests: read
id-token: write # AWS OIDC role assumption only
steps:
- uses: actions/checkout@v4
- name: Resolve PR head SHA
id: pr
env:
GH_TOKEN: ${{ github.token }}
PR_NUM: ${{ github.event.issue.number }}
run: echo "sha=$(gh pr view "$PR_NUM" --json headRefOid -q .headRefOid)" >> "$GITHUB_OUTPUT"
- name: Run Strands-TS Agent
uses: strands-agents/devtools/strands-command/actions/strands-ts-runner@main
with:
command: ${{ github.event.comment.body }}
pr_number: ${{ github.event.issue.number }}
pr_head_sha: ${{ steps.pr.outputs.sha }}
aws_role_arn: ${{ secrets.AWS_ROLE_ARN }}
agents_config: ${{ vars.STRANDS_TS_AGENTS || '' }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: The PR description states this workflow uses the AGENT_SESSIONS_BUCKET secret (matching strands-command.yml, which passes sessions_bucket: ${{ secrets.AGENT_SESSIONS_BUCKET }}), but it's never referenced here.

Suggestion: Confirm whether the strands-ts-runner action needs a sessions bucket. If it does, the input is missing and session persistence will silently break; if it intentionally doesn't, please update the PR description so the secret list is accurate. Either way, worth reconciling before merge.


finalize:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: finalize (and clear-running) have no timeout-minutes. The mirrored strands-command.yml sets timeout-minutes: 30 on its finalize job. Adding a timeout here guards against a hung write-replay step holding the runner indefinitely.

needs: [execute-readonly-agent]
if: ${{ needs.execute-readonly-agent.result == 'success' }}
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write # the ONLY job that can write; replays vetted artifact ops
steps:
- uses: actions/checkout@v4
- name: Replay deferred writes
uses: strands-agents/devtools/strands-command/actions/strands-ts-finalize@main

clear-running:
needs: [mark-running, execute-readonly-agent, finalize]
if: ${{ always() && needs.mark-running.result == 'success' }}
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- name: Remove strands-running label
env:
GH_TOKEN: ${{ github.token }}
PR_NUM: ${{ github.event.issue.number }}
run: gh pr edit "$PR_NUM" --repo "${{ github.repository }}" --remove-label strands-running || true
Loading