What Is the `<promise>COMPLETE</promise>` Signal in Ralph and How Does It End the Loop?

The <promise>COMPLETE</promise> token is an XML-style signal that the AI emits when all user stories are marked complete, causing the ralph.sh orchestration script to terminate the iteration loop with exit status 0.

Ralph is an autonomous AI-agent loop that repeatedly invokes coding tools like Amp or Claude Code until every user story in the Product Requirements Document (PRD) satisfies the condition passes: true. The <promise>COMPLETE</promise> string serves as the deterministic handshake between the AI's generated output and the shell orchestration, eliminating ambiguity about when the autonomous run should conclude.

Understanding the <promise>COMPLETE</promise> Signal

Definition and Purpose

The completion signal is a literal XML-style token that the AI must output verbatim once it determines that zero user stories remain incomplete. Unlike implicit state flags or external API calls, this signal lives purely in the stdout text stream generated by the coding tool. It acts as an explicit assertion from the AI that its task list is fully satisfied and no further iterations are necessary.

According to the Ralph source code, this design choice keeps the orchestration stateless and tool-agnostic—the shell script does not parse JSON or maintain databases; it simply scans text for a unique, unlikely-to-occur-accidentally string.

Where It Is Defined (prompt.md)

The behavior is enforced in prompt.md (lines 94–100), which contains the system instructions telling the AI exactly when and how to emit the token:


## Stop Condition

After completing a user story, check if ALL stories have `passes: true`.

If ALL stories are complete and passing, reply with:
<promise>COMPLETE</promise>

This prompt section effectively hard-codes the stop condition into the AI's context window. The AI evaluates its ownprogress after each story, and only when the aggregate status shows every story passing does it append the magic token to its final output.

How the Signal Ends the Ralph Loop

Detection Logic in ralph.sh (Lines 98–103)

The orchestration logic resides in ralph.sh, the main Bash entry point that manages the iteration lifecycle. After each invocation of the underlying tool (Amp or Claude Code), the script captures stdout and searches for the completion token using grep:


# Run the tool and capture output while preserving visibility

OUTPUT=$(cat "$SCRIPT_DIR/prompt.md" | amp --dangerously-allow-all 2>&1 | tee /dev/stderr)

# Detect completion signal

if echo "$OUTPUT" | grep -q "<promise>COMPLETE</promise>"; then
  echo "Ralph completed all tasks!"
  exit 0
fi

The grep -q test performs a silent match. If the token is absent, the script falls through to the next iteration of the for loop, up to a configurable maximum limit.

The Exit Condition

When the <promise>COMPLETE</promise> string is detected, the script immediately:

  1. Prints a confirmation message to stderr/stdout
  2. Calls exit 0, which terminates the entire Ralph process with a success status
  3. Skips all remaining iterations of the loop

If the token is never found, the loop continues until the hard-coded iteration ceiling is reached, at which point Ralph exits with a non-zero or timeout status to indicate incomplete work.

Code Examples

Example 1: Prompt Instruction Defining Emission Criteria

This excerpt from the system prompt establishes the contract with the AI:


## Stop Condition

After completing a user story, check if ALL stories have `passes: true`.

If ALL stories are complete and passing, reply with:
<promise>COMPLETE</promise>

Source: prompt.md, lines 94–100

Example 2: Bash Implementation of Signal Detection

The concrete implementation in the orchestration script:

#!/usr/bin/env bash

for i in $(seq 1 $MAX_ITERATIONS); do
  echo "--- Iteration $i ---"

  # Pipe prompt to tool and capture full output

  OUTPUT=$(cat "$SCRIPT_DIR/prompt.md" | amp --dangerously-allow-all 2>&1 | tee /dev/stderr)

  # Terminate loop if AI signals completion

  if echo "$OUTPUT" | grep -q "<promise>COMPLETE</promise>"; then
    echo "Ralph completed all tasks!"
    exit 0
  fi

  # Otherwise continue to next iteration

done

echo "Reached maximum iterations without completion signal"
exit 1

Source: ralph.sh, lines 98–103

Example 3: AI Output That Triggers Termination

A typical stdout fragment that would cause the loop to exit:

Successfully implemented user story #5: Add input validation.

All user stories have passed their tests.

<promise>COMPLETE</promise>

When ralph.sh scans this output, the grep match succeeds, the script hits exit 0, and the autonomous run concludes cleanly.

Summary

  • <promise>COMPLETE</promise> is an XML-style token that acts as an explicit completion signal between the AI agent and the Ralph orchestrator.
  • The signal is defined in prompt.md (lines 94–100), which instructs the AI to emit the token only when every user story has passes: true.
  • ralph.sh (lines 98–103) detects the token using grep and terminates the Bash loop with exit 0 upon detection.
  • The mechanism is stateless and requires no external databases or APIs—only stdout text parsing.
  • Failure to emit the token results in the loop continuing until the maximum iteration limit is exhausted.

Frequently Asked Questions

What happens if the AI forgets to emit the <promise>COMPLETE</promise> token?

If the AI omits the token, ralph.sh will not trigger the early exit condition and will continue looping until it reaches the maximum iteration count defined by the user. Once the ceiling is hit, the script exits with an error status, alerting the user that the task list may be incomplete despite the AI finishing its code generation.

Can I change the completion signal to a different string?

Yes, although it requires modifying two files. You must update the instruction in prompt.md (lines 94–100) to tell the AI the new token format, and simultaneously update the grep pattern in ralph.sh (lines 98–103) to match the new string. The token is not configurable via environment variables in the current implementation.

Why use an XML-style tag instead of a JSON object?

The Ralph authors chose a simple XML-style tag because it is easy to grep for and unlikely to appear accidentally in code diffs or natural language explanations. JSON would require parsing logic (e.g., jq) and could be fragmented across multiple lines of output, whereas the literal string <promise>COMPLETE</promise> is atomic and unambiguous in a text stream.

Does the <promise>COMPLETE</promise> token get written to any log files?

The token appears in the stdout of the AI tool, which ralph.sh tees to stderr during execution via the tee /dev/stderr command. This means it appears in your terminal output and any shell redirections you have configured, but Ralph does not explicitly append it to a separate log file unless you redirect the script's output manually.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →