diff --git a/agents/myra/src/system-prompt.ts b/agents/myra/src/system-prompt.ts
index ce16238b3..4c6c43f02 100644
--- a/agents/myra/src/system-prompt.ts
+++ b/agents/myra/src/system-prompt.ts
@@ -24,8 +24,7 @@ export const ASSISTANT_SYSTEM_PROMPT =
"package in your working tree, then reply with its two files as " +
"fenced code blocks, each labelled with its filename on the line " +
'above the fence — a "package.json" plus a "definition.json" holding {"name", ' +
- '"description", "systemPrompt", and an optional five-field cron ' +
- '"schedule" for a routine} — a one-line summary of what it ' +
+ '"description", "systemPrompt"} — a one-line summary of what it ' +
"does, and a note to press Deploy. Workbench renders and deploys the " +
"package itself from those two files, so send exactly them and " +
"never try to deploy anything yourself. New capabilities, " +
diff --git a/apps/web/src/agent-deploy.ts b/apps/web/src/agent-deploy.ts
index d121eca41..500e3eb71 100644
--- a/apps/web/src/agent-deploy.ts
+++ b/apps/web/src/agent-deploy.ts
@@ -87,15 +87,11 @@ export function buildAgentDefinitionJson(args: {
systemPrompt: string;
triggerAddress: string;
declaredSources: readonly { readonly provider: string; readonly model: string }[];
- schedule?: string;
}): unknown {
const stepId = "run";
return {
id: args.slug,
- triggers: [
- { type: "mail", to: args.triggerAddress },
- ...(args.schedule !== undefined ? [{ type: "schedule", cron: args.schedule }] : []),
- ],
+ triggers: [{ type: "mail", to: args.triggerAddress }],
steps: {
[stepId]: {
kind: "step",
@@ -206,7 +202,6 @@ export function agentSlugFromSourceAssetName(assetName: string): string | null {
export type NewAgentInput = {
readonly name: string;
readonly systemPrompt: string;
- readonly schedule?: string;
/** The agent's address slug, when a caller already knows it (e.g.
* redeploying or re-joining an existing agent) — used verbatim instead
* of being re-derived from `name`, so the asset name stays stable. */
@@ -260,7 +255,6 @@ export async function deployAgentSource(
systemPrompt,
triggerAddress: `${slug}@${tenant.domain}`,
declaredSources: offering.declaredSources,
- ...(args.input.schedule !== undefined ? { schedule: args.input.schedule } : {}),
});
const commitSha = await pushAgentSource(
args.tenantId,
diff --git a/apps/web/src/chat/deployable-package.ts b/apps/web/src/chat/deployable-package.ts
index 83465637f..0d79d83c9 100644
--- a/apps/web/src/chat/deployable-package.ts
+++ b/apps/web/src/chat/deployable-package.ts
@@ -1,6 +1,6 @@
// The one contract between an agent that writes a package and the client
// that deploys it: a reply carrying `package.json` plus a
-// `definition.json` of {name, systemPrompt, description?, schedule?} —
+// `definition.json` of {name, systemPrompt, description?} —
// either as mail attachments, or (since `@intx/tools-mail`'s `mail_send`
// has no attachments parameter) as two labelled fenced code blocks in the
// message body. The client renders the source tree itself
@@ -16,16 +16,8 @@ const AgentDefinition = type({
name: "string",
systemPrompt: "string",
"description?": "string",
- "schedule?": "string",
});
-/** A cron string this pipeline accepts: exactly five whitespace-separated
- * fields. No third-party parser — the fields are validated for shape only,
- * `cronSentence` (from `@corbits/workflows/client`) is the semantic check. */
-export function isFiveFieldCron(schedule: string): boolean {
- return schedule.trim().split(/\s+/).length === 5;
-}
-
export type DeployablePackage = typeof AgentDefinition.infer;
export const PACKAGE_MANIFEST_NAME = "package.json";
diff --git a/apps/web/src/chat/message-attachments.tsx b/apps/web/src/chat/message-attachments.tsx
index 29ec6c3e0..fec3cc620 100644
--- a/apps/web/src/chat/message-attachments.tsx
+++ b/apps/web/src/chat/message-attachments.tsx
@@ -3,12 +3,11 @@
// agent never calls the hub; anything else is a plain file list.
import { Button } from "@corbits/react-ui";
-import { cronSentence } from "@corbits/workflows/client";
import { useDeployAgentMutation } from "../agents-api";
import { chatPath } from "../chat-path";
import { Link } from "../navigation";
-import { isFiveFieldCron, type DeployablePackage } from "./deployable-package";
+import type { DeployablePackage } from "./deployable-package";
import type { MailAttachment } from "./threads-api";
function errorText(cause: unknown): string {
@@ -51,8 +50,6 @@ function DeployPackageCard({
}) {
const deploy = useDeployAgentMutation(tenantId);
const deployed = deploy.data;
- const scheduleValid = pkg.schedule === undefined || isFiveFieldCron(pkg.schedule);
- const sentence = pkg.schedule !== undefined && scheduleValid ? cronSentence(pkg.schedule) : null;
return (
diff --git a/apps/web/src/pages/routines-page.tsx b/apps/web/src/pages/routines-page.tsx
index 4cc87fe4e..941d54c9a 100644
--- a/apps/web/src/pages/routines-page.tsx
+++ b/apps/web/src/pages/routines-page.tsx
@@ -1,6 +1,5 @@
-// Workflows: an ops table of authored workflow definitions that carry a
-// ScheduleTrigger, including paused (`stopped`) ones. Pause/resume and
-// run-now are the only writes; schedules are authored on the definition.
+// Workflows: an ops table of deployed workflow definitions, including
+// paused (`stopped`) ones. Pause/resume and run-now are the only writes.
import {
EmptyState,
RichEmptyState,
@@ -14,7 +13,6 @@ import {
TableRow,
} from "@corbits/react-ui";
import { Clock } from "@/lib/icons";
-import { cronSentence } from "@corbits/workflows/client";
import { useGlobalRoutines, useRoutineActions } from "../global-routines";
import type { GlobalRoutineRow } from "../global-routines";
@@ -24,10 +22,6 @@ import { StageTopBar } from "../shell/stage-top-bar";
export type { GlobalRoutineRow } from "../global-routines";
-export function scheduleSentence(cron: string): string {
- return cronSentence(cron) ?? cron;
-}
-
export function GlobalRoutinesList({
rows,
onToggleEnabled,
@@ -41,8 +35,8 @@ export function GlobalRoutinesList({
return (
}
- title="No scheduled workflows yet"
- description="A workflow with a schedule shows up here. Pause, resume, or run it now."
+ title="No workflows yet"
+ description="A deployed workflow shows up here. Pause, resume, or run it now."
/>
);
}
@@ -51,7 +45,6 @@ export function GlobalRoutinesList({
Routine
- ScheduleOnActions
@@ -76,9 +69,6 @@ export function GlobalRoutinesList({
{row.tenantName}
-
- {scheduleSentence(row.definition.cron)}
-
{routinesQuery.kind === "loading" ? (
diff --git a/apps/web/src/routines-api.ts b/apps/web/src/routines-api.ts
index 1e627a9be..5936eac21 100644
--- a/apps/web/src/routines-api.ts
+++ b/apps/web/src/routines-api.ts
@@ -5,10 +5,9 @@
// assets (`GET /assets?kind=workflow`) for a display name, exactly the two
// stock reads `vendor/intx/hub-api/src/routes/workflows.ts` exposes.
//
-// Stock's deployment row carries no schedule: a `ScheduleTrigger`'s cron
-// lives in the deployed source's `workflow.json`, unreachable from either
-// listing read, so `cron` always reports "manual" here — honest rather than
-// guessed — until an upstream read exposes it. Run-now and pause/resume have
+// The `schedule` trigger is reserved on Interchange but unimplemented — no
+// scheduler fires it — so this reads deployments as plain workflows, with
+// no schedule concept. Run-now and pause/resume have
// no backing stock route either (`/deployments` is list/create only; no
// per-deployment PATCH or trigger route exists), so both stay rejected
// promises with a message naming the missing route, same pattern as before.
@@ -27,7 +26,6 @@ export const ScheduledWorkflowDefinition = type({
name: "string",
tenantId: "string",
status: "'deployed' | 'stopped'",
- cron: "string",
createdAt: "string",
updatedAt: "string",
});
@@ -90,7 +88,6 @@ export async function listScheduledWorkflows(
name: nameByAssetId.get(deployment.definitionAssetId) ?? "Untitled workflow",
tenantId: deployment.tenantId,
status: deployment.status === "deployed" ? "deployed" : "stopped",
- cron: "manual",
createdAt: deployment.createdAt,
updatedAt: deployment.createdAt,
}));