mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:10:44 +00:00
feat(cron): add agentId filtering to cron list (#77602)
Summary: - This PR adds optional `agentId` filtering to `cron.list`, auto-fills it for agent tool calls, exposes `openclaw cron list --agent`, updates generated protocol clients, docs, changelog, tests, and prompt fixtures. - Reproducibility: yes. The motivating behavior is source-reproducible on current main because cron tool, CLI, ... e list paths do not accept or apply `agentId`; the PR diff adds that path with focused regression coverage. Automerge notes: - Ran the ClawSweeper repair loop before final review. - Included post-review commit in the final squash: chore: regenerate protocol schema after adding agentId to CronListParams - Included post-review commit in the final squash: feat(cron): add agentId filtering to cron list Validation: - ClawSweeper review passed for head35b692bc97. - Required merge gates passed before the squash merge. Prepared head SHA:35b692bc97Review: https://github.com/openclaw/openclaw/pull/77602#issuecomment-4375631700 Co-authored-by: zhanggttry <zhanggttry@163.com> Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
This commit is contained in:
@@ -23,6 +23,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Plugins/active-memory: skip session-store channel entries that contain `:` when resolving the recall subagent's channel, so QQ c2c agent IDs (e.g. `c2c:10D4F7C2…`) and other scoped conversation IDs do not reach bundled-plugin `dirName` validation and crash the recall run. The same guard already applied to explicit `channelId` params (#76704); this extends it to store-derived channels. (#77396) Thanks @hclsys.
|
||||
- Secrets/external channel contracts: also look in `<rootDir>/dist/` when resolving the `secret-contract-api` sidecar, so npm-published externalized channel plugins (e.g. `@openclaw/discord` since 2026.5.2) whose compiled artifacts live under `dist/` actually contribute their channel SecretRef contracts to the runtime snapshot. Without this, env-backed `channels.discord.token` SecretRefs silently failed to resolve at gateway start on 2026.5.3, leaving the channel `not configured` even though #76449 had landed the generic external-contract loader. Thanks @mogglemoss.
|
||||
- Models/auth: add `openclaw models auth list [--provider <id>] [--json]` so users can inspect saved per-agent auth profiles without dumping secrets or hitting the old “too many arguments” path. Thanks @vincentkoc.
|
||||
- Cron CLI: add `openclaw cron list --agent <id>`, normalize the requested agent id, and include jobs without a stored agent id under the configured default agent while keeping `cron list` unfiltered when no agent is supplied. Fixes #77118. Thanks @zhanggttry.
|
||||
- Control UI/header: show the active agent name in dashboard breadcrumbs without adding the current session key, keeping non-chat views oriented without crowding the topbar.
|
||||
- Control UI/cron: make the New Job sidebar collapsible so the jobs list can reclaim space while keeping the form one click away. Thanks @BunsDev.
|
||||
- Gateway/startup: keep model-catalog test helpers, run-session lookup code, QR pairing helpers, and TypeBox memory-tool schema construction out of hot startup import paths, reducing default gateway benchmark plugin-load and memory pressure.
|
||||
|
||||
@@ -4172,6 +4172,7 @@ public struct CronListParams: Codable, Sendable {
|
||||
public let enabled: AnyCodable?
|
||||
public let sortby: AnyCodable?
|
||||
public let sortdir: AnyCodable?
|
||||
public let agentid: String?
|
||||
|
||||
public init(
|
||||
includedisabled: Bool?,
|
||||
@@ -4180,7 +4181,8 @@ public struct CronListParams: Codable, Sendable {
|
||||
query: String?,
|
||||
enabled: AnyCodable?,
|
||||
sortby: AnyCodable?,
|
||||
sortdir: AnyCodable?)
|
||||
sortdir: AnyCodable?,
|
||||
agentid: String?)
|
||||
{
|
||||
self.includedisabled = includedisabled
|
||||
self.limit = limit
|
||||
@@ -4189,6 +4191,7 @@ public struct CronListParams: Codable, Sendable {
|
||||
self.enabled = enabled
|
||||
self.sortby = sortby
|
||||
self.sortdir = sortdir
|
||||
self.agentid = agentid
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
@@ -4199,6 +4202,7 @@ public struct CronListParams: Codable, Sendable {
|
||||
case enabled
|
||||
case sortby = "sortBy"
|
||||
case sortdir = "sortDir"
|
||||
case agentid = "agentId"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4172,6 +4172,7 @@ public struct CronListParams: Codable, Sendable {
|
||||
public let enabled: AnyCodable?
|
||||
public let sortby: AnyCodable?
|
||||
public let sortdir: AnyCodable?
|
||||
public let agentid: String?
|
||||
|
||||
public init(
|
||||
includedisabled: Bool?,
|
||||
@@ -4180,7 +4181,8 @@ public struct CronListParams: Codable, Sendable {
|
||||
query: String?,
|
||||
enabled: AnyCodable?,
|
||||
sortby: AnyCodable?,
|
||||
sortdir: AnyCodable?)
|
||||
sortdir: AnyCodable?,
|
||||
agentid: String?)
|
||||
{
|
||||
self.includedisabled = includedisabled
|
||||
self.limit = limit
|
||||
@@ -4189,6 +4191,7 @@ public struct CronListParams: Codable, Sendable {
|
||||
self.enabled = enabled
|
||||
self.sortby = sortby
|
||||
self.sortdir = sortdir
|
||||
self.agentid = agentid
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
@@ -4199,6 +4202,7 @@ public struct CronListParams: Codable, Sendable {
|
||||
case enabled
|
||||
case sortby = "sortBy"
|
||||
case sortdir = "sortDir"
|
||||
case agentid = "agentId"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -211,12 +211,15 @@ Manual run and inspection:
|
||||
|
||||
```bash
|
||||
openclaw cron list
|
||||
openclaw cron list --agent ops
|
||||
openclaw cron show <job-id>
|
||||
openclaw cron run <job-id>
|
||||
openclaw cron run <job-id> --due
|
||||
openclaw cron runs --id <job-id> --limit 50
|
||||
```
|
||||
|
||||
`openclaw cron list` shows all matching jobs by default. Pass `--agent <id>` to show only jobs whose effective normalized agent id matches; jobs without a stored agent id count as the configured default agent.
|
||||
|
||||
`cron runs` entries include delivery diagnostics with the intended cron target, the resolved target, message-tool sends, fallback use, and delivered state.
|
||||
|
||||
Agent and session retargeting:
|
||||
|
||||
@@ -210,6 +210,34 @@ describe("cron tool", () => {
|
||||
expect(callGatewayMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("filters cron list by the requester agent session", async () => {
|
||||
const tool = createTestCronTool({
|
||||
agentSessionKey: "agent:agent-123:telegram:direct:channing",
|
||||
});
|
||||
|
||||
await tool.execute("call-list", {
|
||||
action: "list",
|
||||
});
|
||||
|
||||
const params = expectSingleGatewayCallMethod("cron.list");
|
||||
expect(params).toEqual({ includeDisabled: false, agentId: "agent-123" });
|
||||
});
|
||||
|
||||
it("prefers explicit cron list agent id over the requester session", async () => {
|
||||
const tool = createTestCronTool({
|
||||
agentSessionKey: "agent:agent-123:telegram:direct:channing",
|
||||
});
|
||||
|
||||
await tool.execute("call-list-explicit", {
|
||||
action: "list",
|
||||
agentId: "ops",
|
||||
includeDisabled: true,
|
||||
});
|
||||
|
||||
const params = expectSingleGatewayCallMethod("cron.list");
|
||||
expect(params).toEqual({ includeDisabled: true, agentId: "ops" });
|
||||
});
|
||||
|
||||
it("documents deferred follow-up guidance in the tool description", () => {
|
||||
const tool = createTestCronTool();
|
||||
expect(tool.description).toContain(
|
||||
|
||||
@@ -307,6 +307,7 @@ export const CronToolSchema = Type.Object(
|
||||
contextMessages: Type.Optional(
|
||||
Type.Number({ minimum: 0, maximum: REMINDER_CONTEXT_MESSAGES_MAX }),
|
||||
),
|
||||
agentId: Type.Optional(Type.String({ description: "Filter by agent id (list action)" })),
|
||||
},
|
||||
{ additionalProperties: true },
|
||||
);
|
||||
@@ -570,7 +571,7 @@ Main-session cron jobs enqueue system events for heartbeat handling. Isolated cr
|
||||
|
||||
ACTIONS:
|
||||
- status: Check cron scheduler status
|
||||
- list: List jobs (use includeDisabled:true to include disabled)
|
||||
- list: List jobs (use includeDisabled:true to include disabled; agentId filters by agent, auto-filled from session)
|
||||
- add: Create job (requires job object, see schema below)
|
||||
- update: Modify job (requires jobId + patch object)
|
||||
- remove: Delete job (requires jobId)
|
||||
@@ -653,12 +654,21 @@ Use jobId as the canonical identifier; id is accepted for compatibility. Use con
|
||||
switch (action) {
|
||||
case "status":
|
||||
return jsonResult(await callGateway("cron.status", gatewayOpts, {}));
|
||||
case "list":
|
||||
case "list": {
|
||||
const cfg = getRuntimeConfig();
|
||||
const listAgentId =
|
||||
typeof params.agentId === "string" && params.agentId.trim()
|
||||
? params.agentId.trim()
|
||||
: opts?.agentSessionKey
|
||||
? resolveSessionAgentId({ sessionKey: opts.agentSessionKey, config: cfg })
|
||||
: undefined;
|
||||
return jsonResult(
|
||||
await callGateway("cron.list", gatewayOpts, {
|
||||
includeDisabled: Boolean(params.includeDisabled),
|
||||
agentId: listAgentId,
|
||||
}),
|
||||
);
|
||||
}
|
||||
case "add": {
|
||||
// Flat-params recovery: non-frontier models (e.g. Grok) sometimes flatten
|
||||
// job properties to the top level alongside `action` instead of nesting
|
||||
|
||||
@@ -481,6 +481,20 @@ describe("cron cli", () => {
|
||||
expect(patch.enabled).toBe(expectedEnabled);
|
||||
});
|
||||
|
||||
it("leaves cron list unfiltered when --agent is omitted", async () => {
|
||||
await runCronCommand(["cron", "list"]);
|
||||
|
||||
const listCall = callGatewayFromCli.mock.calls.find((call) => call[0] === "cron.list");
|
||||
expect(listCall?.[2]).toEqual({ includeDisabled: false });
|
||||
});
|
||||
|
||||
it("sends normalized agent id on cron list --agent", async () => {
|
||||
await runCronCommand(["cron", "list", "--agent", " Ops "]);
|
||||
|
||||
const listCall = callGatewayFromCli.mock.calls.find((call) => call[0] === "cron.list");
|
||||
expect(listCall?.[2]).toEqual({ includeDisabled: false, agentId: "ops" });
|
||||
});
|
||||
|
||||
it("paginates cron show lookups", async () => {
|
||||
resetGatewayMock();
|
||||
callGatewayFromCli.mockImplementation(
|
||||
|
||||
@@ -45,12 +45,18 @@ export function registerCronListCommand(cron: Command) {
|
||||
.command("list")
|
||||
.description("List cron jobs")
|
||||
.option("--all", "Include disabled jobs", false)
|
||||
.option("--agent <id>", "Filter by agent id")
|
||||
.option("--json", "Output JSON", false)
|
||||
.action(async (opts) => {
|
||||
try {
|
||||
const res = await callGatewayFromCli("cron.list", opts, {
|
||||
const listParams: Record<string, unknown> = {
|
||||
includeDisabled: Boolean(opts.all),
|
||||
});
|
||||
};
|
||||
const agentId = normalizeOptionalString(opts.agent);
|
||||
if (agentId) {
|
||||
listParams.agentId = sanitizeAgentId(agentId);
|
||||
}
|
||||
const res = await callGatewayFromCli("cron.list", opts, listParams);
|
||||
if (opts.json) {
|
||||
printCronJson(res);
|
||||
return;
|
||||
|
||||
@@ -50,4 +50,56 @@ describe("cron listPage sort guards", () => {
|
||||
const page = await listPage(state, { sortBy: "nextRunAtMs", sortDir: "asc" });
|
||||
expect(page.jobs).toHaveLength(2);
|
||||
});
|
||||
|
||||
it("normalizes requested agent ids before filtering", async () => {
|
||||
const jobs = [
|
||||
createBaseJob({ id: "job-main", agentId: "main", name: "main" }),
|
||||
createBaseJob({ id: "job-ops", agentId: "ops", name: "ops" }),
|
||||
createBaseJob({ id: "job-unset", agentId: undefined, name: "unset" }),
|
||||
];
|
||||
const state = createMockCronStateForJobs({ jobs });
|
||||
|
||||
const page = await listPage(state, { agentId: " Ops " });
|
||||
|
||||
expect(page.jobs.map((job) => job.id)).toEqual(["job-ops"]);
|
||||
});
|
||||
|
||||
it("matches omitted job agent ids to the configured default agent when filtering", async () => {
|
||||
const jobs = [
|
||||
createBaseJob({ id: "job-main", agentId: "main", name: "main" }),
|
||||
createBaseJob({ id: "job-ops", agentId: "ops", name: "ops" }),
|
||||
createBaseJob({ id: "job-unset", agentId: undefined, name: "unset" }),
|
||||
];
|
||||
const state = createMockCronStateForJobs({ jobs });
|
||||
state.deps.defaultAgentId = " Ops ";
|
||||
|
||||
const page = await listPage(state, { agentId: "ops" });
|
||||
|
||||
expect(page.jobs.map((job) => job.id)).toEqual(["job-ops", "job-unset"]);
|
||||
});
|
||||
|
||||
it("matches omitted job agent ids to main when no default agent is configured", async () => {
|
||||
const jobs = [
|
||||
createBaseJob({ id: "job-main", agentId: "main", name: "main" }),
|
||||
createBaseJob({ id: "job-ops", agentId: "ops", name: "ops" }),
|
||||
createBaseJob({ id: "job-unset", agentId: undefined, name: "unset" }),
|
||||
];
|
||||
const state = createMockCronStateForJobs({ jobs });
|
||||
|
||||
const page = await listPage(state, { agentId: "main" });
|
||||
|
||||
expect(page.jobs.map((job) => job.id)).toEqual(["job-main", "job-unset"]);
|
||||
});
|
||||
|
||||
it("keeps listPage unfiltered when agent id is omitted", async () => {
|
||||
const jobs = [
|
||||
createBaseJob({ id: "job-main", agentId: "main", name: "main" }),
|
||||
createBaseJob({ id: "job-ops", agentId: "ops", name: "ops" }),
|
||||
];
|
||||
const state = createMockCronStateForJobs({ jobs });
|
||||
|
||||
const page = await listPage(state);
|
||||
|
||||
expect(page.jobs.map((job) => job.id)).toEqual(["job-main", "job-ops"]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,6 +12,7 @@ export type CronListPageOptions = {
|
||||
enabled?: CronJobsEnabledFilter;
|
||||
sortBy?: CronJobsSortBy;
|
||||
sortDir?: CronSortDir;
|
||||
agentId?: string;
|
||||
};
|
||||
|
||||
export type CronListPageResult<TJobs extends readonly CronJob[] = CronJob[]> = {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { enqueueCommandInLane } from "../../process/command-queue.js";
|
||||
import { CommandLane } from "../../process/lanes.js";
|
||||
import { DEFAULT_AGENT_ID } from "../../routing/session-key.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
|
||||
import {
|
||||
completeTaskRunByRunId,
|
||||
@@ -30,6 +31,7 @@ import type {
|
||||
CronSortDir,
|
||||
} from "./list-page-types.js";
|
||||
import { locked } from "./locked.js";
|
||||
import { normalizeOptionalAgentId } from "./normalize.js";
|
||||
import type { CronServiceState } from "./state.js";
|
||||
import { ensureLoaded, persist, warnIfDisabled } from "./store.js";
|
||||
import {
|
||||
@@ -272,6 +274,14 @@ function sortJobs(jobs: CronJob[], sortBy: CronJobsSortBy, sortDir: CronSortDir)
|
||||
});
|
||||
}
|
||||
|
||||
function resolveEffectiveJobAgentId(job: CronJob, defaultAgentId: string | undefined) {
|
||||
return (
|
||||
normalizeOptionalAgentId(job.agentId) ??
|
||||
normalizeOptionalAgentId(defaultAgentId) ??
|
||||
DEFAULT_AGENT_ID
|
||||
);
|
||||
}
|
||||
|
||||
export async function listPage(state: CronServiceState, opts?: CronListPageOptions) {
|
||||
return await locked(state, async () => {
|
||||
await ensureLoadedForRead(state);
|
||||
@@ -279,6 +289,7 @@ export async function listPage(state: CronServiceState, opts?: CronListPageOptio
|
||||
const enabledFilter = resolveEnabledFilter(opts);
|
||||
const sortBy = opts?.sortBy ?? "nextRunAtMs";
|
||||
const sortDir = opts?.sortDir ?? "asc";
|
||||
const requestedAgentId = normalizeOptionalAgentId(opts?.agentId);
|
||||
const source = state.store?.jobs ?? [];
|
||||
const filtered = source.filter((job) => {
|
||||
if (enabledFilter === "enabled" && !isJobEnabled(job)) {
|
||||
@@ -287,6 +298,12 @@ export async function listPage(state: CronServiceState, opts?: CronListPageOptio
|
||||
if (enabledFilter === "disabled" && isJobEnabled(job)) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
requestedAgentId &&
|
||||
resolveEffectiveJobAgentId(job, state.deps.defaultAgentId) !== requestedAgentId
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (!query) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -111,9 +111,11 @@ describe("cron protocol validators", () => {
|
||||
enabled: "all",
|
||||
sortBy: "nextRunAtMs",
|
||||
sortDir: "asc",
|
||||
agentId: "ops",
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(validateCronListParams({ offset: -1 })).toBe(false);
|
||||
expect(validateCronListParams({ agentId: "" })).toBe(false);
|
||||
});
|
||||
|
||||
it("enforces runs limit minimum for id and jobId selectors", () => {
|
||||
|
||||
@@ -343,6 +343,7 @@ export const CronListParamsSchema = Type.Object(
|
||||
enabled: Type.Optional(CronJobsEnabledFilterSchema),
|
||||
sortBy: Type.Optional(CronJobsSortBySchema),
|
||||
sortDir: Type.Optional(CronSortDirSchema),
|
||||
agentId: Type.Optional(NonEmptyString),
|
||||
},
|
||||
{ additionalProperties: false },
|
||||
);
|
||||
|
||||
@@ -199,6 +199,7 @@ export const cronHandlers: GatewayRequestHandlers = {
|
||||
enabled?: "all" | "enabled" | "disabled";
|
||||
sortBy?: "nextRunAtMs" | "updatedAtMs" | "name";
|
||||
sortDir?: "asc" | "desc";
|
||||
agentId?: string;
|
||||
};
|
||||
const page = await context.cron.listPage({
|
||||
includeDisabled: p.includeDisabled,
|
||||
@@ -208,6 +209,7 @@ export const cronHandlers: GatewayRequestHandlers = {
|
||||
enabled: p.enabled,
|
||||
sortBy: p.sortBy,
|
||||
sortDir: p.sortDir,
|
||||
agentId: p.agentId,
|
||||
});
|
||||
const deliveryPreviews = await resolveCronDeliveryPreviews({
|
||||
cfg: context.getRuntimeConfig(),
|
||||
|
||||
@@ -200,7 +200,7 @@
|
||||
"name": "nodes"
|
||||
},
|
||||
{
|
||||
"description": "Manage Gateway cron jobs (status/list/add/update/remove/run/runs) and send wake events. Use this for reminders, \"check back later\" requests, delayed follow-ups, and recurring tasks. Do not emulate scheduling with exec sleep or process polling.\n\nMain-session cron jobs enqueue system events for heartbeat handling. Isolated cron jobs create background task runs that appear in `openclaw tasks`.\n\nACTIONS:\n- status: Check cron scheduler status\n- list: List jobs (use includeDisabled:true to include disabled)\n- add: Create job (requires job object, see schema below)\n- update: Modify job (requires jobId + patch object)\n- remove: Delete job (requires jobId)\n- run: Trigger job immediately (requires jobId)\n- runs: Get job run history (requires jobId)\n- wake: Send wake event (requires text, optional mode)\n\nJOB SCHEMA (for add action):\n{\n \"name\": \"string (optional)\",\n \"schedule\": { ... }, // Required: when to run\n \"payload\": { ... }, // Required: what to execute\n \"delivery\": { ... }, // Optional: announce summary (isolated/current/session:xxx only) or webhook POST\n \"sessionTarget\": \"main\" | \"isolated\" | \"current\" | \"session:<custom-id>\", // Optional, defaults based on context\n \"enabled\": true | false // Optional, default true\n}\n\nSESSION TARGET OPTIONS:\n- \"main\": Run in the main session (requires payload.kind=\"systemEvent\")\n- \"isolated\": Run in an ephemeral isolated session (requires payload.kind=\"agentTurn\")\n- \"current\": Bind to the current session where the cron is created (resolved at creation time)\n- \"session:<custom-id>\": Run in a persistent named session (e.g., \"session:project-alpha-daily\")\n\nDEFAULT BEHAVIOR (unchanged for backward compatibility):\n- payload.kind=\"systemEvent\" → defaults to \"main\"\n- payload.kind=\"agentTurn\" → defaults to \"isolated\"\nTo use current session binding, explicitly set sessionTarget=\"current\".\n\nSCHEDULE TYPES (schedule.kind):\n- \"at\": One-shot at absolute time\n { \"kind\": \"at\", \"at\": \"<ISO-8601 timestamp>\" }\n- \"every\": Recurring interval\n { \"kind\": \"every\", \"everyMs\": <interval-ms>, \"anchorMs\": <optional-start-ms> }\n- \"cron\": Cron expression evaluated in the supplied timezone, or the Gateway host local timezone when tz is omitted\n { \"kind\": \"cron\", \"expr\": \"<cron-expression>\", \"tz\": \"<optional-IANA-timezone>\" }\n Write expr in the selected timezone's local wall-clock time; do not convert the requested local time to UTC first.\n If tz is omitted, do not assume UTC; the Gateway host local timezone is used.\n Example: \"Remind me every day at 6pm Shanghai time\" -> { \"kind\": \"cron\", \"expr\": \"0 18 * * *\", \"tz\": \"Asia/Shanghai\" }\n\nFor schedule.kind=\"at\", ISO timestamps without an explicit timezone are treated as UTC.\n\nPAYLOAD TYPES (payload.kind):\n- \"systemEvent\": Injects text as system event into session\n { \"kind\": \"systemEvent\", \"text\": \"<message>\" }\n- \"agentTurn\": Runs agent with message (isolated sessions only)\n { \"kind\": \"agentTurn\", \"message\": \"<prompt>\", \"model\": \"<optional>\", \"thinking\": \"<optional>\", \"timeoutSeconds\": <optional, 0 means no timeout> }\n\nDELIVERY (top-level):\n { \"mode\": \"none|announce|webhook\", \"channel\": \"<optional>\", \"to\": \"<optional>\", \"threadId\": \"<optional>\", \"bestEffort\": <optional-bool> }\n - Default for isolated agentTurn jobs (when delivery omitted): \"announce\"\n - announce: send to chat channel (optional channel/to target)\n - threadId: chat thread/topic id for channels that support threaded delivery\n - webhook: send finished-run event as HTTP POST to delivery.to (URL required)\n - If the task needs to send to a specific chat/recipient, set announce delivery.channel/to; do not call messaging tools inside the run.\n\nCRITICAL CONSTRAINTS:\n- sessionTarget=\"main\" REQUIRES payload.kind=\"systemEvent\"\n- sessionTarget=\"isolated\" | \"current\" | \"session:xxx\" REQUIRES payload.kind=\"agentTurn\"\n- For webhook callbacks, use delivery.mode=\"webhook\" with delivery.to set to a URL.\nDefault: prefer isolated agentTurn jobs unless the user explicitly wants current-session binding.\n\nWAKE MODES (for wake action):\n- \"next-heartbeat\" (default): Wake on next heartbeat\n- \"now\": Wake immediately\n\nUse jobId as the canonical identifier; id is accepted for compatibility. Use contextMessages (0-10) to add previous messages as context to the job text.",
|
||||
"description": "Manage Gateway cron jobs (status/list/add/update/remove/run/runs) and send wake events. Use this for reminders, \"check back later\" requests, delayed follow-ups, and recurring tasks. Do not emulate scheduling with exec sleep or process polling.\n\nMain-session cron jobs enqueue system events for heartbeat handling. Isolated cron jobs create background task runs that appear in `openclaw tasks`.\n\nACTIONS:\n- status: Check cron scheduler status\n- list: List jobs (use includeDisabled:true to include disabled; agentId filters by agent, auto-filled from session)\n- add: Create job (requires job object, see schema below)\n- update: Modify job (requires jobId + patch object)\n- remove: Delete job (requires jobId)\n- run: Trigger job immediately (requires jobId)\n- runs: Get job run history (requires jobId)\n- wake: Send wake event (requires text, optional mode)\n\nJOB SCHEMA (for add action):\n{\n \"name\": \"string (optional)\",\n \"schedule\": { ... }, // Required: when to run\n \"payload\": { ... }, // Required: what to execute\n \"delivery\": { ... }, // Optional: announce summary (isolated/current/session:xxx only) or webhook POST\n \"sessionTarget\": \"main\" | \"isolated\" | \"current\" | \"session:<custom-id>\", // Optional, defaults based on context\n \"enabled\": true | false // Optional, default true\n}\n\nSESSION TARGET OPTIONS:\n- \"main\": Run in the main session (requires payload.kind=\"systemEvent\")\n- \"isolated\": Run in an ephemeral isolated session (requires payload.kind=\"agentTurn\")\n- \"current\": Bind to the current session where the cron is created (resolved at creation time)\n- \"session:<custom-id>\": Run in a persistent named session (e.g., \"session:project-alpha-daily\")\n\nDEFAULT BEHAVIOR (unchanged for backward compatibility):\n- payload.kind=\"systemEvent\" → defaults to \"main\"\n- payload.kind=\"agentTurn\" → defaults to \"isolated\"\nTo use current session binding, explicitly set sessionTarget=\"current\".\n\nSCHEDULE TYPES (schedule.kind):\n- \"at\": One-shot at absolute time\n { \"kind\": \"at\", \"at\": \"<ISO-8601 timestamp>\" }\n- \"every\": Recurring interval\n { \"kind\": \"every\", \"everyMs\": <interval-ms>, \"anchorMs\": <optional-start-ms> }\n- \"cron\": Cron expression evaluated in the supplied timezone, or the Gateway host local timezone when tz is omitted\n { \"kind\": \"cron\", \"expr\": \"<cron-expression>\", \"tz\": \"<optional-IANA-timezone>\" }\n Write expr in the selected timezone's local wall-clock time; do not convert the requested local time to UTC first.\n If tz is omitted, do not assume UTC; the Gateway host local timezone is used.\n Example: \"Remind me every day at 6pm Shanghai time\" -> { \"kind\": \"cron\", \"expr\": \"0 18 * * *\", \"tz\": \"Asia/Shanghai\" }\n\nFor schedule.kind=\"at\", ISO timestamps without an explicit timezone are treated as UTC.\n\nPAYLOAD TYPES (payload.kind):\n- \"systemEvent\": Injects text as system event into session\n { \"kind\": \"systemEvent\", \"text\": \"<message>\" }\n- \"agentTurn\": Runs agent with message (isolated sessions only)\n { \"kind\": \"agentTurn\", \"message\": \"<prompt>\", \"model\": \"<optional>\", \"thinking\": \"<optional>\", \"timeoutSeconds\": <optional, 0 means no timeout> }\n\nDELIVERY (top-level):\n { \"mode\": \"none|announce|webhook\", \"channel\": \"<optional>\", \"to\": \"<optional>\", \"threadId\": \"<optional>\", \"bestEffort\": <optional-bool> }\n - Default for isolated agentTurn jobs (when delivery omitted): \"announce\"\n - announce: send to chat channel (optional channel/to target)\n - threadId: chat thread/topic id for channels that support threaded delivery\n - webhook: send finished-run event as HTTP POST to delivery.to (URL required)\n - If the task needs to send to a specific chat/recipient, set announce delivery.channel/to; do not call messaging tools inside the run.\n\nCRITICAL CONSTRAINTS:\n- sessionTarget=\"main\" REQUIRES payload.kind=\"systemEvent\"\n- sessionTarget=\"isolated\" | \"current\" | \"session:xxx\" REQUIRES payload.kind=\"agentTurn\"\n- For webhook callbacks, use delivery.mode=\"webhook\" with delivery.to set to a URL.\nDefault: prefer isolated agentTurn jobs unless the user explicitly wants current-session binding.\n\nWAKE MODES (for wake action):\n- \"next-heartbeat\" (default): Wake on next heartbeat\n- \"now\": Wake immediately\n\nUse jobId as the canonical identifier; id is accepted for compatibility. Use contextMessages (0-10) to add previous messages as context to the job text.",
|
||||
"inputSchema": {
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
@@ -208,6 +208,10 @@
|
||||
"enum": ["status", "list", "add", "update", "remove", "run", "runs", "wake"],
|
||||
"type": "string"
|
||||
},
|
||||
"agentId": {
|
||||
"description": "Filter by agent id (list action)",
|
||||
"type": "string"
|
||||
},
|
||||
"contextMessages": {
|
||||
"maximum": 10,
|
||||
"minimum": 0,
|
||||
|
||||
@@ -200,7 +200,7 @@
|
||||
"name": "nodes"
|
||||
},
|
||||
{
|
||||
"description": "Manage Gateway cron jobs (status/list/add/update/remove/run/runs) and send wake events. Use this for reminders, \"check back later\" requests, delayed follow-ups, and recurring tasks. Do not emulate scheduling with exec sleep or process polling.\n\nMain-session cron jobs enqueue system events for heartbeat handling. Isolated cron jobs create background task runs that appear in `openclaw tasks`.\n\nACTIONS:\n- status: Check cron scheduler status\n- list: List jobs (use includeDisabled:true to include disabled)\n- add: Create job (requires job object, see schema below)\n- update: Modify job (requires jobId + patch object)\n- remove: Delete job (requires jobId)\n- run: Trigger job immediately (requires jobId)\n- runs: Get job run history (requires jobId)\n- wake: Send wake event (requires text, optional mode)\n\nJOB SCHEMA (for add action):\n{\n \"name\": \"string (optional)\",\n \"schedule\": { ... }, // Required: when to run\n \"payload\": { ... }, // Required: what to execute\n \"delivery\": { ... }, // Optional: announce summary (isolated/current/session:xxx only) or webhook POST\n \"sessionTarget\": \"main\" | \"isolated\" | \"current\" | \"session:<custom-id>\", // Optional, defaults based on context\n \"enabled\": true | false // Optional, default true\n}\n\nSESSION TARGET OPTIONS:\n- \"main\": Run in the main session (requires payload.kind=\"systemEvent\")\n- \"isolated\": Run in an ephemeral isolated session (requires payload.kind=\"agentTurn\")\n- \"current\": Bind to the current session where the cron is created (resolved at creation time)\n- \"session:<custom-id>\": Run in a persistent named session (e.g., \"session:project-alpha-daily\")\n\nDEFAULT BEHAVIOR (unchanged for backward compatibility):\n- payload.kind=\"systemEvent\" → defaults to \"main\"\n- payload.kind=\"agentTurn\" → defaults to \"isolated\"\nTo use current session binding, explicitly set sessionTarget=\"current\".\n\nSCHEDULE TYPES (schedule.kind):\n- \"at\": One-shot at absolute time\n { \"kind\": \"at\", \"at\": \"<ISO-8601 timestamp>\" }\n- \"every\": Recurring interval\n { \"kind\": \"every\", \"everyMs\": <interval-ms>, \"anchorMs\": <optional-start-ms> }\n- \"cron\": Cron expression evaluated in the supplied timezone, or the Gateway host local timezone when tz is omitted\n { \"kind\": \"cron\", \"expr\": \"<cron-expression>\", \"tz\": \"<optional-IANA-timezone>\" }\n Write expr in the selected timezone's local wall-clock time; do not convert the requested local time to UTC first.\n If tz is omitted, do not assume UTC; the Gateway host local timezone is used.\n Example: \"Remind me every day at 6pm Shanghai time\" -> { \"kind\": \"cron\", \"expr\": \"0 18 * * *\", \"tz\": \"Asia/Shanghai\" }\n\nFor schedule.kind=\"at\", ISO timestamps without an explicit timezone are treated as UTC.\n\nPAYLOAD TYPES (payload.kind):\n- \"systemEvent\": Injects text as system event into session\n { \"kind\": \"systemEvent\", \"text\": \"<message>\" }\n- \"agentTurn\": Runs agent with message (isolated sessions only)\n { \"kind\": \"agentTurn\", \"message\": \"<prompt>\", \"model\": \"<optional>\", \"thinking\": \"<optional>\", \"timeoutSeconds\": <optional, 0 means no timeout> }\n\nDELIVERY (top-level):\n { \"mode\": \"none|announce|webhook\", \"channel\": \"<optional>\", \"to\": \"<optional>\", \"threadId\": \"<optional>\", \"bestEffort\": <optional-bool> }\n - Default for isolated agentTurn jobs (when delivery omitted): \"announce\"\n - announce: send to chat channel (optional channel/to target)\n - threadId: chat thread/topic id for channels that support threaded delivery\n - webhook: send finished-run event as HTTP POST to delivery.to (URL required)\n - If the task needs to send to a specific chat/recipient, set announce delivery.channel/to; do not call messaging tools inside the run.\n\nCRITICAL CONSTRAINTS:\n- sessionTarget=\"main\" REQUIRES payload.kind=\"systemEvent\"\n- sessionTarget=\"isolated\" | \"current\" | \"session:xxx\" REQUIRES payload.kind=\"agentTurn\"\n- For webhook callbacks, use delivery.mode=\"webhook\" with delivery.to set to a URL.\nDefault: prefer isolated agentTurn jobs unless the user explicitly wants current-session binding.\n\nWAKE MODES (for wake action):\n- \"next-heartbeat\" (default): Wake on next heartbeat\n- \"now\": Wake immediately\n\nUse jobId as the canonical identifier; id is accepted for compatibility. Use contextMessages (0-10) to add previous messages as context to the job text.",
|
||||
"description": "Manage Gateway cron jobs (status/list/add/update/remove/run/runs) and send wake events. Use this for reminders, \"check back later\" requests, delayed follow-ups, and recurring tasks. Do not emulate scheduling with exec sleep or process polling.\n\nMain-session cron jobs enqueue system events for heartbeat handling. Isolated cron jobs create background task runs that appear in `openclaw tasks`.\n\nACTIONS:\n- status: Check cron scheduler status\n- list: List jobs (use includeDisabled:true to include disabled; agentId filters by agent, auto-filled from session)\n- add: Create job (requires job object, see schema below)\n- update: Modify job (requires jobId + patch object)\n- remove: Delete job (requires jobId)\n- run: Trigger job immediately (requires jobId)\n- runs: Get job run history (requires jobId)\n- wake: Send wake event (requires text, optional mode)\n\nJOB SCHEMA (for add action):\n{\n \"name\": \"string (optional)\",\n \"schedule\": { ... }, // Required: when to run\n \"payload\": { ... }, // Required: what to execute\n \"delivery\": { ... }, // Optional: announce summary (isolated/current/session:xxx only) or webhook POST\n \"sessionTarget\": \"main\" | \"isolated\" | \"current\" | \"session:<custom-id>\", // Optional, defaults based on context\n \"enabled\": true | false // Optional, default true\n}\n\nSESSION TARGET OPTIONS:\n- \"main\": Run in the main session (requires payload.kind=\"systemEvent\")\n- \"isolated\": Run in an ephemeral isolated session (requires payload.kind=\"agentTurn\")\n- \"current\": Bind to the current session where the cron is created (resolved at creation time)\n- \"session:<custom-id>\": Run in a persistent named session (e.g., \"session:project-alpha-daily\")\n\nDEFAULT BEHAVIOR (unchanged for backward compatibility):\n- payload.kind=\"systemEvent\" → defaults to \"main\"\n- payload.kind=\"agentTurn\" → defaults to \"isolated\"\nTo use current session binding, explicitly set sessionTarget=\"current\".\n\nSCHEDULE TYPES (schedule.kind):\n- \"at\": One-shot at absolute time\n { \"kind\": \"at\", \"at\": \"<ISO-8601 timestamp>\" }\n- \"every\": Recurring interval\n { \"kind\": \"every\", \"everyMs\": <interval-ms>, \"anchorMs\": <optional-start-ms> }\n- \"cron\": Cron expression evaluated in the supplied timezone, or the Gateway host local timezone when tz is omitted\n { \"kind\": \"cron\", \"expr\": \"<cron-expression>\", \"tz\": \"<optional-IANA-timezone>\" }\n Write expr in the selected timezone's local wall-clock time; do not convert the requested local time to UTC first.\n If tz is omitted, do not assume UTC; the Gateway host local timezone is used.\n Example: \"Remind me every day at 6pm Shanghai time\" -> { \"kind\": \"cron\", \"expr\": \"0 18 * * *\", \"tz\": \"Asia/Shanghai\" }\n\nFor schedule.kind=\"at\", ISO timestamps without an explicit timezone are treated as UTC.\n\nPAYLOAD TYPES (payload.kind):\n- \"systemEvent\": Injects text as system event into session\n { \"kind\": \"systemEvent\", \"text\": \"<message>\" }\n- \"agentTurn\": Runs agent with message (isolated sessions only)\n { \"kind\": \"agentTurn\", \"message\": \"<prompt>\", \"model\": \"<optional>\", \"thinking\": \"<optional>\", \"timeoutSeconds\": <optional, 0 means no timeout> }\n\nDELIVERY (top-level):\n { \"mode\": \"none|announce|webhook\", \"channel\": \"<optional>\", \"to\": \"<optional>\", \"threadId\": \"<optional>\", \"bestEffort\": <optional-bool> }\n - Default for isolated agentTurn jobs (when delivery omitted): \"announce\"\n - announce: send to chat channel (optional channel/to target)\n - threadId: chat thread/topic id for channels that support threaded delivery\n - webhook: send finished-run event as HTTP POST to delivery.to (URL required)\n - If the task needs to send to a specific chat/recipient, set announce delivery.channel/to; do not call messaging tools inside the run.\n\nCRITICAL CONSTRAINTS:\n- sessionTarget=\"main\" REQUIRES payload.kind=\"systemEvent\"\n- sessionTarget=\"isolated\" | \"current\" | \"session:xxx\" REQUIRES payload.kind=\"agentTurn\"\n- For webhook callbacks, use delivery.mode=\"webhook\" with delivery.to set to a URL.\nDefault: prefer isolated agentTurn jobs unless the user explicitly wants current-session binding.\n\nWAKE MODES (for wake action):\n- \"next-heartbeat\" (default): Wake on next heartbeat\n- \"now\": Wake immediately\n\nUse jobId as the canonical identifier; id is accepted for compatibility. Use contextMessages (0-10) to add previous messages as context to the job text.",
|
||||
"inputSchema": {
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
@@ -208,6 +208,10 @@
|
||||
"enum": ["status", "list", "add", "update", "remove", "run", "runs", "wake"],
|
||||
"type": "string"
|
||||
},
|
||||
"agentId": {
|
||||
"description": "Filter by agent id (list action)",
|
||||
"type": "string"
|
||||
},
|
||||
"contextMessages": {
|
||||
"maximum": 10,
|
||||
"minimum": 0,
|
||||
|
||||
@@ -200,7 +200,7 @@
|
||||
"name": "nodes"
|
||||
},
|
||||
{
|
||||
"description": "Manage Gateway cron jobs (status/list/add/update/remove/run/runs) and send wake events. Use this for reminders, \"check back later\" requests, delayed follow-ups, and recurring tasks. Do not emulate scheduling with exec sleep or process polling.\n\nMain-session cron jobs enqueue system events for heartbeat handling. Isolated cron jobs create background task runs that appear in `openclaw tasks`.\n\nACTIONS:\n- status: Check cron scheduler status\n- list: List jobs (use includeDisabled:true to include disabled)\n- add: Create job (requires job object, see schema below)\n- update: Modify job (requires jobId + patch object)\n- remove: Delete job (requires jobId)\n- run: Trigger job immediately (requires jobId)\n- runs: Get job run history (requires jobId)\n- wake: Send wake event (requires text, optional mode)\n\nJOB SCHEMA (for add action):\n{\n \"name\": \"string (optional)\",\n \"schedule\": { ... }, // Required: when to run\n \"payload\": { ... }, // Required: what to execute\n \"delivery\": { ... }, // Optional: announce summary (isolated/current/session:xxx only) or webhook POST\n \"sessionTarget\": \"main\" | \"isolated\" | \"current\" | \"session:<custom-id>\", // Optional, defaults based on context\n \"enabled\": true | false // Optional, default true\n}\n\nSESSION TARGET OPTIONS:\n- \"main\": Run in the main session (requires payload.kind=\"systemEvent\")\n- \"isolated\": Run in an ephemeral isolated session (requires payload.kind=\"agentTurn\")\n- \"current\": Bind to the current session where the cron is created (resolved at creation time)\n- \"session:<custom-id>\": Run in a persistent named session (e.g., \"session:project-alpha-daily\")\n\nDEFAULT BEHAVIOR (unchanged for backward compatibility):\n- payload.kind=\"systemEvent\" → defaults to \"main\"\n- payload.kind=\"agentTurn\" → defaults to \"isolated\"\nTo use current session binding, explicitly set sessionTarget=\"current\".\n\nSCHEDULE TYPES (schedule.kind):\n- \"at\": One-shot at absolute time\n { \"kind\": \"at\", \"at\": \"<ISO-8601 timestamp>\" }\n- \"every\": Recurring interval\n { \"kind\": \"every\", \"everyMs\": <interval-ms>, \"anchorMs\": <optional-start-ms> }\n- \"cron\": Cron expression evaluated in the supplied timezone, or the Gateway host local timezone when tz is omitted\n { \"kind\": \"cron\", \"expr\": \"<cron-expression>\", \"tz\": \"<optional-IANA-timezone>\" }\n Write expr in the selected timezone's local wall-clock time; do not convert the requested local time to UTC first.\n If tz is omitted, do not assume UTC; the Gateway host local timezone is used.\n Example: \"Remind me every day at 6pm Shanghai time\" -> { \"kind\": \"cron\", \"expr\": \"0 18 * * *\", \"tz\": \"Asia/Shanghai\" }\n\nFor schedule.kind=\"at\", ISO timestamps without an explicit timezone are treated as UTC.\n\nPAYLOAD TYPES (payload.kind):\n- \"systemEvent\": Injects text as system event into session\n { \"kind\": \"systemEvent\", \"text\": \"<message>\" }\n- \"agentTurn\": Runs agent with message (isolated sessions only)\n { \"kind\": \"agentTurn\", \"message\": \"<prompt>\", \"model\": \"<optional>\", \"thinking\": \"<optional>\", \"timeoutSeconds\": <optional, 0 means no timeout> }\n\nDELIVERY (top-level):\n { \"mode\": \"none|announce|webhook\", \"channel\": \"<optional>\", \"to\": \"<optional>\", \"threadId\": \"<optional>\", \"bestEffort\": <optional-bool> }\n - Default for isolated agentTurn jobs (when delivery omitted): \"announce\"\n - announce: send to chat channel (optional channel/to target)\n - threadId: chat thread/topic id for channels that support threaded delivery\n - webhook: send finished-run event as HTTP POST to delivery.to (URL required)\n - If the task needs to send to a specific chat/recipient, set announce delivery.channel/to; do not call messaging tools inside the run.\n\nCRITICAL CONSTRAINTS:\n- sessionTarget=\"main\" REQUIRES payload.kind=\"systemEvent\"\n- sessionTarget=\"isolated\" | \"current\" | \"session:xxx\" REQUIRES payload.kind=\"agentTurn\"\n- For webhook callbacks, use delivery.mode=\"webhook\" with delivery.to set to a URL.\nDefault: prefer isolated agentTurn jobs unless the user explicitly wants current-session binding.\n\nWAKE MODES (for wake action):\n- \"next-heartbeat\" (default): Wake on next heartbeat\n- \"now\": Wake immediately\n\nUse jobId as the canonical identifier; id is accepted for compatibility. Use contextMessages (0-10) to add previous messages as context to the job text.",
|
||||
"description": "Manage Gateway cron jobs (status/list/add/update/remove/run/runs) and send wake events. Use this for reminders, \"check back later\" requests, delayed follow-ups, and recurring tasks. Do not emulate scheduling with exec sleep or process polling.\n\nMain-session cron jobs enqueue system events for heartbeat handling. Isolated cron jobs create background task runs that appear in `openclaw tasks`.\n\nACTIONS:\n- status: Check cron scheduler status\n- list: List jobs (use includeDisabled:true to include disabled; agentId filters by agent, auto-filled from session)\n- add: Create job (requires job object, see schema below)\n- update: Modify job (requires jobId + patch object)\n- remove: Delete job (requires jobId)\n- run: Trigger job immediately (requires jobId)\n- runs: Get job run history (requires jobId)\n- wake: Send wake event (requires text, optional mode)\n\nJOB SCHEMA (for add action):\n{\n \"name\": \"string (optional)\",\n \"schedule\": { ... }, // Required: when to run\n \"payload\": { ... }, // Required: what to execute\n \"delivery\": { ... }, // Optional: announce summary (isolated/current/session:xxx only) or webhook POST\n \"sessionTarget\": \"main\" | \"isolated\" | \"current\" | \"session:<custom-id>\", // Optional, defaults based on context\n \"enabled\": true | false // Optional, default true\n}\n\nSESSION TARGET OPTIONS:\n- \"main\": Run in the main session (requires payload.kind=\"systemEvent\")\n- \"isolated\": Run in an ephemeral isolated session (requires payload.kind=\"agentTurn\")\n- \"current\": Bind to the current session where the cron is created (resolved at creation time)\n- \"session:<custom-id>\": Run in a persistent named session (e.g., \"session:project-alpha-daily\")\n\nDEFAULT BEHAVIOR (unchanged for backward compatibility):\n- payload.kind=\"systemEvent\" → defaults to \"main\"\n- payload.kind=\"agentTurn\" → defaults to \"isolated\"\nTo use current session binding, explicitly set sessionTarget=\"current\".\n\nSCHEDULE TYPES (schedule.kind):\n- \"at\": One-shot at absolute time\n { \"kind\": \"at\", \"at\": \"<ISO-8601 timestamp>\" }\n- \"every\": Recurring interval\n { \"kind\": \"every\", \"everyMs\": <interval-ms>, \"anchorMs\": <optional-start-ms> }\n- \"cron\": Cron expression evaluated in the supplied timezone, or the Gateway host local timezone when tz is omitted\n { \"kind\": \"cron\", \"expr\": \"<cron-expression>\", \"tz\": \"<optional-IANA-timezone>\" }\n Write expr in the selected timezone's local wall-clock time; do not convert the requested local time to UTC first.\n If tz is omitted, do not assume UTC; the Gateway host local timezone is used.\n Example: \"Remind me every day at 6pm Shanghai time\" -> { \"kind\": \"cron\", \"expr\": \"0 18 * * *\", \"tz\": \"Asia/Shanghai\" }\n\nFor schedule.kind=\"at\", ISO timestamps without an explicit timezone are treated as UTC.\n\nPAYLOAD TYPES (payload.kind):\n- \"systemEvent\": Injects text as system event into session\n { \"kind\": \"systemEvent\", \"text\": \"<message>\" }\n- \"agentTurn\": Runs agent with message (isolated sessions only)\n { \"kind\": \"agentTurn\", \"message\": \"<prompt>\", \"model\": \"<optional>\", \"thinking\": \"<optional>\", \"timeoutSeconds\": <optional, 0 means no timeout> }\n\nDELIVERY (top-level):\n { \"mode\": \"none|announce|webhook\", \"channel\": \"<optional>\", \"to\": \"<optional>\", \"threadId\": \"<optional>\", \"bestEffort\": <optional-bool> }\n - Default for isolated agentTurn jobs (when delivery omitted): \"announce\"\n - announce: send to chat channel (optional channel/to target)\n - threadId: chat thread/topic id for channels that support threaded delivery\n - webhook: send finished-run event as HTTP POST to delivery.to (URL required)\n - If the task needs to send to a specific chat/recipient, set announce delivery.channel/to; do not call messaging tools inside the run.\n\nCRITICAL CONSTRAINTS:\n- sessionTarget=\"main\" REQUIRES payload.kind=\"systemEvent\"\n- sessionTarget=\"isolated\" | \"current\" | \"session:xxx\" REQUIRES payload.kind=\"agentTurn\"\n- For webhook callbacks, use delivery.mode=\"webhook\" with delivery.to set to a URL.\nDefault: prefer isolated agentTurn jobs unless the user explicitly wants current-session binding.\n\nWAKE MODES (for wake action):\n- \"next-heartbeat\" (default): Wake on next heartbeat\n- \"now\": Wake immediately\n\nUse jobId as the canonical identifier; id is accepted for compatibility. Use contextMessages (0-10) to add previous messages as context to the job text.",
|
||||
"inputSchema": {
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
@@ -208,6 +208,10 @@
|
||||
"enum": ["status", "list", "add", "update", "remove", "run", "runs", "wake"],
|
||||
"type": "string"
|
||||
},
|
||||
"agentId": {
|
||||
"description": "Filter by agent id (list action)",
|
||||
"type": "string"
|
||||
},
|
||||
"contextMessages": {
|
||||
"maximum": 10,
|
||||
"minimum": 0,
|
||||
|
||||
@@ -214,8 +214,8 @@ This is the deterministic model-bound layer stack OpenClaw can snapshot for the
|
||||
"roughTokens": 158
|
||||
},
|
||||
"dynamicToolsJson": {
|
||||
"chars": 50457,
|
||||
"roughTokens": 12615
|
||||
"chars": 50629,
|
||||
"roughTokens": 12658
|
||||
},
|
||||
"openClawDeveloperInstructions": {
|
||||
"chars": 5870,
|
||||
@@ -226,8 +226,8 @@ This is the deterministic model-bound layer stack OpenClaw can snapshot for the
|
||||
"roughTokens": 7256
|
||||
},
|
||||
"totalWithDynamicToolsJson": {
|
||||
"chars": 79481,
|
||||
"roughTokens": 19871
|
||||
"chars": 79653,
|
||||
"roughTokens": 19914
|
||||
},
|
||||
"userInputText": {
|
||||
"chars": 870,
|
||||
|
||||
@@ -214,8 +214,8 @@ This is the deterministic model-bound layer stack OpenClaw can snapshot for the
|
||||
"roughTokens": 158
|
||||
},
|
||||
"dynamicToolsJson": {
|
||||
"chars": 50148,
|
||||
"roughTokens": 12537
|
||||
"chars": 50320,
|
||||
"roughTokens": 12580
|
||||
},
|
||||
"openClawDeveloperInstructions": {
|
||||
"chars": 4999,
|
||||
@@ -226,8 +226,8 @@ This is the deterministic model-bound layer stack OpenClaw can snapshot for the
|
||||
"roughTokens": 6913
|
||||
},
|
||||
"totalWithDynamicToolsJson": {
|
||||
"chars": 77801,
|
||||
"roughTokens": 19451
|
||||
"chars": 77973,
|
||||
"roughTokens": 19494
|
||||
},
|
||||
"userInputText": {
|
||||
"chars": 370,
|
||||
|
||||
@@ -215,8 +215,8 @@ This is the deterministic model-bound layer stack OpenClaw can snapshot for the
|
||||
"roughTokens": 158
|
||||
},
|
||||
"dynamicToolsJson": {
|
||||
"chars": 51271,
|
||||
"roughTokens": 12818
|
||||
"chars": 51443,
|
||||
"roughTokens": 12861
|
||||
},
|
||||
"openClawDeveloperInstructions": {
|
||||
"chars": 4999,
|
||||
@@ -227,8 +227,8 @@ This is the deterministic model-bound layer stack OpenClaw can snapshot for the
|
||||
"roughTokens": 7693
|
||||
},
|
||||
"totalWithDynamicToolsJson": {
|
||||
"chars": 82042,
|
||||
"roughTokens": 20511
|
||||
"chars": 82214,
|
||||
"roughTokens": 20554
|
||||
},
|
||||
"userInputText": {
|
||||
"chars": 608,
|
||||
|
||||
Reference in New Issue
Block a user