Skip to content

Cloud Adapters

Every cloud adapter implements the same four-method contract defined in adapters/base.py. The agent loop never calls cloud SDKs directly — it only calls these methods.

The contract

class CloudAdapter(ABC):

    def list_resources(
        self,
        ignore_regions: list[str] | None = None,
    ) -> list[Resource]:
        """Return every billable resource, excluding ignored regions."""

    def get_metrics(
        self,
        resource_id: str,
        resource_type: str,
        days: int = 14,
    ) -> MetricSummary:
        """Return usage metrics for the past N days."""

    def get_cost(
        self,
        resource_ids: list[str],
        days: int = 30,
    ) -> dict[str, float]:
        """Return USD cost per resource. Always called with all IDs at once."""

    def get_last_activity(
        self,
        resource_id: str,
        resource_type: str,
    ) -> datetime | None:
        """Return the last meaningful activity timestamp, or None."""

AWS adapter

Method AWS service Notes
list_resources Resource Explorer v2 Aggregator index, paginated, filters non-billable types
get_metrics CloudWatch GetMetricData 43 resource types + dynamic ListMetrics fallback
get_cost Cost Explorer GetCostAndUsageWithResources Single batched call; requires resource-level data enabled
get_last_activity CloudTrail LookupEvents 90-day lookback; filters read-only events

GCP adapter

Method GCP service Notes
list_resources Cloud Asset Inventory 22 billable asset types; normalizes zones → regions
get_metrics Cloud Monitoring 15 resource types + dynamic ListMetricDescriptors fallback
get_cost BigQuery billing export Parameterized query; falls back to zeros if not configured
get_last_activity Cloud Audit Logs Filters by resource name and service; 90-day lookback

Azure adapter

Method Azure service Notes
list_resources Resource Graph (KQL) Cross-subscription, paginated, excludes non-billable types
get_metrics Azure Monitor MetricsQueryClient 25 resource types + list_metric_definitions fallback
get_cost Cost Management QueryDefinition Batched by 50 resource IDs per subscription
get_last_activity Log Analytics KQL → Activity Log REST fallback Filters out read-only operations

Resource and MetricSummary types

@dataclass
class Resource:
    resource_id: str        # ARN / full resource path / Azure resource ID
    resource_type: str      # e.g. "AWS::EC2::Instance"
    cloud: str              # "aws" | "gcp" | "azure"
    region: str
    name: str | None        # from Name tag or display name
    tags: dict[str, str]    # all tags

@dataclass
class MetricSummary:
    has_data: bool                   # False if no CloudWatch/Monitoring data exists
    metrics: dict[str, float]        # metric_name → 90-day average value

Non-billable resource filter (AWS)

list_resources filters out types that never appear on an AWS bill before returning results:

  • All AWS::IAM::* (roles, policies, users, groups)
  • EC2 primitives: subnets, route tables, network ACLs, DHCP options, internet gateways
  • CloudFormation stacks and stacksets
  • SSM parameters, documents, patch baselines
  • Config rules, Lambda event source mappings, SNS subscriptions, CloudWatch alarms
  • And more — see adapters/aws/resource_explorer.py

This cuts 60–70% of the resource list before the AI sees it.