fix(checkins): use systemEvent for cron triggers instead of agentTurn

Isolated agent sessions load plugins fresh with storage=null, causing
the tool factory to return null and no tools to be available. The agent
then outputs XML-like text instead of making proper tool calls.

Switch cron jobs to use systemEvent payload which runs in the main
gateway process where storage IS initialized. The message_received
hook already handles [system] checkins:trigger: and checkins:cleanup:
events.
This commit is contained in:
Simon KP 2026-01-27 10:16:20 +11:00
parent 9e9aea6482
commit 75c9496cd2
2 changed files with 10 additions and 19 deletions

View File

@ -59,6 +59,7 @@ export function buildCleanupCronJobs(storage: CheckinsStorage): CronJobCreate[]
} }
// Build cleanup job for each timezone // Build cleanup job for each timezone
// Use systemEvent to run in main gateway process (has access to initialized storage)
const jobs: CronJobCreate[] = []; const jobs: CronJobCreate[] = [];
for (const tz of timezones) { for (const tz of timezones) {
jobs.push({ jobs.push({
@ -70,12 +71,11 @@ export function buildCleanupCronJobs(storage: CheckinsStorage): CronJobCreate[]
expr: "5 0 * * *", // 00:05 (5 minutes past midnight per RESEARCH.md) expr: "5 0 * * *", // 00:05 (5 minutes past midnight per RESEARCH.md)
tz, tz,
}, },
sessionTarget: "isolated", sessionTarget: "main",
wakeMode: "now", wakeMode: "now",
payload: { payload: {
kind: "agentTurn", kind: "systemEvent",
message: `[system] checkins:cleanup:${tz}`, text: `[system] checkins:cleanup:${tz}`,
deliver: false,
}, },
}); });
} }

View File

@ -32,17 +32,8 @@ export function getCheckInJobId(memberId: string): string {
* @returns CronJobCreate configuration * @returns CronJobCreate configuration
*/ */
export function buildCheckInCronJob(member: Member, team: Team): CronJobCreate { export function buildCheckInCronJob(member: Member, team: Team): CronJobCreate {
// Build a clear instruction for the agent to call the trigger tool // Use systemEvent to trigger check-in via the main gateway process
const triggerMessage = [ // This avoids isolated agent sessions which don't have initialized plugin storage
"SCHEDULED CHECK-IN TRIGGER",
"",
"You must call the checkins_trigger tool with these exact parameters:",
` memberId: "${member.id}"`,
` teamId: "${team.id}"`,
"",
"Do not respond with any other message. Just call the tool.",
].join("\n");
return { return {
name: `Check-in: ${member.displayName ?? member.discordUserId}`, name: `Check-in: ${member.displayName ?? member.discordUserId}`,
description: `Daily check-in for team ${team.name}`, description: `Daily check-in for team ${team.name}`,
@ -52,12 +43,12 @@ export function buildCheckInCronJob(member: Member, team: Team): CronJobCreate {
expr: convertTimeToCronExpr(member.schedule.checkInTime), expr: convertTimeToCronExpr(member.schedule.checkInTime),
tz: member.schedule.timezone, tz: member.schedule.timezone,
}, },
sessionTarget: "isolated", // sessionTarget is auto-set to "main" for systemEvent payloads
sessionTarget: "main",
wakeMode: "now", wakeMode: "now",
payload: { payload: {
kind: "agentTurn", kind: "systemEvent",
message: triggerMessage, text: `[system] checkins:trigger:${member.id}:${team.id}`,
deliver: false,
}, },
}; };
} }