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
This commit is contained in:
viettranx committed 2026-03-11 07:26:43 +07:00
1 parent 13a3e25d40
commit c5b886048e
2 files changed
+30 -12

No files matched your search

+29 -11
View File
@@ -39,19 +39,37 @@ func makeCronJobHandler(sched *scheduler.Scheduler, msgBus *bus.MessageBus, cfg
// Resolve channel type for system prompt context. // Resolve channel type for system prompt context.
channelType := resolveChannelType(channelMgr, channel) 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 // Schedule through cron lane — scheduler handles agent resolution and concurrency
outCh := sched.Schedule(context.Background(), scheduler.LaneCron, agent.RunRequest{ outCh := sched.Schedule(context.Background(), scheduler.LaneCron, agent.RunRequest{
SessionKey: sessionKey, SessionKey: sessionKey,
Message: job.Payload.Message, Message: job.Payload.Message,
Channel: channel, Channel: channel,
ChannelType: channelType, ChannelType: channelType,
ChatID: job.Payload.To, ChatID: job.Payload.To,
PeerKind: peerKind, PeerKind: peerKind,
UserID: job.UserID, UserID: job.UserID,
RunID: fmt.Sprintf("cron:%s", job.ID), RunID: fmt.Sprintf("cron:%s", job.ID),
Stream: false, Stream: false,
TraceName: fmt.Sprintf("Cron [%s] - %s", job.Name, agentID), ExtraSystemPrompt: extraPrompt,
TraceTags: []string{"cron"}, TraceName: fmt.Sprintf("Cron [%s] - %s", job.Name, agentID),
TraceTags: []string{"cron"},
}) })
// Block until the scheduled run completes // Block until the scheduled run completes
+1 -1
View File
@@ -78,7 +78,7 @@ func (m *CronMethods) handleCreate(ctx context.Context, client *gateway.Client,
return 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 { if err != nil {
client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInvalidRequest, err.Error())) client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInvalidRequest, err.Error()))
return return