Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 8 additions & 11 deletions docs/ar/concepts/checkpointing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ crew = Crew(
agents=[...],
tasks=[...],
checkpoint=CheckpointConfig(
directory="./my_checkpoints",
location="./my_checkpoints",
on_events=["task_completed", "crew_kickoff_completed"],
max_checkpoints=5,
),
Expand All @@ -50,7 +50,7 @@ crew = Crew(

| الحقل | النوع | الافتراضي | الوصف |
|:------|:------|:----------|:------|
| `directory` | `str` | `"./.checkpoints"` | مسار ملفات نقاط الحفظ |
| `location` | `str` | `"./.checkpoints"` | مسار ملفات نقاط الحفظ |
| `on_events` | `list[str]` | `["task_completed"]` | انواع الاحداث التي تطلق نقطة حفظ |
| `provider` | `BaseProvider` | `JsonProvider()` | واجهة التخزين |
| `max_checkpoints` | `int \| None` | `None` | الحد الاقصى للملفات؛ يتم حذف الاقدم اولا |
Expand Down Expand Up @@ -95,7 +95,7 @@ result = crew.kickoff() # يستأنف من اخر مهمة مكتملة
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, write_task, review_task],
checkpoint=CheckpointConfig(directory="./crew_cp"),
checkpoint=CheckpointConfig(location="./crew_cp"),
)
```

Expand All @@ -118,7 +118,7 @@ class MyFlow(Flow):

flow = MyFlow(
checkpoint=CheckpointConfig(
directory="./flow_cp",
location="./flow_cp",
on_events=["method_execution_finished"],
),
)
Expand All @@ -137,7 +137,7 @@ agent = Agent(
goal="Research topics",
backstory="Expert researcher",
checkpoint=CheckpointConfig(
directory="./agent_cp",
location="./agent_cp",
on_events=["lite_agent_execution_completed"],
),
)
Expand All @@ -160,7 +160,7 @@ crew = Crew(
agents=[...],
tasks=[...],
checkpoint=CheckpointConfig(
directory="./my_checkpoints",
location="./my_checkpoints",
provider=JsonProvider(),
max_checkpoints=5,
),
Expand All @@ -179,15 +179,12 @@ crew = Crew(
agents=[...],
tasks=[...],
checkpoint=CheckpointConfig(
directory="./.checkpoints.db",
provider=SqliteProvider(max_checkpoints=50),
location="./.checkpoints.db",
provider=SqliteProvider(),
),
)
```

<Note>
عند استخدام `SqliteProvider`، حقل `directory` هو مسار ملف قاعدة البيانات، وليس مجلدا.
</Note>

## انواع الاحداث

Expand Down
27 changes: 12 additions & 15 deletions docs/en/concepts/checkpointing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ crew = Crew(
agents=[...],
tasks=[...],
checkpoint=CheckpointConfig(
directory="./my_checkpoints",
location="./my_checkpoints",
on_events=["task_completed", "crew_kickoff_completed"],
max_checkpoints=5,
),
Expand All @@ -50,10 +50,10 @@ crew = Crew(

| Field | Type | Default | Description |
|:------|:-----|:--------|:------------|
| `directory` | `str` | `"./.checkpoints"` | Filesystem path for checkpoint files |
| `location` | `str` | `"./.checkpoints"` | Storage destination — a directory for `JsonProvider`, a database file path for `SqliteProvider` |
| `on_events` | `list[str]` | `["task_completed"]` | Event types that trigger a checkpoint |
| `provider` | `BaseProvider` | `JsonProvider()` | Storage backend |
| `max_checkpoints` | `int \| None` | `None` | Max files to keep; oldest pruned first |
| `max_checkpoints` | `int \| None` | `None` | Max checkpoints to keep. Oldest are pruned after each write. Pruning is handled by the provider. |

### Inheritance and Opt-Out

Expand Down Expand Up @@ -95,7 +95,7 @@ The restored crew skips already-completed tasks and resumes from the first incom
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, write_task, review_task],
checkpoint=CheckpointConfig(directory="./crew_cp"),
checkpoint=CheckpointConfig(location="./crew_cp"),
)
```

Expand All @@ -118,7 +118,7 @@ class MyFlow(Flow):

flow = MyFlow(
checkpoint=CheckpointConfig(
directory="./flow_cp",
location="./flow_cp",
on_events=["method_execution_finished"],
),
)
Expand All @@ -137,7 +137,7 @@ agent = Agent(
goal="Research topics",
backstory="Expert researcher",
checkpoint=CheckpointConfig(
directory="./agent_cp",
location="./agent_cp",
on_events=["lite_agent_execution_completed"],
),
)
Expand All @@ -160,14 +160,14 @@ crew = Crew(
agents=[...],
tasks=[...],
checkpoint=CheckpointConfig(
directory="./my_checkpoints",
location="./my_checkpoints",
provider=JsonProvider(), # this is the default
max_checkpoints=5, # prunes oldest files
),
)
```

Files are named `<timestamp>_<uuid>.json` inside the directory.
Files are named `<timestamp>_<uuid>.json` inside the location directory.

### SqliteProvider

Expand All @@ -181,17 +181,14 @@ crew = Crew(
agents=[...],
tasks=[...],
checkpoint=CheckpointConfig(
directory="./.checkpoints.db",
provider=SqliteProvider(max_checkpoints=50),
location="./.checkpoints.db",
provider=SqliteProvider(),
max_checkpoints=50,
),
)
```

`SqliteProvider` accepts its own `max_checkpoints` parameter that prunes old rows via SQL. WAL journal mode is enabled for concurrent read access.

<Note>
When using `SqliteProvider`, the `directory` field is the database file path, not a directory. The `max_checkpoints` on `CheckpointConfig` controls filesystem pruning (for `JsonProvider`), while `SqliteProvider.max_checkpoints` controls row pruning in the database.
</Note>
WAL journal mode is enabled for concurrent read access.

## Event Types

Expand Down
19 changes: 8 additions & 11 deletions docs/ko/concepts/checkpointing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ crew = Crew(
agents=[...],
tasks=[...],
checkpoint=CheckpointConfig(
directory="./my_checkpoints",
location="./my_checkpoints",
on_events=["task_completed", "crew_kickoff_completed"],
max_checkpoints=5,
),
Expand All @@ -50,7 +50,7 @@ crew = Crew(

| 필드 | 타입 | 기본값 | 설명 |
|:-----|:-----|:-------|:-----|
| `directory` | `str` | `"./.checkpoints"` | 체크포인트 파일 경로 |
| `location` | `str` | `"./.checkpoints"` | 체크포인트 파일 경로 |
| `on_events` | `list[str]` | `["task_completed"]` | 체크포인트를 트리거하는 이벤트 타입 |
| `provider` | `BaseProvider` | `JsonProvider()` | 스토리지 백엔드 |
| `max_checkpoints` | `int \| None` | `None` | 보관할 최대 파일 수; 오래된 것부터 삭제 |
Expand Down Expand Up @@ -95,7 +95,7 @@ result = crew.kickoff() # 마지막으로 완료된 태스크부터 재개
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, write_task, review_task],
checkpoint=CheckpointConfig(directory="./crew_cp"),
checkpoint=CheckpointConfig(location="./crew_cp"),
)
```

Expand All @@ -118,7 +118,7 @@ class MyFlow(Flow):

flow = MyFlow(
checkpoint=CheckpointConfig(
directory="./flow_cp",
location="./flow_cp",
on_events=["method_execution_finished"],
),
)
Expand All @@ -137,7 +137,7 @@ agent = Agent(
goal="Research topics",
backstory="Expert researcher",
checkpoint=CheckpointConfig(
directory="./agent_cp",
location="./agent_cp",
on_events=["lite_agent_execution_completed"],
),
)
Expand All @@ -160,7 +160,7 @@ crew = Crew(
agents=[...],
tasks=[...],
checkpoint=CheckpointConfig(
directory="./my_checkpoints",
location="./my_checkpoints",
provider=JsonProvider(),
max_checkpoints=5,
),
Expand All @@ -179,15 +179,12 @@ crew = Crew(
agents=[...],
tasks=[...],
checkpoint=CheckpointConfig(
directory="./.checkpoints.db",
provider=SqliteProvider(max_checkpoints=50),
location="./.checkpoints.db",
provider=SqliteProvider(),
),
)
```

<Note>
`SqliteProvider`를 사용할 때 `directory` 필드는 디렉토리가 아닌 데이터베이스 파일 경로입니다.
</Note>

## 이벤트 타입

Expand Down
19 changes: 8 additions & 11 deletions docs/pt-BR/concepts/checkpointing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ crew = Crew(
agents=[...],
tasks=[...],
checkpoint=CheckpointConfig(
directory="./my_checkpoints",
location="./my_checkpoints",
on_events=["task_completed", "crew_kickoff_completed"],
max_checkpoints=5,
),
Expand All @@ -50,7 +50,7 @@ crew = Crew(

| Campo | Tipo | Padrao | Descricao |
|:------|:-----|:-------|:----------|
| `directory` | `str` | `"./.checkpoints"` | Caminho para os arquivos de checkpoint |
| `location` | `str` | `"./.checkpoints"` | Caminho para os arquivos de checkpoint |
| `on_events` | `list[str]` | `["task_completed"]` | Tipos de evento que acionam um checkpoint |
| `provider` | `BaseProvider` | `JsonProvider()` | Backend de armazenamento |
| `max_checkpoints` | `int \| None` | `None` | Maximo de arquivos a manter; os mais antigos sao removidos primeiro |
Expand Down Expand Up @@ -95,7 +95,7 @@ A crew restaurada pula tarefas ja concluidas e retoma a partir da primeira incom
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, write_task, review_task],
checkpoint=CheckpointConfig(directory="./crew_cp"),
checkpoint=CheckpointConfig(location="./crew_cp"),
)
```

Expand All @@ -118,7 +118,7 @@ class MyFlow(Flow):

flow = MyFlow(
checkpoint=CheckpointConfig(
directory="./flow_cp",
location="./flow_cp",
on_events=["method_execution_finished"],
),
)
Expand All @@ -137,7 +137,7 @@ agent = Agent(
goal="Research topics",
backstory="Expert researcher",
checkpoint=CheckpointConfig(
directory="./agent_cp",
location="./agent_cp",
on_events=["lite_agent_execution_completed"],
),
)
Expand All @@ -160,7 +160,7 @@ crew = Crew(
agents=[...],
tasks=[...],
checkpoint=CheckpointConfig(
directory="./my_checkpoints",
location="./my_checkpoints",
provider=JsonProvider(),
max_checkpoints=5,
),
Expand All @@ -179,15 +179,12 @@ crew = Crew(
agents=[...],
tasks=[...],
checkpoint=CheckpointConfig(
directory="./.checkpoints.db",
provider=SqliteProvider(max_checkpoints=50),
location="./.checkpoints.db",
provider=SqliteProvider(),
),
)
```

<Note>
Ao usar `SqliteProvider`, o campo `directory` e o caminho do arquivo de banco de dados, nao um diretorio.
</Note>

## Tipos de Evento

Expand Down
9 changes: 5 additions & 4 deletions lib/crewai/src/crewai/state/checkpoint_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,10 @@ class CheckpointConfig(BaseModel):
automatically whenever the specified event(s) fire.
"""

directory: str = Field(
location: str = Field(
default="./.checkpoints",
description="Filesystem path where checkpoint JSON files are written.",
description="Storage destination. For JsonProvider this is a directory "
"path; for SqliteProvider it is a database file path.",
)
on_events: list[CheckpointEventType | Literal["*"]] = Field(
default=["task_completed"],
Expand All @@ -180,8 +181,8 @@ class CheckpointConfig(BaseModel):
)
max_checkpoints: int | None = Field(
default=None,
description="Maximum checkpoint files to keep. Oldest are pruned first. "
"None means keep all.",
description="Maximum checkpoints to keep. Oldest are pruned after "
"each write. None means keep all.",
)

@property
Expand Down
24 changes: 3 additions & 21 deletions lib/crewai/src/crewai/state/checkpoint_listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@

from __future__ import annotations

import glob
import logging
import os
import threading
from typing import Any

Expand Down Expand Up @@ -105,29 +103,13 @@ def _find_checkpoint(source: Any) -> CheckpointConfig | None:


def _do_checkpoint(state: RuntimeState, cfg: CheckpointConfig) -> None:
"""Write a checkpoint synchronously and optionally prune old files."""
"""Write a checkpoint and prune old ones if configured."""
_prepare_entities(state.root)
data = state.model_dump_json()
cfg.provider.checkpoint(data, cfg.directory)
cfg.provider.checkpoint(data, cfg.location)

if cfg.max_checkpoints is not None:
_prune(cfg.directory, cfg.max_checkpoints)


def _safe_remove(path: str) -> None:
try:
os.remove(path)
except OSError:
logger.debug("Failed to remove checkpoint file %s", path, exc_info=True)


def _prune(directory: str, max_keep: int) -> None:
"""Remove oldest checkpoint files beyond *max_keep*."""
pattern = os.path.join(directory, "*.json")
files = sorted(glob.glob(pattern), key=os.path.getmtime)
to_remove = files if max_keep == 0 else files[:-max_keep]
for path in to_remove:
_safe_remove(path)
cfg.provider.prune(cfg.location, cfg.max_checkpoints)


def _should_checkpoint(source: Any, event: BaseEvent) -> CheckpointConfig | None:
Expand Down
Loading
Loading