Skip to main content
Polpo persists tasks, runs, missions, sessions, memory, logs, notifications, and approval state using a pluggable store layer. All stores implement a common interface and can be swapped via configuration.

TaskStore Interface

The core TaskStore interface defines the abstract contract that all task persistence backends must implement:
interface TaskStore {
  // State access
  getState(): PolpoState;
  setState(partial: Partial<PolpoState>): void;

  // Task CRUD
  addTask(task: Omit<Task, "id" | "status" | "retries" | "createdAt" | "updatedAt">): Task;
  getTask(taskId: string): Task | undefined;
  getAllTasks(): Task[];
  updateTask(taskId: string, updates: Partial<Omit<Task, "id" | "status">>): Task;
  removeTask(taskId: string): boolean;
  removeTasks(filter: (task: Task) => boolean): number;

  // State machine
  transition(taskId: string, newStatus: TaskStatus): Task;

  // Bypass state machine (recovery only)
  unsafeSetStatus(taskId: string, newStatus: TaskStatus, reason: string): Task;

  // Lifecycle
  close?(): void;

  // Mission persistence (optional)
  saveMission?(mission: Omit<Mission, "id" | "createdAt" | "updatedAt">): Mission;
  getMission?(missionId: string): Mission | undefined;
  getMissionByName?(name: string): Mission | undefined;
  getAllMissions?(): Mission[];
  updateMission?(missionId: string, updates: Partial<Omit<Mission, "id">>): Mission;
  deleteMission?(missionId: string): boolean;
  nextMissionName?(): string;
}
unsafeSetStatus bypasses the state machine and should only be used for recovery, race-condition fallbacks, and fix/Q&A re-runs. A mandatory reason string is logged.

Configuration Stores

StorePurposeLocation
JsonConfigStoreProject configuration.polpo/polpo.json
The JsonConfigStore (aliased as PolpoConfigStore) manages the polpo.json configuration file. It is always used regardless of the storage backend setting.

Choosing a Backend

ScenarioRecommended Backend
Getting started / single userFile (default)
Multiple concurrent orchestratorsSQLite
CI/CD pipelinesSQLite
Large task sets (100+ tasks)SQLite or PostgreSQL
Production / multi-serverPostgreSQL
Debugging / inspecting stateFile
Set the storage backend in .polpo/polpo.json:
{
  "settings": {
    "storage": "sqlite"
  }
}
Supported values: "file" (default), "sqlite", and "postgres". SQLite and PostgreSQL both use Drizzle ORM via the @polpo-ai/drizzle package, sharing the same store interface. Switching between them is a one-line config change.
All stores share the same .polpo/ directory by convention. The directory is created automatically by polpo init.