# Headless execution: example scenario

A GitHub Actions workflow runs the agent headless when an issue gets the label agent-ready and opens a pull request for a human to review.

Source: https://ai-sw-factory.mellicci.dev/fundamentals/headless-execution/example-scenario

## Scenario

In `ticket-service`, small and well-specified issues wait days for someone to open an agent, paste the issue and babysit the run. The work is routine; the waiting is not.

This page shows one way to remove the wait: when a maintainer adds the label `agent-ready` to an issue, a CI job runs the agent headless, and a pull request appears for a person to review.

## Before → after

| | Before | After |
|---|---|---|
| Time | The issue waits until someone has a free hour | The run starts within moments of the label |
| Effort | Open the agent, paste the issue, watch the run | Add a label, then review a pull request |
| Consistency | Each run uses whatever that person's setup allows | Every run uses the same prompt, tools and limits |
| Risk | The agent runs on a developer machine with their access | The agent runs on a disposable runner with narrow permissions |

## Design

**Diagram:** The label starts a disposable CI runner, where the headless agent implements the issue and the job opens a pull request for a human to review.

- Issue labeled — agent-ready
- → trigger
- CI runner · disposable (security model, sandboxing):
  - Headless agent — prompt from the issue
  - →
  - Tests — exit code gates
  - →
  - Push branch — agent/issue-number
  - →
  - Pull request — references the issue
- → review
- Human review — merges or rejects

The workflow is a file in the repository. This is generic; syntax and agent options differ per agent.

```text
# generic: .github/workflows/agent-ready.yml
on: issue labeled "agent-ready"
permissions: contents write, pull-requests write, issues read
timeout: 20 minutes
steps:
  - checkout the repository
  - set up pnpm, install dependencies
  - run the agent headless:
      prompt:        issue number, title and body
      allowed tools: edit files, pnpm, git   (nothing else)
      max turns:     30
      credentials:   repository secret
  - if the run succeeded and pnpm test passes:
      push branch agent/issue-<number>, open a pull request
  - comment the result on the issue
```

The agent's credentials come from a repository secret, and the workflow's token gets only the three permissions listed. Nobody can answer a prompt, so the allowed tools are decided up front and kept narrow.

## What happens at runtime

<steps>

<step title="Trigger">

A maintainer adds `agent-ready` to issue #42. GitHub Actions starts the workflow on a fresh runner.

</step>

<step title="Prepare">

The job checks out the repo and installs dependencies with pnpm. The prompt is built from the issue's number, title and body.

</step>

<step title="Run headless">

The agent implements the change and runs `pnpm test`, using only the pre-approved tools. It stops when it finishes or hits the turn cap.

</step>

<step title="Read the result">

The run returns a final message and an exit code, optionally as structured JSON. The workflow branches on them: a failed run opens no pull request.

</step>

<step title="Publish">

On success, the job pushes `agent/issue-42` and opens a pull request that references the issue. It also comments the result on the issue.

</step>

<step title="Review">

A person reads the diff and the test results, then merges, asks for changes or closes it. The agent never merges.

</step>

</steps>

## What can go wrong

| Failure | How you notice | What to do |
|---|---|---|
| Issue text is untrusted input: anyone who can label or edit issues steers the agent | The diff contains changes the issue never asked for | Restrict who can add the label, treat the prompt as attacker-controlled, and read the [security model](https://ai-sw-factory.mellicci.dev/fundamentals/security-model) |
| Secrets are exposed to the agent | A credential appears in logs, a diff or a comment | Give the job only the secrets it needs, keep the token scoped, and run on a disposable runner; see [sandboxing](https://ai-sw-factory.mellicci.dev/fundamentals/sandboxing) |
| Runaway cost | A run uses far more turns or minutes than usual | Set a turn cap and a job timeout; review usage per run |
| Flaky tests make the agent "fix" tests | The diff edits tests that were unrelated to the issue | Stabilize the suite, reject test-only edits in review, and consider a [hook](https://ai-sw-factory.mellicci.dev/fundamentals/hooks) or a retry [loop](https://ai-sw-factory.mellicci.dev/fundamentals/loops) with a limit |
| A pull request opens with failing tests | Red checks on a fresh agent pull request | Gate the publish step on the agent's exit code and on a separate `pnpm test` step |
