체크포인팅 (Checkpointing)¶
실행 상태를 자동 저장해서, 크루(crew)·플로우(flow)·에이전트(agent)가 실패 후에도 이어서 재개할 수 있게 해주는 기능이에요.
개요¶
체크포인팅(Checkpointing)은 실행 도중 실행 상태의 스냅샷(snapshot)을 저장해 두는 기능이에요. 덕분에 크루, 플로우, 에이전트가 실패 후 이어서 재개(resume)하거나, 다른 분기(branch)로 포크(fork)할 수 있어요.
체크포인트가 캡처하는 것¶
체크포인트 하나에는 CrewAI가 실행 도중 상태를 그대로 재현하는 데 필요한 모든 것이 담겨요.
- 크루·플로우·에이전트의 전체 상태 — 설정(configuration), 에이전트 메모리와 지식 소스, 태스크 진행 상황, 중간 산출물, 내부 상태와 속성
- 킥오프 입력값(kickoff inputs)
- 해당 시점까지의 이벤트 히스토리
- 그 체크포인트가 어느 실행에서 왔는지 연결하는 lineage ID(계보 ID)
복원(restore)하면 그 상태를 다시 만들어 이어서 진행해요. 완료된 태스크는 건너뛰고, 메모리와 지식은 다시 채워지며(rehydrate), 이후 작업은 원래 실행이 만들었던 것과 동일한 출력을 기준으로 돌아가요.
포킹(forking)은 새로운 lineage 아래에서 동일한 복원을 수행해요. 그래서 새 분기와 원래 실행이 서로 덮어쓰지 않고 체크포인트를 나란히 쓸 수 있어요.
체크포인트가 기록되는 시점¶
체크포인팅은 이벤트 기반(event-driven) 이에요. 런타임이 on_events로 고른 이벤트를 구독하고, 해당 이벤트가 발생할 때마다 체크포인트를 하나씩 써요.
기본값인 task_completed는 태스크 하나가 끝날 때마다 체크포인트 한 개를 만들어요. 세밀함(granularity)과 디스크 사용량 사이에서 꽤 합리적인 절충안이에요.
llm_call_completed처럼 더 자주 발생하는 이벤트는 더 세밀한 복구가 가능하지만, 파일을 훨씬 많이 써요.
저장소 (Storage)¶
CrewAI에 기본으로 포함된 제공자(provider)는 두 가지예요.
JsonProvider— 체크포인트당 파일 한 개를 써요. 사람이 읽고 검사하기 쉬워요.SqliteProvider— 단일 SQLite 데이터베이스에 저장해요. 빈번한 체크포인팅에 더 적합해요.
둘 다 max_checkpoints가 설정되면 가장 오래된 체크포인트부터 정리(prune)해요.
참고 — 이벤트 기반 자동 체크포인트 쓰기는 best-effort(최선형)예요. 쓰기 실패는 로그로 남기고 실행은 계속돼요. 반면 수동
state.checkpoint()·state.acheckpoint()호출은 실패 시 예외를 다시 던져요(re-raise).
상속 모델 (Inheritance model)¶
Crew, Flow, Agent 모두 checkpoint 인자를 받아요. 자식은 부모의 값을 상속받는데, 자식이 자기 값을 설정하거나 False를 넘겨 탈퇴(opt out)하지 않는 한 그대로 물려받아요. 크루 한 곳에서 체크포인팅을 켜면 모든 에이전트가 참여하고, 특정 에이전트만 골라서 제외할 수도 있어요.
튜토리얼: 실패한 크루 재개하기¶
약 5분 걸리는 워크스루예요. 태스크 두 개짜리 크루를 실행하다 중간에 끊고, 저장된 체크포인트에서 재개할 거예요.
1단계 — 체크포인팅을 켠 크루 만들기
from crewai import Agent, Crew, Task
researcher = Agent(role="Researcher", goal="Research", backstory="Expert")
writer = Agent(role="Writer", goal="Write", backstory="Expert")
crew = Crew(
agents=[researcher, writer],
tasks=[
Task(description="Research AI trends", agent=researcher, expected_output="bullets"),
Task(description="Write a summary", agent=writer, expected_output="paragraph"),
],
checkpoint=True,
)
2단계 — 첫 태스크 후 중단하기
첫 태스크가 끝난 뒤 Ctrl+C를 누르세요. ./.checkpoints/ 안에 <timestamp>_<uuid>.json 이름의 파일이 체크포인트예요.
3단계 — 체크포인트에서 재개하기
from crewai import CheckpointConfig
result = crew.kickoff(
from_checkpoint=CheckpointConfig(
restore_from="./.checkpoints/<timestamp>_<uuid>.json",
),
)
리서치 태스크는 건너뛰고, 라이터는 저장된 리서치 출력을 바탕으로 실행되며, 크루가 끝까지 완료돼요.
어떻게 하는지 (How-to)¶
기본값으로 체크포인팅 켜기¶
task_completed마다 ./.checkpoints/에 저장돼요.
저장소와 빈도 커스터마이즈하기¶
from crewai import Crew, CheckpointConfig
crew = Crew(
agents=[...],
tasks=[...],
checkpoint=CheckpointConfig(
location="./my_checkpoints",
on_events=["task_completed", "crew_kickoff_completed"],
max_checkpoints=5,
),
)
저장소 제공자 고르기¶
# JsonProvider
from crewai import Crew, CheckpointConfig
from crewai.state import JsonProvider
crew = Crew(
agents=[...],
tasks=[...],
checkpoint=CheckpointConfig(
location="./my_checkpoints",
provider=JsonProvider(),
max_checkpoints=5,
),
)
# SqliteProvider
from crewai import Crew, CheckpointConfig
from crewai.state import SqliteProvider
crew = Crew(
agents=[...],
tasks=[...],
checkpoint=CheckpointConfig(
location="./.checkpoints.db",
provider=SqliteProvider(),
max_checkpoints=50,
),
)
팁 — SQLite는 WAL 저널 모드를 켜서 동시 읽기를 지원해요. 고빈도 체크포인팅이면 SQLite를 권장해요.
에이전트 하나 제외하기¶
crew = Crew(
agents=[
Agent(role="Researcher", ...),
Agent(role="Writer", ..., checkpoint=False),
],
tasks=[...],
checkpoint=True,
)
새 분기로 포크하기¶
fork()는 새 lineage 아래에서 체크포인트를 복원해서, 새 실행이 원래 실행과 충돌하지 않아요.
config = CheckpointConfig(restore_from="./my_checkpoints/<file>.json")
crew = Crew.fork(config, branch="experiment-a")
result = crew.kickoff(inputs={"strategy": "aggressive"})
branch 라벨은 선택사항이고, 생략하면 자동 생성돼요.
Crew, Flow, Agent 체크포인트¶
# Crew — 기본 트리거: task_completed
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, write_task, review_task],
checkpoint=CheckpointConfig(location="./crew_cp"),
)
# Flow
from crewai.flow.flow import Flow, start, listen
from crewai import CheckpointConfig
class MyFlow(Flow):
@start()
def step_one(self):
return "data"
@listen(step_one)
def step_two(self, data):
return process(data)
flow = MyFlow(
checkpoint=CheckpointConfig(
location="./flow_cp",
on_events=["method_execution_finished"],
),
)
result = flow.kickoff()
# Agent
agent = Agent(
role="Researcher",
goal="Research topics",
backstory="Expert researcher",
checkpoint=CheckpointConfig(
location="./agent_cp",
on_events=["lite_agent_execution_completed"],
),
)
result = agent.kickoff(messages=[{"role": "user", "content": "Research AI trends"}])
수동으로 체크포인트 쓰기¶
어떤 이벤트에든 핸들러를 등록하고 state.checkpoint()를 호출하면 돼요.
# 동기(sync)
from __future__ import annotations
from typing import TYPE_CHECKING, Any
from crewai.events.event_bus import crewai_event_bus
from crewai.events.types.llm_events import LLMCallCompletedEvent
if TYPE_CHECKING:
from crewai.state.runtime import RuntimeState
@crewai_event_bus.on(LLMCallCompletedEvent)
def on_llm_done(source: Any, event: LLMCallCompletedEvent, state: RuntimeState) -> None:
path = state.checkpoint("./my_checkpoints")
print(f"Saved checkpoint: {path}")
# 비동기(async)
from __future__ import annotations
from typing import TYPE_CHECKING, Any
from crewai.events.event_bus import crewai_event_bus
from crewai.events.types.llm_events import LLMCallCompletedEvent
if TYPE_CHECKING:
from crewai.state.runtime import RuntimeState
@crewai_event_bus.on(LLMCallCompletedEvent)
async def on_llm_done_async(source: Any, event: LLMCallCompletedEvent, state: RuntimeState) -> None:
path = await state.acheckpoint("./my_checkpoints")
print(f"Saved checkpoint: {path}")
핸들러가 세 개의 파라미터를 받으면 state 인자는 자동으로 공급돼요. 전체 이벤트 카탈로그는 Event Listeners를 참고하세요.
CLI로 살펴보기·재개·포크¶
crewai checkpoint
crewai checkpoint --location ./my_checkpoints
crewai checkpoint --location ./.checkpoints.db
왼쪽 패널이 체크포인트를 분기별로 묶어 보여주고, 포크는 부모 아래 중첩돼요. 체크포인트를 선택하면 메타데이터·엔티티 상태·태스크 진행 상황이 담긴 상세 패널이 열려요. Resume은 실행을 이어가고, Fork는 새 분기를 시작해요.
상세 패널에는 편집 가능한 영역이 두 곳 있어요.
- Inputs — 원래 킥오프 입력값이 미리 채워지고, 편집 가능해요.
- Task outputs — 완료된 태스크의 출력. 출력을 수정하고 Fork를 누르면 다운스트림 태스크가 무효화되어 수정된 컨텍스트를 기준으로 다시 실행돼요.
팁 — "what if" 탐색에 유용해요. 포크하고, 조정하고, 관찰하기.
TUI 없이 체크포인트 검사하기¶
crewai checkpoint list ./my_checkpoints
crewai checkpoint info ./my_checkpoints/<file>.json
crewai checkpoint info ./.checkpoints.db
참고 (Reference)¶
CheckpointConfig¶
| 파라미터 | 타입 | 기본값 | 설명 |
|---|---|---|---|
location |
str |
"./.checkpoints" |
저장 위치. JsonProvider면 디렉터리, SqliteProvider면 DB 파일 경로. |
on_events |
list[CheckpointEventType \| Literal["*"]] |
["task_completed"] |
체크포인트를 트리거하는 이벤트 타입. CheckpointEventType은 Literal이라 타입 체커가 자동완성하고 지원하지 않는 값은 거부해요. |
provider |
BaseProvider |
JsonProvider() |
저장 백엔드. JsonProvider 또는 SqliteProvider. |
max_checkpoints |
int \| None |
None |
유지할 최대 체크포인트 수. 쓰기마다 가장 오래된 것부터 정리돼요. |
restore_from |
Path \| str \| None |
None |
from_checkpoint으로 넘길 때 복원할 체크포인트. |
checkpoint 필드 값¶
Crew, Flow, Agent 모두 받는 값이에요.
| 값 | 동작 |
|---|---|
None |
부모로부터 상속. |
True |
기본값으로 켜기. |
False |
명시적 탈퇴. 상속을 멈춤. |
CheckpointConfig(...) |
커스텀 설정. |
이벤트 타입¶
on_events에는 CheckpointEventType 값을 조합해 넣을 수 있어요. 기본값 ["task_completed"]는 태스크 하나가 끝날 때마다 체크포인트 한 개를 쓰고, ["*"]는 모든 이벤트에 반응해요.
경고 —
["*"]와llm_call_completed같은 고빈도 이벤트는 체크포인트를 매우 많이 써서 성능이 떨어질 수 있어요. 이런 경우max_checkpoints와 함께 쓰세요.
지원되는 이벤트 전체 목록:
- Task —
task_started,task_completed,task_failed,task_evaluation - Crew —
crew_kickoff_started,crew_kickoff_completed,crew_kickoff_failed,crew_train_started,crew_train_completed,crew_train_failed,crew_test_started,crew_test_completed,crew_test_failed,crew_test_result - Agent —
agent_execution_started,agent_execution_completed,agent_execution_error,lite_agent_execution_started,lite_agent_execution_completed,lite_agent_execution_error,agent_evaluation_started,agent_evaluation_completed,agent_evaluation_failed - Flow —
flow_created,flow_started,flow_finished,flow_paused,method_execution_started,method_execution_finished,method_execution_failed,method_execution_paused,human_feedback_requested,human_feedback_received,flow_input_requested,flow_input_received - LLM —
llm_call_started,llm_call_completed,llm_call_failed,llm_stream_chunk,llm_thinking_chunk - LLM Guardrail —
llm_guardrail_started,llm_guardrail_completed,llm_guardrail_failed - Tool —
tool_usage_started,tool_usage_finished,tool_usage_error,tool_validate_input_error,tool_selection_error,tool_execution_error - Memory —
memory_save_started,memory_save_completed,memory_save_failed,memory_query_started,memory_query_completed,memory_query_failed,memory_retrieval_started,memory_retrieval_completed,memory_retrieval_failed - Knowledge —
knowledge_search_query_started,knowledge_search_query_completed,knowledge_query_started,knowledge_query_completed,knowledge_query_failed,knowledge_search_query_failed - Reasoning —
agent_reasoning_started,agent_reasoning_completed,agent_reasoning_failed - MCP —
mcp_connection_started,mcp_connection_completed,mcp_connection_failed,mcp_tool_execution_started,mcp_tool_execution_completed,mcp_tool_execution_failed,mcp_config_fetch_failed - Observation —
step_observation_started,step_observation_completed,step_observation_failed,plan_refinement,plan_replan_triggered,goal_achieved_early - Skill —
skill_discovery_started,skill_discovery_completed,skill_loaded,skill_activated,skill_load_failed - Logging —
agent_logs_started,agent_logs_execution - A2A —
a2a_delegation_started,a2a_delegation_completed,a2a_conversation_started,a2a_conversation_completed,a2a_message_sent,a2a_response_received,a2a_polling_started,a2a_polling_status,a2a_push_notification_registered,a2a_push_notification_received,a2a_push_notification_sent,a2a_parallel_delegation_started,a2a_parallel_delegation_completed,a2a_transport_negotiated,a2a_content_type_negotiated,a2a_context_created,a2a_context_expired,a2a_context_idle,a2a_context_completed,a2a_context_pruned - System signals —
SIGTERM,SIGINT,SIGHUP,SIGTSTP,SIGCONT - Wildcard —
"*"— 모든 이벤트에 반응.
저장소 제공자¶
| 제공자 | 설명 |
|---|---|
JsonProvider |
체크포인트당 파일 한 개. location 안에 <timestamp>_<uuid>.json 이름으로 저장돼요. |
SqliteProvider |
location에 있는 단일 DB 파일. WAL 저널링을 사용해요. |
CLI¶
| 명령 | 용도 |
|---|---|
crewai checkpoint |
TUI 실행. 저장소 자동 감지. |
crewai checkpoint --location <path> |
특정 위치를 대상으로 TUI 실행. |
crewai checkpoint list <path> |
체크포인트 목록. |
crewai checkpoint info <path> |
체크포인트 파일 또는 SQLite DB의 최신 항목 검사. |
실무 관점¶
- 복구의 기본값은
task_completed— 태스크 단위로 복구 지점을 만들면 대부분의 실패 시나리오에서 손실이 작아요. 세밀함이 필요한 경우에만llm_call_completed같은 고빈도 이벤트로 올리세요. - 고빈도 체크포인팅은 SQLite +
max_checkpoints— 파일 수가 폭발하지 않게 상한을 잡아두는 게 좋아요. - 포크로 "what if" 실험 — 같은 체크포인트에서 새 분기를 만들어 입력값이나 태스크 출력을 바꿔보면 원본 실행을 건드리지 않고 비교할 수 있어요.
- 상속 모델 활용 — 크루 단위로 한 번 켜고, 제외할 에이전트만
checkpoint=False로 끄는 편이 명시적이고 관리하기 쉬워요.
더 알아보기¶
- Event Listeners — 이벤트 카탈로그와 핸들러 등록 방법
- CrewAI 문서 — 원문