Skip to content

fix(claude-swe-agent): add scope-discipline guardrails so the agent stops instead of over-reaching (#185) - #189

Merged
imaustink merged 1 commit into
mainfrom
fix/claude-agent-scope-discipline-185
Aug 1, 2026
Merged

fix(claude-swe-agent): add scope-discipline guardrails so the agent stops instead of over-reaching (#185)#189
imaustink merged 1 commit into
mainfrom
fix/claude-agent-scope-discipline-185

Conversation

@k5s-bot

@k5s-bot k5s-bot Bot commented Aug 1, 2026

Copy link
Copy Markdown

Closes #185.

Problem

The Claude code SWE agent (apps/claude-code-swe-agent) runs headless as a one-shot Kubernetes Job — there is no interactive human in the loop while it works. But the fixed, trusted policy in buildPrompt() (the text that wraps every task) only covered the git workflow and the destructive-command bans. Nothing told the agent to:

  • stay within the scope of the task it was handed, or
  • stop when it hits a wall (missing repo access/permissions, an ambiguous or wrong-looking instruction, a repeatedly-failing command).

So when it was unsure or something went wrong, it tended to keep going — expanding the task, or improvising a workaround (substituting or creating a repository, guessing at intent) — instead of pausing for a human. That's the "too eager / goes off the rails" behavior reported in the issue.

The triage promptTemplate already carries some of this language, but only for the triage flow. Putting it in buildPrompt() makes it apply to every Claude agent invocation, which is where the general behavior lives.

Change

Three scope-discipline rules added to the ## Rules (must follow) block in buildPrompt():

  1. Stay in scope — do the task asked and no more; surface extra ideas in the final summary instead of doing them.
  2. Stop, don't improvise, when blocked or unsure — missing access, ambiguous/wrong instructions, or persistently-failing commands mean the turn is done. Explicitly: do not substitute a different repository, create a repo the task didn't call for, broaden the task, or guess at intent to keep making progress.
  3. Surface the blocker — explain the blocker/question plainly in the final reply (and in an issue/PR comment where one exists) so a human can decide and re-trigger. A halted turn with a clear question is a successful outcome, not a failure.

The human-in-the-loop mechanism in this headless, one-turn model is exactly this: stop, report clearly, and let a maintainer re-trigger (e.g. via the existing label workflow) rather than having the agent barrel through on its own guess.

Tests

claude.ts previously had no test module. Added claude.test.ts covering the existing buildClaudeSettings/buildPrompt behavior (continuation context, instruction embedding) plus the new guardrails, asserting they are present on both fresh and continuation turns.

  • npm test -w claude-code-swe-agent → 7 files / 62 tests pass (12 in the new claude.test.ts).
  • npm run typecheck -w claude-code-swe-agent → clean (after npm run build:libs).

Scope note

Deliberately kept to the Claude agent that the issue names. The sibling opencode-swe-agent has a parallel buildPrompt(); mirroring these rules there is a reasonable follow-up but was intentionally left out to avoid broadening this change beyond the issue.


Maintainer: apply the ai-review label to this PR to request an automated code review, or the ai-triage label to have the review feedback addressed and the branch brought back in sync with its base. (The automation can't apply either label to its own PR, so a human needs to.)

…ompt (#185)

The Claude code SWE agent runs headless with no interactive human in the
loop, yet the fixed task policy in buildPrompt() only covered the git
workflow and destructive-command bans. Nothing told the agent to stay in
scope or to stop when blocked, so it would over-reach — expanding the
task, or improvising a workaround (substituting/creating a repo, guessing
at intent) when it hit missing access or an ambiguous instruction, exactly
the "too eager" behavior reported in #185.

Bake three scope-discipline rules into the trusted policy that wraps every
invocation (not just the triage flow):

- Stay within the scope of the task as given; surface extra ideas in the
  summary instead of doing them.
- When blocked or unsure, STOP rather than improvise — no substituting or
  creating repos, broadening the task, or guessing to keep making progress.
- Surface the blocker/question plainly in the final reply (and in an
  issue/PR comment where one exists) so a human can decide and re-trigger.
  A halted turn with a clear question is a success, not a failure.

Add claude.test.ts (the module previously had no test) covering the
existing continuation/settings behavior plus these guardrails, asserting
they are present on both fresh and continuation turns.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015i4V7Nsz4v15Kr6YjvRGVC
@imaustink
imaustink merged commit 4f66bfe into main Aug 1, 2026
4 checks passed
@imaustink
imaustink deleted the fix/claude-agent-scope-discipline-185 branch August 1, 2026 21:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Claude Agent is Too Eager

2 participants