Skip to content

SDK Reference

Low-level access to the Komodo Platform HTTP APIs (IAM, etc.). get_snowflake_connection() constructs a Client internally; use Client directly when you need client.iam or other generated API wrappers.

from komodo import Client
def __init__(
self,
account_id: str | None = None,
auth_session: Session | None = None,
**kwargs,
) -> None
  • account_id — Komodo account UUID. If omitted, taken from the session / credentials when available.
  • auth_session — Optional Komodo Session (komodo.auth.Session). If omitted, a default Session() is created and connect() is called.
MemberDescription
authActive Session (tokens, refresh).
iamGenerated IAM API client (IamApi).
x_account_idResolved account ID for API calls.
komodo_api_client()Underlying OpenAPI ApiClient.
classmethod async def create(...) -> Client
async def close()
async def __aenter__ / __aexit__

Use async with await Client.create(...) as client: when you need explicit cleanup of the HTTP session.


Returns a DB-API 2.0 Connection to your account’s Snowflake warehouse through the Marmot Development Kit, with query tags applied for observability.

from komodo import get_snowflake_connection
def get_snowflake_connection(
account_id: str | None = None,
jwt: str | None = None,
client_id: str | None = None,
client_secret: str | None = None,
profile: str | None = None,
use_main_account: bool = False,
app_id: str | None = None,
query_tag_extra: Mapping[str, Any] | None = None,
) -> Connection
NameTypeDescription
account_idstr | NoneKomodo account UUID. Required unless the session / profile supplies it. Cannot be combined with profile if the profile already defines an account.
jwtstr | NoneBearer token for user-style auth. Cannot be combined with client_id / client_secret.
client_idstr | NoneService principal client ID (M2M). Must be used with client_secret and account_id (unless profile supplies them).
client_secretstr | NoneService principal secret (M2M).
profilestr | NoneNamed section in the credentials file (M2M + account). Mutually exclusive with passing jwt or split client_id/client_secret in the same call.
use_main_accountboolRoute to the shared main Snowflake account instead of the caller’s tenant. Cannot be combined with account_id.
app_idstr | NoneOverrides the app id reported to the gateway. Defaults to $KOMODO_APP_ID or kdk.
query_tag_extraMapping[str, Any] | NoneOptional caller metadata shallow-merged into the structured Snowflake QUERY_TAG under client.properties (e.g. a request or job id, for attribution in query history). Keys and values must be JSON-serializable. Must not contain secrets or PHI — the tag is stored in Snowflake’s query history.

Connection — DB-API 2.0 connection (Komodo Snowflake proxy). Use conn.cursor() to obtain a KomodoSnowflakeCursor.

ExceptionWhen
ValueErrorInvalid combination of arguments (e.g. JWT + client secret, or profile with explicit creds), or a non-JSON-serializable query_tag_extra.
UnsetAccountErrorNo account_id and none could be resolved from the session / file.
from komodo import get_snowflake_connection
conn = get_snowflake_connection()
cur = conn.cursor()
cur.execute("SELECT 1")
print(cur.fetchone())
conn.close()
# Tag every query on this connection with caller context for attribution
# in Snowflake query history. Values must be JSON-serializable; no secrets/PHI.
conn = get_snowflake_connection(query_tag_extra={"request_id": "abc-123", "job": "nightly-refresh"})

Async helper: execute_async on the cursor, poll until the query finishes, then attach results to the cursor and return that cursor.

from komodo import execute_query_async
async def execute_query_async(
cursor: KomodoSnowflakeCursor,
query: str,
query_params: list[str] | dict[str, str] | None = None,
) -> KomodoSnowflakeCursor
NameDescription
cursorOpen cursor from get_snowflake_connection().cursor().
querySQL string.
query_paramsOptional bind parameters for the query.

The same cursor after results are loaded — call fetchall(), fetch_pandas_all(), etc.

import asyncio
from komodo import get_snowflake_connection, execute_query_async
async def main():
conn = get_snowflake_connection()
cur = conn.cursor()
cur = await execute_query_async(cur, "SELECT CURRENT_TIMESTAMP()")
print(cur.fetchone())
conn.close()
asyncio.run(main())

Fetch diagnostic detail for a previously executed query so you can self-diagnose failures: the error code/message, execution status, warehouse, and timing Snowflake recorded.

from komodo import get_query_diagnostics
def get_query_diagnostics(
connection: Connection,
query_id: str,
) -> dict[str, Any] | None
NameTypeDescription
connectionConnectionAn open connection from get_snowflake_connection().
query_idstrThe Snowflake query id (cursor.sfqid, also shown as Query ID: in surfaced errors).

A dict of the recorded fields (QUERY_ID, QUERY_TEXT, EXECUTION_STATUS, ERROR_CODE, ERROR_MESSAGE, WAREHOUSE_NAME, START_TIME, END_TIME, TOTAL_ELAPSED_TIME), or None if no matching query is found.

Backed by Snowflake’s INFORMATION_SCHEMA.QUERY_HISTORY table function, scoped to the connection’s role and account. A current database must be set (e.g. USE DATABASE DATA) for INFORMATION_SCHEMA to resolve, and the query must be within the history retention window.

from komodo import get_snowflake_connection, get_query_diagnostics
conn = get_snowflake_connection()
cur = conn.cursor()
cur.execute("USE DATABASE DATA")
try:
cur.execute("SELECT * FROM SOME_SECURE_VIEW")
except Exception as err:
print(err)
print(get_query_diagnostics(conn, cur.sfqid))
conn.close()

def is_still_running(map_connection: Connection, query_id: str) -> bool

Returns whether a given Snowflake query id is still running. Used internally by execute_query_async; may raise SnowflakeException if status checks fail.


NameModuleDescription
UnsetAccountErrorkomodo.snowflakeMissing account context when opening a connection.
SnowflakeExceptionkomodo.snowflakeWrapped errors around query status / Map connection operations.
from komodo.snowflake import UnsetAccountError, SnowflakeException

UnsetAccountError is also available from the top-level komodo package (from komodo import UnsetAccountError).


Generated clients raise subclasses of OpenApiException (for example ApiException, ApiValueError). Import from komodo:

from komodo import ApiException, ApiValueError, OpenApiException

After cursor = conn.cursor():

Method / attributeTypical use
execute(sql, params=None)Run SQL.
fetchone, fetchmany, fetchallDB-API results.
fetch_pandas_all, fetch_pandas_batchesPandas DataFrames (Snowflake cursor).
execute_async, get_results_from_sfqidAdvanced / used by execute_query_async.
descriptionColumn metadata after a select.

For SQL and CLI patterns, see Executing Queries and Pandas Integration.


Programmatic access to the Komodo Secrets Service for storing, reading, updating, and deleting secrets. Secrets can be scoped to a user, an application, or shared across the organization. Every synchronous method has an _async counterpart (e.g. create_secret_async) for use in async runtimes.

from komodo.secrets_api import SecretsApi, SecretType

Enum that determines the scope/namespace of a secret.

class SecretType(str, Enum):
USER = "user"
APPLICATION = "application"
SHARED = "shared"
ValueDescription
SecretType.USERPersonal secrets tied to the authenticated user
SecretType.APPLICATIONApplication-scoped secrets (requires app_id)
SecretType.SHAREDOrganization-wide secrets accessible by all account members
class SecretsApi:
def __init__(
self,
api_client: Optional[ApiClient] = None,
session: Optional[Session] = None,
environment: Optional[str] = None,
access_token: Optional[str] = None,
account_id: Optional[str] = None,
)
ParameterTypeDescription
api_clientApiClientKomodo API client instance. Uses the default client if omitted.
sessionSessionKomodo auth session. Creates a new session if omitted.
environmentstr"production". Defaults to KOMODO_ENVIRONMENT.
access_tokenstrOverride token (useful in MCP/service contexts).
account_idstrOverride account ID.

Store a new secret.

def create_secret(
self,
secret_type: SecretType,
secret_path: str,
data: Dict[str, Any],
metadata: Optional[Dict[str, str]] = None,
app_id: Optional[str] = None,
platform: bool = False,
) -> Union[SecretResponse, PlatformSecretResponse]
ParameterTypeDescription
secret_typeSecretTypeScope of the secret
secret_pathstrPath for the secret (e.g. "my-api-key")
datadictKey-value pairs to store
metadatadictOptional metadata
app_idstrRequired when secret_type is APPLICATION
platformboolUse the platform secrets endpoint (advanced; default False)

Read a secret’s value and metadata.

def read_secret(
self,
secret_type: SecretType,
secret_path: str,
app_id: Optional[str] = None,
platform: bool = False,
) -> Union[SecretResponse, PlatformSecretResponse]

The returned SecretResponse has .data (dict), .metadata (dict or None), .success (bool), and .message (str).

List secret paths within a scope.

def list_secrets(
self,
secret_type: SecretType,
prefix: Optional[str] = None,
app_id: Optional[str] = None,
platform: bool = False,
next_token: Optional[str] = None,
) -> Union[SecretListResponse, PlatformSecretListResponse]
ParameterTypeDescription
prefixstrFilter to paths starting with this prefix
next_tokenstrPagination token from a previous response

The returned SecretListResponse has .secrets (list), .has_more (bool), and .next_token (str or None).

Replace a secret’s data. Creates a new version.

def update_secret(
self,
secret_type: SecretType,
secret_path: str,
data: Dict[str, Any],
metadata: Optional[Dict[str, str]] = None,
app_id: Optional[str] = None,
platform: bool = False,
) -> Union[SecretResponse, PlatformSecretResponse]

Permanently remove a secret.

def delete_secret(
self,
secret_type: SecretType,
secret_path: str,
app_id: Optional[str] = None,
platform: bool = False,
) -> Dict[str, Any]

Copy a secret from one scope to another, optionally deleting the original.

def move_secret(
self,
source_type: SecretType,
source_path: str,
dest_type: SecretType,
dest_path: str,
source_app_id: Optional[str] = None,
dest_app_id: Optional[str] = None,
delete_original: bool = False,
) -> SecretResponse
from komodo.secrets_api import SecretsApi, SecretType
api = SecretsApi(environment="production")
# Create a user secret
api.create_secret(
secret_type=SecretType.USER,
secret_path="my-api-key",
data={"key": "abc123"},
)
# List all user secrets
result = api.list_secrets(SecretType.USER)
for path in result.secrets:
print(path)
# Read a secret
secret = api.read_secret(SecretType.USER, "my-api-key")
print(secret.data) # {"key": "abc123"}
# Update a secret
api.update_secret(
SecretType.USER,
"my-api-key",
data={"key": "new-value"},
)
# Create an app-scoped secret
api.create_secret(
secret_type=SecretType.APPLICATION,
secret_path="db-password",
data={"password": "s3cret"},
app_id="4cb8894f-90ff-43a8-beba-451f2da3033a",
)
# Delete a secret
api.delete_secret(SecretType.USER, "my-api-key")
import asyncio
from komodo.secrets_api import SecretsApi, SecretType
async def main():
api = SecretsApi(environment="production")
await api.create_secret_async(
secret_type=SecretType.USER,
secret_path="async-key",
data={"token": "xyz"},
)
secret = await api.read_secret_async(SecretType.USER, "async-key")
print(secret.data)
asyncio.run(main())