Skip to main content

Overview

Tool Name

Purpose

The databricks_action tool provides programmatic control of Databricks workspaces. It enables notebook CRUD, cross-workspace copy and move for existing Workspace notebooks and files, workspace file sync and upload flows, SQL execution, permissions management, and job or cluster interactions so you can orchestrate Databricks work without using the UI.

Functions Available

  1. databricks_action: Performs Databricks operations, including notebook lifecycle actions, workspace file sync, SQL execution, job control, and status checks through the Databricks APIs.

Key Features

Notebook Lifecycle

Create, read, update, list, and delete notebooks programmatically in workspace folders.

Execute & Monitor

Run notebooks on clusters with params and monitor run state, logs, and results.

Workspace Sync & Export

Sync repo-backed notebooks and workspace files into Databricks Workspace, export notebook content in supported formats, or copy and move existing Workspace notebooks and files between configured Databricks connections.

Permissions & Sharing

Manage access to notebooks and align with workspace sharing policies.

Jobs, Clusters, & SQL

Target specific clusters or jobs for scheduled flows, and submit single-statement or batched SQL work.

Input Parameters for Each Function

databricks_action

Parameters
Genesis Tip
When running production jobs, pass params for date ranges or environment flags instead of hardcoding them in notebook cells.

Action Routing

In-thread completion notices

When a Databricks action leaves a job run, pipeline update, or SQL statement running in the current Genesis conversation, Genesis can watch it and send the terminal result to that thread. If the server restarts while the completion notice is only queued in memory, Genesis retains the watch and retries delivery. Follow the tool response’s status-check instructions if it does not confirm that a watch was set up. For a signed-in person, run_notebook also returns project_tracking when a live migration project published that notebook on the same Databricks connection. Genesis attempts to file the submitted run under that project; the field says whether it was tracked or why filing failed. See checked project records for what qualifies as a passing run. upload_file restore behavior.

update_job task replacement and persistence checks

update_job updates an existing Databricks Job by job_id. The action always reads the complete Job back after writing it, so each call makes one write request and one or more jobs/get requests, one per response page. Job reads use the Jobs API 2.2 pagination contract so task, cluster, parameter, and environment arrays are not silently limited to the first 100 elements. The read-back compares only the fields that can be verified from the response: persisted task keys, submitted task parameter containers, the top-level name, timeout_seconds, max_concurrent_runs, and parameters settings, and requested removals. The result places these under verification.checked and returns success: false with named divergences when a checked value differs. Other submitted fields—including notebook paths, task types, dependencies, clusters, libraries, schedules, Git source, run_as, tags, notifications, and environments—are not verified; call get_job when the complete definition matters. If the write succeeds but the read-back is incomplete or unusable, the result uses verification.status: 'unverifiable' and write_issued: true rather than claiming success. A response without a task collection is not treated as an empty collection. Invalid task entries, duplicate task_key values, invalid fields_to_remove, duplicate job parameters, and other rejected claims fail before writing when they cannot be verified safely. Examples:

list_clusters compute scope

list_clusters lists the workspace’s clusters through the Databricks clusters API. It accepts the standard connection_id parameter; it does not accept a parameter that enables or checks serverless compute.
  • Each cluster includes cluster_source. When Databricks does not provide that field, the tool returns "UNKNOWN"; do not treat it as an all-purpose cluster.
  • serverless_compute.status is "unknown" because this API does not report whether serverless is enabled. An empty or all-terminated cluster list does not mean that notebooks cannot run.
  • For serverless job compute, call run_notebook or run_notebook_live without cluster_id. For run_notebook, passing the literal cluster_id="serverless" selects the same serverless Jobs path; do so only when serverless execution has been explicitly approved. Use list_jobs and check_run_status to see whether runs have already succeeded through that path.
  • SQL warehouses are a separate compute path listed by get_workspace_info. They can serve SQL but cannot run a notebook. Check these paths before reporting that no compute is available.

execute_python process isolation and recovery

execute_python runs in a separate Databricks execution process instead of the Genesis server process. The process is created lazily for the first call and is shared by sessions for the same connection_id and bot. This contains native Spark Connect or gRPC crashes to that execution process, so the Genesis server and other connections remain available. On deployments where Genesis runs as root and the image provides the restricted cortex_sandbox user (Snowflake, EKS and self-hosted Docker), the execution process runs as cortex_sandbox, the same user execute_python_code runs as. It gets no server credentials: its environment holds only PATH, locale, TLS trust-store and proxy settings, and its own home directory. The connection’s token reaches it only for its Databricks session. Where Genesis cannot switch users (Genesis Desktop, a local development server, or any server not running as root), it runs as the server’s own user, as before. Because execute_python reuses its worker across calls, Python child processes can remain active after a call returns; they end when Genesis tears down that worker. In a Databricks App, sessions are also isolated by signed-in user because the connection runs with that user’s forwarded token. A call without a signed-in user cannot create or use a session. Each signed-in user can have at most 2 execution processes, with at most 8 across all App users. If either limit is reached, session creation returns an error; wait for an idle session to expire after 10 minutes before trying again. The App bundle must request the sql user scope for Databricks connection SQL; see Databricks connection authentication.
  • Use connection_id to select the Databricks workspace. execute_python uses serverless compute automatically; do not pass cluster_id for this action.
  • Use session_id to preserve variables between calls. If it is omitted, the response creates a session and returns its session_id. Sessions expire after 10 minutes without use; check session_expires_at or use list_python_sessions to inspect the current thread’s sessions.
  • When a new session is created because session_id was omitted, was not found, or had expired after more than 10 minutes of inactivity, the response includes session_note. This is normal session recycling, not a context limit or an error. If the previous session expired or the supplied ID was missing, rerun the setup code; when no ID was supplied, save the returned session_id for subsequent calls.
  • A normal Python exception is returned in the result with success: false, error, error_type, and traceback details. A crashed execution process is returned with error_type: "SparkWorkerCrashed" and lost_sessions; every session listed there has lost its variables.
  • If the worker fails during startup, its captured output may include spark worker entrypoint reached pid=.... This means the child reached its entrypoint; if the marker is absent, the process may have failed before then, so investigate worker startup or spawning.
  • After SparkWorkerCrashed, omit session_id to create a fresh session and rerun the setup code. The response explains that the Genesis server was unaffected; do not treat this result as a server outage.
Example recovery call:

Command execution and confirmation

execute_command accepts command with an explicit language; an existing context uses execute_command_in_context with command and context_id and sends no language. SQL reads sent with language="SQL" do not need confirmation. Python, Scala, and R commands require the user to approve code that may write data before retrying with params={"confirm": True}. Direct SQL writes are refused by these command actions even with confirmation; use run_sql_statement for SQL writes instead. Because execute_command_in_context sends no language, SQL text that is classified as a read can run without confirmation, while ambiguous read-like text requires confirmation. For example, after the user approves running Python that may write data, submit without waiting and use the returned command_id and context_id to check or cancel it:

Stopping remote Databricks work

When a user stops a polling action, Genesis also stops the work already running in Databricks instead of only ending local status polling:
  • run_notebook_live cancels the Databricks job run identified by databricks_run_id.
  • run_notebook_cells and execute_command cancel the active command on its cluster using cluster_id, context_id, and command_id.
  • run_sql_statement cancels the SQL Statement API request it is polling. This also applies when a spec-author seat’s hard-stop stops the tool call. The statement cancellation is best effort; the tool reports the stop even if Databricks does not confirm cancellation.
  • Genesis retries the remote cancellation once after a one-second delay. The tool still reports the user stop even if both cancellation attempts fail.
  • For execute_command with wait_for_result, Genesis destroys the temporary execution context after the stop, including when cancellation fails.
If remote cancellation cannot be delivered, the result names the affected job run, command, or statement and states that it may still be running. Use check_run_status for a job run, cancel_command with the returned command identifiers, or check_sql_statement with the statement id to inspect remaining work. This cancellation applies when the tool call is stopped, not when SQL polling reaches its ceiling: a statement still running at max_poll_seconds returns timed_out: true and remains running in Databricks. Use check_sql_statement with its statement_id to inspect it.

Uncertain notebook submission

If run_notebook receives a transport failure after submission may have reached Databricks, it returns success: false with submission_state: "uncertain". Treat that as an unknown outcome, not a failed run: inspect recent Jobs runs for the notebook, use the matching run id with check_run_status if one exists, and submit again only after confirming that no run was created. This avoids duplicate billable work.

SOURCE notebook structure warnings

When create_notebook imports a notebook with format="SOURCE", the tool checks the finalized payload before sending it to Databricks. The import remains non-blocking: the notebook is still sent, but the response includes structural_warnings when the payload may have lost its structure. If the supplied content is only one complete Markdown code fence, the tool removes the fence and imports its body. An unlabelled fence is accepted, as are fences labelled for the selected notebook language (python, py, python3, sql, scala, or r). Content that already has a Databricks notebook header is left unchanged. The tool does not guess when the content is ambiguous. If the payload contains multiple fenced blocks, text outside a single fence, or a fence labelled for a different notebook language, it imports the content verbatim with the fence markers and adds an actionable structural_warnings entry. Send only the notebook code or one complete fence with the matching language label to avoid this warning. Warnings identify:
  • A cell separator that is not exactly the language-specific marker on its own line, such as # COMMAND ---------- for Python or -- COMMAND ---------- for SQL.
  • A Databricks magic directive such as %md, %sql, or %python that is not prefixed with the language-specific MAGIC marker.
  • An empty cell caused by a lost or duplicated cell separator.
Each warning includes the affected line or cell number and a description of the issue. Inspect the generated notebook in Databricks when structural_warnings is present. For SOURCE imports that contain a # MAGIC %md (or language-specific equivalent) cell, the tool also exports the imported notebook in JUPYTER format and compares the stored cell_type values with the intended source cells. This catches code that Databricks stored as markdown when a markdown block was not closed with a cell separator. The import still succeeds, but the response adds a warning that the affected code will not execute and that the notebook can report SUCCESS without running it. If the JUPYTER export fails, is empty, or cannot be parsed, the response instead says that cell-type verification could not be completed; export the notebook as JUPYTER and inspect its cell_type values. sync_from_git applies the same structure and cell-type checks to repository notebooks. With the default validate_transfer=True, success is false when any file is not validated, and unvalidated_files lists those repository paths. Each entry in validation_results can include cell_types with one of these values:
  • VERIFIED: The stored cells match the source, or the notebook has no Markdown cell that could cause this type of drift.
  • DRIFTED: An intended code cell was stored as Markdown. The path is also listed in drifted_files; this is the only result that establishes the code will not execute, even if a job reports SUCCESS.
  • STRUCTURE_LOST: Databricks stored a different number of cells than the source sent. The path is listed in structure_lost_files, and which cells execute is not established.
  • UNVERIFIED: The JUPYTER export check could not run. The path is listed in unverified_files, and executability is unknown rather than known-bad.
FAILED without cell_types: DRIFTED means only that the workspace copy does not match the source; it does not establish whether the notebook executes. structural_warnings is included when a notebook-structure finding is raised, including warnings collected across the sync. The JUPYTER round trip costs one additional export request for a notebook containing # MAGIC %md (or the language-specific equivalent); notebooks without that marker skip the check. The cell-type check runs even when validate_transfer=False, but transfer validation status fields are only produced when transfer validation is enabled.

stage_from_s3 AWS credentials

When params.aws_credential_name / params.aws_connection is omitted, stage_from_s3 resolves the caller’s scoped default AWS connection (My default, then Role default). If that default resolves but its secrets cannot be loaded, Genesis returns an error instead of silently using ambient host credentials. When no scoped AWS default applies, Genesis may fall back to ambient boto3 credentials and logs a warning — set a user or role default on an AWS connection in Config → Connections, or pass an explicit params.aws_credential_name, for predictable S3 access. See Connections — AWS connection modes and Default connection layers.

SQL Safety for run_sql_statement and run_sql_batch

The shared SQL safety and execution-outcome contract is in Connections; it also covers execute_command_in_context. Use params.sql_file_ref instead of params.statement or params.sql when the statement is in a saved file. The shared reference format, optional hash check, and receipt are documented under _query_database. The receipt always identifies the saved file; it includes executed_sql_sha256 and a text preview only when submission is proven by a returned statement_id. Without those fields, execution is unproven. The file runs as one statement; semicolon-separated batches remain unsupported. If a safety refusal asks you to confirm or authorize a saved-file statement, re-issue run_sql_statement with the same params.sql_file_ref and the requested flag inside params (for example, params.confirm: true or the exact params.user_override value). Do not retype the file’s SQL. If the file contains multiple statements, save each statement separately and run each with its own params.sql_file_ref. Use run_sql_statement for Databricks writes that _query_database refuses. Privilege changes are governed writes too. GRANT, REVOKE, SET TAG, and UNSET TAG are classified as privilege changes and return the normal confirmation response; review the returned classification and sql before retrying. Command Execution requests that contain SQL are classified from the command text rather than only from the caller’s language label, so a command that hides a write is not treated as Python-only execution. It accepts one statement per call; review the returned classification before retrying with params.confirm: true for a table-level destructive statement. params.confirm does not authorize catastrophic namespace operations, which require the exact params.user_override value described above. execute_python applies the same table-discard safeguard to code containing DROP TABLE, CREATE OR REPLACE TABLE, or REPLACE TABLE. Those operations are refused unless the user has agreed to discard the current table data and the call is repeated with params={"confirm": true}. For row removal, use DELETE FROM ... WHERE ... or a MERGE instead.
If Databricks SQL returns requires_confirmation: true, review the returned classification and sql before retrying. params.confirm does not authorize CATASTROPHIC operations. For run_sql_batch, Genesis reclassifies each statement independently, so one params.user_override authorizes only the matching catastrophic operation type. Split namespace changes into separate statements when you need explicit approval.When the optional SQL intent-match guard is enabled, run_sql_statement can also return requires_confirmation: true with severity: intent_mismatch if the planned statement does not clearly match the user’s latest request. run_sql_batch still evaluates each statement separately before execution. The correct recovery is a fresh chat reply that explicitly names the exact operation and target; if the statement is still destructive or catastrophic, keep params.confirm or params.user_override on the retry as required.
CREATE OR REPLACE VIEW ... WITH METRICS is classified as destructive even when the target name is new, so review the confirmation instead of assuming that a new name makes the statement non-destructive. DESCRIBE TABLE EXTENDED ... AS JSON is a read, but the local SQL parser can classify its AS JSON suffix as unknown and request confirmation; treat that prompt as parser caution before retrying.

Unity Catalog metric views

Use list_metric_views to identify metric views in one Unity Catalog schema. The documented TABLE_TYPE values for information_schema.tables do not include METRIC_VIEW, although some workspaces return that value there anyway. SHOW VIEWS and the Databricks JDBC driver do not provide a consistent discriminator, so this action uses the Unity Catalog REST catalog’s table_type value instead. It requires params.catalog and params.schema, and uses the selected connection_id (or the configured Databricks environment credentials when connection_id is omitted).
The result includes each visible metric view’s full_name, name, table_type, owner, comment, updated_at, and properties, plus returned_count, objects_examined, and pages_read. Read complete before treating the result as exhaustive: true means the listing reached the end of the schema, while false means the result is only a prefix after the action’s page limit. A successful empty metric_views list means no metric views are visible to the calling identity in that schema; a failed request returns success: false rather than an empty list. The action performs one Unity Catalog HTTPS request per page and does not use a SQL warehouse. When querying a metric view, wrap every measure in MEASURE(), for example SELECT MEASURE(\Total Revenue`) FROM main.analytics.revenue_metrics. A bare measure reference can return a plausible number without raising an error, but it is not the measure as defined by the semantic layer. To recover the metric-view definition, use DESCRIBE TABLE EXTENDED catalog.schema.metric_view AS JSON; its view_textcontains the YAML definition.information_schema.views` does not reliably return metric views.

Unity Catalog registration for the semantic layer

Genie Ontology is derived from Unity Catalog metadata rather than directly authored by this tool. These actions register the descriptions, tags, certification, informational keys and domains that Unity Catalog exposes to Catalog Explorer and Genie. They use the selected Databricks connection and SQL warehouse for SQL operations; domain and tag-policy actions use the REST API instead. Use register_uc_assets to register several tables in one schema. It is the batch form of the comment, tag and key actions and also records migration provenance on the real Unity Catalog table, not as a separate shadow object. Pass params.dry_run=true first for a large registration: every write statement is returned without being sent. A live registration runs one warehouse statement per comment, tagged object and constraint, and key verification may also scan tables. When a table-comment decision depends on the comment already on the table, both a dry run and a live run send one information_schema.tables read per call to fetch the existing comments. COMMENT ON TABLE replaces the whole comment, so existing table comments are preserved by default by these Unity Catalog actions. A raw COMMENT ON sent through run_sql_statement replaces the whole comment; use apply_uc_comments to append a note after the live comment. Provenance alone writes only the genesis_* provenance tags, not a comment. Use params.comment_mode to change that: A comment consisting only of an earlier provenance sentence for the same source is treated as generated provenance, not authored guidance: it is recomposed under append, and an explicit comment replaces it rather than being appended to it. Column comments (assets[].columns) and params.schema_comment follow the same rules as an explicit table comment, without a provenance sentence: under preserve and append a note is appended after the existing comment, skipped when it is already there, and held back when the existing comment could not be read; only replace overwrites. Deciding them costs one information_schema.columns read when any asset carries column comments and one information_schema.schemata read when schema_comment is given, in a dry run too. schema_comment_written indicates whether a schema comment was included for writing, and schema_comment_appended says whether it was appended; existing_schema_comment_error reports a failed schema-comment read. For each asset, column_comments_written counts comment statements sent (or composed in a dry run), while column_comments_appended, column_comments_held_back, and column_comments_replaced report the per-column outcomes. The top-level existing_column_comments_error reports a failed column-comment read. Because no mode but replace removes text, a correction or rewording of an existing comment needs comment_mode: "replace" with the full corrected text. Sent under the default, it is appended beside the old wording. Matching is by whole paragraph: a short note that only appears inside a longer sentence is still appended. Every comment write that would lose existing comment text is listed with existing_length and new_length (a table entry names its table, a column entry its table and column, a schema entry its schema): in would_replace_existing_comment for a dry run and in replaced_existing_comment for a live run. A null existing_length means the existing comment could not be read. A write that fails is reported in failures, not in these lists. An unrecognised field on an asset, such as assets[].comment_mode, is refused naming it. Check this list before applying a registration; an empty failures list does not mean no text is lost. Primary and foreign keys are informational, not enforced by Unity Catalog. Primary-key columns must become NOT NULL, so the action requires allow_schema_change=true to make that schema change. Foreign keys are declared after all primary keys so an asset’s order does not determine whether its references can be registered. Inspect totals.keys_not_declared and each key’s skipped_reason; success reports SQL execution, not whether every candidate key was accepted.
For one table, apply_uc_comments takes params.catalog, params.schema, params.table, and optional params.comment, params.columns (a map of column names to comments), params.provenance, and params.comment_mode. It executes one warehouse statement per comment, plus one information_schema.tables read when deciding a table comment; that read also runs in a dry run. With params.dry_run (default false), it returns the write statements without sending them. Use it for governance or annotation notes: comment_mode defaults to append here, so params.comment is added after the existing table comment once, and re-running the same note writes nothing. replace overwrites. The result reports table_comment_appended and comment_held_back; existing_comment_error identifies a failed comment read. If a write replaces existing text, the result names it in replaced_existing_comment, or would_replace_existing_comment in a dry run. An empty column comment is refused, naming the column. Column comments get the same treatment per column, and column_comments_written counts comment statements sent (or composed in a dry run), at the cost of one information_schema.columns read: the result lists column_comments_appended, column_comments_held_back and replaced_existing_column_comments (or would_replace_existing_column_comments), and existing_column_comments_error names a failed read. params.warehouse_id optionally selects the warehouse; otherwise the connection’s configured warehouse is used. apply_uc_tags accepts params.catalog and params.schema, optional params.table, params.schema_tags, params.tags, params.column_tags, params.certify (boolean, default false), params.dry_run (boolean, default false), and params.warehouse_id (otherwise the connection’s configured warehouse). It runs one warehouse statement per tagged schema, table or column. certify=true adds the governed tag system.certification_status=certified to the table. Dry runs that compose tag writes—including register_uc_assets, apply_uc_tags, and assign_to_domain—do not check account tag policies. Their response includes tag_policies_checked: false and a tag_policies_note; a governed key or a value disallowed by its policy can still be refused when the statements run. Use list_tag_policies to inspect the policies. declare_uc_keys takes params.catalog, params.schema, params.table, optional params.primary_key and params.foreign_keys[] in the shapes above, and the verify, rely, allow_schema_change, dry_run (default false), and warehouse_id controls. warehouse_id defaults to the connection’s configured warehouse. It scans the table once per candidate key and runs one statement per constraint, so it can incur warehouse compute. Verification is on by default, and a key whose data cannot be verified is not declared. params.rely is only the default for the call. params.primary_key and each params.foreign_keys[] entry may state its own rely, and the narrower statement wins, so one call can trust four measured keys and withhold RELY from a fifth. RELY licenses the query optimiser to rewrite queries assuming the constraint holds, so each key’s entry in the result reports the rely actually emitted on it — read that rather than success, which only covers the statements that were sent. The rely value accepts the boolean text spellings listed in the register_uc_assets parameter table above; other values are rejected. A key spec carrying a field the action cannot act on is refused naming it rather than accepted and ignored. Use describe_uc_registration before or after publishing. It requires params.catalog and params.schema, and optionally filters to params.table. It makes four aggregate information_schema reads on the selected warehouse (the connection’s configured warehouse unless params.warehouse_id is given): tables, columns, table tags and constraints. Check summary.counts_complete before using the column totals; unreadable counts are named in summary.unreadable_count_rows. The call costs four warehouse reads; params.dry_run is not supported for this read action. create_metric_view creates or replaces a metric view with one warehouse statement. It requires params.catalog, params.schema, params.name, and params.spec; optionally pass params.comment, params.dry_run (default false), and params.warehouse_id (otherwise the connection’s configured warehouse is used). spec requires source and at least one measure. Its optional dimensions[] and measures[] entries each have name and expr, with optional window and partition. Optional joins[] entries have name, source, and either on or using[]; declared foreign keys are not inferred. The action generates YAML from this structured spec rather than accepting YAML or SQL text. View-level descriptions use params.comment; dimensions and measures cannot carry comments. The result includes a query_hint using MEASURE() for the first measure. list_metric_views identifies metric views; see the section above for its listing behavior.

Databricks Genie spaces and semantic-layer binding

These databricks_action actions manage Genie spaces directly; they are separate from mcp_admin_tools’ runtime add_genie_space, which exposes an existing Genie space as MCP tools. Register Unity Catalog comments before binding: Genie space table entries have no column list, so column meaning comes from Unity Catalog comments. See the registration actions above. bind_semantic_layer_to_genie discovers tables and metric views in a schema, copies each table comment to its Genie description, and creates a new space or updates an existing one. It requires a SQL warehouse for one information_schema query; creating a space also uses that warehouse as the space’s query warehouse. An existing space keeps its own warehouse unless params.warehouse_id is passed. The default binds all discovered tables; use params.only_metric_views=true to bind only metric views. params.verify_question optionally asks the bound space and returns its generated SQL and answer, incurring Genie planning and warehouse compute in addition to discovery and the write. A verification failure does not undo a successful binding. Check discovery.tables_without_comments and discovery.descriptions_complete to see whether all bound tables have comments. discovery.tables_skipped_unnameable and discovery.schema_fully_bound report table names that could not be represented safely. A schema with more than 200 discovered data sources is refused; use the returned names with create_genie_space or update_genie_space to select a smaller set.
Use create_genie_space to author a space from explicit sources instead of discovering a whole schema. It requires params.title and at least one of params.tables, params.metric_views, or params.volumes; table and metric-view entries are strings or {identifier, description} objects. Optional content includes params.instructions (text or lines), params.sql_expressions[] (display_name, sql, optional comment), and params.benchmark_questions[] (question, answer_sql). It resolves params.warehouse_id from the explicit value or the selected connection and makes one HTTPS POST; no compute is billed until the space is asked a question. Set params.dry_run=true to inspect the payload without writing. list_genie_spaces accepts params.page_size (default 100, maximum 1000) and params.title_contains (case-insensitive, client-side filter). It makes one HTTPS GET per page, up to 50 pages; check complete and unreadable_rows before treating the returned list as exhaustive. get_genie_space requires params.space_id, makes one GET, and returns the parsed serialized_space and etag for a later guarded update. update_genie_space requires params.space_id and an explicit params.mode (merge or replace). It may also update params.title or params.warehouse_id, or content sections: params.tables, params.metric_views, params.volumes, params.instructions, params.sql_expressions, and params.benchmark_questions. In replace mode, content this call omits is removed. In merge mode, the action reads the current space and rewrites only named sections, preserving the others; it sends the read etag so concurrent changes are refused. A merge normally costs one GET plus one PATCH. If the workspace refuses that etag with modified since this export was taken, the action re-reads and re-merges once, then retries with the fresh etag. If that write is refused too, it reads once more: an unchanged etag allows one final PATCH without an etag, while a changed etag stops the update without writing. The result’s etag_conflict explains a retry; an edit saved between the final read and an etag-less write would not be kept. Retrying can add up to two GETs and two PATCHes. A caller-supplied params.expect_etag is never retried past. Replace costs one PATCH. For an explicitly guarded replace, pass params.expect_etag from get_genie_space. Both write modes accept params.dry_run=true. delete_genie_space requires params.space_id and params.confirm_title, which must exactly match the current title. It reads the live title before deleting; params.dry_run=true performs that check without deleting. The action cannot establish who created a space, so only delete spaces you own. ask_genie requires params.space_id and params.question. It runs a Genie planning pass and the generated SQL on the space’s warehouse, typically taking 20–60 seconds and billing compute. The result includes generated_sql, answer, and a sample of result rows; params.include_rows defaults to true and params.max_rows defaults to 50 (maximum 1000). params.timeout_seconds defaults to 180 (maximum 900). A timeout returns success: false with conversation and message IDs; Genie may still finish after the wait ends. Stopping the tool cancels SQL execution if it has started, but does not cancel Genie planning.

Unity Catalog domains and governed tag policies

Domains are a Public Preview capability behind the account-admin “Domains and Discover Page” preview. The domain REST API is Beta. A domain requires an account-level tag policy, and assigning an asset to a domain sets that policy’s governed tag on the asset. These operations use REST calls except for assign_to_domain, which runs one warehouse statement per asset.
  • list_tag_policies takes no action-specific parameters and returns the account-level policies visible to the identity with one HTTPS request.
  • create_tag_policy requires params.tag_key; optional params.description and params.allowed_values[] define the policy; params.dry_run defaults to false. Creating a policy writes an account-level object, not a workspace-scoped setting. It makes one HTTPS POST and, when allowed values are supplied, one PATCH to store them; inspect allowed_values_stored before assigning values.
  • create_domain requires params.tag_key for an existing policy. Optional params.subtitle, params.description, params.parent_domain_id and params.icon are sent with the domain; params.dry_run defaults to false. It lists domains and then makes one HTTPS POST only when no domain exists on that key. A listing error prevents creation.
  • list_domains takes optional params.parent_domain_id to filter visible domains and makes one HTTPS GET. A non-empty result carries visibility_limited: false and reports the visible count. An empty result carries visibility_limited: true and says that this identity cannot see any domains, while some may exist; when filtering by parent, the message names that parent. It does not prove none exist.
  • assign_to_domain requires params.tag_key, params.value (one allowed by its policy), and params.assets[]. Each asset has catalog, schema, and optional table; omitting table assigns the schema. params.dry_run defaults to false and returns statements without running them. params.warehouse_id optionally selects the SQL warehouse; otherwise the connection’s configured warehouse is used.

Unity Catalog Pages

Unity Catalog Pages hold governed definitions of business concepts and are read by Genie when published. Pages have no public Databricks API; these actions use the Databricks console’s undocumented, unsupported GraphQL API, which can change without notice. Use them only for an attended, one-time glossary seed or migration, not in scheduled or recurring work. Enable tools.databricks.unity_catalog_pages_enabled (default false) in Genesis configuration before calling them. The setting is read for each call, so turning it off blocks the next call without a restart. When disabled, each action refuses and sends nothing to the workspace. For configuration details, see Unity Catalog Pages authoring. A Page must belong to an existing Domain. Use list_domains to find its ID, or create an account tag policy and Domain with create_tag_policy and create_domain first. New Pages are DRAFT, invisible to users and unread by Genie until published. All write actions accept params.dry_run (default false) to inspect payloads without sending them.

Unity Catalog external metadata and lineage

Use external metadata when the source system will remain alongside Databricks: it creates foreign-system objects as Unity Catalog securables and can connect them to Unity Catalog tables. For a migration from a system being retired, use register_uc_assets to put provenance on the real Databricks table instead. External metadata and lineage consume per-metastore limits of 10,000 objects and 100,000 relationships. External lineage is visible in Catalog Explorer and through this API, but is not written to system.access.table_lineage or system.access.column_lineage. publish_external_metadata requires params.name; optional fields are params.system_type, params.entity_type (default asset), params.description, params.url, params.columns[], params.properties, and params.dry_run (default false). Names are lowercased and may contain only letters, digits, -, _, :, and @; periods, spaces and forward slashes are not accepted. Supported system_type values are AMAZON_REDSHIFT, AZURE_SYNAPSE, CONFLUENT, DATABRICKS, GOOGLE_BIGQUERY, KAFKA, LOOKER, MICROSOFT_FABRIC, MICROSOFT_SQL_SERVER, MONGODB, MYSQL, ORACLE, OTHER, POSTGRESQL, POWER_BI, SALESFORCE, SAP, SERVICENOW, SNOWFLAKE, STREAM_NATIVE, TABLEAU, TERADATA, and WORKDAY. If omitted, the type is OTHER. A create conflict is updated with a patch. list_external_metadata optionally takes params.name_prefix and params.entity_type; both filters are client-side, so all pages are still read. params.page_size defaults to 1000 and is capped at 1000. The result includes objects_examined, pages_read, complete, and the observed metastore budget. The listing stops after 50 pages; complete=false means it is only a prefix. It makes one HTTPS GET per page, up to 50. delete_external_metadata requires params.name and makes one HTTPS DELETE. Delete lineage relationships first: removing an object can make its edges unlistable without proving they were released from the relationship limit. Lineage endpoints are objects such as {type: "external_metadata", name: "source:table:orders"} or {type: "table", name: "main.analytics.orders"}. The other supported types are path (provide url, or use name as the URL) and model_version (provide name and version). publish_external_lineage requires params.source and params.target; optional params.columns[] contains {source, target} column pairs, params.properties adds string properties, and params.dry_run defaults to false. Declare external-object columns before publishing edges that map those columns. Publishing makes one HTTPS POST; a duplicate edge is reported unchanged rather than patched. list_external_lineage requires params.object_type and params.direction (UPSTREAM or DOWNSTREAM). For a path, pass params.object_type="path" and params.url; other endpoint types use params.object_name, and a model_version also needs params.version. Optionally pass params.page_size (default 1000, maximum 1000). The request reads one direction and returns complete to show whether another page exists. delete_external_lineage requires the original params.source and params.target endpoint pair; it accepts params.dry_run (default false) and makes one HTTPS DELETE when not in dry-run mode. publish_context_subgraph publishes a set of Genesis graph nodes and data-flow edges together. It requires params.name_prefix and params.nodes[]; pass params.edges[] for graph edges, params.default_system_type as an optional fallback, and params.dry_run (default false) to inspect all payloads before sending requests. Each node uses its qualified_name and may include entity_type, description, url, columns[], properties, or system_type. The prefix namespaces encoded names, and the full qualified name is retained in the external object’s properties. Optional params.uc_table_targets maps qualified names to three-part Unity Catalog table names to add migration edges; params.column_maps maps each qualified name to [{source, target}] pairs. Each graph edge identifies nodes with actor_id (or source) and target_id (or target), and may set properties.edge_type and operation. Nodes are sent before edges. The result counts skipped placeholder nodes, non-data-flow edges, and dangling edges. Only data_flow and executes graph edge types are published (an edge without properties.edge_type defaults to data_flow); READS edges reverse source and target to represent the direction of data flow. Review metastore_budget_consumed before a large publish. Each object and edge makes an HTTPS request (an existing object may require a second PATCH); no SQL warehouse compute is used.

Lakeflow Designer visual flows

A Lakeflow Designer flow is the canvas rendering of a pipeline: operators wired together that a person opens and edits in the Databricks editor. On disk it is a notebook whose path ends .designer.ipynb, which is what makes the workspace store it as a DESIGNER_FILE; one notebook cell is one canvas node, and the graph lives in a YAML docstring at the top of each cell. Genesis emits that graph and the generated code body each cell carries beneath it. A generated flow has been measured to open as a complete, editable canvas, including its operators, names, edges, ports and positions. Whether a generated flow runs without being edited first has not been established. Every result carries run_readiness with that limitation; treat the flow as a drawing to review and edit, not as a verified runnable pipeline. describe_designer_templates returns the 16 canvas operators with their template_version, input ports, output ports, ports that accept several inputs, and default config; pass params.template for one of them. It reads a catalog embedded in Genesis and makes no request. Call it before writing a flow specification: the vocabulary is not guessable, and a wrong value produces a file that opens as an empty canvas with no error. The palette’s “Select” operator serialises as template transform; a filter has two output ports, filtered_data and excluded_data; a join’s inputs are left and right while the other operators use their listed ports; and a row limit is a string. Five palette operators — Notifications, Guardrails, Note, Group and Visualization — have no captured schema and are named as such rather than refused as unknown. generate_designer_flow requires params.name and params.nodes[], each {id, template, name?, config?, position?}, and takes params.edges[] of {from, to, output_port?, input_port?}. A port defaults to the template’s first, which is the kept rows for a filter. Edges may instead be embedded on a node as input[], the spelling get_designer_flow returns. Nodes without a position are laid out left to right by dependency depth on the editor’s own grid; params.layout sets column_spacing, row_spacing, origin_x and origin_y, and a node carrying position keeps it. The whole specification is validated before anything is emitted — unknown template, unreal port name, edge to a missing node, a cycle, or a second edge into a port that takes one input — so a refusal means nothing was produced. The notebook is returned only with params.include_content=true; content_sha256 and content_bytes travel either way. Nothing is sent to the workspace. render_pipeline_as_designer_flow takes params.pipeline of {name, steps[]}, each step {id, kind, name?, inputs?} plus that kind’s own arguments: table or path for a read, condition for a filter, columns for a select or a drop, renames for a rename, join_keys for a join, query for SQL, code for the python and custom kinds, and a three-part table for a write. Edges come from inputs, and a join’s two inputs land on left and right in the order given, which is also the order its conditions address them. Supported step arguments are composed into operator config. Other kinds render with the operator’s default config and are counted in steps_with_default_config and named in warnings; pass step.config to set or override config explicitly. Missing required read or write arguments are refused unless step.config supplies them. Nothing is sent to the workspace. publish_designer_flow takes everything either generator takes, or params.pipeline, plus params.path. The designer extension is added when the path lacks it, and the result reports the path written. The path is read first: an existing flow that already matches is reported unchanged and not rewritten, and an object that is not a designer file is refused rather than overwritten. result.url opens the canvas at /editor/designer-files/<object_id>, which is not the workspace path URL. Publishing creates the containing folder if needed, and makes 3-5 HTTPS requests plus one connection-details lookup for the canvas link; re-publishing an existing flow adds an export to compare it. It starts no compute. list_designer_files requires params.path and takes params.recursive (default true). The workspace listing has no type filter, so every object is read and objects_examined reports how many; complete=false means the walk reached its 200-directory ceiling and the rows are only a prefix. It makes one HTTPS GET per directory, up to 200, and one connection-details lookup when flows are found. get_designer_flow requires params.path and parses each cell’s YAML back into nodes and edges, dropping the codegenHash and previewCodeHash values the editor stamps on a node it has evaluated; a cell that does not parse is listed in unparsed_cells with its index and the reason, and complete goes false. delete_designer_flow requires params.path and reads the object type first, refusing anything that is not a designer file. Get makes two HTTPS GETs plus a connection-details lookup; delete makes one HTTPS GET and one POST. Both answer about the path given, unchanged.

delete_pipeline cascade survivors

Use delete_pipeline with params.pipeline_id and an explicit params.cascade. When params.cascade=true, the action reads the pipeline’s target catalog and schema, inventories that schema before deletion, and then sends the delete request. Metric views are read from the Unity Catalog REST catalog. Tables whose names start with __materialization_mat_ are read from information_schema.tables using one SQL statement on a SQL warehouse. Pass params.warehouse_id to select the warehouse explicitly; otherwise the action uses the warehouse metadata stored with the connection. The warehouse must already be RUNNING, because this action never starts a warehouse. The action returns the delete result together with target_catalog, target_schema, and the following survivor fields:
  • survivors_in_target_schema: metric views (table_type is METRIC_VIEW) and tables whose names start with __materialization_mat_ that were present in the target schema before deletion. These objects are named, not dropped. If no survivor is known while either surface was unread or failed, this field is null, not an empty list.
  • survivors_complete: true only when both the Unity Catalog listing and the information_schema.tables read reached their end; false when either surface is incomplete or unavailable. An empty list is returned only after both reads completed and found no survivor.
  • survivors_unknown_reason: which survivor class could not be checked and why, including when no SQL warehouse is available, the warehouse is not RUNNING, or the SQL read fails.
The inventory is schema-wide and class-based, not a verified dependency check: an unrelated metric view in the same schema is included, so confirm ownership before acting on any listed object. A metric view whose source table the cascade removed can keep resolving to nothing, causing dashboards and Genie agents to fail with UC_DEPENDENCY_DOES_NOT_EXIST until the view is dropped or repointed. With params.cascade=false, no schema inventory is performed and the survivor fields are likewise unavailable. The REST listing costs one HTTPS request per page and no warehouse compute; the materialization-table check costs one warehouse-state request and, only for a RUNNING warehouse, one SQL statement whose compute is billed for the statement’s duration.

Workspace transfer safety for copy_workspace_object and move_workspace_object

If a transfer returns requires_confirmation: true, present the exact source and destination connections and paths, the overwrite impact, and the non-atomic move warning when applicable. Wait for an explicit user reply before retrying with confirm_overwrite=True or confirm_move=True; never self-confirm. If the destination already exists with a different object type, choose a different target_path instead of overwriting.move_workspace_object always requires confirm_move=True before deletion. Moves are verified copies followed by best-effort source deletion and are not atomic across workspaces. If a transfer is partial or indeterminate, retain the source and inspect both paths rather than retrying automatically.

edit_workspace_file

Use edit_workspace_file to change an existing Workspace NOTEBOOK or FILE without sending the whole object through the tool. It reads and writes content server-side using the selected Databricks connection. Supply the absolute Workspace path either as the top-level argument or as params.path; if both are supplied, they must name the same object. The action does not edit canonical onboarding notebooks; use the guarded create_notebook action for those. Choose exactly one edit mode: An exact-span edit is refused if the text has zero or multiple matches. A cell edit without expected_cell_sha256 returns its current hash and a bounded cell preview without writing. Notebooks keep at least one cell, so the last cell cannot be deleted. Supported notebook languages are PYTHON, SQL, SCALA, and R. When replacing or inserting a %md cell, include the # MAGIC prefixes in cell_source as they appear in the notebook source. The result includes before/after SHA-256 hashes, byte counts and delta, and a bounded unified diff (diff_truncated indicates that the diff was cut). Applied edits are exported again and report whether the stored content matches the proposed text. Content itself is not returned. An applied edit makes four Workspace API calls (status, export, import, and verifying export); a dry run uses two (status and export).

sync_from_git path mapping

sync_from_git maps each selected source to the requested target_workspace_path before uploading it. For a directory, the directory’s basename becomes the first path component and repository ancestors above that directory are not reproduced. For example, selecting projects/acme/notebooks with target_workspace_path="/Workspace/Shared/project" deploys projects/acme/notebooks/analysis.py to /Workspace/Shared/project/notebooks/analysis (the .py notebook-source extension is removed). A single source file such as projects/acme/job.py deploys directly to /Workspace/Shared/project/job. Set preserve_structure=False to flatten all selected files to their basenames. The response includes sorted deployed_paths with the exact workspace paths accepted by Databricks. The success message lists up to 10 paths and reports how many additional paths were deployed. If a computed path diverges from the requested target, the file is not deployed and the response includes misplaced_files with success: false. If different source files claim the same destination, none of those contested destinations are deployed; the response includes colliding_files and marks the sync unsuccessful.

Use Cases

  1. Automated data processing Run ELT notebooks on a schedule and collect run logs for audit.
  2. ML training orchestration Kick off parameterized training runs and export resulting notebooks or metrics.
  3. Cross-environment promotion Copy or move existing Workspace notebooks and files between Databricks connections with content verification, or sync notebook source files and workspace assets from Git into /Workspace/... while preserving folder structure.
  4. Operational monitoring Poll execution status, capture stdout and error traces, and surface results to stakeholders.
  5. Batch SQL orchestration Submit related DDL or DML statements together with run_sql_batch when a workflow needs ordered execution.
IMPORTANT: Notebook execution can modify data and incur compute costs. Use non-production clusters for testing and set wait limits conservatively.

Workflow/How It Works

  1. Authenticate Provide connection_id, or configure DATABRICKS_HOST and DATABRICKS_TOKEN. Databricks Apps must use a Databricks connection: PAT connections and direct bearer-token overrides are refused there; choose a User OAuth or Service Principal (OAuth M2M) connection.
  2. Choose an action For example copy_workspace_object, create_notebook, sync_from_git, upload_file, run_notebook, or run_sql_batch.
  3. Provide context Set path, target_connection_id, target_path, source_paths, target_workspace_path, file_path, params, and other action-specific inputs as needed.
  4. Execute and observe Receive job or run identifiers, then fetch logs or results until completion.
  5. Promote or share Export artifacts, store with file_manager_tools, and link runs back to tasks or tickets.
Use consistent workspace paths like /Workspace/Shared/project. For an existing Workspace notebook or file on another connection, use copy_workspace_object or move_workspace_object. For a single new notebook, use create_notebook; for repo-backed files, use sync_from_git. upload_file is for DBFS and Unity Catalog Volume paths, not workspace paths.

Integration Relevance

  • data_connector_tools: Open connections and run SQL inside notebooks that the action executes.
  • file_manager_tools: Capture notebook exports or logs and attach them to missions or tasks.
  • project_manager_tools: Track notebook work as todos with linked runs and outcomes.
  • git_action: Version notebook source, diffs, and promotion artifacts.
  • dbt_action: Coordinate dbt transformations before or after a Databricks notebook run.

Configuration Details

  • Generate a Databricks personal access token with the permissions required for your operations.
  • Prefer connection_id over direct host and token handling when possible.
  • Ensure cluster_id points to a running or auto-start cluster that your token can access.
  • Align format with your import or export destination.
  • sync_from_git supports notebook source files .py, .sql, and .scala, plus workspace file types .md, .csv, .json, .yaml, .yml, .txt, .toml, .cfg, .ini, .xml, .html, and .r.
  • For notebook source files, sync_from_git writes the Databricks notebook header with the file’s language comment marker: # Databricks notebook source for Python, -- Databricks notebook source for SQL, and // Databricks notebook source for Scala. If a source file already has a header with a different marker, Genesis replaces it so the uploaded notebook has exactly one language-correct header.
  • bulk_upload recognises Databricks notebook headers in .py, .sql, and .scala files uploaded outside /Volumes/. When the first line is a language-specific Databricks notebook header, the response includes a non-blocking warning recommending sync_from_git, which removes the source extension when importing notebooks.
  • bulk_upload and sync_from_git never include .git metadata, regardless of include patterns. sync_from_git also refuses source paths outside the selected repository or paths that resolve into .git.
  • run_sql_batch requires params.statements and accepts up to 50 SQL strings in one call.
  • Parameter names in params must match widgets or parameter parsing in the notebook when you use notebook execution actions.

Limitations or Notes

  1. Requires valid workspace access and API permissions.
  2. API rate limits and cluster capacity can throttle concurrent runs.
  3. Large exports or logs may take time to transfer.
  4. sync_from_git requires explicit source_paths; the repo root values "", /, ., and ./ are rejected.
  5. upload_file does not support /Workspace/... or /Users/... destinations.
  6. copy_workspace_object and move_workspace_object support only NOTEBOOK and FILE objects. Notebook languages must be PYTHON, SQL, SCALA, or R. Each object is limited to 10 MB for Workspace export/import. Directories, repos, libraries, and dashboards are not supported.
  7. Some advanced workspace features are not exposed in REST endpoints.
  8. Tokens expire and must be rotated according to your security policy.

Output

  • Create and update Confirmation with notebook metadata and path.
  • Run execution Run or job identifier, life-cycle state, result summary, and log access.
  • Failed notebook runs By default, check_run_status and run_notebook_live return a bounded error_digest containing the error class, exception type, message, SQLSTATE, notebook cell and line, source line, and Spark suggestions, plus trimmed error rows with the task, message, and traceback excerpt. Repeated task failures are de-duplicated, and additional rows are counted in errors_omitted. When trimming removes at least 4 KB, the untrimmed errors are saved and the response includes error_trace_spill_path and guidance for reading the file from the apps repository. If saving fails, the response explains that only the digest and excerpt remain. Set verbose_errors=True to receive the raw error payload, including the full JVM stack, Spark logical plan, and duplicated task rows.
  • Listing Arrays of notebooks with paths, languages, and modification timestamps.
  • Import and export Content in the requested format and related download details. For get_notebook and export_notebook, the response includes language and language_source. language is the language reported by the export response or workspace object metadata, and is null when neither source reports one; it should not be assumed to be PYTHON. language_source is one of export response, workspace get-status, not reported, or metadata unreadable, so callers can distinguish an absent platform value from a metadata lookup failure.
  • SOURCE notebook imports When a create_notebook import with format="SOURCE" may have malformed separators, unprefixed magic directives, or empty cells, the response includes a non-blocking structural_warnings array with human-readable line or cell diagnostics.
  • sync_from_git validation Repository notebook syncs return per-file validation results and, when applicable, unvalidated_files, drifted_files, structure_lost_files, unverified_files, and aggregated structural_warnings. A sync with an unvalidated file returns success: false.
  • Workspace transfer Source and destination metadata, exact-content validation (validation with SHA-256 and byte count), destination URL, and partial-move state such as copy_completed, source_deleted, and source_retained. Confirmation responses include requires_confirmation, confirmation_fields, and suggested_next_calls.
  • Pipeline deletion delete_pipeline returns survivors_in_target_schema, survivors_complete, and survivors_unknown_reason alongside the delete result when applicable. published_tables_dropped remains null because the action does not read the schema after deletion.
  • Errors HTTP status, Databricks error code, message, troubleshooting hints, and for invalid action values a suggested close match plus valid_actions when available.