GCS Media Storage
Store agent media in a Google Cloud Storage bucket with GCSMediaStorage.
GCSMediaStorage uploads media to a Google Cloud Storage bucket and keeps only a MediaReference in the database.
Usage
Install the required packages:
uv pip install "agno[gcs]" openai sqlalchemyAuthenticate with gcloud auth application-default login, or pass a service-account JSON through credentials_path.
Choose an existing bucket and credentials authorized to read, write, and delete its objects. The backend does not create the bucket. Set the bucket name before running Python and set the model key before any Agent run:
export MEDIA_GCS_BUCKET="your-existing-bucket"
export OPENAI_API_KEY="your-api-key"import os
from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.media.storage import GCSMediaStorage
from agno.models.openai import OpenAIResponses
storage = GCSMediaStorage(
bucket=os.environ["MEDIA_GCS_BUCKET"],
project=os.getenv("GCP_PROJECT"),
prefix="agno/media/",
)
agent = Agent(
model=OpenAIResponses(id="gpt-5.5"),
db=SqliteDb(db_file="tmp/data.db"),
media_storage=storage,
)Async
AsyncGCSMediaStorage takes the same parameters. google-cloud-storage has no native async API, so each call runs in a worker thread.
from agno.media.storage import AsyncGCSMediaStorage
storage = AsyncGCSMediaStorage(bucket=os.environ["MEDIA_GCS_BUCKET"])URLs
Signing a URL needs a credential that carries a private key. Pass credentials_path, or point GOOGLE_APPLICATION_CREDENTIALS at a service-account JSON.
storage = GCSMediaStorage(
bucket=os.environ["MEDIA_GCS_BUCKET"],
credentials_path="/path/to/service-account.json",
)Application-default credentials from gcloud auth or a VM carry only a token. With those, get_url returns None and AgentOS streams the bytes through its media route.
public=True returns the public object URL instead of a signed one. It grants no access by itself: when uniform bucket-level access is enabled, the bucket must already grant roles/storage.objectViewer to allUsers or the URL answers 403.
Bucket access defaults depend on how the bucket was created and organization policy. Check the bucket's setting; the gcloud creation command exposes it explicitly.
Params
| Parameter | Type | Default | Description |
|---|---|---|---|
bucket | str | - | Name of the destination GCS bucket. |
prefix | str | "agno/media/" | Key prefix for stored objects. |
credentials_path | Optional[str] | None | Path to a service-account JSON file. Supplies the private key used to sign URLs, as does GOOGLE_APPLICATION_CREDENTIALS. |
project | Optional[str] | None | GCP project ID. |
presigned_url_expiry | int | 3600 | Signed URL lifetime in seconds. Above the V4 maximum of seven days, signing fails and URLs fall back to streaming. |
public | bool | False | Return the public object URL instead of a signed one. Grants no access by itself. |
persist_remote_urls | bool | False | Download and store media passed as a URL. Skipped when False. |
See the full example here.