AI Learning
intermediate ⏱️ 15 min read · 🎬 ~22 min video

Build a Proactive Agent Workflow with Claude Code

Turn Claude Code from a reactive assistant into a proactive teammate using Routines — scheduled, event-driven agents that read your repo and open PRs before you've touched your laptop.

This lesson is original educational writing based on this video by Anthropic (published May 20, 2026). All credit for the original content goes to the creators.

#claude-code #agents #agentic-coding
Video thumbnail: Build a Proactive Agent Workflow with Claude Code
Original video — all credit to the creators. Watch the original on YouTube ↗

1. Reactive vs proactive: a fundamental distinction

Every Claude Code session you have ever had is reactive. You type a prompt, Claude acts, you read the result, you type again. The loop only advances when you push it forward. That model is powerful, but it has a ceiling: Claude can only work when you are working.

Proactive agents flip this. Instead of waiting for your prompt, they watch for a condition and act when that condition is true — whether you are at your desk, asleep, or on a flight. Claude Code calls these Routines.

A Routine is an autonomous Claude Code session that:

  1. Starts on a trigger (a schedule, an event, or an API call)
  2. Gathers context from the repository and any connected data sources
  3. Executes a task using the same tools Claude Code has in interactive mode
  4. Produces an artifact — a PR, a report, a comment — and stops

The result lands in your repository ready for your review. You shifted from being the driver to being the approver.

2. The anatomy of a Routine

Every Routine — no matter how simple or complex — is defined by three decisions. Getting these three things right is the whole design job.

Trigger

When should the Routine fire? The three trigger categories are:

Trigger typeExampleBest for
Schedule (cron)Every weekday at 08:00Daily reports, recurring reviews
EventOn push to mainPost-merge summaries, lint checks
On-demand/schedule run standupManual kicks, demos, one-offs

A scheduled trigger takes a standard cron expression. An event trigger hooks into repository webhooks or CI signals. On-demand triggers run immediately and are useful when you want a Routine’s structured output but are initiating it yourself.

Context

What should the Routine read before it starts working? Context is the most important lever you have. A Routine with rich, targeted context produces dramatically better output than the same Routine with shallow context.

Typical context sources:

  • Git historygit log --since=yesterday, git diff HEAD~1
  • Open issues and PRs — fetched via the GitHub CLI or MCP servers
  • Configuration files — package.json, CI configs, CLAUDE.md
  • External data — error logs, monitoring dashboards, calendar events

The ROUTINE.md file (described below) is where you specify which context to gather and how.

Steering

How does the Routine know what good output looks like? Steering is the set of instructions that guide the Routine’s judgment: what to prioritize, what to skip, what format to use for its output, and what to do when it is uncertain.

Steering lives in the ROUTINE.md system prompt. It is different from a one-off interactive prompt because it must anticipate all the cases you will not be there to handle.

Triggercron / event / manualContextgit / issues / logsClaude Agentreads ROUTINE.mdsteering + toolsruns autonomously↑ no human in loopArtifactPR / report / alert→ human review08:00 weekdaysROUTINE.md
A Routine's lifecycle: trigger fires, context is gathered, the agent executes with steering, and the artifact lands in the repo for human review.

3. ROUTINE.md: the Routine’s memory

A Routine does not have you to ask questions mid-run. The ROUTINE.md file compensates for that. It is a Markdown document committed to your repository that serves as the Routine’s persistent instructions — the equivalent of a CLAUDE.md but scoped to a single automated job.

A well-written ROUTINE.md answers four questions:

  1. What is the goal? One sentence describing the desired end state.
  2. What data should I read? Explicit commands or file paths for gathering context.
  3. What should the output look like? Format, length, conventions.
  4. What are the guardrails? What the Routine must never do, and what to do when uncertain.

Here is a minimal example for a daily standup Routine:

# Daily Standup Routine

## Goal
Create a draft PR each morning that summarises what changed in the main branch
since yesterday and flags anything that needs team attention.

## Context to gather
- Run `git log --since=yesterday --oneline main`
- Run `git diff $(git log --since=yesterday --format="%H" main | tail -1)..HEAD`
- Read open PR titles: `gh pr list --state open --json title,number,author`

## Output format
Open a pull request titled "Standup: <date>" against main with a body that contains:
- A bullet list of commits grouped by author
- A "Needs attention" section for anything touching shared config or migration files
- A "No action needed" section for everything else

## Guardrails
- Do NOT merge the PR. Only open it as a draft.
- Do NOT push directly to main.
- If git log returns nothing, open a PR with body "No commits since yesterday."
- If a git command fails, stop and write the error to a file called ROUTINE_ERROR.md.

The guardrails section is the most important and most often skipped part. Explicit negative constraints prevent the Routine from taking irreversible actions when something unexpected happens.

4. Scheduling a Routine with /schedule

Once your ROUTINE.md is in place, scheduling the Routine takes one command inside Claude Code:

/schedule "Run the daily standup routine" --cron "0 8 * * 1-5" --routine ROUTINE.md

Breaking this down:

  • "Run the daily standup routine" — the task description Claude receives as its starting prompt
  • --cron "0 8 * * 1-5" — standard cron syntax: 08:00 UTC on Monday through Friday
  • --routine ROUTINE.md — the file whose contents are injected as the system context

You can also trigger a Routine manually at any time for testing:

/schedule run standup

And list all configured Routines:

/schedule list

To stop a Routine from running again:

/schedule delete standup

Viewing Routine output

After a Routine fires, you will see its artifact in the repository — a PR, a commit, or whatever your ROUTINE.md specifies. Claude Code also keeps a log of each run accessible via the Anthropic console, where you can inspect every tool call the agent made, the context it read, and any errors it encountered.

5. Designing effective proactive agents

Moving from a working Routine to a great one requires thinking through a few recurring failure modes.

Stale context produces stale output

A Routine that only reads git log will miss issues filed today, comments left on open PRs, or a failing CI run. Think about everything a human teammate would check before writing the standup, then make sure the Routine reads all of it.

For richer context, combine git with the GitHub CLI and any MCP servers your team uses:

## Context to gather
- git log --since=yesterday --oneline main
- gh issue list --state open --label "bug" --json title,number
- gh run list --workflow=ci.yml --limit=5 --json conclusion,headBranch

Idempotency prevents duplicate artifacts

If a Routine fires twice because of a scheduling edge case, it should not open two identical PRs. Add an idempotency check to your guardrails:

## Guardrails
- Before opening a PR, run `gh pr list --search "Standup: $(date +%Y-%m-%d)" --json number`.
  If a result exists, add a comment to that PR instead of opening a new one.

Scope creep is the main failure mode

The longer a Routine’s task description and the richer its context, the more likely it is to wander. A Routine told to “review the codebase” will do something different every day. A Routine told to “report commits to src/api/ that modify response schemas” does exactly the same thing every time.

Narrow scope → consistent output → Routine you can trust and keep.

Check your understanding

5 questions · your answers are saved in this browser only

  1. 1. What is the fundamental difference between a reactive Claude Code session and a proactive Routine?

  2. 2. Which three decisions define the design of any Routine?

  3. 3. In the /schedule command, what does the --routine flag do?

  4. 4. Why is an explicit "Guardrails" section the most important part of a ROUTINE.md?

  5. 5. What is the best practice before activating a cron schedule for a new Routine?

6. Real-world Routine patterns

The standup Routine is a learning vehicle. Here are four patterns that appear in real production workflows:

Dependency drift report

Fires weekly, reads package.json and package-lock.json, compares installed versions against the latest published versions on npm, and opens a PR that upgrades any package more than one major version behind. The guardrails exclude packages that are pinned in a no-upgrade.txt file and cap the PR at five packages per run to keep diffs reviewable.

Test coverage gate

Fires on every push to a feature branch via a repository webhook. Reads the coverage report from the last CI run, compares it against a threshold in .claude/coverage-policy.json, and posts a PR comment. If coverage dropped, it lists the uncovered lines and suggests which test cases would close the gap. It never modifies tests directly — it only suggests.

Security advisory scanner

Fires nightly. Reads package.json and runs npm audit --json, then cross-references the advisory list against your project’s dependencies. Opens a draft PR for each high-severity advisory with a patch already applied. Guardrail: only patches devDependencies automatically; production dependency patches are flagged for human review.

Release notes generator

Fires when a tag matching v* is pushed. Reads git log since the previous tag, groups commits by conventional commit prefix (feat:, fix:, chore:), and opens a PR that adds a CHANGELOG.md entry. The output format mirrors the existing CHANGELOG style — the Routine reads three previous entries before writing the new one.

Build it yourself

Follow these exact steps to reproduce it yourself · estimated time: ~25 min

Prerequisites

  • Claude Code installed and authenticated (`claude --version`)
  • A git repository on GitHub with at least one recent commit
  • GitHub CLI installed and authenticated (`gh auth status`)
  • Repository access to open pull requests

Step 1 — Create the .claude directory

mkdir -p .claude

All Claude Code configuration for this project will live here.

Step 2 — Write the ROUTINE.md

Create a file called ROUTINE.md at your project root:

# Daily Standup Routine

## Goal
Each weekday morning, open a draft pull request that summarises what changed in
main since yesterday and highlights anything that needs team attention.

## Context to gather
Before writing anything, run these commands and read their output:

1. `git log --since="yesterday 00:00" --until="today 00:00" --oneline main`
2. `git diff $(git log --since="yesterday 00:00" --format="%H" main | tail -1)..HEAD -- . ':(exclude)package-lock.json'`
3. `gh pr list --state open --json number,title,author,reviewDecision`
4. `gh run list --workflow=ci.yml --limit=3 --json conclusion,headBranch,createdAt`

If any command fails, note the failure in the PR body and continue.

## Output format
Open a pull request titled exactly: "Standup: YYYY-MM-DD" (today's date).
Target branch: main.
PR body sections:
- **What shipped** — bullets from git log, grouped by author
- **Open PRs** — list with review status
- **CI** — last three runs with pass/fail
- **Needs attention** — anything touching migrations, shared config, or CI workflows

## Guardrails
- Open the PR as a DRAFT. Never merge.
- Never push directly to main.
- Before opening, check: `gh pr list --search "Standup: $(date +%Y-%m-%d)" --json number`
  If a PR already exists today, add a comment to it instead of opening a new one.
- If git log returns no commits, open the PR with body "No commits since yesterday."
- Maximum one PR opened per run.

Step 3 — Test the Routine manually

Inside a Claude Code session in your repository, run:

/schedule run standup --routine ROUTINE.md

Claude Code will execute the Routine immediately. Watch the terminal output to see which tools it calls.

Step 4 — Inspect the artifact

Go to your repository on GitHub and find the newly opened draft PR titled “Standup: <today’s date>”. Read through it carefully:

  • Are the commits grouped correctly?
  • Is the “Needs attention” section accurate?
  • Is the format right?

If anything is wrong, edit ROUTINE.md and run /schedule run standup again. Repeat until the output matches what you would write by hand.

Step 5 — Enable the cron schedule

Once the output is right, activate the schedule:

/schedule "Run the daily standup routine" --cron "0 8 * * 1-5" --routine ROUTINE.md --name standup

This fires the Routine at 08:00 UTC Monday through Friday. Adjust the cron expression to match your team’s timezone:

Target timeCron expression
08:00 UTC0 8 * * 1-5
08:00 EST (UTC-5)0 13 * * 1-5
08:00 CET (UTC+1)0 7 * * 1-5
08:00 PST (UTC-8)0 16 * * 1-5

Step 6 — Verify the schedule

List all active Routines to confirm registration:

/schedule list

You should see standup with status active and the next scheduled run time.

Step 7 — Monitor the first automated run

The morning after enabling the schedule, check GitHub for the draft PR. Also check the Anthropic console (console.anthropic.com) under the Claude Code section to view the run log — every tool call the Routine made, the context it gathered, and any errors.

Step 8 — Commit the ROUTINE.md

git add ROUTINE.md
git commit -m "Add daily standup Routine"
git push

Committing the ROUTINE.md means every team member who clones the repo can activate the same Routine immediately with /schedule run standup --routine ROUTINE.md.

Expected result: A draft PR appears each weekday morning titled “Standup: <date>” with an accurate summary of the previous day’s activity. If no PR appears after the first scheduled run, check /schedule list for error state and review the run log in the console.

Where to go next

  • Watch the original video for a live end-to-end demo of a Routine being built and triggered.
  • Learn about Claude Code hooks to combine deterministic lifecycle guards with your proactive Routines.
  • Explore headless mode (claude -p) for cases where you need proactive automation driven by external scripts rather than the /schedule command.

Related lessons

intermediate 🎬 Anthropic · ~37 min

Stop Babysitting Your Agents: From Approval Mode to Orchestration

The workflows Claude Code engineers use to stop hand-holding their AI and start orchestrating it — permission architecture, verification-first design, parallel fanout, and headless automation.

#claude-code #agentic-coding #agents #productivity #multiagent
advanced 🎬 Anthropic · ~9 min

Agent Battle: Build the Best Diamond-Mining Agent

An Anthropic workshop where participants build diamond-mining agents in 45 minutes and compete on a live leaderboard. Learn agent configuration, eval-driven improvement, and what separates winning architectures.

#agents #evaluation #claude-code
advanced 🎬 Anthropic · ~26 min

Agentic Analytics: How Omni Built a Production Harness with Claude Code

How Omni's CTO Chris Merrick designed a multi-agent analytics system powered entirely by Claude — covering coordinator architecture, tool sizing, the semantic layer as CLAUDE.md analogy, evaluation with LLM-as-Judge, and the critical design pivots that drove 86x token growth.

#agents #claude-code #evaluation