Skip to content

Add cron job support #310

@bracesproul

Description

@bracesproul

We should support users creating cron jobs via the UI. We should expose a cron job button/icon on the card of every agent that allows a user to both view all of their existing cron jobs on that agent, and create a new cron job for that agent.
The cron job dialog UI should list all of the crons a user has, and allow them to inspect their input and schedule. It should also allow them to edit and delete them. (maybe show a data table for this? if so, please use the existing data table component)

Somewhere in that dialog, there should be a way to create a new cron job.
We should allow users to set:

  • cron job name
  • schedule
  • input message

ensure these cron jobs which are kicked off will call the specific agent they were added to (agent = assistant)

do not allow crons to be added to default assistants

IMPORTANT: Ensure you set the owner field inside the metadata of the cron to the user's ID (supabase user ID)

Here is the documentation on crons in LangGraph: https://langchain-ai.github.io/langgraphjs/cloud/how-tos/cron_jobs/

Context: an agent in Open Agent Platform is the same as an assistant in LangGraph

Agent Context { "tasks": [ { "id": "14f2504a-43bb-4658-a4c1-652001bb5e86", "taskIndex": 0, "request": "[original issue]\n**Add cron job support**\nWe should support users creating cron jobs via the UI. We should expose a cron job button/icon on the card of every agent that allows a user to both view all of their existing cron jobs on that agent, and create a new cron job for that agent.\nThe cron job dialog UI should list all of the crons a user has, and allow them to inspect their input and schedule. It should also allow them to edit and delete them. (maybe show a data table for this? if so, please use the existing data table component)\n\nSomewhere in that dialog, there should be a way to create a new cron job.\nWe should allow users to set:\n- cron job name\n- schedule\n- input message\n\nensure these cron jobs which are kicked off will call the specific agent they were added to (agent = assistant)\n\ndo not allow crons to be added to default assistants\n\nIMPORTANT: Ensure you set the `owner` field inside the metadata of the cron to the user's ID (supabase user ID)\n\nHere is the documentation on crons in LangGraph: https://langchain-ai.github.io/langgraphjs/cloud/how-tos/cron_jobs/\n\nContext: an agent in Open Agent Platform is the same as an assistant in LangGraph", "title": "Add cron job support to Open Agent Platform with UI for creating, viewing, editing, and deleting cron jobs on agents", "createdAt": 1754010518754, "completed": true, "planRevisions": [ { "revisionIndex": 0, "plans": [ { "index": 0, "plan": "**Create TypeScript types and interfaces for cron jobs**\n- Create `apps/web/src/types/cron.ts` with interfaces for Cron, CronInput, and CronMetadata\n- Ensure CronMetadata includes an `owner` field for the Supabase user ID\n- Define types that align with the LangGraph SDK cron API structure", "completed": true, "summary": "Created TypeScript types and interfaces for cron jobs in `apps/web/src/types/cron.ts`. The file defines:\n\n1. **CronMetadata** - Includes required `owner` field (Supabase user ID) and optional `name` field\n2. **CronInput** - Structure for creating/updating crons with schedule, input messages, and metadata\n3. **Cron** - Complete cron object with all fields returned by the API including cron_id, assistant_id, timestamps\n4. **CreateCronFormData** - User-friendly form data structure with name, schedule, and inputMessage fields\n5. **UpdateCronInput** - Partial input for updating existing crons\n\nAll interfaces align with the LangGraph SDK cron API structure and support the required functionality for creating, viewing, editing, and deleting cron jobs." }, { "index": 1, "plan": "**Create a custom hook for cron job API operations**\n- Create `apps/web/src/hooks/use-crons.tsx` that uses the LangGraph SDK client\n- Implement functions: `listCrons(assistantId)`, `createCron(assistantId, input)`, `updateCron(cronId, input)`, `deleteCron(cronId)`\n- Use `useAuthContext()` to get the user ID and set it in the cron metadata.owner field\n- Handle authentication by passing the session token to `createClient()`", "completed": true, "summary": "Created a custom hook `use-crons.tsx` in `apps/web/src/hooks/` that provides comprehensive cron job API operations:\n\n1. **listCrons(assistantId, deploymentId)** - Fetches all crons and filters by assistant_id and owner (user ID)\n2. **createCron(assistantId, deploymentId, formData)** - Creates new cron with user ID in metadata.owner\n3. **updateCron(cronId, deploymentId, assistantId, formData)** - Updates existing cron while preserving ownership\n4. **deleteCron(cronId, deploymentId, assistantId)** - Deletes cron and refreshes the list\n\nThe hook:\n- Uses `useAuthContext()` to access user ID and session token\n- Authenticates API calls by passing session.access_token to `createClient()`\n- Manages loading states and cron list state\n- Provides error handling with toast notifications\n- Automatically refreshes cron list after mutations\n- Ensures all crons are properly owned by the creating user" }, { "index": 2, "plan": "**Add cron button to agent card component**\n- Modify `apps/web/src/features/agents/components/agent-card.tsx`\n- Import Clock icon from lucide-react\n- Add a cron button next to the Edit button in CardFooter (only show if `!isDefaultAgent`)\n- Add state management for showing the cron dialog\n- Pass agent data to the cron dialog component", "completed": true, "summary": "Successfully added cron button to the agent card component:\n\n1. Modified `apps/web/src/features/agents/components/agent-card.tsx` to add cron functionality\n2. Imported `Clock` icon from lucide-react \n3. Added `showCronDialog` state management using `useState(false)`\n4. Added \"Crons\" button with Clock icon next to the Edit button in CardFooter\n - Button only shows for non-default agents (`!isDefaultAgent`)\n - Wrapped both Edit and Crons buttons in a flex container for proper spacing\n5. Added `CronDialog` component at the end of the component, passing:\n - `agent` prop with the agent data\n - `open` prop with `showCronDialog` state\n - `onOpenChange` prop to control dialog visibility\n6. Added import for `CronDialog` from `@/features/crons/components/cron-dialog`\n\nThe cron button is now integrated into the agent card UI and will open the cron dialog when clicked." }, { "index": 3, "plan": "**Create cron dialog component with table view**\n- Create `apps/web/src/features/crons/components/cron-dialog.tsx`\n- Use AlertDialog components for the modal structure\n- Implement a table using the existing Table components from `@/components/ui/table`\n- Display columns: Name, Schedule, Input Message, Actions (Edit/Delete)\n- Add a \"Create New Cron Job\" button above the table\n- Use the `use-crons` hook to fetch and display crons for the specific agent", "completed": true, "summary": "Created the cron dialog component with table view in `apps/web/src/features/crons/components/cron-dialog.tsx`:\n\n1. **Dialog Structure**: Used AlertDialog components for modal with proper header and title\n2. **Table Implementation**: \n - Used existing Table components from `@/components/ui/table`\n - Displays columns: Name, Schedule, Input Message, Actions\n - Shows cron name from metadata or \"Unnamed\" as fallback\n - Displays both raw cron expression and human-readable format\n - Shows first user message as input message\n3. **Create Button**: Added \"Create New Cron Job\" button above the table with Plus icon\n4. **Data Fetching**: \n - Uses `useCrons` hook to fetch crons when dialog opens\n - Filters crons by assistant_id and user ownership\n - Includes loading state with spinner\n5. **UI States**:\n - Loading state with animated spinner\n - Empty state with helpful message\n - Table view when crons exist\n6. **Action Buttons**: Added Edit and Delete buttons for each row (functionality to be implemented in task 5)\n7. **Helper Functions**:\n - `getInputMessage()` - Extracts user message from cron input\n - `formatSchedule()` - Converts common cron patterns to readable descriptions\n8. **Placeholder**: Added temporary placeholder for form component (to be implemented in task 4)" }, { "index": 4, "plan": "**Create form component for creating/editing cron jobs**\n- Create `apps/web/src/features/crons/components/cron-form.tsx`\n- Use react-hook-form with FormProvider pattern\n- Add form fields: name (Input), schedule (Input with helper text for cron syntax), input message (Textarea)\n- Implement validation to ensure all fields are filled\n- Handle both create and edit modes by accepting optional initial values\n- Show the form in a nested dialog or replace the table view when creating/editing", "completed": true, "summary": "Created form component for creating/editing cron jobs:\n\n1. **Created `cron-form.tsx`** in `apps/web/src/features/crons/components/`\n - Uses react-hook-form with FormProvider pattern\n - Accepts agent, optional cron (for editing), onSuccess, and onCancel props\n\n2. **Form Fields**:\n - **Name**: Input field with required indicator and placeholder\n - **Schedule**: Input field with cron expression format\n - Helper text explaining the format (minute hour day month weekday)\n - Examples of common cron expressions\n - Link to external cron expression builder\n - **Input Message**: Textarea for the message sent to the agent\n\n3. **Validation**:\n - All fields are required with trim() validation\n - Cron expression format validation (must have 5 parts)\n - Toast notifications for validation errors\n\n4. **Dual Mode Support**:\n - Create mode: Empty form that calls `createCron`\n - Edit mode: Pre-fills form with existing cron data and calls `updateCron`\n - useEffect hook to reset form when cron prop changes\n\n5. **Integration**:\n - Updated `cron-dialog.tsx` to import and use CronForm\n - Shows form in a bordered section below the table\n - Passes appropriate callbacks to hide form on success/cancel\n - Dynamic heading: \"Create New Cron Job\" or \"Edit Cron Job\"\n\n6. **User Experience**:\n - Loading states with disabled inputs and spinner in submit button\n - Clear Cancel and Create/Update buttons\n - Form resets after successful creation\n - Automatic cron list refresh via the useCrons hook" }, { "index": 5, "plan": "**Implement edit and delete functionality in the cron table**\n- Add action buttons (Edit, Delete) to each row in the cron table\n- For edit: open the cron form with pre-filled values\n- For delete: show a confirmation dialog using AlertDialog\n- Use toast notifications for success/error feedback\n- Refresh the cron list after successful operations", "completed": true, "summary": "Implemented edit and delete functionality in the cron table:\n\n1. **Action Buttons**: \n - Added Edit and Delete icon buttons to each row in the cron table\n - Buttons use ghost variant and icon size for consistent UI\n\n2. **Edit Functionality**:\n - Edit button click sets `editingCron` state with the selected cron\n - This triggers the CronForm to show with pre-filled values (name, schedule, input message)\n - Form handles update mode by calling `updateCron` from the `useCrons` hook\n - After successful update, form closes and list refreshes automatically\n\n3. **Delete Functionality**:\n - Delete button click sets `deletingCron` state with the selected cron\n - Shows a confirmation AlertDialog with:\n - Warning title: \"Are you absolutely sure?\"\n - Description showing the cron name that will be deleted\n - Cancel and Delete action buttons\n - Delete button styled with destructive variant (red)\n - Calls `deleteCron` from the `useCrons` hook on confirmation\n - After successful deletion, dialog closes and list refreshes\n\n4. **Toast Notifications**:\n - Success messages: \"Cron job updated successfully\", \"Cron job deleted successfully\"\n - Error messages: \"Failed to update cron job\", \"Failed to delete cron job\"\n - All handled in the `useCrons` hook\n\n5. **Automatic Refresh**:\n - Both `updateCron` and `deleteCron` in the hook call `listCrons` after successful operations\n - Ensures the table always shows the latest data without manual refresh" }, { "index": 6, "plan": "**Format code and fix linting issues**\n- Run `yarn format` to format all modified files with Prettier\n- Run `yarn lint:fix` to fix any ESLint issues\n- Ensure no console.log statements are used (use console.warn or console.error instead)", "completed": true, "summary": "Formatted code and fixed linting issues:\n\n1. **Ran `yarn format`**:\n - Successfully formatted all files with Prettier\n - Only one file was modified: `src/hooks/use-crons.tsx`\n - All other files were already properly formatted\n\n2. **Ran `yarn lint:fix`**:\n - Successfully executed with no errors\n - Only warnings were found, which are acceptable:\n - Fast refresh warnings for exported constants (standard in Next.js)\n - React hooks dependency warnings (often intentional omissions)\n - No actual linting errors that needed fixing\n\n3. **Verified no console.log statements**:\n - Checked all cron-related files created or modified\n - No console.log statements found in:\n - `apps/web/src/types/cron.ts`\n - `apps/web/src/hooks/use-crons.tsx`\n - `apps/web/src/features/agents/components/agent-card.tsx`\n - `apps/web/src/features/crons/components/cron-dialog.tsx`\n - `apps/web/src/features/crons/components/cron-form.tsx`\n - All logging uses console.error or console.warn as required\n\nThe cron job implementation is now complete with properly formatted and linted code that follows the project's coding standards." } ], "createdAt": 1754010518754, "createdBy": "agent" } ], "activeRevisionIndex": 0, "pullRequestNumber": 312, "completedAt": 1754011354948, "summary": "Cron job support has been fully implemented: added a cron button on non-default agent cards; created a dialog listing user crons with edit/delete actions; built a form for creating/editing crons with validation; ensured cron metadata includes the user’s Supabase ID as owner; integrated with LangGraph SDK; included confirmation dialogs and toast notifications; and completed code formatting and linting with no console.log statements. All changes follow project structure and UI patterns." }, { "id": "c031c291-69fb-4b14-a818-1658a7bd751e", "taskIndex": 1, "request": "there's a build error (you're trying to access \"access_token\" instead of \"accessToken\")\n\nPlease fix that\nAlso, I'm not a big fan of the styling. Can you improve it? It seems a little compact right now", "title": "Fix access_token error and improve cron dialog styling", "createdAt": 1754013214786, "completed": false, "planRevisions": [ { "revisionIndex": 0, "plans": [ { "index": 0, "plan": "**Fix the access_token error in the cron hook**\n- In `apps/web/src/hooks/use-crons.tsx`, change all instances of `session.access_token` to `session.accessToken` to match the Session interface definition in `/apps/web/src/lib/auth/types.ts`\n- The createClient function expects `accessToken` as the parameter name, so ensure it's passed correctly", "completed": false }, { "index": 1, "plan": "**Improve dialog and table spacing for better visual appearance**\n- In `apps/web/src/features/crons/components/cron-dialog.tsx`:\n - Change AlertDialogContent className from `gap-4` to `gap-6` for more vertical spacing\n - Add `space-y-6` between the header and table sections\n - Update table cells from `p-2` to `p-4` for more spacious feel\n - Add `gap-2` to action button containers for better icon spacing\n - Increase the dialog max width from `sm:max-w-lg` to `sm:max-w-2xl` for better table display", "completed": false }, { "index": 2, "plan": "**Enhance form field spacing and visual hierarchy**\n- In `apps/web/src/features/crons/components/cron-form.tsx`:\n - Change form field spacing from `space-y-4` to `space-y-6`\n - Add `mt-2` to helper text elements for better separation\n - Update button container spacing to use `gap-3` instead of `gap-2`\n - Add visual separator (border) between form sections if the form is shown inline with the table", "completed": false }, { "index": 3, "plan": "**Run code formatting and linting**\n- Execute `yarn format` to format all modified files with Prettier\n- Execute `yarn lint:fix` to fix any ESLint issues\n- Verify no console.log statements are present in the cron-related files", "completed": false } ], "createdAt": 1754013214786, "createdBy": "agent" } ], "activeRevisionIndex": 0 } ], "activeTaskIndex": 1 }

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions