Repository navigation
feat(agents): the agent schedules its own follow-ups on the daemon clock - #5694
kovtcharov wants to merge 27 commits into
Conversation
"Check on the build in 2 hours" or "remind me tomorrow at 9" had nowhere to go: a reminder was a memory note that only came up in the next chat, and the daemon's clock had no way to register a job and nothing to run one. - schedule_follow_up, list_follow_ups and cancel_follow_up register one-shot agent_follow_up jobs through new /daemon/v1/followups routes: a minute to 7 days ahead, at most 10 waiting. - The clock's first executor runs a due one as a fresh /v1/gaia/query turn on the model the chat used, keeps the answer (or the failure), and posts a desktop notification. - The next turn's context opens with finished follow-ups, then marks them seen. It only attaches to a running daemon, never starts one. - With follow-ups available, a reminder at a time is scheduled as well as remembered, so it alerts.
|
Verdict: Request changes This PR gives GAIA working follow-ups: "check on the build in 2 hours" now runs on the daemon's clock, posts a desktop notification, and the result shows up in the next chat. The design holds up: real limits, a fired run that can't use approval-gated tools, and tests that run the real clock and store. One delivery bug needs fixing before merge, because it can stop the user from ever hearing a result.
Real-world evidenceN/A: no evidence bundle was produced for this run. This verdict comes from reading the code, plus the author's own live macOS test notes in the PR description (scheduling, firing, notification, cancelling, each result shown once). Nothing was re-run here. 🔍 Technical details🟡 Fired follow-up run consumes other follow-ups' results (
🟡 Results marked seen before delivery; mark-seen failures uncaught (
Also pass 🟢 🟢 Strengths
|
…import order The Chat agent's full profile now registers the three follow-up tools, so its manifest's tools_count is 68, not 65. The registry import goes back to the wrapped form isort expects.
# Conflicts: # hub/agents/gaia/npm/CHANGELOG.md # hub/agents/gaia/npm/README.md
…e first Three ways a result could be lost before the user heard it: - A fired follow-up's own run read the unseen results and marked them seen, so when two fired before the user chatted again, the second run used up the first one's result. Each fired run now runs in its own follow-up-<job id> session, and the agent skips the follow-up line (and listing) there. The run also says it can't answer a question mid-run. - Results were marked seen before the model answered, so a failed turn lost them. They are now marked seen after the turn, and only when it answered. - Marking seen could raise out of the turn and could start a daemon. It now attaches only and is logged on failure. "Tomorrow at 9am" also keeps its hour across a DST change: wall-clock times take the offset for the day they land on.
…own tests The unit suite runs without the hub agent packages installed, so importing gaia_agent_chat there failed every platform and tripped the import guard. The session-id check moves to the chat agent's tests; the unit test keeps the daemon-side assertions.
The chat agent's follow-up tools and its test_chat_follow_ups_told.py import gaia.daemon.followups, so a change to it must run that lane.
) `test_trickle_just_under_the_idle_limit_is_not_killed` failed the Linux unit job on amd#5694, a PR that doesn't touch the stream watchdog: the stream was cut off as stalled. The test's server paused 1.5 s between bytes against a 2 s idle limit, so 0.5 s of scheduling delay on a loaded runner was enough. It now pauses 0.8 s eight times, which still adds up to more than three idle limits. A watchdog that ignored the trickled bytes would still kill the stream, so the test still catches what it's for. ## Test plan - [x] `pytest tests/unit/test_stream_stall_watchdog.py` (24 passed) - [x] The changed test three more times (3 passed, ~6.8 s each) Co-authored-by: Kalin Ovtcharov <kalin@Kalins-Mac-mini.local>
# Conflicts: # hub/agents/gaia/npm/SPEC.md # src/gaia/apps/webui/src/components/AgentActivity.tsx
…witches A follow-up scheduled from a chat with internet off, or from a private chat, ran later with internet on and memory saving, because the fired run started in a fresh session with the sidecar's defaults. The tool now records the chat's internet_off and memory mode with the job, the daemon route accepts them, and the fired /query carries them alongside the model.
|
A follow-up scheduled from a chat with internet turned off, or from a private chat, ran later with internet on and memory saving. Fixed in 25972b5: the fired run now carries the chat's internet and memory switches along with its model. The other permission paths hold: a fired run that reaches an approval-gated tool ends with a refusal the user sees in the next chat, rather than waiting or approving. The earlier review's delivery findings are addressed by f4d5cfa. 🔍 Technical details
|
…ol set The full profile now registers schedule_follow_up, list_follow_ups and cancel_follow_up, so its characterization goldens list them. The other rows and every captured prompt are unchanged.
|
Holding this for eval results: the permission fix checks out, but the new always-on "remind me" tool sits right on top of memory scenarios that use "remind me" to mean "tell me again", and there are no eval numbers yet showing the agent still recalls instead of scheduling. Before merge, please run 🔍 Technical detailsWhy this plausibly shifts baselined behaviour
What I checked and found sound
|
ChatAgent moved into the flagship package (amd#6139), so the follow-up mixin, profile group and bundle now land in gaia_agent.chat_agent, gaia_agent.profiles and gaia_agent.tool_bundles, and the told-marking test moves to the flagship's tests.
Tool labels moved to the i18n locales (amd#6165), so the follow-up tools get their icon in TOOL_ICON and English and Arabic labels there.
Main's flagship guide now counts load_tools as the 102nd tool; with the three follow-up tools it is the 105th.
…golden The memory prompt now tells the model to schedule a follow-up for a reminder at a time; the golden from main predates that line.
Keep main's Gemma tool-tier note and its "on a larger model" wording, with the counts that include the follow-up tools (104 tools, 69 in the full profile).
main now ships forget_everything (amd#5687), so both changes count: 105 tools, 70 in the full profile, 69 for the Chat agent, and 18 core tools. The dynamic-tools cap grows to 31 so 13 slots stay free for loaded bundles, as the cap's comment asks when the core set grows.
main now starts sessions on a 27-tool core and finds the rest with search_tools. schedule_follow_up stays in that core so a reminder request always reaches it, which makes 28 core tools and 106 in all. The guide's "26 most-used" becomes 28 core tools.
main adds analyze_transcript and export_transcript; with the three follow-up tools that is 108 in all, 72 in the full profile and 71 for the Chat agent.
On Windows the follow-up scheduling test failed by a tenth of a microsecond: datetime.timestamp() and time.time() disagree at that scale, so a later clock read could land the 2-hour gap just over 7200 s. The check now brackets fire_at between clock reads taken before and after the call.
cancel_follow_up now accepts only ids in the form the daemon mints them and returns an actionable error for anything else without contacting the daemon. The id is also URL-quoted when building the request path.
# Conflicts: # hub/agents/gaia/npm/SKILL.md
# Conflicts: # hub/agents/chat/python/gaia-agent.yaml
GAIA couldn't follow up on anything by itself. "Check on the build in 2 hours" or "remind me tomorrow at 9" got a cheerful "Set!", but nothing ever ran or alerted. A reminder was just a memory note that came up the next time you chatted (#5681). Now the agent schedules its own one-shot follow-ups. At the set time, even with no chat open, GAIA runs the task, posts a desktop notification, and opens your next chat, in the terminal app or the Agent UI, with the result. It builds on the daemon's existing clock, which until now had no executor at all, as
docs/plans/autonomy-engine.mdx§5 planned.Test plan
pytest tests/unit/test_daemon_followups.py tests/unit/test_follow_up_tools.py: 27 pass. They use the real daemon clock and store on a temp DB, with the agent call and notification stubbed. They cover:test_memory_mixin.pyadds a test that the timed-reminder rule appears only where follow-ups exist. 577 pass across the memory, scheduler, bundle, relay-profile, prompt-context, registry and capability-matrix suites. All 783 daemon tests pass except one that fails on main too under a customGAIA_HOME.vitest(components): 1042 pass;tscclean.Not in this PR: the cheap pre-fire gate and the agent noticing on its own that it's waiting (§5, #3969). No Windows banner yet: the existing notification sink only supports macOS and Linux, and on Windows the result is still kept and shown in the next chat.
Part of #555 (the agent schedules its own follow-ups; proactive messaging beyond that is still open there).