Skip to content

feat(examples): agent-wakeups hook — wake the agent only for its own checks, notifications and the person - #352

Merged
sarah-chitty-1 merged 58 commits into
mainfrom
sarahchitty/agent-wakeups-hook
Oct 30, 2026
Merged

sarah-chitty-1 merged 58 commits into
mainfrom
sarahchitty/agent-wakeups-hook

Conversation

@sarah-chitty-1

@sarah-chitty-1 sarah-chitty-1 commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #351 (notifications). #265 is merged. This retargets to main once #351 merges.

What and why

advance-to-next-event is an example post-turn hook for prompt_agent that lets one conversation span simulated days.

After each agent turn, if nothing is due for the agent, it moves the frozen clock forward to the next thing that is:

Whatever the world does in between happens silently. The agent only finds out by going to look.

The hook only moves time. Since #351, prompt_agent delivers what's due itself: it puts each item at the start of the agent's next message, labelled with its time and source:

[Tue Mar 3, 6:00 PM · your scheduled check] look for new rugs

Each turn:

  1. Settle the triggers.
  2. Let a firing agent trigger answer first.
  3. If something is due for the agent's role, or a person message is due, return.
  4. Otherwise jump the clock to the earliest of: the next world event (next_event_at), the role's next_due_at, or the next person message, and repeat.

The run ends when nothing else can happen, at end_time, or after max_jumps_per_turn.

Params:

  • end_time
  • role: the agent's AgentEnv-Role; default default
  • time_zone: for the person messages' timestamps
  • person_messages
  • settle_timeout_seconds
  • max_jumps_per_turn

It ships as the example bundle examples/advance-to-next-event. Unlike next-env-event, which nudges the agent at every env event, it lets world events pass silently.

The only framework change: post_turn_hooks._INVOKABLE includes the notifications extension, so hooks can read state.

How it was tested

  • Unit: tst/unit/task_step/test_advance_to_next_event_hook.py, 11 passed, against an in-process gateway's real clock, triggers and notifications. It covers:
    • silent world events;
    • notify;
    • only the agent's role moving the clock;
    • person messages arriving once each;
    • items due together going into one message;
    • end_time;
    • a trigger answering first;
    • repeating checks;
    • param validation.
  • Integration: tst/integration/task_step/test_advance_to_next_event_hook_local.py (-m int_test_slow) passed on a real local Docker gateway. Only the agent's own check and a declared notification moved it forward, with exactly the expected lines.
  • Known failure: a shipped bundle must include a task or eval, and this example has none, so the bundle and installer tests fail on it. It needs a small tasks/ file like next-env-event's, or to stop shipping as a bundle.
  • Earlier real-model runs (before the feat(gateway): notifications — checks a role schedules for itself, notify, and prompt_agent delivers them #351 rework), on the PSI laptop self-host:
    • Curbfinch furnish-week, 3 runs on Opus 5.5: the agent scheduled checks every 2–4 h, and all 3 runs found and bought a silently listed rug at the first check after it appeared, for $5.69–8.02 per run.
    • A 10-day rug hunt on Opus, GPT and Gemini (6 runs): 43 schedule_check calls, none refused. Every alert and scripted message arrived once, at its time.

@earakely-scale

🤖 Generated with Claude Code

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; both numbered findings are fixed and no new blocking issue was found.

Summary

Adds advance-to-next-event, an example hook that moves a frozen clock past silent world events and wakes the agent for its checks, notifications, or scripted person messages.

  • Agents can set reminders and receive trigger notices for their role.
  • Due notices appear before the reply in the agent’s next message.
  • The example hook advances time silently until something reaches the agent.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Agent finishes a turn] --> B[Wait for triggers to finish]
  B --> C{Agent trigger answers?}
  C -->|Yes| D[Return its answer]
  C -->|No| E{Anything due for the agent or person?}
  E -->|Yes| F[Return message]
  F --> G[prompt_agent adds due checks and notifications]
  E -->|No| H{Another event within limits?}
  H -->|Yes| I[Advance clock]
  I --> B
  H -->|No| J[End conversation]
Loading

Reviews (4) · Last reviewed commit: "fix(examples): advance-to-next-event rea..." · Reviewed by Greptile

sarah-chitty-1 and others added 20 commits October 19, 2026 16:37
…to the next on simulated time

prompt_agent's opt-in between_turns: next_env_event makes a multi-turn run
event-driven, for long-running and background-agent evals whose events are
hours or days apart. After each agent turn it reads the envs' trigger state,
brings the armed env clocks up to the earliest pending time-trigger mark,
waits for the triggers due there to fire, fail or be cancelled (with a
timeout), and wakes the agent with a neutral message or the user simulator's
agent-trigger decide step. It stops when no time trigger is pending, at
end_time, or at max_conversation_turns. The user side is never asked.

The gateway clock gains PUT /clock/advance (clock/v1 "advance"): a forward
jump on the current arm that keeps t0, rate and generation, so relative and
recurring time-trigger marks keep their meaning and delays count the jumped
time. set_time is a re-arm that re-anchors them; against a gateway without
advance, prompt_agent re-arms at the env's own rate and refuses a run whose
pending time triggers are relative or recurring.

With between_turns set, or record_env_clock, every conversation message
prompt_agent records carries env_clock, each env's virtual time when it was
sent or received, so a grader can place the agent's messages on the same axis
as the trigger firing log and the gateway trajectory.

Both options are off by default; unset, prompt_agent, the conversation store
and the clock behave as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two envs can each have a trigger with the same id due at one mark; keyed by id
alone, the second was skipped and the wait ran to its timeout. Outcomes are now
keyed by (env id, trigger id) and recorded as {env_id: {trigger_id: outcome}}.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dvance lands is not an error

With a running clock the mark can pass between the clock read and the advance,
which the gateway then refuses as backwards. On that 400 the clock is read again,
and if it has reached the mark the move is recorded as "passed"; any other
refusal still fails the step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…next mark in the schedule

A recurring trigger whose fire outlived the wait (an action delay on a frozen
clock, say) stays firing with its next mark already stamped; only armed ones
were scheduled, so the run could end with "no_pending_time_triggers" despite
future marks. Firing and queued triggers with a next mark are now scheduled too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… with carries the env clock too

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ect with 400, not a server error

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…gain

A recurring trigger whose fire outlives its interval on a frozen clock stays
firing with the same next mark, so every later turn chose that mark again,
waited out the timeout and woke the agent without moving time. Marks that timed
out are now skipped, so the run moves on to the next event or end_time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rring mark, as every other jump does

Against a gateway without clock advance, stopping at end_time re-armed the clock
unchecked, re-anchoring a pending relative or recurring time trigger past
end_time for the steps after it. That jump now runs the same check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… stored message carries the env clock

Hooks are Python FileArtifacts defining `async def post_turn(turn, params)`, run in
order after every agent turn; the first to return a message or an end decides, else
the user side is asked as today, which moved into _UserSide unchanged.
test_prompt_agent_user_side.py pins that path and passes unchanged.

Agent triggers/v1 decide takes record_unfired, so user_triggers() can ask again in
the same turn without resetting once-only triggers. The verifier run context reads
env_clock as one EnvClock per armed env.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t_event_at and resumes_at; /step tags a hook's calls

PUT /clock/advance runs the trigger time check at once and returns `due`, waking
actions that wait out a delay. /triggers/state reports next_event_at, the earliest
time the engine acts on its own, and each trigger's resumes_at (triggers/v1 feature
next_event_at). /step takes source post_turn_hook with hook_artifact_id (step/v1
feature source).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…om env event to env event

The hook waits for what the agent's turn set off, lets a firing agent trigger answer,
advances each clock to the earliest next_event_at, waits for it to settle, then asks
the agent triggers again or wakes the agent. It ends when nothing is pending or past
end_time, and on a gateway without advance. It ships as a bundle with an inbox env
and a week-long task; the slow test runs it against the echo agent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both sides add a fourth shipped bundle, mail-mcp and next-env-event: the entry points
and the shipped-bundle lists keep both, and the installer journey expects 5 bundles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…so a change to it fails the test

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e next opening

_await_hours reckoned the opening again only when the clock's generation changed,
and advance keeps it, so a jump past the close left a stale opening behind and the
executor ran outside its hours. It now reckons the opening on every pass, and
clock_advanced counts a wait as ended only while its window is open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tify_agent

What wakes an agent between its turns, on the env's virtual clock (urn:agentenv:wakeups/v1):

- schedule_check / list_scheduled_checks / cancel_scheduled_check: gateway built-in tools, next to get_time,
  that exist only once a task turns them on (configure_wakeups step, or POST /wakeups/config). A check takes
  `at` (RFC 3339 or a duration from now) and/or `every` with `until`; max_active and min_interval cap them.
- notify_agent: a trigger action that queues a notification ({channel, text}, text templated from the provoking
  call) at the current virtual time. Only task designers write it; the agent has no general alert tool.
- GET /wakeups/state says when the next check is due and what is pending; POST /wakeups/take hands out each due
  check and notification once (a repeating check passed several times in one jump comes out once, with a count).

Nothing here wakes anyone: a post-turn hook reads state, moves the clock and takes what is due. Opt-in throughout:
without configure_wakeups no tool appears, and a gateway without notify_agent is refused by register_env_triggers
before any request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ps-hook

# Conflicts:
#	src/agent_env/env/gateway/constants.py
#	tst/unit/bundle/installed_test.py
#	tst/unit/bundle/shipped_bundles_test.py
#	tst/unit/test_clean_install_wheel.py
…checks, notifications and the person

A prompt_agent post-turn hook (example bundle agent-wakeups) that runs a conversation over simulated days:
after each turn it jumps the clock, silently, to the next thing that happens — a world event, a check the agent
scheduled (wakeups/v1), or a person's message at a set time — and wakes the agent only when one of its own checks,
a notify_agent notification or a person's message has come due. World events with no channel wake no one, so the
agent isn't told when to look. Each wake is one message, a line per thing with its time and source
("[Tue Mar 3, 6:00 PM · your scheduled check] …", "[Wed Mar 4, 8:00 AM · Messages] …"), so nothing poses as the
person; the hook's record names what each wake was for.

post_turn_hooks: a hook may also invoke wakeups/v1 (state, take).

Stacked on #265 (post-turn hooks, clock advance, next_event_at) and on the wakeups/v1 gateway change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sarah-chitty-1 and others added 9 commits October 27, 2026 10:01
Resolves the bundle-list conflicts in three tests: main added the drivers bundle, this branch next-env-event; keep both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…on times, wait for discovery

- take counts how often a repeating check came due and its next time directly, so a long jump over a short every
  costs nothing, and works the whole batch out before marking anything handed out
- schedule refuses an every (or at) too long to count forward, which would otherwise break every later take
- notifications are due by their parsed time, not their text (fractional seconds sorted wrong)
- /wakeups/config finishes tool discovery before its name check (503 if discovery fails), so a later discovery
  can't replace schedule_check unseen
- configure_wakeups logs a one-line completion, not the request body

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ler expects six bundles

- /triggers/state shows each trigger's `evaluating`, and the next-env-event hook waits for a state check the agent's
  turn set off before it moves the clock
- test_container_journey: next-env-event makes six shipped bundles

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	tst/unit/bundle/installed_test.py
#	tst/unit/bundle/shipped_bundles_test.py
#	tst/unit/test_clean_install_wheel.py
… set off before it moves the clock

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… tools and config take

The state, list_scheduled_checks and the too-short error showed Python's timedelta text (3:00:00), which /wakeups/config
then refused when sent back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sarah-chitty-1 and others added 16 commits October 29, 2026 10:36
…fications/v1)

What the extension holds is notifications: checks a role schedules for itself, and messages triggers send.
"Wakeups" named the effect on the agent. Nothing has merged, so the rename stays in v1.

- urn:agentenv:notifications/v1 (EXT_NOTIFICATIONS_URI), routes /notifications/config|state|take|clear,
  env/gateway/notifications.py with class Notifications. The card says it is unrelated to A2A push notifications.
- Task step configure_scheduled_checks; it records metadata.scheduled_check_configurations.
- Trigger action notify (TRIGGER_NOTIFY); a taken trigger notification has kind "trigger".
- state's next_due_at replaces next_check_at and is the earliest of the active checks' next time and the pending
  notifications' time, so a runner waiting on it no longer sits on a queued notification.

The agent's tools keep their names: schedule_check, list_scheduled_checks, cancel_scheduled_check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e note back

The result echoed the note the agent had just written: up to 2,000 characters in its context with nothing new,
and the trajectory already logs the call's arguments. It now returns check_id, next and, when set, every and
until. list_scheduled_checks still shows each note, since that is how the agent tells its checks apart; state and
take keep the full note for the harness.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…a task names roles

Any role that listed the gateway's tools saw schedule_check, persona executors included, and one shared queue
meant a check a persona scheduled reached the solver, since take returned everything to whoever called it.

- config takes roles, the roles that get the scheduled-check tools. It defaults to [] and replaces the
  scheduled_checks boolean: [] turns checks off, removing the tools and cancelling active checks; a role left out
  loses its own. Unknown config fields are refused, so a leftover scheduled_checks is caught.
- The gateway's role filter (_is_disabled) hides the three tools from every role the config doesn't name, on MCP
  tools/list and tools/call and on /step, whatever the tool-access rules say.
- schedule_check records the calling role as the check's recipient, to; list_scheduled_checks and
  cancel_scheduled_check see only that role's checks, and max_active counts each role's checks on their own.
  /step binds its caller's role for gateway tools, as the MCP path already does.
- The notify trigger action takes an optional to (default "default", the solver's role). Receiving needs no
  tools, so it need not be one of the config's roles.
- take takes to (default "default") and hands out only that recipient's items; state takes ?to= for one
  recipient's items and next_due_at, and shows every recipient's without it.
- configure_scheduled_checks requires a non-empty roles, so a task always names who gets the tools.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…start of the agent's next message

A scheduled check reached the agent only if the task's prompt_agent step listed a particular post-turn hook; a task
that configured checks without it gave the agent checks that never arrived, and nothing warned about it.

- After each turn the conversation goes on from, prompt_agent takes what came due for its agent's role
  (DeployedAgent.role, else "default") on every env whose card offers notifications/v1 take, and puts it at the
  start of the next message, oldest first, ahead of the user side's reply, which is unchanged.
- Each item is one text part labelled with when and through what, as the #352 hook wrote them:
  "[Mon Feb 1, 3:00 PM · your scheduled check] <note>" (with "(it came due N times while you were away)") and
  "[Mon Feb 1, 3:10 PM · Curbfinch alert] <text>". Each carries metadata.agentenv ({"source": "scheduled_check",
  "check_id", ...} or {"source": "trigger", "id", "trigger_id", ...}), so a verifier can tell delivered lines from
  the person's words in the one stored user turn.
- A time_zone step param sets the labels' zone; UTC by default, stored only when set.
- An answer that ends the conversation, the last turn and a failed turn take nothing: what is due stays queued.
  The user side is asked exactly as before, and the user sim never sees the delivered lines.
- A post-turn hook may now return {"message": []} to say nothing: the agent then gets only what came due, and the
  conversation ends (nothing_to_send) if nothing has. An empty closing message on an end records nothing.
- A take that keeps failing (three tries) fails the step rather than drop what is due.
- The builder is task_step/task_steps/notification_delivery.py, for hooks to reuse; it documents the rules above.

With nothing due, every message is what it was; the only addition is one take per turn on gateways that offer the
extension. tst/integration/task_step/test_prompt_agent_notifications_local.py runs it on a real gateway with the
next-env-event hook.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… retry delay

- take accepts a take_id; the same id for the same recipient returns the stored batch, so a retry after a lost
  response can't come back empty (the gateway keeps the last 64)
- prompt_agent sends one take_id per env per take, reused across its retries, and asks every env before failing
- _TAKE_RETRY_BASE_DELAY_S names the retry delay

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A scheduled check and a trigger notification were two shapes told apart by kind, so every consumer branched on it,
and a third kind would have broken any that treated "not a check" as a notification.

- take returns every item as {id, to, at, times, source, source_id, channel, parts}: source is "scheduled_check"
  or "trigger", source_id the check's or the trigger's id, channel the label the agent sees ("your scheduled
  check", or the trigger's channel), parts the note or the trigger's text as one text part. times is 1 for a
  notification. state is unchanged: checks and pending_notifications keep their own bookkeeping.
- The delivery builder no longer branches on the source: "[when · {channel}]" plus the item's text, with "(it came
  due N times while you were away)" when times > 1. Each delivered part's metadata.agentenv is the item without its
  parts (source and source_id among them, plus env_id); a part that isn't text would follow the line as it is.
- validate_channel refuses "your scheduled check" (any case), so a trigger can't pass itself off as the agent's own
  reminder.
- The card's description gives the item shape.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… name the agent's argument

The descriptions left out rules the agent only learned from errors, and "ISO 8601 duration" promised more than the
parser takes (P1M, P1Y and PT1.5H are all refused). A bad time's error named the clock's virtual_time, a field the
agent never sees.

- at: "When it first comes due: a time with seconds and its UTC offset (2027-02-02T18:00:00-08:00), or a duration
  from now (PT6H)."
- every: "Repeat this often: a duration in weeks, days, hours, minutes or seconds (PT6H, P1D, P1W), at least
  {min_interval}. No months or years; P1D is exactly 24 hours, not the same local time each day."
- until: "Only with every: stop after this time, or after this duration from now (not from at)."
- The tool description ends "You can have at most {max_active} checks at once. Times you get back are in UTC."
- The limits come from the config, so each config rebuilds the tools (and their mirrored descriptors) instead of
  keeping the first ones it registered.
- _when and _duration give their own errors, naming at, every or until and the rule broken: a time needs seconds
  and a UTC offset; a duration is in capitals, with no months or years, and only seconds may have a fraction. A
  leading lowercase p is read as a duration, so pt6h gets a duration error. A duration of the right shape that is too
  big to count is "too long".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…m; turning checks off is never refused

- config replaces every setting: a field left out goes back to its default, so {"max_active": 5} on its own turns
  checks off (roles defaults to []). The card's description and configure's docstring say so; the
  configure_scheduled_checks step already sends every field.
- A new config leaves existing checks as they are unless it drops their role: lowering max_active leaves extra active
  checks in place, and raising min_interval leaves existing repeats unchanged. Also in the description, and tested.
- A config that turns checks off (roles: [], or left out) registers nothing, so it skips the tool-discovery wait and
  the 409 for a backing server that already serves one of the tool names; neither can block it any more.
- clear resets roles, max_active and min_interval to their defaults as well as dropping every check and
  notification, so state afterwards shows the defaults rather than the last config's limits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ps-hook

#351 renamed wakeups/v1 to notifications/v1; hooks may now invoke EXT_NOTIFICATIONS_URI in place of EXT_WAKEUPS_URI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s (notifications/v1)

The hook no longer takes or labels what came due: after moving the frozen clock to the next thing due for the
agent's role (a world event, notifications/v1 next_due_at, or a person message) it returns {"message": []}, and
prompt_agent takes and delivers. A person's message is still the hook's own reply, after the delivered lines.

- names from #351: notifications/v1, configure_scheduled_checks with roles, the notify action, next_due_at
- new `role` param (default "default"): the recipient whose state it reads, since a hook can't see the agent's role
- `time_zone` stays only for the person-message timestamps; delivered lines use prompt_agent's time_zone
- records name each due item's `source` (scheduled_check, trigger) plus "person"

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Its job is moving time forward to the next thing due for the agent, and wakeups/v1 is now notifications/v1. The
bundle, its artifact, the entry point, the shipped-bundle lists and the hook's tests follow; the README says how it
differs from next-env-event.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…/agent-wakeups-hook

Brings in the agentenv-framework version the hub SDK needs (>=0.9.1384), which is
what the CodeBuild integration tests failed on. Bundle-list test conflicts resolved
by keeping advance-to-next-event alongside main's new computers and desktop bundles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fication

A whole-value optional placeholder such as ${result.message?} used to reach the agent as
literal text when the field was missing. The text now resolves inside an object, so it drops,
and an empty text skips the notification (action_ok records why).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A shipped bundle needs a task to run; week.json runs the hook on next-env-event's inbox.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sarah-chitty-1
sarah-chitty-1 marked this pull request as ready for review October 29, 2026 23:21
@sarah-chitty-1
sarah-chitty-1 requested a review from a team as a code owner October 29, 2026 23:21
sarah-chitty-1 and others added 5 commits October 29, 2026 16:32
…triggers don't settle, wakes after its last jump

- an env whose clock was never armed is left out instead of crashing the hook on its missing time
- triggers still firing at settle_timeout_seconds end the run as triggers_still_firing, so a slow notify
  isn't lost behind a "nothing can wake the agent" end
- what the last allowed jump makes due wakes the agent before max_jumps_per_turn ends the turn

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…in UTC and say so

Everything else the agent reads about time is UTC (get_time, schedule_check), and the label
didn't name its zone, so 11:00 PM could be read as local. Lines now read
[Mon Feb 1, 11:00 PM UTC · your scheduled check] ... (Edgar's review).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s in UTC; no time_zone param

Follows #351 dropping time_zone from prompt_agent: every delivered line, the person's included,
is labelled in UTC and says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Base automatically changed from sarahchitty/agent-wakeups to main October 30, 2026 18:00
…s records; integration test labels in UTC

- Turn.records(): this hook's records for this step, so another conversation delivering a person
  message at the same time no longer makes this one skip it
- the local integration test no longer passes the removed time_zone, and expects UTC labels

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sarah-chitty-1
sarah-chitty-1 merged commit 749a50f into main Oct 30, 2026
29 checks passed
@sarah-chitty-1
sarah-chitty-1 deleted the sarahchitty/agent-wakeups-hook branch October 30, 2026 19:13
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.

2 participants