Automate a workspace with Python
Use the griot SDK when you need repeatable catalog and data workflows without hand-building HTTP requests. The code exists in this repository under sdk/griot-py; it has not been published to a package registry. Install it from a checkout containing the SDK feature branches:
python -m pip install -e sdk/griot-py
Before you begin
Obtain a personal access token and tenant UUID from your workspace administrator. Set GRIOT_API_URL, GRIOT_API_KEY, and GRIOT_TENANT_ID in a secret-aware environment. A PAT needs explicit workspace context; a session JWT instead carries a workspace claim. Do not put either credential in source code.
Find the destination
import os
from griot import Griot
with Griot(
os.environ["GRIOT_API_URL"],
api_key=os.environ["GRIOT_API_KEY"],
workspace_id=os.environ["GRIOT_TENANT_ID"],
) as client:
for catalog in client.catalog.list():
print(catalog["catalog"])
for domain in client.domain.list():
print(domain["slug"])
Griot also groups workspace members and roles, compute definitions, authored notebooks, and reports. client.api exposes the generated operation tree when a convenience method is not present. The client checks API-surface skew; keep SDK and server revisions aligned.
Preserve a file, then create a table deliberately
Use a bucket for original bytes. This is a separate operation from creating a queryable table:
with Griot(
os.environ["GRIOT_API_URL"],
api_key=os.environ["GRIOT_API_KEY"],
workspace_id=os.environ["GRIOT_TENANT_ID"],
) as client:
client.buckets.files.upload(
"./orders.csv",
catalog="default", domain="sales", bucket="imports",
path="2026/orders.csv",
)
The bucket and domain must already exist and your principal must have write access. An existing file path is refused; there is no overwrite flag. upload_folder retains relative paths and returns uploaded, failed, and retry_paths so you can retry only failures. It skips symbolic links.
Creating a table from those bytes requires a human steward session, not a PAT or agent key. Obtain a session through the approved sign-in flow; do not copy browser tokens into scripts. With that session in GRIOT_SESSION_JWT, the explicit step is:
with Griot(
os.environ["GRIOT_API_URL"],
api_key=os.environ["GRIOT_SESSION_JWT"],
workspace_id=os.environ["GRIOT_TENANT_ID"],
) as client:
table = client.tables.create_from_file(
catalog="default", domain="sales", bucket="imports",
path="2026/orders.csv", name="orders",
)
print(table)
The SDK checks for a structured extension and a session; the server is the final authority for source access, lineage, and ingestion. Uploading does not imply the table is ready to query. Inspect its lifecycle and contract before following the governed query guide.
Use an async client for concurrent reads
AsyncGriot is a real async transport, not a sync call hidden in a coroutine. It also covers bucket byte/folder uploads, scoped table reads and creation, and queries. Its single-file upload accepts bytes rather than a filesystem path; use upload_folder for a directory and inspect each outcome before retrying failed paths.
import asyncio
from griot import AsyncGriot
async def inspect() -> None:
async with AsyncGriot(
os.environ["GRIOT_API_URL"],
api_key=os.environ["GRIOT_API_KEY"],
workspace_id=os.environ["GRIOT_TENANT_ID"],
) as client:
catalogs, tables = await asyncio.gather(
client.catalog.list(), client.tables.list(catalog="default", domain="sales")
)
print(catalogs, tables)
asyncio.run(inspect())
These SDK slices are implemented in feature branches and require the matching integrated API contract. They are not a claim that the current stg deployment or a published PyPI release supports this journey yet.