Skip to content
Closed
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
49 changes: 7 additions & 42 deletions workshop/22-error-handling-and-resilience.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ The skill applies all three changes and recompiles the lock file. Review the dif
<details>
<summary>:pencil2: Manual edit path</summary>

Make the three edits manually (see the reference content below), then run:
Make the three edits manually, then run:

```bash
gh aw compile
Expand All @@ -60,55 +60,20 @@ git push

</details>

### Write a defensive task brief

A defensive task brief tells the agent what to do when data is missing or sparse. Add an explicit fallback instruction in your task description:
> [!TIP]
> Optional side quest: if you want full syntax examples, predict-and-try checks, and enterprise timeout notes before you edit manually, use [Side Quest: Resilience Techniques Reference](side-quest-22-01-resilience-reference.md), then return here to continue.

```markdown .github/workflows/daily-status.md
If there are no open pull requests or issues to summarise,
write a brief "No activity" report instead of skipping the output step.
Always call the safe output tool — even for empty results.
```
### Write a defensive task brief

This prevents the most common failure: the agent silently completes without writing any output.
A defensive task brief tells the agent exactly what to do when data is missing or sparse. Add an explicit fallback instruction ("if there is no activity, publish a short no-activity report and still write output") so quiet runs are still observable and do not look like silent failures.

### Set a timeout

Long-running tasks can stall a workflow run indefinitely. Add `timeout-minutes` to your workflow frontmatter to cap the run:

```markdown .github/workflows/daily-status.md
---
name: Daily Status Report
on:
schedule: daily
workflow_dispatch: {}
permissions:
contents: read
issues: write
timeout-minutes: 10
---
```

> [!TIP]
> <details>
> <summary>`timeout-minutes` belongs at the top level of gh-aw frontmatter. Do not nest it under `jobs:` or `run:`.</summary>
>
> Start with a generous limit (10–15 minutes) and tighten it once you know how long typical runs take.
>
> </details>

On GitHub Enterprise Server (GHES) and GitHub Enterprise Cloud (GHEC), administrators can set a maximum job timeout at the organisation or enterprise level. When that policy is more restrictive than your `timeout-minutes` value, the enterprise limit takes precedence and the workflow job will be cancelled at the admin-set threshold. Check with your GitHub administrator before relying on a specific `timeout-minutes` value in an enterprise environment.
Long-running tasks can stall or be cancelled unpredictably, so set `timeout-minutes` at the top level of your workflow frontmatter. Start with a safe default (for example, 10) and tune based on real run durations so your workflow fails fast instead of hanging indefinitely.

### Add a fallback message to [safe outputs](https://github.github.com/gh-aw/reference/safe-outputs/)

When your workflow uses a `noop` or comment safe output, always include a meaningful fallback body. If the agent reaches the output step but has nothing to report, this ensures the run still records a visible result:

```markdown .github/workflows/daily-status.md
If no meaningful changes were found, call noop with the message:
"No changes found in the past 24 hours — workflow ran successfully."
```

This makes it easy to distinguish a healthy "quiet" run from a silent failure in the Actions run log.
When your workflow uses a `noop` or comment safe output, include a meaningful fallback message for quiet runs. A clear "no changes found" message gives you a visible success signal in Actions logs and makes healthy no-op runs easy to distinguish from failures.

### Commit and push your changes

Expand Down
1 change: 1 addition & 0 deletions workshop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ A hands-on workshop that takes you from zero to a fully automated, AI-powered wo
- [Configure an OpenAI API Key](side-quest-11-07-openai-key.md) — step-by-step guide to generating an OpenAI key, storing it as a repository secret, and switching your workflow to `engine: codex`; branches from [Step 7](07-your-first-workflow.md).
- [Choosing Between Cache Memory and Repo Memory](side-quest-20-01-memory-patterns.md) — decision guide, full field references, and example task briefs for both `cache-memory` and `repo-memory`; branches from [Step 20](20-persistent-memory.md).
- [Sub-Agent Syntax Reference](side-quest-21-01-sub-agent-syntax.md) — name rules, block boundary rules, supported frontmatter fields, and model alias table for inline sub-agents; branches from [Step 21](21-inline-sub-agents.md).
- [Resilience Techniques Reference](side-quest-22-01-resilience-reference.md) — defensive task brief, `timeout-minutes`, and safe-output fallback syntax with predict-and-try checks; branches from [Step 22](22-error-handling-and-resilience.md).
- [Agent Session Phases Explained](side-quest-11-09-agent-session-phases.md) — full phase reference table, activity feed tips, steering prompts, and advanced agent merge / `--watch` paths; branches from [Step 9](09-agentic-editing.md).
- [Audit Reference — Artifacts, Firewall Logs, and Report Contents](side-quest-25-01-audit-reference.md) — detailed breakdown of `gh aw audit` report fields, agent artifact files, ⌖ AIC billing, `firewall.md`, and `network.allow`; branches from [Step 25](25-audit-and-observability.md).
- [Self-Hosted Runner Infrastructure Deep Dive](side-quest-24-01-runner-infrastructure.md) — enterprise infrastructure primer covering ephemeral and JIT runners, proxy configuration, and network isolation for air-gapped environments; branches from [Step 24](24-self-hosted-runners.md).
Expand Down
105 changes: 105 additions & 0 deletions workshop/side-quest-22-01-resilience-reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<!-- page-journey: all -->
<!-- page-adventure: side-quest -->
# Side Quest: Resilience Techniques Reference

> _Optional: use this reference if you want full syntax for all three resilience techniques before or after [Step 22](22-error-handling-and-resilience.md), then return to the main path._

## :dart: What You'll Do

Review copy-ready examples for a defensive task brief, `timeout-minutes`, and safe-output fallback messages, then run quick predict-and-try checks to confirm you can apply each pattern in your own workflow.

## :clipboard: Before You Start

- You have completed or started [Make Your Workflows Resilient to Failure](22-error-handling-and-resilience.md).
- You have a workflow source file in `.github/workflows/` (for example `daily-status.md`).
- You know how to recompile workflow lock files with `gh aw compile`.

---

## Technique 1: defensive task brief

Use explicit fallback instructions in the task brief so the agent still writes output when the dataset is empty.

```markdown .github/workflows/daily-status.md
Summarize open pull requests and open issues from the past 24 hours.

If there are no open pull requests or issues to summarize:
- Write a short "No activity in the past 24 hours" report.
- Still call the configured safe-output tool.
- Do not skip output.
```

> :thinking: **Predict and try:** If there are zero open items, what should the run produce? Trigger a manual run and verify you still get a visible output message.

---

## Technique 2: `timeout-minutes`

Set `timeout-minutes` in frontmatter to prevent long-running jobs from hanging indefinitely.

```markdown .github/workflows/daily-status.md
---
name: Daily Status Report
on:
schedule: daily
workflow_dispatch: {}
permissions:
contents: read
issues: write
timeout-minutes: 10
---
```

> [!TIP]
> `timeout-minutes` is a top-level field in gh-aw frontmatter. Do not nest it under `jobs:` or `run:`.

On GitHub Enterprise Server (GHES) and GitHub Enterprise Cloud (GHEC), administrators can enforce a stricter job timeout policy than the value in your workflow. If they do, the admin limit wins and your run is cancelled at that earlier threshold.

> :thinking: **Predict and try:** If your workflow usually finishes in 2 minutes, is `timeout-minutes: 10` reasonable? Run once, check duration in Actions, and tighten the value if needed.

---

## Technique 3: safe-output fallback message

When writing via safe outputs, include a fallback body for no-change runs so success stays visible in logs and comments.

```markdown .github/workflows/daily-status.md
If no meaningful changes were found, call noop with this message:
"No changes found in the past 24 hours — workflow ran successfully."
```

If your workflow writes comments instead of `noop`, use the same pattern: provide a concise fallback body rather than leaving output blank.

> :thinking: **Predict and try:** What message should reviewers see on a quiet day? Trigger a no-change run and confirm the fallback text appears exactly as written.

---

## Apply all three in one pass

After editing your workflow file, recompile and commit both files:

```bash
gh aw compile
git add .
git commit -m "feat: harden workflow resilience behavior"
git push
```

> [!TIP]
> If you are iterating on wording, run `gh aw compile --watch` in another terminal for faster feedback while you edit.

---

## :white_check_mark: Checkpoint

- [ ] My task brief includes an explicit fallback for empty data
- [ ] My frontmatter sets `timeout-minutes` at the top level
- [ ] My safe-output behavior includes a fallback message for quiet runs
- [ ] I recompiled and committed the updated `.lock.yml`
- [ ] I verified at least one run where the fallback path still produced visible output

---

<!-- journey: all -->
Return to [Make Your Workflows Resilient to Failure](22-error-handling-and-resilience.md).
<!-- /journey -->