portia.storage
Storage classes for managing the saving and retrieval of plans, runs, and tool calls.
This module defines a set of storage classes that provide different backends for saving, retrieving, and managing plans, runs, and tool calls. These storage classes include both in-memory and file-based storage, as well as integration with the Portia Cloud API. Each class is responsible for handling interactions with its respective storage medium, including validating responses and raising appropriate exceptions when necessary.
Classes:
- Storage (Base Class): A base class that defines common interfaces for all storage types, ensuring consistent methods for saving and retrieving plans, runs, and tool calls.
- InMemoryStorage: An in-memory implementation of the
Storage
class for storing plans, runs, and tool calls in a temporary, volatile storage medium. - FileStorage: A file-based implementation of the
Storage
class for storing plans, runs, and tool calls as local files in the filesystem. - PortiaCloudStorage: A cloud-based implementation of the
Storage
class that interacts with the Portia Cloud API to save and retrieve plans, runs, and tool call records.
Each storage class handles the following tasks:
- Sending and receiving data to its respective storage medium - memory, file system, or API.
- Validating responses from storage and raising errors when necessary.
- Handling exceptions and re-raising them as custom
StorageError
exceptions to provide more informative error handling.
PlanStorage Objects
class PlanStorage(ABC)
Abstract base class for storing and retrieving plans.
Subclasses must implement the methods to save and retrieve plans.
Methods:
save_plan(self, plan: Plan) -> None: Save a plan. get_plan(self, plan_id: PlanUUID) -> Plan: Get a plan by ID.
save_plan
@abstractmethod
def save_plan(plan: Plan) -> None
Save a plan.
Arguments:
plan
Plan - The Plan object to save.
Raises:
NotImplementedError
- If the method is not implemented.
get_plan
@abstractmethod
def get_plan(plan_id: PlanUUID) -> Plan
Retrieve a plan by its ID.
Arguments:
plan_id
PlanUUID - The UUID of the plan to retrieve.
Returns:
Plan
- The Plan object associated with the provided plan_id.
Raises:
NotImplementedError
- If the method is not implemented.
PlanRunListResponse Objects
class PlanRunListResponse(BaseModel)
Response for the get_plan_runs operation. Can support pagination.
RunStorage Objects
class RunStorage(ABC)
Abstract base class for storing and retrieving runs.
Subclasses must implement the methods to save and retrieve PlanRuns.
Methods:
save_plan_run(self, run: Run) -> None: Save a PlanRun. get_plan_run(self, plan_run_id: PlanRunUUID) -> PlanRun: Get PlanRun by ID. get_plan_runs(self, run_state: RunState | None = None, page=int | None = None) -> PlanRunListResponse: Return runs that match the given run_state
save_plan_run
@abstractmethod
def save_plan_run(plan_run: PlanRun) -> None
Save a PlanRun.
Arguments:
plan_run
PlanRun - The Run object to save.
Raises:
NotImplementedError
- If the method is not implemented.
get_plan_run
@abstractmethod
def get_plan_run(plan_run_id: PlanRunUUID) -> PlanRun
Retrieve PlanRun by its ID.
Arguments:
plan_run_id
RunUUID - The UUID of the run to retrieve.
Returns:
Run
- The Run object associated with the provided plan_run_id.
Raises:
NotImplementedError
- If the method is not implemented.
get_plan_runs
@abstractmethod
def get_plan_runs(run_state: PlanRunState | None = None,
page: int | None = None) -> PlanRunListResponse
List runs by their state.
Arguments:
run_state
RunState | None - Optionally filter runs by their state.page
int | None - Optional pagination data
Returns:
list[Run]
- A list of Run objects that match the given state.
Raises:
NotImplementedError
- If the method is not implemented.
AdditionalStorage Objects
class AdditionalStorage(ABC)
Abstract base class for additional storage.
Subclasses must implement the methods.
Methods:
save_tool_call(self, tool_call: ToolCallRecord) -> None: Save a tool_call.
save_tool_call
@abstractmethod
def save_tool_call(tool_call: ToolCallRecord) -> None
Save a ToolCall.
Arguments:
tool_call
ToolCallRecord - The ToolCallRecord object to save.
Raises:
NotImplementedError
- If the method is not implemented.
LogAdditionalStorage Objects
class LogAdditionalStorage(AdditionalStorage)
AdditionalStorage that logs calls rather than persisting them.
Useful for storages that don't care about tool_calls etc.
save_tool_call
def save_tool_call(tool_call: ToolCallRecord) -> None
Log the tool call.
Arguments:
tool_call
ToolCallRecord - The ToolCallRecord object to log.
Storage Objects
class Storage(PlanStorage, RunStorage, LogAdditionalStorage)
Combined base class for Plan Run + Additional storages.
InMemoryStorage Objects
class InMemoryStorage(PlanStorage, RunStorage, LogAdditionalStorage)
Simple storage class that keeps plans + runs in memory.
Tool Calls are logged via the LogAdditionalStorage.
__init__
def __init__() -> None
Initialize Storage.
save_plan
def save_plan(plan: Plan) -> None
Add plan to dict.
Arguments:
plan
Plan - The Plan object to save.
get_plan
def get_plan(plan_id: PlanUUID) -> Plan
Get plan from dict.
Arguments:
plan_id
PlanUUID - The UUID of the plan to retrieve.
Returns:
Plan
- The Plan object associated with the provided plan_id.
Raises:
PlanNotFoundError
- If the plan is not found.
save_plan_run
def save_plan_run(plan_run: PlanRun) -> None
Add run to dict.
Arguments:
plan_run
PlanRun - The Run object to save.
get_plan_run
def get_plan_run(plan_run_id: PlanRunUUID) -> PlanRun
Get run from dict.
Arguments:
plan_run_id
PlanRunUUID - The UUID of the PlanRun to retrieve.
Returns:
PlanRun
- The PlanRun object associated with the provided plan_run_id.
Raises:
PlanRunNotFoundError
- If the PlanRun is not found.
get_plan_runs
def get_plan_runs(run_state: PlanRunState | None = None,
page: int | None = None) -> PlanRunListResponse
Get run from dict.
Arguments:
run_state
RunState | None - Optionally filter runs by their state.page
int | None - Optional pagination data which is not used for in memory storage.
Returns:
list[Run]
- A list of Run objects that match the given state.
DiskFileStorage Objects
class DiskFileStorage(PlanStorage, RunStorage, LogAdditionalStorage)
Disk-based implementation of the Storage interface.
Stores serialized Plan and Run objects as JSON files on disk.
__init__
def __init__(storage_dir: str | None) -> None
Set storage dir.
Arguments:
storage_dir
str | None - Optional directory for storing files.
save_plan
def save_plan(plan: Plan) -> None
Save a Plan object to the storage.
Arguments:
plan
Plan - The Plan object to save.
get_plan
def get_plan(plan_id: PlanUUID) -> Plan
Retrieve a Plan object by its ID.
Arguments:
plan_id
PlanUUID - The ID of the Plan to retrieve.
Returns:
Plan
- The retrieved Plan object.
Raises:
PlanNotFoundError
- If the Plan is not found or validation fails.
save_plan_run
def save_plan_run(plan_run: PlanRun) -> None
Save PlanRun object to the storage.
Arguments:
plan_run
PlanRun - The Run object to save.
get_plan_run
def get_plan_run(plan_run_id: PlanRunUUID) -> PlanRun
Retrieve PlanRun object by its ID.
Arguments:
plan_run_id
RunUUID - The ID of the Run to retrieve.
Returns:
Run
- The retrieved Run object.
Raises:
RunNotFoundError
- If the Run is not found or validation fails.
get_plan_runs
def get_plan_runs(run_state: PlanRunState | None = None,
page: int | None = None) -> PlanRunListResponse
Find all plan runs in storage that match state.
Arguments:
run_state
RunState | None - Optionally filter runs by their state.page
int | None - Optional pagination data which is not used for in memory storage.
Returns:
list[Run]
- A list of Run objects that match the given state.
PortiaCloudStorage Objects
class PortiaCloudStorage(Storage)
Save plans, runs and tool calls to portia cloud.
__init__
def __init__(config: Config) -> None
Initialize the PortiaCloudStorage instance.
Arguments:
config
Config - The configuration containing API details for Portia Cloud.
check_response
def check_response(response: httpx.Response) -> None
Validate the response from Portia API.
Arguments:
response
httpx.Response - The response from the Portia API to check.
Raises:
StorageError
- If the response from the Portia API indicates an error.
save_plan
def save_plan(plan: Plan) -> None
Save a plan to Portia Cloud.
Arguments:
plan
Plan - The Plan object to save to the cloud.
Raises:
StorageError
- If the request to Portia Cloud fails.
get_plan
def get_plan(plan_id: PlanUUID) -> Plan
Retrieve a plan from Portia Cloud.
Arguments:
plan_id
PlanUUID - The ID of the plan to retrieve.
Returns:
Plan
- The Plan object retrieved from Portia Cloud.
Raises:
StorageError
- If the request to Portia Cloud fails or the plan does not exist.
save_plan_run
def save_plan_run(plan_run: PlanRun) -> None
Save PlanRun to Portia Cloud.
Arguments:
plan_run
PlanRun - The Run object to save to the cloud.
Raises:
StorageError
- If the request to Portia Cloud fails.
get_plan_run
def get_plan_run(plan_run_id: PlanRunUUID) -> PlanRun
Retrieve PlanRun from Portia Cloud.
Arguments:
plan_run_id
RunUUID - The ID of the run to retrieve.
Returns:
Run
- The Run object retrieved from Portia Cloud.
Raises:
StorageError
- If the request to Portia Cloud fails or the run does not exist.
get_plan_runs
def get_plan_runs(run_state: PlanRunState | None = None,
page: int | None = None) -> PlanRunListResponse
Find all runs in storage that match state.
Arguments:
run_state
RunState | None - Optionally filter runs by their state.page
int | None - Optional pagination data which is not used for in memory storage.
Returns:
list[Run]
- A list of Run objects retrieved from Portia Cloud.
Raises:
StorageError
- If the request to Portia Cloud fails.
save_tool_call
def save_tool_call(tool_call: ToolCallRecord) -> None
Save a tool call to Portia Cloud.
Arguments:
tool_call
ToolCallRecord - The ToolCallRecord object to save to the cloud.
Raises:
StorageError
- If the request to Portia Cloud fails.