From c5b886048e708bb52b90eeb6431f17e2c2c9cbca Mon Sep 17 00:00:00 2001 From: viettranx Date: Wed, 11 Mar 2026 07:26:32 +0700 Subject: [PATCH] fix(cron): inject delivery context into cron job system prompt Cron jobs ran in isolated sessions with no context about who requested them or where to deliver responses. The agent would misroute responses (e.g., using team_message instead of replying to the original chat). - Inject ExtraSystemPrompt with job name, requester ID, and delivery target so the agent knows to produce content directly - Pass client.UserID() in Web UI cron.create instead of empty string --- cmd/gateway_cron.go | 40 +++++++++++++++++++++++--------- internal/gateway/methods/cron.go | 2 +- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/cmd/gateway_cron.go b/cmd/gateway_cron.go index 071f9973..660c8d2f 100644 --- a/cmd/gateway_cron.go +++ b/cmd/gateway_cron.go @@ -39,19 +39,37 @@ func makeCronJobHandler(sched *scheduler.Scheduler, msgBus *bus.MessageBus, cfg // Resolve channel type for system prompt context. channelType := resolveChannelType(channelMgr, channel) + // Build cron context so the agent knows delivery target and requester. + var extraPrompt string + if job.Payload.Deliver && job.Payload.Channel != "" && job.Payload.To != "" { + extraPrompt = fmt.Sprintf( + "[Cron Job]\nThis is scheduled job \"%s\" (ID: %s).\n"+ + "Requester: user %s on channel \"%s\" (chat %s).\n"+ + "Your response will be automatically delivered to that chat — just produce the content directly.", + job.Name, job.ID, job.UserID, job.Payload.Channel, job.Payload.To, + ) + } else { + extraPrompt = fmt.Sprintf( + "[Cron Job]\nThis is scheduled job \"%s\" (ID: %s), created by user %s.\n"+ + "Delivery is not configured — respond normally.", + job.Name, job.ID, job.UserID, + ) + } + // Schedule through cron lane — scheduler handles agent resolution and concurrency outCh := sched.Schedule(context.Background(), scheduler.LaneCron, agent.RunRequest{ - SessionKey: sessionKey, - Message: job.Payload.Message, - Channel: channel, - ChannelType: channelType, - ChatID: job.Payload.To, - PeerKind: peerKind, - UserID: job.UserID, - RunID: fmt.Sprintf("cron:%s", job.ID), - Stream: false, - TraceName: fmt.Sprintf("Cron [%s] - %s", job.Name, agentID), - TraceTags: []string{"cron"}, + SessionKey: sessionKey, + Message: job.Payload.Message, + Channel: channel, + ChannelType: channelType, + ChatID: job.Payload.To, + PeerKind: peerKind, + UserID: job.UserID, + RunID: fmt.Sprintf("cron:%s", job.ID), + Stream: false, + ExtraSystemPrompt: extraPrompt, + TraceName: fmt.Sprintf("Cron [%s] - %s", job.Name, agentID), + TraceTags: []string{"cron"}, }) // Block until the scheduled run completes diff --git a/internal/gateway/methods/cron.go b/internal/gateway/methods/cron.go index 240a4f5d..75aacd69 100644 --- a/internal/gateway/methods/cron.go +++ b/internal/gateway/methods/cron.go @@ -78,7 +78,7 @@ func (m *CronMethods) handleCreate(ctx context.Context, client *gateway.Client, return } - job, err := m.service.AddJob(params.Name, params.Schedule, params.Message, params.Deliver, params.Channel, params.To, params.AgentID, "") + job, err := m.service.AddJob(params.Name, params.Schedule, params.Message, params.Deliver, params.Channel, params.To, params.AgentID, client.UserID()) if err != nil { client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInvalidRequest, err.Error())) return