langgraph-sdk 0.3.3__tar.gz → 0.3.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/PKG-INFO +2 -2
  2. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/langgraph_sdk/__init__.py +1 -1
  3. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/langgraph_sdk/client.py +184 -4
  4. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/langgraph_sdk/schema.py +30 -0
  5. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/pyproject.toml +2 -2
  6. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/tests/test_crons_client.py +209 -0
  7. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/uv.lock +235 -239
  8. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/.gitignore +0 -0
  9. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/LICENSE +0 -0
  10. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/Makefile +0 -0
  11. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/README.md +0 -0
  12. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/langgraph_sdk/auth/__init__.py +0 -0
  13. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/langgraph_sdk/auth/exceptions.py +0 -0
  14. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/langgraph_sdk/auth/types.py +0 -0
  15. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/langgraph_sdk/encryption/__init__.py +0 -0
  16. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/langgraph_sdk/encryption/types.py +0 -0
  17. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/langgraph_sdk/errors.py +0 -0
  18. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/langgraph_sdk/py.typed +0 -0
  19. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/langgraph_sdk/sse.py +0 -0
  20. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/tests/fixtures/response.txt +0 -0
  21. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/tests/test_api_parity.py +0 -0
  22. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/tests/test_assistants_client.py +0 -0
  23. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/tests/test_client_stream.py +0 -0
  24. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/tests/test_encryption.py +0 -0
  25. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/tests/test_errors.py +0 -0
  26. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/tests/test_serde.py +0 -0
  27. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/tests/test_serde_schema.py +0 -0
  28. {langgraph_sdk-0.3.3 → langgraph_sdk-0.3.4}/tests/test_skip_auto_load_api_key.py +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langgraph-sdk
3
- Version: 0.3.3
3
+ Version: 0.3.4
4
4
  Summary: SDK for interacting with LangGraph API
5
5
  Project-URL: Source, https://github.com/langchain-ai/langgraph/tree/main/libs/sdk-py
6
- Project-URL: Twitter, https://x.com/LangChainAI
6
+ Project-URL: Twitter, https://x.com/LangChain
7
7
  Project-URL: Slack, https://www.langchain.com/join-community
8
8
  Project-URL: Reddit, https://www.reddit.com/r/LangChain/
9
9
  License-Expression: MIT
@@ -3,6 +3,6 @@ from langgraph_sdk.client import get_client, get_sync_client
3
3
  from langgraph_sdk.encryption import Encryption
4
4
  from langgraph_sdk.encryption.types import EncryptionContext
5
5
 
6
- __version__ = "0.3.3"
6
+ __version__ = "0.3.4"
7
7
 
8
8
  __all__ = ["Auth", "Encryption", "EncryptionContext", "get_client", "get_sync_client"]
@@ -2984,6 +2984,7 @@ class CronClient:
2984
2984
  webhook: str | None = None,
2985
2985
  multitask_strategy: str | None = None,
2986
2986
  end_time: datetime | None = None,
2987
+ enabled: bool | None = None,
2987
2988
  headers: Mapping[str, str] | None = None,
2988
2989
  params: QueryParamTypes | None = None,
2989
2990
  ) -> Run:
@@ -2994,6 +2995,7 @@ class CronClient:
2994
2995
  assistant_id: The assistant ID or graph name to use for the cron job.
2995
2996
  If using graph name, will default to first assistant created from that graph.
2996
2997
  schedule: The cron schedule to execute this job on.
2998
+ Schedules are interpreted in UTC.
2997
2999
  input: The input to the graph.
2998
3000
  metadata: Metadata to assign to the cron job runs.
2999
3001
  config: The configuration for the assistant.
@@ -3008,6 +3010,7 @@ class CronClient:
3008
3010
  multitask_strategy: Multitask strategy to use.
3009
3011
  Must be one of 'reject', 'interrupt', 'rollback', or 'enqueue'.
3010
3012
  end_time: The time to stop running the cron job. If not provided, the cron job will run indefinitely.
3013
+ enabled: Whether the cron job is enabled or not.
3011
3014
  headers: Optional custom headers to include with the request.
3012
3015
  params: Optional query parameters to include with the request.
3013
3016
 
@@ -3028,7 +3031,8 @@ class CronClient:
3028
3031
  interrupt_before=["node_to_stop_before_1","node_to_stop_before_2"],
3029
3032
  interrupt_after=["node_to_stop_after_1","node_to_stop_after_2"],
3030
3033
  webhook="https://my.fake.webhook.com",
3031
- multitask_strategy="interrupt"
3034
+ multitask_strategy="interrupt",
3035
+ enabled=True,
3032
3036
  )
3033
3037
  ```
3034
3038
  """
@@ -3044,6 +3048,7 @@ class CronClient:
3044
3048
  "interrupt_after": interrupt_after,
3045
3049
  "webhook": webhook,
3046
3050
  "end_time": end_time.isoformat() if end_time else None,
3051
+ "enabled": enabled,
3047
3052
  }
3048
3053
  if multitask_strategy:
3049
3054
  payload["multitask_strategy"] = multitask_strategy
@@ -3071,6 +3076,7 @@ class CronClient:
3071
3076
  on_run_completed: OnCompletionBehavior | None = None,
3072
3077
  multitask_strategy: str | None = None,
3073
3078
  end_time: datetime | None = None,
3079
+ enabled: bool | None = None,
3074
3080
  headers: Mapping[str, str] | None = None,
3075
3081
  params: QueryParamTypes | None = None,
3076
3082
  ) -> Run:
@@ -3080,6 +3086,7 @@ class CronClient:
3080
3086
  assistant_id: The assistant ID or graph name to use for the cron job.
3081
3087
  If using graph name, will default to first assistant created from that graph.
3082
3088
  schedule: The cron schedule to execute this job on.
3089
+ Schedules are interpreted in UTC.
3083
3090
  input: The input to the graph.
3084
3091
  metadata: Metadata to assign to the cron job runs.
3085
3092
  config: The configuration for the assistant.
@@ -3096,6 +3103,7 @@ class CronClient:
3096
3103
  multitask_strategy: Multitask strategy to use.
3097
3104
  Must be one of 'reject', 'interrupt', 'rollback', or 'enqueue'.
3098
3105
  end_time: The time to stop running the cron job. If not provided, the cron job will run indefinitely.
3106
+ enabled: Whether the cron job is enabled or not.
3099
3107
  headers: Optional custom headers to include with the request.
3100
3108
  params: Optional query parameters to include with the request.
3101
3109
 
@@ -3115,7 +3123,8 @@ class CronClient:
3115
3123
  interrupt_before=["node_to_stop_before_1","node_to_stop_before_2"],
3116
3124
  interrupt_after=["node_to_stop_after_1","node_to_stop_after_2"],
3117
3125
  webhook="https://my.fake.webhook.com",
3118
- multitask_strategy="interrupt"
3126
+ multitask_strategy="interrupt",
3127
+ enabled=True,
3119
3128
  )
3120
3129
  ```
3121
3130
 
@@ -3133,6 +3142,7 @@ class CronClient:
3133
3142
  "webhook": webhook,
3134
3143
  "on_run_completed": on_run_completed,
3135
3144
  "end_time": end_time.isoformat() if end_time else None,
3145
+ "enabled": enabled,
3136
3146
  }
3137
3147
  if multitask_strategy:
3138
3148
  payload["multitask_strategy"] = multitask_strategy
@@ -3170,11 +3180,88 @@ class CronClient:
3170
3180
  """
3171
3181
  await self.http.delete(f"/runs/crons/{cron_id}", headers=headers, params=params)
3172
3182
 
3183
+ async def update(
3184
+ self,
3185
+ cron_id: str,
3186
+ *,
3187
+ schedule: str | None = None,
3188
+ end_time: datetime | None = None,
3189
+ input: Input | None = None,
3190
+ metadata: Mapping[str, Any] | None = None,
3191
+ config: Config | None = None,
3192
+ context: Context | None = None,
3193
+ webhook: str | None = None,
3194
+ interrupt_before: All | list[str] | None = None,
3195
+ interrupt_after: All | list[str] | None = None,
3196
+ on_run_completed: OnCompletionBehavior | None = None,
3197
+ enabled: bool | None = None,
3198
+ headers: Mapping[str, str] | None = None,
3199
+ params: QueryParamTypes | None = None,
3200
+ ) -> Cron:
3201
+ """Update a cron job by ID.
3202
+
3203
+ Args:
3204
+ cron_id: The cron ID to update.
3205
+ schedule: The cron schedule to execute this job on.
3206
+ Schedules are interpreted in UTC.
3207
+ end_time: The end date to stop running the cron.
3208
+ input: The input to the graph.
3209
+ metadata: Metadata to assign to the cron job runs.
3210
+ config: The configuration for the assistant.
3211
+ context: Static context added to the assistant.
3212
+ webhook: Webhook to call after LangGraph API call is done.
3213
+ interrupt_before: Nodes to interrupt immediately before they get executed.
3214
+ interrupt_after: Nodes to interrupt immediately after they get executed.
3215
+ on_run_completed: What to do with the thread after the run completes.
3216
+ Must be one of 'delete' or 'keep'. 'delete' removes the thread
3217
+ after execution. 'keep' creates a new thread for each execution but does not
3218
+ clean them up.
3219
+ enabled: Enable or disable the cron job.
3220
+ headers: Optional custom headers to include with the request.
3221
+ params: Optional query parameters to include with the request.
3222
+
3223
+ Returns:
3224
+ The updated cron job.
3225
+
3226
+ ???+ example "Example Usage"
3227
+
3228
+ ```python
3229
+ client = get_client(url="http://localhost:2024")
3230
+ updated_cron = await client.crons.update(
3231
+ cron_id="1ef3cefa-4c09-6926-96d0-3dc97fd5e39b",
3232
+ schedule="0 10 * * *",
3233
+ enabled=False,
3234
+ )
3235
+ ```
3236
+
3237
+ """
3238
+ payload = {
3239
+ "schedule": schedule,
3240
+ "end_time": end_time.isoformat() if end_time else None,
3241
+ "input": input,
3242
+ "metadata": metadata,
3243
+ "config": config,
3244
+ "context": context,
3245
+ "webhook": webhook,
3246
+ "interrupt_before": interrupt_before,
3247
+ "interrupt_after": interrupt_after,
3248
+ "on_run_completed": on_run_completed,
3249
+ "enabled": enabled,
3250
+ }
3251
+ payload = {k: v for k, v in payload.items() if v is not None}
3252
+ return await self.http.patch(
3253
+ f"/runs/crons/{cron_id}",
3254
+ json=payload,
3255
+ headers=headers,
3256
+ params=params,
3257
+ )
3258
+
3173
3259
  async def search(
3174
3260
  self,
3175
3261
  *,
3176
3262
  assistant_id: str | None = None,
3177
3263
  thread_id: str | None = None,
3264
+ enabled: bool | None = None,
3178
3265
  limit: int = 10,
3179
3266
  offset: int = 0,
3180
3267
  sort_by: CronSortBy | None = None,
@@ -3188,6 +3275,7 @@ class CronClient:
3188
3275
  Args:
3189
3276
  assistant_id: The assistant ID or graph name to search for.
3190
3277
  thread_id: the thread ID to search for.
3278
+ enabled: The enabled status to search for.
3191
3279
  limit: The maximum number of results to return.
3192
3280
  offset: The number of results to skip.
3193
3281
  headers: Optional custom headers to include with the request.
@@ -3203,6 +3291,7 @@ class CronClient:
3203
3291
  cron_jobs = await client.crons.search(
3204
3292
  assistant_id="my_assistant_id",
3205
3293
  thread_id="my_thread_id",
3294
+ enabled=True,
3206
3295
  limit=5,
3207
3296
  offset=5,
3208
3297
  )
@@ -3237,6 +3326,7 @@ class CronClient:
3237
3326
  payload = {
3238
3327
  "assistant_id": assistant_id,
3239
3328
  "thread_id": thread_id,
3329
+ "enabled": enabled,
3240
3330
  "limit": limit,
3241
3331
  "offset": offset,
3242
3332
  }
@@ -6292,6 +6382,7 @@ class SyncCronClient:
6292
6382
  webhook: str | None = None,
6293
6383
  multitask_strategy: str | None = None,
6294
6384
  end_time: datetime | None = None,
6385
+ enabled: bool | None = None,
6295
6386
  headers: Mapping[str, str] | None = None,
6296
6387
  params: QueryParamTypes | None = None,
6297
6388
  ) -> Run:
@@ -6302,6 +6393,7 @@ class SyncCronClient:
6302
6393
  assistant_id: The assistant ID or graph name to use for the cron job.
6303
6394
  If using graph name, will default to first assistant created from that graph.
6304
6395
  schedule: The cron schedule to execute this job on.
6396
+ Schedules are interpreted in UTC.
6305
6397
  input: The input to the graph.
6306
6398
  metadata: Metadata to assign to the cron job runs.
6307
6399
  config: The configuration for the assistant.
@@ -6314,6 +6406,7 @@ class SyncCronClient:
6314
6406
  multitask_strategy: Multitask strategy to use.
6315
6407
  Must be one of 'reject', 'interrupt', 'rollback', or 'enqueue'.
6316
6408
  end_time: The time to stop running the cron job. If not provided, the cron job will run indefinitely.
6409
+ enabled: Whether the cron job is enabled. By default, it is considered enabled.
6317
6410
  headers: Optional custom headers to include with the request.
6318
6411
 
6319
6412
  Returns:
@@ -6333,7 +6426,8 @@ class SyncCronClient:
6333
6426
  interrupt_before=["node_to_stop_before_1","node_to_stop_before_2"],
6334
6427
  interrupt_after=["node_to_stop_after_1","node_to_stop_after_2"],
6335
6428
  webhook="https://my.fake.webhook.com",
6336
- multitask_strategy="interrupt"
6429
+ multitask_strategy="interrupt",
6430
+ enabled=True
6337
6431
  )
6338
6432
  ```
6339
6433
  """
@@ -6350,6 +6444,7 @@ class SyncCronClient:
6350
6444
  "webhook": webhook,
6351
6445
  "multitask_strategy": multitask_strategy,
6352
6446
  "end_time": end_time.isoformat() if end_time else None,
6447
+ "enabled": enabled,
6353
6448
  }
6354
6449
  payload = {k: v for k, v in payload.items() if v is not None}
6355
6450
  return self.http.post(
@@ -6375,6 +6470,7 @@ class SyncCronClient:
6375
6470
  on_run_completed: OnCompletionBehavior | None = None,
6376
6471
  multitask_strategy: str | None = None,
6377
6472
  end_time: datetime | None = None,
6473
+ enabled: bool | None = None,
6378
6474
  headers: Mapping[str, str] | None = None,
6379
6475
  params: QueryParamTypes | None = None,
6380
6476
  ) -> Run:
@@ -6384,6 +6480,7 @@ class SyncCronClient:
6384
6480
  assistant_id: The assistant ID or graph name to use for the cron job.
6385
6481
  If using graph name, will default to first assistant created from that graph.
6386
6482
  schedule: The cron schedule to execute this job on.
6483
+ Schedules are interpreted in UTC.
6387
6484
  input: The input to the graph.
6388
6485
  metadata: Metadata to assign to the cron job runs.
6389
6486
  config: The configuration for the assistant.
@@ -6400,6 +6497,7 @@ class SyncCronClient:
6400
6497
  multitask_strategy: Multitask strategy to use.
6401
6498
  Must be one of 'reject', 'interrupt', 'rollback', or 'enqueue'.
6402
6499
  end_time: The time to stop running the cron job. If not provided, the cron job will run indefinitely.
6500
+ enabled: Whether the cron job is enabled. By default, it is considered enabled.
6403
6501
  headers: Optional custom headers to include with the request.
6404
6502
 
6405
6503
  Returns:
@@ -6419,7 +6517,8 @@ class SyncCronClient:
6419
6517
  interrupt_before=["node_to_stop_before_1","node_to_stop_before_2"],
6420
6518
  interrupt_after=["node_to_stop_after_1","node_to_stop_after_2"],
6421
6519
  webhook="https://my.fake.webhook.com",
6422
- multitask_strategy="interrupt"
6520
+ multitask_strategy="interrupt",
6521
+ enabled=True
6423
6522
  )
6424
6523
  ```
6425
6524
 
@@ -6438,6 +6537,7 @@ class SyncCronClient:
6438
6537
  "on_run_completed": on_run_completed,
6439
6538
  "multitask_strategy": multitask_strategy,
6440
6539
  "end_time": end_time.isoformat() if end_time else None,
6540
+ "enabled": enabled,
6441
6541
  }
6442
6542
  payload = {k: v for k, v in payload.items() if v is not None}
6443
6543
  return self.http.post(
@@ -6473,11 +6573,88 @@ class SyncCronClient:
6473
6573
  """
6474
6574
  self.http.delete(f"/runs/crons/{cron_id}", headers=headers, params=params)
6475
6575
 
6576
+ def update(
6577
+ self,
6578
+ cron_id: str,
6579
+ *,
6580
+ schedule: str | None = None,
6581
+ end_time: datetime | None = None,
6582
+ input: Input | None = None,
6583
+ metadata: Mapping[str, Any] | None = None,
6584
+ config: Config | None = None,
6585
+ context: Context | None = None,
6586
+ webhook: str | None = None,
6587
+ interrupt_before: All | list[str] | None = None,
6588
+ interrupt_after: All | list[str] | None = None,
6589
+ on_run_completed: OnCompletionBehavior | None = None,
6590
+ enabled: bool | None = None,
6591
+ headers: Mapping[str, str] | None = None,
6592
+ params: QueryParamTypes | None = None,
6593
+ ) -> Cron:
6594
+ """Update a cron job by ID.
6595
+
6596
+ Args:
6597
+ cron_id: The cron ID to update.
6598
+ schedule: The cron schedule to execute this job on.
6599
+ Schedules are interpreted in UTC.
6600
+ end_time: The end date to stop running the cron.
6601
+ input: The input to the graph.
6602
+ metadata: Metadata to assign to the cron job runs.
6603
+ config: The configuration for the assistant.
6604
+ context: Static context added to the assistant.
6605
+ webhook: Webhook to call after LangGraph API call is done.
6606
+ interrupt_before: Nodes to interrupt immediately before they get executed.
6607
+ interrupt_after: Nodes to interrupt immediately after they get executed.
6608
+ on_run_completed: What to do with the thread after the run completes.
6609
+ Must be one of 'delete' or 'keep'. 'delete' removes the thread
6610
+ after execution. 'keep' creates a new thread for each execution but does not
6611
+ clean them up.
6612
+ enabled: Enable or disable the cron job.
6613
+ headers: Optional custom headers to include with the request.
6614
+ params: Optional query parameters to include with the request.
6615
+
6616
+ Returns:
6617
+ The updated cron job.
6618
+
6619
+ ???+ example "Example Usage"
6620
+
6621
+ ```python
6622
+ client = get_sync_client(url="http://localhost:8123")
6623
+ updated_cron = client.crons.update(
6624
+ cron_id="1ef3cefa-4c09-6926-96d0-3dc97fd5e39b",
6625
+ schedule="0 10 * * *",
6626
+ enabled=False,
6627
+ )
6628
+ ```
6629
+
6630
+ """
6631
+ payload = {
6632
+ "schedule": schedule,
6633
+ "end_time": end_time.isoformat() if end_time else None,
6634
+ "input": input,
6635
+ "metadata": metadata,
6636
+ "config": config,
6637
+ "context": context,
6638
+ "webhook": webhook,
6639
+ "interrupt_before": interrupt_before,
6640
+ "interrupt_after": interrupt_after,
6641
+ "on_run_completed": on_run_completed,
6642
+ "enabled": enabled,
6643
+ }
6644
+ payload = {k: v for k, v in payload.items() if v is not None}
6645
+ return self.http.patch(
6646
+ f"/runs/crons/{cron_id}",
6647
+ json=payload,
6648
+ headers=headers,
6649
+ params=params,
6650
+ )
6651
+
6476
6652
  def search(
6477
6653
  self,
6478
6654
  *,
6479
6655
  assistant_id: str | None = None,
6480
6656
  thread_id: str | None = None,
6657
+ enabled: bool | None = None,
6481
6658
  limit: int = 10,
6482
6659
  offset: int = 0,
6483
6660
  sort_by: CronSortBy | None = None,
@@ -6491,6 +6668,7 @@ class SyncCronClient:
6491
6668
  Args:
6492
6669
  assistant_id: The assistant ID or graph name to search for.
6493
6670
  thread_id: the thread ID to search for.
6671
+ enabled: Whether the cron job is enabled.
6494
6672
  limit: The maximum number of results to return.
6495
6673
  offset: The number of results to skip.
6496
6674
  headers: Optional custom headers to include with the request.
@@ -6505,6 +6683,7 @@ class SyncCronClient:
6505
6683
  cron_jobs = client.crons.search(
6506
6684
  assistant_id="my_assistant_id",
6507
6685
  thread_id="my_thread_id",
6686
+ enabled=True,
6508
6687
  limit=5,
6509
6688
  offset=5,
6510
6689
  )
@@ -6538,6 +6717,7 @@ class SyncCronClient:
6538
6717
  payload = {
6539
6718
  "assistant_id": assistant_id,
6540
6719
  "thread_id": thread_id,
6720
+ "enabled": enabled,
6541
6721
  "limit": limit,
6542
6722
  "offset": offset,
6543
6723
  }
@@ -372,6 +372,35 @@ class Cron(TypedDict):
372
372
  """The next run date of the cron."""
373
373
  metadata: dict
374
374
  """The metadata of the cron."""
375
+ enabled: bool
376
+ """Whether the cron is enabled."""
377
+
378
+
379
+ class CronUpdate(TypedDict, total=False):
380
+ """Payload for updating a cron job. All fields are optional."""
381
+
382
+ schedule: str
383
+ """The cron schedule to execute this job on."""
384
+ end_time: datetime
385
+ """The end date to stop running the cron."""
386
+ input: Input
387
+ """The input to the graph."""
388
+ metadata: dict[str, Any]
389
+ """Metadata to assign to the cron job runs."""
390
+ config: Config
391
+ """The configuration for the assistant."""
392
+ context: Context
393
+ """Static context added to the assistant."""
394
+ webhook: str
395
+ """Webhook to call after LangGraph API call is done."""
396
+ interrupt_before: All | list[str]
397
+ """Nodes to interrupt immediately before they get executed."""
398
+ interrupt_after: All | list[str]
399
+ """Nodes to interrupt immediately after they get executed."""
400
+ on_run_completed: OnCompletionBehavior
401
+ """What to do with the thread after the run completes."""
402
+ enabled: bool
403
+ """Enable or disable the cron job."""
375
404
 
376
405
 
377
406
  # Select field aliases for client-side typing of `select` parameters.
@@ -428,6 +457,7 @@ CronSelectField = Literal[
428
457
  "metadata",
429
458
  "now",
430
459
  "on_run_completed",
460
+ "enabled",
431
461
  ]
432
462
 
433
463
  PrimitiveData = str | int | float | bool | None
@@ -18,7 +18,7 @@ path = "langgraph_sdk/__init__.py"
18
18
 
19
19
  [project.urls]
20
20
  Source = "https://github.com/langchain-ai/langgraph/tree/main/libs/sdk-py"
21
- Twitter = "https://x.com/LangChainAI"
21
+ Twitter = "https://x.com/LangChain"
22
22
  Slack = "https://www.langchain.com/join-community"
23
23
  Reddit = "https://www.reddit.com/r/LangChain/"
24
24
 
@@ -30,7 +30,7 @@ test = [
30
30
  "pytest-watch",
31
31
  ]
32
32
  lint = [
33
- "ruff==0.14.7",
33
+ "ruff==0.14.11",
34
34
  "codespell",
35
35
  "mypy==1.19.0",
36
36
  "ty==0.0.1a27",
@@ -276,3 +276,212 @@ def test_sync_create_with_end_time():
276
276
  )
277
277
 
278
278
  assert result == cron
279
+
280
+
281
+ @pytest.mark.parametrize(
282
+ "enabled_value",
283
+ [True, False],
284
+ ids=["enabled", "disabled"],
285
+ )
286
+ def test_sync_create_with_enabled_parameter(enabled_value):
287
+ """Test that SyncCronClient.create includes enabled parameter in the payload."""
288
+ cron = _cron_payload()
289
+
290
+ def handler(request: httpx.Request) -> httpx.Response:
291
+ assert request.method == "POST"
292
+ assert request.url.path == "/runs/crons"
293
+
294
+ body = json.loads(request.content)
295
+ assert body["schedule"] == "0 12 * * *"
296
+ assert body["assistant_id"] == "asst_456"
297
+ assert body["enabled"] == enabled_value
298
+
299
+ return httpx.Response(200, json=cron)
300
+
301
+ transport = httpx.MockTransport(handler)
302
+ with httpx.Client(transport=transport, base_url="https://example.com") as client:
303
+ http_client = SyncHttpClient(client)
304
+ cron_client = SyncCronClient(http_client)
305
+ result = cron_client.create(
306
+ assistant_id="asst_456",
307
+ schedule="0 12 * * *",
308
+ enabled=enabled_value,
309
+ )
310
+
311
+ assert result == cron
312
+
313
+
314
+ def _cron_response() -> dict[str, object]:
315
+ """Return a mock Cron object response."""
316
+ return {
317
+ "cron_id": "cron_123",
318
+ "assistant_id": "asst_123",
319
+ "thread_id": "thread_123",
320
+ "on_run_completed": None,
321
+ "end_time": "2025-12-31T23:59:59+00:00",
322
+ "schedule": "0 10 * * *",
323
+ "created_at": "2024-01-01T00:00:00Z",
324
+ "updated_at": "2024-01-02T00:00:00Z",
325
+ "payload": {},
326
+ "user_id": None,
327
+ "next_run_date": "2024-01-03T10:00:00Z",
328
+ "metadata": {},
329
+ "enabled": True,
330
+ }
331
+
332
+
333
+ @pytest.mark.asyncio
334
+ async def test_async_update():
335
+ """Test that CronClient.update works with schedule and enabled parameters."""
336
+ cron = _cron_response()
337
+
338
+ async def handler(request: httpx.Request) -> httpx.Response:
339
+ assert request.method == "PATCH"
340
+ assert request.url.path == "/runs/crons/cron_123"
341
+
342
+ # Parse the request body
343
+ body = json.loads(request.content)
344
+ assert body["schedule"] == "0 10 * * *"
345
+ assert body["enabled"] is False
346
+ assert "end_time" not in body # Should be filtered out by the None check
347
+
348
+ return httpx.Response(200, json=cron)
349
+
350
+ transport = httpx.MockTransport(handler)
351
+ async with httpx.AsyncClient(
352
+ transport=transport, base_url="https://example.com"
353
+ ) as client:
354
+ http_client = HttpClient(client)
355
+ cron_client = CronClient(http_client)
356
+ result = await cron_client.update(
357
+ cron_id="cron_123",
358
+ schedule="0 10 * * *",
359
+ enabled=False,
360
+ )
361
+
362
+ assert result == cron
363
+
364
+
365
+ @pytest.mark.asyncio
366
+ async def test_async_update_with_end_time():
367
+ """Test that CronClient.update includes end_time in the payload."""
368
+ cron = _cron_response()
369
+ end_time = datetime(2025, 12, 31, 23, 59, 59, tzinfo=timezone.utc)
370
+
371
+ async def handler(request: httpx.Request) -> httpx.Response:
372
+ assert request.method == "PATCH"
373
+ assert request.url.path == "/runs/crons/cron_123"
374
+
375
+ # Parse the request body
376
+ body = json.loads(request.content)
377
+ assert body["schedule"] == "0 10 * * *"
378
+ assert body["end_time"] == "2025-12-31T23:59:59+00:00"
379
+ assert body["enabled"] is True
380
+
381
+ return httpx.Response(200, json=cron)
382
+
383
+ transport = httpx.MockTransport(handler)
384
+ async with httpx.AsyncClient(
385
+ transport=transport, base_url="https://example.com"
386
+ ) as client:
387
+ http_client = HttpClient(client)
388
+ cron_client = CronClient(http_client)
389
+ result = await cron_client.update(
390
+ cron_id="cron_123",
391
+ schedule="0 10 * * *",
392
+ end_time=end_time,
393
+ enabled=True,
394
+ )
395
+
396
+ assert result == cron
397
+
398
+
399
+ def test_sync_update():
400
+ """Test that SyncCronClient.update works with schedule and enabled parameters."""
401
+ cron = _cron_response()
402
+
403
+ def handler(request: httpx.Request) -> httpx.Response:
404
+ assert request.method == "PATCH"
405
+ assert request.url.path == "/runs/crons/cron_123"
406
+
407
+ # Parse the request body
408
+ body = json.loads(request.content)
409
+ assert body["schedule"] == "0 10 * * *"
410
+ assert body["enabled"] is False
411
+ assert "end_time" not in body # Should be filtered out by the None check
412
+
413
+ return httpx.Response(200, json=cron)
414
+
415
+ transport = httpx.MockTransport(handler)
416
+ with httpx.Client(transport=transport, base_url="https://example.com") as client:
417
+ http_client = SyncHttpClient(client)
418
+ cron_client = SyncCronClient(http_client)
419
+ result = cron_client.update(
420
+ cron_id="cron_123",
421
+ schedule="0 10 * * *",
422
+ enabled=False,
423
+ )
424
+
425
+ assert result == cron
426
+
427
+
428
+ def test_sync_update_with_end_time():
429
+ """Test that SyncCronClient.update includes end_time in the payload."""
430
+ cron = _cron_response()
431
+ end_time = datetime(2025, 12, 31, 23, 59, 59, tzinfo=timezone.utc)
432
+
433
+ def handler(request: httpx.Request) -> httpx.Response:
434
+ assert request.method == "PATCH"
435
+ assert request.url.path == "/runs/crons/cron_123"
436
+
437
+ # Parse the request body
438
+ body = json.loads(request.content)
439
+ assert body["schedule"] == "0 10 * * *"
440
+ assert body["end_time"] == "2025-12-31T23:59:59+00:00"
441
+ assert body["enabled"] is True
442
+
443
+ return httpx.Response(200, json=cron)
444
+
445
+ transport = httpx.MockTransport(handler)
446
+ with httpx.Client(transport=transport, base_url="https://example.com") as client:
447
+ http_client = SyncHttpClient(client)
448
+ cron_client = SyncCronClient(http_client)
449
+ result = cron_client.update(
450
+ cron_id="cron_123",
451
+ schedule="0 10 * * *",
452
+ end_time=end_time,
453
+ enabled=True,
454
+ )
455
+
456
+ assert result == cron
457
+
458
+
459
+ @pytest.mark.parametrize(
460
+ "enabled_value",
461
+ [True, False],
462
+ ids=["enabled", "disabled"],
463
+ )
464
+ def test_sync_update_with_enabled_parameter(enabled_value):
465
+ """Test that SyncCronClient.update includes enabled parameter in the payload."""
466
+ cron = _cron_response()
467
+
468
+ def handler(request: httpx.Request) -> httpx.Response:
469
+ assert request.method == "PATCH"
470
+ assert request.url.path == "/runs/crons/cron_456"
471
+
472
+ body = json.loads(request.content)
473
+ assert body["enabled"] == enabled_value
474
+ assert "schedule" not in body # Only enabled is set
475
+
476
+ return httpx.Response(200, json=cron)
477
+
478
+ transport = httpx.MockTransport(handler)
479
+ with httpx.Client(transport=transport, base_url="https://example.com") as client:
480
+ http_client = SyncHttpClient(client)
481
+ cron_client = SyncCronClient(http_client)
482
+ result = cron_client.update(
483
+ cron_id="cron_456",
484
+ enabled=enabled_value,
485
+ )
486
+
487
+ assert result == cron