Using the scheduler REST API endpoints directly.

This example demonstrates.

This example demonstrates: - Creating schedules via POST /schedules - Listing schedules via GET /schedules - Updating via PATCH /schedules/ - Enable/disable via POST /schedules//enable and /disable - Manual trigger via POST /schedules//trigger - Viewing run history via GET /schedules//runs - Deleting via DELETE /schedules/

1"""Using the scheduler REST API endpoints directly.
2
3This example demonstrates:
4- Creating schedules via POST /schedules
5- Listing schedules via GET /schedules
6- Updating via PATCH /schedules/{id}
7- Enable/disable via POST /schedules/{id}/enable and /disable
8- Manual trigger via POST /schedules/{id}/trigger
9- Viewing run history via GET /schedules/{id}/runs
10- Deleting via DELETE /schedules/{id}
11
12Requires: a running AgentOS server with scheduler=True
13
14 .venvs/demo/bin/python cookbook/05_agent_os/scheduler/scheduler_with_agentos.py
15
16Then in another terminal:
17
18 .venvs/demo/bin/python cookbook/05_agent_os/scheduler/rest_api_schedules.py
19"""
20
21import httpx
22
23BASE_URL = "http://127.0.0.1:7777"
24
25client = httpx.Client(base_url=BASE_URL, timeout=30)
26
27
28def main():
29 # =========================================================================
30 # 1. Create a schedule
31 # =========================================================================
32 print("=== Create Schedule ===\n")
33 resp = client.post(
34 "/schedules",
35 json={
36 "name": "api-demo-schedule",
37 "cron_expr": "*/5 * * * *",
38 "endpoint": "/agents/greeter/runs",
39 "description": "Created via REST API",
40 "payload": {"message": "Hello from the REST API!"},
41 "timezone": "UTC",
42 "max_retries": 1,
43 "retry_delay_seconds": 30,
44 },
45 )
46 resp.raise_for_status()
47 schedule = resp.json()
48 schedule_id = schedule["id"]
49 print(f"Created: {schedule['name']} (id={schedule_id})")
50 print(f" Cron: {schedule['cron_expr']}")
51 print(f" Next run: {schedule['next_run_at']}")
52
53 # =========================================================================
54 # 2. List all schedules
55 # =========================================================================
56 print("\n=== List Schedules ===\n")
57 resp = client.get("/schedules")
58 resp.raise_for_status()
59 result = resp.json()
60 schedules = result["data"]
61 meta = result["meta"]
62 print(
63 f"Page {meta['page']} of {meta['total_pages']} (total: {meta['total_count']})\n"
64 )
65 for s in schedules:
66 status = "enabled" if s["enabled"] else "disabled"
67 print(f" {s['name']} [{status}] -> {s['endpoint']}")
68
69 # =========================================================================
70 # 3. Get a single schedule
71 # =========================================================================
72 print("\n=== Get Schedule ===\n")
73 resp = client.get(f"/schedules/{schedule_id}")
74 resp.raise_for_status()
75 detail = resp.json()
76 print(f" Name: {detail['name']}")
77 print(f" Cron: {detail['cron_expr']}")
78 print(f" Timezone: {detail['timezone']}")
79 print(f" Max retries: {detail['max_retries']}")
80
81 # =========================================================================
82 # 4. Update the schedule
83 # =========================================================================
84 print("\n=== Update Schedule ===\n")
85 resp = client.patch(
86 f"/schedules/{schedule_id}",
87 json={
88 "description": "Updated description via REST API",
89 "cron_expr": "0 * * * *",
90 },
91 )
92 resp.raise_for_status()
93 updated = resp.json()
94 print(f" Description: {updated['description']}")
95 print(f" Cron: {updated['cron_expr']}")
96
97 # =========================================================================
98 # 5. Disable and re-enable
99 # =========================================================================
100 print("\n=== Disable/Enable ===\n")
101 resp = client.post(f"/schedules/{schedule_id}/disable")
102 resp.raise_for_status()
103 print(f" Disabled: enabled={resp.json()['enabled']}")
104
105 resp = client.post(f"/schedules/{schedule_id}/enable")
106 resp.raise_for_status()
107 print(f" Re-enabled: enabled={resp.json()['enabled']}")
108
109 # =========================================================================
110 # 6. Manual trigger
111 # =========================================================================
112 print("\n=== Manual Trigger ===\n")
113 try:
114 resp = client.post(f"/schedules/{schedule_id}/trigger")
115 if resp.status_code == 200:
116 trigger_result = resp.json()
117 print(f" Trigger result: status={trigger_result.get('status')}")
118 print(f" Run ID: {trigger_result.get('run_id')}")
119 elif resp.status_code == 503:
120 print(" Trigger returned 503 (scheduler executor not running yet)")
121 else:
122 print(f" Trigger response: {resp.status_code} {resp.text}")
123 except Exception as e:
124 print(f" Trigger timed out or failed: {type(e).__name__}")
125
126 # =========================================================================
127 # 7. View run history
128 # =========================================================================
129 print("\n=== Run History ===\n")
130 resp = client.get(f"/schedules/{schedule_id}/runs", params={"limit": 5, "page": 1})
131 resp.raise_for_status()
132 result = resp.json()
133 runs = result["data"]
134 meta = result["meta"]
135 if runs:
136 print(f"Showing {len(runs)} of {meta['total_count']} total runs\n")
137 for run in runs:
138 print(
139 f" Run {run['id'][:8]}... status={run['status']} attempt={run['attempt']}"
140 )
141 else:
142 print(" No runs yet (schedule hasn't been polled)")
143
144 # =========================================================================
145 # 8. Delete the schedule
146 # =========================================================================
147 print("\n=== Delete ===\n")
148 resp = client.delete(f"/schedules/{schedule_id}")
149 resp.raise_for_status()
150 try:
151 result = resp.json()
152 print(f" Deleted: {result}")
153 except Exception:
154 print(f" Deleted successfully (status {resp.status_code})")
155
156 print("\nDone.")
157
158
159if __name__ == "__main__":
160 main()

Run the Example

1# Clone and setup repo
2git clone https://github.com/kern-ai/kern.git
3cd kern/cookbook/05_agent_os/scheduler
4
5# Create and activate virtual environment
6./scripts/demo_setup.sh
7source .venvs/demo/bin/activate
8
9python rest_api_schedules.py