Skip to content

Commit d50cfbb

Browse files
committed
feat(cron): add agentId filtering to cron list
Adds optional agentId parameter to cron list action, allowing agents to filter cron jobs by their own agentId. This reduces noise in multi-agent setups where each agent sees all jobs across all agents. Changes: - Protocol schema: add optional agentId to CronListParamsSchema - Service types: add agentId to CronListPageOptions - Service ops: filter by agentId when provided - Gateway handler: pass through agentId param - Agent tool: auto-fill agentId from session context (like cron add) - CLI: add --agent <id> option to 'openclaw cron list' When called from an agent session without explicit agentId, the tool auto-fills it from the calling agent's session context. When called from CLI without --agent, all jobs are shown (backward compatible). Closes #77118
1 parent b31c001 commit d50cfbb

6 files changed

Lines changed: 26 additions & 4 deletions

File tree

src/agents/tools/cron-tool.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ export const CronToolSchema = Type.Object(
307307
contextMessages: Type.Optional(
308308
Type.Number({ minimum: 0, maximum: REMINDER_CONTEXT_MESSAGES_MAX }),
309309
),
310+
agentId: Type.Optional(Type.String({ description: "Filter by agent id (list action)" })),
310311
},
311312
{ additionalProperties: true },
312313
);
@@ -570,7 +571,7 @@ Main-session cron jobs enqueue system events for heartbeat handling. Isolated cr
570571
571572
ACTIONS:
572573
- status: Check cron scheduler status
573-
- list: List jobs (use includeDisabled:true to include disabled)
574+
- list: List jobs (use includeDisabled:true to include disabled; agentId filters by agent, auto-filled from session)
574575
- add: Create job (requires job object, see schema below)
575576
- update: Modify job (requires jobId + patch object)
576577
- remove: Delete job (requires jobId)
@@ -653,12 +654,21 @@ Use jobId as the canonical identifier; id is accepted for compatibility. Use con
653654
switch (action) {
654655
case "status":
655656
return jsonResult(await callGateway("cron.status", gatewayOpts, {}));
656-
case "list":
657+
case "list": {
658+
const cfg = getRuntimeConfig();
659+
const listAgentId =
660+
typeof params.agentId === "string" && params.agentId.trim()
661+
? params.agentId.trim()
662+
: opts?.agentSessionKey
663+
? resolveSessionAgentId({ sessionKey: opts.agentSessionKey, config: cfg })
664+
: undefined;
657665
return jsonResult(
658666
await callGateway("cron.list", gatewayOpts, {
659667
includeDisabled: Boolean(params.includeDisabled),
668+
agentId: listAgentId,
660669
}),
661670
);
671+
}
662672
case "add": {
663673
// Flat-params recovery: non-frontier models (e.g. Grok) sometimes flatten
664674
// job properties to the top level alongside `action` instead of nesting

src/cli/cron-cli/register.cron-add.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,17 @@ export function registerCronListCommand(cron: Command) {
4545
.command("list")
4646
.description("List cron jobs")
4747
.option("--all", "Include disabled jobs", false)
48+
.option("--agent <id>", "Filter by agent id")
4849
.option("--json", "Output JSON", false)
4950
.action(async (opts) => {
5051
try {
51-
const res = await callGatewayFromCli("cron.list", opts, {
52+
const listParams: Record<string, unknown> = {
5253
includeDisabled: Boolean(opts.all),
53-
});
54+
};
55+
if (opts.agent) {
56+
listParams.agentId = opts.agent;
57+
}
58+
const res = await callGatewayFromCli("cron.list", opts, listParams);
5459
if (opts.json) {
5560
printCronJson(res);
5661
return;

src/cron/service/list-page-types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export type CronListPageOptions = {
1212
enabled?: CronJobsEnabledFilter;
1313
sortBy?: CronJobsSortBy;
1414
sortDir?: CronSortDir;
15+
agentId?: string;
1516
};
1617

1718
export type CronListPageResult<TJobs extends readonly CronJob[] = CronJob[]> = {

src/cron/service/ops.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,9 @@ export async function listPage(state: CronServiceState, opts?: CronListPageOptio
286286
if (enabledFilter === "disabled" && isJobEnabled(job)) {
287287
return false;
288288
}
289+
if (opts?.agentId && job.agentId !== opts.agentId) {
290+
return false;
291+
}
289292
if (!query) {
290293
return true;
291294
}

src/gateway/protocol/schema/cron.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ export const CronListParamsSchema = Type.Object(
288288
enabled: Type.Optional(CronJobsEnabledFilterSchema),
289289
sortBy: Type.Optional(CronJobsSortBySchema),
290290
sortDir: Type.Optional(CronSortDirSchema),
291+
agentId: Type.Optional(NonEmptyString),
291292
},
292293
{ additionalProperties: false },
293294
);

src/gateway/server-methods/cron.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ export const cronHandlers: GatewayRequestHandlers = {
199199
enabled?: "all" | "enabled" | "disabled";
200200
sortBy?: "nextRunAtMs" | "updatedAtMs" | "name";
201201
sortDir?: "asc" | "desc";
202+
agentId?: string;
202203
};
203204
const page = await context.cron.listPage({
204205
includeDisabled: p.includeDisabled,
@@ -208,6 +209,7 @@ export const cronHandlers: GatewayRequestHandlers = {
208209
enabled: p.enabled,
209210
sortBy: p.sortBy,
210211
sortDir: p.sortDir,
212+
agentId: p.agentId,
211213
});
212214
const deliveryPreviews = await resolveCronDeliveryPreviews({
213215
cfg: context.getRuntimeConfig(),

0 commit comments

Comments
 (0)