CLI Reference¶
Shell Completion¶
dao-ai supports tab-completion of subcommands and flags via
argcomplete (a core dependency —
nothing extra to install). Enable it once in your shell:
bash — add to ~/.bashrc:
zsh — add to ~/.zshrc:
Restart the shell (or source the rc file), then dao-ai <TAB> completes
subcommands and dao-ai agent sync --<TAB> completes flags.
Global Options¶
-p/--profile and -v/--verbose are accepted at any level (before or after the
subcommand). When --profile is set, dao-ai clears the ambient DATABRICKS_*
environment variables (DATABRICKS_TOKEN, DATABRICKS_HOST,
DATABRICKS_CLIENT_ID, DATABRICKS_CLIENT_SECRET, DATABRICKS_AUTH_TYPE) for
the current process so the profile is authoritative. This prevents a stray token
or host in your shell or a .env file from silently overriding the profile and
targeting the wrong workspace. If you rely on env-var auth, omit --profile.
Config Sources: local, URL, or git¶
Every command that takes -c/--config accepts a local path, an http(s) URL, or
a git locator — so a project that isn't on your machine runs like one that is.
# Local path
dao-ai validate -c config/my_config.yaml
# Git locator: repo, optional @ref, optional #path-in-repo
dao-ai validate -c 'git+https://github.com/org/repo@v1.0#examples/retail/agent.yaml'
# gh: shorthand
dao-ai agent up -c 'gh:org/repo@main#examples/retail/agent.yaml' -p my-profile
# Split spelling — handy when a repo ships several config variants
dao-ai agent up --from 'gh:org/repo@v1.0' -c examples/retail/agent.yaml -p my-profile
# SSH remote (auth via ssh-agent)
dao-ai validate -c 'git+ssh://git@github.com/org/private@v1#agent.yaml'
--from can only mean a repository, so the git+ prefix is optional there — paste
the URL straight from your browser, or use an scp-style SSH reference:
dao-ai agent up --from 'https://github.com/org/repo@v1.0' -c agent.yaml -p my-profile
dao-ai agent up --from 'git@github.com:org/repo.git' -c agent.yaml -p my-profile
In --config the prefix is required, because there the distinction carries
meaning: a plain https:// URL fetches a single YAML (and rejects a config with
relative assets), while git+https:// brings the whole tree.
Quote the locator. # starts a comment in every common shell, so an unquoted
locator loses its in-repo path.
Unlike a URL — which fetches a single YAML and therefore rejects a config
declaring relative ddl / data / code_paths — a git locator brings the whole
project tree, so colocated assets, src/, skills/, and resources/ all resolve
exactly as they do locally.
@ref may be a branch, tag, or full 40-character commit SHA; omit it for the
remote's default branch. #path may name a file or a directory; omit it (or point
at a directory) and dao-ai discovers the config, preferring dao-ai.yaml and
erroring with the candidates listed if the choice is ambiguous.
| Flag | Purpose |
|---|---|
--from REPO |
Repository to load from (git+ prefix optional); -c is then a repo-relative path |
--refresh |
Re-fetch even if the ref is already cached |
Trust. A git locator runs the repository's code — a config can ship Python via
code_paths / src/ and inline tool code — exactly as git clone followed by
dao-ai agent up would. The resolved commit SHA is reported on every load. Pin a
tag or SHA for repositories you do not control.
Where things land. A git locator has no project directory, so it uses
~/.dao-ai for both the checkout and the bundle it stages:
| Path | Scope | |
|---|---|---|
| Checkouts | ~/.dao-ai/git/<host>/<owner>/<repo>/<sha>/ |
machine |
| Staging (locator) | ~/.dao-ai/bundle/<repo>-<digest>/<kind>/<app>/ |
machine |
| Staging (local config) | ./.dao-ai/bundle/<kind>/<app>/ |
project |
A local config still stages beside its project, which is where you want build
output you're iterating on. A locator stages machine-level and is keyed by
repository plus in-repo config path, so the same locator reuses one staging dir
(and its idempotent-skip) no matter which directory you run it from — and two
projects that happen to name their app the same thing can't collide.
$DAO_AI_GIT_CACHE and $DAO_AI_BUNDLE_DIR override each; -s/--staging-dir
overrides everything.
Caching. Checkouts are keyed by commit, so a full SHA is immutable and never
re-fetched. A branch or tag is re-resolved via git ls-remote on each run and
re-fetched only when it moved, so up on a branch always deploys its current
HEAD; if the remote is unreachable, the newest cached checkout is used with a
warning. Nothing expires on its own:
dao-ai cache dir # both locations, with counts and sizes
dao-ai cache clear # remove every checkout
dao-ai cache clear --repo gh:org/repo # remove just one repository's
dao-ai cache clear --bundles # remove the staged bundles instead
Private repositories. Auth is delegated to git, so ssh-agent and credential
helpers work with no dao-ai configuration. For headless use (a notebook, CI) set
DAO_AI_GIT_TOKEN or GITHUB_TOKEN; it is handed to git through a credential
helper and never written to disk, never placed in a remote URL, and never in a
command line.
Requires git on PATH. Resolution is client-side only — the generated bundle is
self-contained, so nothing needs git at deploy or run time.
Validate Configuration¶
Check your configuration for errors:
dao-ai validate -c config/my_config.yaml
# With parameter overrides (repeatable)
dao-ai validate -c config/my_config.yaml --param catalog=main --param module_id=09
Generate JSON Schema¶
Generate JSON schema for IDE support and validation:
Visualize Agent Workflow¶
Generate a diagram showing how your agent works:
dao-ai graph -c config/my_config.yaml -o workflow.png
# With parameter overrides
dao-ai graph -c config/my_config.yaml -o workflow.png --param catalog=main
Deploy¶
Deploying an agent follows one lifecycle — build → sync → start — whether you
run it as three explicit steps or let a single command do all three. Start with the
one-command path and reach for the granular verbs only when you need them.
All deploy paths call AppConfig.create_agent() + deploy_agent() in-process: for
Model Serving it registers the MLflow model and creates the serving endpoint
(agents.deploy); for Apps it uploads the config + source and drives the Apps REST
API. Every path auto-links the UC trace destination and auto-grants the runtime
service principal the trace-write permissions (gated on app.manage_permissions).
Start here: up — build, sync, and start in one command¶
dao-ai agent up is the fast path to a live agent. It builds the bundle (if
nothing is staged), syncs it to the workspace, links the trace destination, then
starts it — the whole build → sync → start lifecycle in one idempotent command.
This is what you want most of the time.
# Bring up a Databricks App (default mode) — build → sync → start
dao-ai agent up -c config/my_config.yaml --profile fevm
# Bring up the MCP-server App
dao-ai agent up -c config/my_config.yaml --as-mcp --profile fevm
# Bring up on Model Serving (builds a thin deploy-agent Job, runs it to
# register the model + create the endpoint)
dao-ai agent up -c config/my_config.yaml --mode model_serving --profile fevm
up is safe to re-run: an unchanged config skips the build (config
checksum) and the sync is convergent, so re-running never duplicates the
bundle. The start step always executes — an app restarts, a model_serving job
re-runs and registers a new model version — which is start doing its job.
The --direct option — skip the bundle on disk¶
Add --direct to up to go straight through the SDK without writing a bundle to
disk. There is no staged artifact to inspect or hand-edit — dao-ai calls
create_agent/deploy_agent directly. It works for all three modes (apps,
mcp, model_serving) and inherently syncs and starts. Use it for fast iteration
when you don't need an auditable bundle artifact. --direct is an up-only flag
(it has no meaning on build/sync/start, which are defined by the bundle they act
on).
# Bring up as an App via the SDK directly — no bundle on disk (fast iteration)
dao-ai agent up -c config/my_config.yaml --mode apps --direct --profile fevm
The granular lifecycle: build → sync → start¶
When you want to inspect or hand-edit the bundle before it ships — or run the CI-style build once, sync once, start N times flow — drive the three steps yourself, in order:
# 1. build — stage the bundle to disk (inspect / hand-edit before shipping)
dao-ai agent build -c config/my_config.yaml --profile fevm
# 2. sync — push the staged bundle to the workspace (does NOT start it)
dao-ai agent sync -c config/my_config.yaml --profile fevm
# 3. start — make the synced bundle live (no re-sync; starts/restarts the app)
dao-ai agent start -c config/my_config.yaml --profile fevm
buildstages the bundle and does nothing else.sync/start/downrequire it first (they never build) — or useup, the one command that builds for you.syncpushes to the workspace but does not start the app (it runsdatabricks bundle deploy) and does not build — it errors if nothing is staged. Asyncthat failed on a transient error is safe to retry on its own — no rebuild.startmakes the synced bundle live (databricks bundle run <app>), and does not re-sync or rebuild — it errors if nothing is synced. Re-run it any time to restart an app or re-execute a model_serving/workflow job.
If
app.trace_locationis set, rundao-ai trace linkbetweensyncandstart— otherwise traces silently drop (TABLE_DOES_NOT_EXIST) on re-deploys. See Linking the UC trace destination. The one-commanduppath does this linking for you.
To ship the local dao-ai wheel instead of the published PyPI package, add
--development on build (or on up, which builds):
dao-ai agent build -c config/my_config.yaml --development --profile fevm
dao-ai agent sync -c config/my_config.yaml --profile fevm
Mode resolution: --mode flag wins; default is apps.
No extra install is required: a plain pip install dao-ai is enough to deploy to
any mode. Model Serving logs the MLflow model in-process, which touches
spark-connect — the core databricks-connect dependency supplies a
protobuf-5-compatible pyspark for this, so do not add a standalone pyspark
(pyspark 4.x needs protobuf ≥ 6.33 and collides with databricks-ai-search's
protobuf < 6 cap; see issue #211). The Databricks runtime provides its own Spark,
so this local stack never ships to the deployed endpoint.
When to use which:
dao-ai agent up— the one-command path (build → sync → start). Reach for this first for any mode:apps(default),mcp, ormodel_serving.dao-ai agent up --direct— same, but SDK-direct with no bundle on disk. Best for fast iteration when you don't need an auditable bundle artifact.dao-ai agent build → sync → start— the granular flow. Use it to inspect or hand-edit the staged bundle before shipping, or for the CI pattern build once, sync once, start N times.dao-ai workflow— provision the full backing infra (schemas, Vector Search, Lakebase, Genie, UC functions) and deploy the agent, as a multi-task Databricks Job. The job's deploy step runs the samecreate_agent/deploy_agentcode as the direct deploy paths.
Bundle Generators: agent, workflow¶
The bundle generators are verb-under-noun commands — pick a noun for what you're shipping, then a verb for the lifecycle step:
| Noun | What it ships |
|---|---|
dao-ai agent |
A Databricks App running the agent graph (default: --mode apps). Use --as-mcp to emit the MCP-server App instead, or --mode model_serving on sync to go SDK-direct. |
dao-ai workflow |
A multi-task Databricks Job that provisions the backing infra (schemas, Vector Search, Lakebase, Genie, UC functions) and deploys the agent. |
Each noun takes the same five verbs:
dao-ai agent up|build|sync|start|down -c <cfg> [-p <profile>]
dao-ai workflow up|build|sync|start|down -c <cfg> [-p <profile>]
The mental model — plain-language lifecycle:
| Verb | What it does | Databricks CLI underneath |
|---|---|---|
build |
build the bundle artifact (stage to disk) | — (writes files) |
sync |
push the bundle to the workspace — does not start it | databricks bundle deploy |
start |
make it live — no re-sync | databricks bundle run <resource> |
up |
all-in-one: build-if-needed → sync → start (idempotent) | — (orchestrates the three) |
down |
tear the deployment down (never your data) | databricks bundle destroy (+ delete the serving endpoint for model_serving) |
The verbs are dao-ai's plain-language names for the DAB lifecycle; the "underneath" column is the
databricks bundlesubcommand each one runs. Notesyncrunsbundle deploy— the word "deploy" is the Databricks CLI subcommand, not the dao-ai verb; in dao-ai, syncing does not start the app.
The one-command path — up:
upis the fast path to a live agent: it builds the bundle (if nothing is staged), syncs it, links the trace destination, then starts it — equivalent tobuild → sync → startin one command. This is what you want most of the time:dao-ai agent up -c <cfg> -p fevm. For--mode model_servingit builds a thin deploy-agent Job bundle, syncs it, then starts it (bundle run deploy_job) — which registers the model and deploys the endpoint (the endpoint serves onceREADY). Add--direct(apps/mcp/model_serving) to go via the SDK with no bundle written to disk.upis safe to re-run. On the artifact-and-sync axes it is idempotent: an unchanged config skips the build (config checksum — see The staging dir is ephemeral build output below) and the sync is convergent, so re-runningupnever duplicates the bundle. Thestartstep, by contrast, always executes: an app restarts, and a workflow/model_serving job re-runs (a model_servingstartregisters a new model version each time). That is the start step doing its job, not an artifact/sync concern.
The granular lifecycle — build → sync → start → down:
buildstages a bundle to disk (<base>/<noun>/<app>, where<base>is$DAO_AI_BUNDLE_DIRor./.dao-ai/bundle, or-s <dir>) and does nothing else — inspect or hand-edit the staged files before shipping.syncpushes the already-built bundle to the workspace but does not start it, and does not build — runbuild(orup) first; it errors with the exact next command if nothing is staged. This is uniform across every noun and mode (agent/workflow×apps/mcp/model_serving) — a primitive acts on prepared state, it never provisions its own prerequisites. Foragent/mcp,syncrunsdatabricks bundle deploy— it creates/updates the App resource and uploads its source; a staged bundle is synced in place, and on config drift it warns and deploys as-is rather than rebuilding (runbuildorupto pick up the change). Use--mode model_servingonagent syncto sync the deploy-agent Job bundle.startmakes the synced bundle live and does not re-sync, build, or push — it errors if nothing is synced. Foragent/mcp,startrunsdatabricks bundle run <app>(starts/restarts the app — a DABs App is not serving untilbundle run); forworkflowandmodel_serving,startrunsdatabricks bundle run deploy_job(executes the job — for model_serving that registers the model and deploys the endpoint).startis the verb for the manual/CI flow — build once, sync once, start N times — and for restarting an app or re-executing a job without re-syncing.downtears the deployment down — it removes the deployment, never your data. Foragent/mcpit runsdatabricks bundle destroy, deleting the App. Foragent --mode model_servingit runsbundle destroy(removing the deploy_job) and deletes the serving endpoint — the endpoint is created by the deploy-agent job, not the DAB, sobundle destroyalone would leave it running and billing; the registered UC model + versions are kept (a reusable artifact). Forworkflow,downremoves the provisioning job and the agent it deployed — the App (apps/mcp) or serving endpoint (model_serving) thedeploy_agentstep created imperatively, whichbundle destroyalone would orphan. It does not delete the data infrastructure that job provisioned (Vector Search indexes, Lakebase, Genie spaces, UC schemas/functions); tear those down yourself if you no longer need them.
This is the payoff: a sync that failed on a transient error can be retried with
just dao-ai agent sync -c <cfg> -p fevm — no rebuild. To build, sync, and
start in one shot, use dao-ai agent up instead.
The staging dir is ephemeral build output. Everything in the default
staging dir (<base>/<noun>/<app>) is either generated from your config or
copied from the config directory (custom code_paths, src/ packages,
resources/ overlays, the rendered config), so build/up regenerate it in
place — a default dir is wiped and rebuilt on each run, and on config drift up
rebuilds it automatically. Don't hand-edit generated files — to add your own
Databricks resources (Jobs, Pipelines, …) to the bundle, drop a *.yml in a
resources/ directory next to your config (auto-shipped, like src/ for code),
or list files explicitly via app.resource_paths: [path/to/jobs.yml, …]; each is
copied into the bundle's resources/ directory where DABs'
include: [resources/*.yml] merges it at deploy, with no generated file touched.
Your own src//code_paths are always preserved (copied once, never
overwritten). A -s <dir> you supply is treated as your territory: it is never
auto-wiped, and its files follow the writer's per-file overwrite rules. The
source-selection flags --overwrite, --development, and --no-development
take effect on the verbs that build — up and build (--overwrite also
re-copies the user-owned artifacts for a full clean slate). sync/start/down
act on already-built artifacts and never build, so these flags don't apply
there.
Migration: the flat commands
generate-agent,generate-mcp, andgenerate-workflowhave been removed. Usedao-ai agent build,dao-ai agent build --as-mcp, anddao-ai workflow buildinstead. See Migration reference below.
Workflow: Provision and Deploy¶
The dao-ai workflow command deploys your agent to Databricks (under the hood it drives a Databricks Asset Bundle) and supports multi-cloud deployments with automatic cloud detection.
Basic Deployment¶
# Provision infra + deploy + run the deploy_job in one command
dao-ai workflow up -c config/my_config.yaml
# With parameter overrides
dao-ai workflow up -c config/my_config.yaml --param catalog=prod_catalog --param schema=prod_schema
# Re-deploy the already-staged bundle without regenerating (e.g. retry a transient failure)
dao-ai workflow sync -c config/my_config.yaml
--param (and the --var alias) values are baked into the staged config, and are also forwarded to the underlying databricks bundle ... invocation as --var only for names the generated databricks.yaml actually declares as bundle variables — so Databricks Asset Bundles' own ${var.NAME} substitution sees the same values when the names overlap, without failing on a dao-ai-only parameter the bundle doesn't declare.
Multi-Cloud Deployment¶
The CLI automatically detects the cloud provider from your Databricks workspace and selects the appropriate configuration (node types, etc.):
# Deploy to AWS workspace
dao-ai workflow up -c config/my_config.yaml --profile aws-field-eng
# Deploy to Azure workspace
dao-ai workflow up -c config/my_config.yaml --profile azure-retail
# Deploy to GCP workspace
dao-ai workflow up -c config/my_config.yaml --profile gcp-analytics
Granular Lifecycle¶
# Stage the bundle only (inspect / hand-edit before shipping)
dao-ai workflow build -c config/my_config.yaml --profile aws-field-eng
# Sync the staged bundle to the workspace (run `build` or `up` first — this does not auto-build)
dao-ai workflow sync -c config/my_config.yaml --profile aws-field-eng
# Start the deploy_job on an already-synced bundle (databricks bundle run deploy_job)
dao-ai workflow start -c config/my_config.yaml --profile aws-field-eng
Explicit Cloud Override¶
Cloud is auto-detected from the workspace URL. If detection can't determine it,
the command stops and asks you to pass --cloud explicitly:
Dry Run¶
Preview commands without executing:
Agent / MCP Bundle¶
Generate a complete, deployable Databricks Apps bundle directory from a dao-ai config file. This is distinct from the bundle command -- while bundle wraps databricks bundle deploy/run/destroy, dao-ai agent build creates the bundle project itself.
When the source config uses ${param.NAME} / ${var.NAME} parameters or ${workspace.*} references, the generated bundle writes the resolved config (all references substituted to literal values, parameters: block dropped) so the deployed app does not need the original --param flags or a runtime workspace lookup.
Basic Usage¶
dao-ai agent build -c config/retail.yaml -s ./my-bundle
# With parameter overrides baked into the generated bundle
dao-ai agent build -c config/retail.yaml -s ./my-bundle --param catalog=prod_catalog
# Generate, deploy, and start the app in one command
dao-ai agent up -c config/retail.yaml -p fevm
# Ship the already-staged bundle without regenerating (e.g. after hand-editing, or retrying a transient deploy failure)
dao-ai agent sync -c config/retail.yaml -p fevm
# Deploy the staged bundle, then start it
dao-ai agent sync -c config/retail.yaml -p fevm
dao-ai agent start -c config/retail.yaml -p fevm
MCP server bundles use dao-ai agent build --as-mcp (a protocol modifier on --mode apps, not a separate mode or noun). Use dao-ai agent start to databricks bundle run <app> an already-deployed bundle, and dao-ai agent down to tear it down. See Bundle Generators for the full lifecycle.
A chat App and an MCP server can coexist from one config.
--as-mcpdeploys under anmcp--prefixed App name (mcp-<app>), so it does not replace the chat App built from the sameapp.name— the two are separate App resources with separate bundles, service principals, and MLflow experiments. (The prefix is idempotent: anapp.namethat already starts withmcp-is left alone rather than becomingmcp-mcp-….) Multi-Agent Supervisor pattern-matches themcp-prefix when auto-discovering MCP-hosted Apps, so this is also the naming convention MAS expects.model_servingis unaffected — it keys its endpoint offapp.name/endpoint_name.
Output location¶
Both generators (agent, workflow) resolve where to write the bundle in this
order:
-s/--staging-dir <dir>— used verbatim.DAO_AI_BUNDLE_DIRenv var — bundles land at$DAO_AI_BUNDLE_DIR/<kind>/<app>(<kind>isagentorworkflow). Set this for a central location, e.g.export DAO_AI_BUNDLE_DIR=~/.dao-ai/bundle.- Default —
./.dao-ai/bundle/<kind>/<app>(per-app, so multiple configs never collide; gitignored).
The per-app <kind>/<app> structure is always appended to the env-var/default
base, so deploying many configs stays isolated. Under the agent noun the path
continues with the serving platform and, for Apps, the protocol — mirroring
the --mode / --as-mcp flags, so each combination is isolated and never
clobbers another:
| Command | Staging dir |
|---|---|
agent … --mode apps |
agent/<app>/apps/chat |
agent … --mode apps --as-mcp |
agent/<app>/apps/mcp |
agent … --mode model_serving |
agent/<app>/model_serving |
workflow … |
workflow/<app> (mode-agnostic) |
force-includes its own source via sync.include, so App deploys work even when |
|
| the bundle is staged under a git-ignored directory. |
What Gets Generated¶
The command creates a self-contained bundle directory with everything needed to deploy a Databricks App:
| File | Description |
|---|---|
databricks.yaml |
Bundle definition with app config, resources, and scopes |
<config>.yaml |
Copy of your dao-ai agent configuration (retains its original filename) |
pyproject.toml |
Python project with dao-ai dependency |
.gitignore |
Ignore patterns for build artifacts |
.python-version |
Python version pin (3.12) |
src/<package>/ |
Stub package for custom code |
resources/app.yml |
The App + experiment resource block (owned by dao-ai) |
resources/<your>.yml |
Your own resource overlays (see below) |
Extending the bundle with your own resources¶
The staging dir is regenerated on every build, so don't hand-edit generated
files. To add your own Databricks Asset Bundle resources (Jobs, Pipelines, …)
alongside the generated App, you have two options (they compose):
Convention — drop *.yml files in a resources/ directory next to your
config. They're auto-shipped with no declaration, exactly like src/ packages
are for code:
Explicit — list files anywhere (relative to the config dir) via
app.resource_paths:
app:
name: my_app
resource_paths:
- overlays/nightly_job.yml # relative to your config file's directory
Either way, each file is copied into the bundle's resources/ directory, where
the generated databricks.yaml's include: [resources/*.yml] merges it at
deploy — so your resources ship without touching a single generated file.
Overlays are user-owned: copied once and never overwritten by a rebuild (pass
--overwrite to re-copy). File basenames must be unique and may not be app.yml
(reserved for the generated App block). This works identically on the agent,
mcp, and workflow nouns.
Dependency install: pyproject.toml + portable uv.lock¶
dao-ai agent build writes a pyproject.toml and a portable uv.lock to the bundle (no requirements.txt — its presence would take precedence and force the pip path). The Databricks Apps build phase runs uv sync --locked --no-dev from them. Published mode (--no-development) pins dao-ai[<extras>]==<version> for reproducible redeploys; --development redirects dao-ai to the bundled local wheel via [tool.uv.sources]. uv lock records the full closure, and any internal-mirror host (pypi-proxy.dev.databricks.com) is rewritten to the public CDN so the lock resolves from Apps containers.
Pre-publish note: published-mode lock generation resolves
dao-ai==<version>from PyPI, so it fails with an actionable error until that version is published (release-time / CI). For local/pre-release iteration, generate with--development(locks against the bundled wheel — works anytime).
Upgrading dao-ai in an existing bundle¶
When you pip/uv upgrade dao-ai and want an already-built bundle on the new
version, the right move differs by surface — because the artifacts differ:
- Apps / MCP bundles — the deployed app installs dao-ai as a dependency
(
pyproject.toml+uv.lock), and new runtime behavior ships inside that wheel. The low-risk default is a version bump, not a regenerate: update the pin and re-lock, then redeploy.
# in the staged bundle dir (or edit pyproject.toml's dao-ai==<ver> then):
uv lock --upgrade-package dao-ai
dao-ai agent sync -c <config> -p <profile> # redeploy the same bundle
Only run a full dao-ai agent build --overwrite when you want to adopt a new
bundle shape (a dao-ai release that changed the generated databricks.yaml
/ resources/ layout). Because the staging dir is ephemeral and your resources
live in the config's resources/ dir (or app.resource_paths), a rebuild is
safe — nothing you authored is lost.
- Workflow bundles — the provisioning notebooks (
01–08) ship inside the dao-ai wheel and are materialized into the bundle at build time, so a stale bundle would run old notebooks against a new runtime. Always regenerate after an upgrade:
dao-ai workflow build -c <config> # re-materializes 01–08 from the new wheel
dao-ai workflow up -c <config> -p <profile> # or build + deploy + run in one step
When app.enable_chat_proxy is true (the default), the deployed app automatically clones and builds the Databricks e2e-chatbot-app-next chat UI at startup. The Apps runtime has Node.js pre-installed, so no Node.js is needed on your development machine. Set enable_chat_proxy: false to deploy without the chat UI.
Trace persistence on Apps requires trace_location¶
The default MLflow control-plane trace exporter does not work on Databricks Apps today: the artifact-storage host (us-east-1.storage.cloud.databricks.com) is unreachable from Apps containers and spans silently fail to upload. Watch for this line in databricks apps logs:
WARNING mlflow.tracing.export.mlflow_v3: Failed to send trace to MLflow backend:
HTTPSConnectionPool(host='us-east-1.storage.cloud.databricks.com', port=443):
... Connection refused
To capture traces, configure app.trace_location in your config so traces route through a SQL warehouse to UC OTEL tables (a path Apps CAN reach):
app:
name: my_app
# ...
trace_location:
schema: *retail_schema # reference an existing SchemaModel anchor
warehouse: "your-warehouse-id" # or a *warehouse anchor reference
When trace_location is set, agent build wires up the SQL warehouse as an App resource (CAN_USE for the App SP) and adds MLFLOW_TRACING_SQL_WAREHOUSE_ID to the App's env. The OTEL trace tables themselves are auto-created by MLflow at first trace write — dao-ai does not emit per-table grants because the tables don't exist at deploy time. After deploy, grant the App SP schema-level privileges (one-time):
SP=$(databricks apps get <app-name> -p <profile> --output json | jq -r .service_principal_client_id)
databricks grants update catalog <catalog> -p <profile> \
--json "{\"changes\":[{\"principal\":\"$SP\",\"add\":[\"USE_CATALOG\"]}]}"
databricks grants update schema <catalog>.<schema> -p <profile> \
--json "{\"changes\":[{\"principal\":\"$SP\",\"add\":[\"USE_SCHEMA\",\"CREATE_TABLE\",\"MODIFY\",\"SELECT\"]}]}"
When trace_location is unset, agent build emits a ⚠ warning to alert you. Local notebook/CLI runs and Model Serving deploys are unaffected.
See examples/01_getting_started/ai_gateway.yaml for a drop-in example.
Linking the UC trace destination — run dao-ai trace link between deploy and run¶
MLflow requires the UC trace-destination link to be established on an experiment before that experiment receives any traces. On a re-deploy (or after a trace_location change), the experiment already has traces from prior runs, so the app's runtime attempt to link is rejected with already contains traces and every subsequent trace silently drops with TABLE_DOES_NOT_EXIST.
The fix is a standalone CLI verb that links from your machine (operator credentials, deterministic timing) instead of relying on the running app to link itself:
databricks bundle deploy --target dev -p <profile>
dao-ai trace link -c my_config.yaml -p <profile>
databricks bundle run <app-name> --target dev -p <profile>
# then restart to pick up the freshly-linked destination:
databricks apps restart <app-name> -p <profile>
The verb is idempotent — safe on every deploy — but load-bearing on re-deploys and after trace_location changes. agent build prints a one-line reminder in its "Next steps" when trace_location is configured.
See Trace Commands for full flag reference and the migration playbook for moving traces between destinations.
Runtime trace-destination sync (apply_runtime_trace_destination)¶
dao-ai trace link writes the trace-destination tag on the experiment record so that future traces route to the configured UC schema. That works when MLflow's runtime picks up the linkage from the experiment — but if the app also has MLFLOW_TRACING_DESTINATION env set (dao-ai's agent build sets it as catalog.schema for warehouse routing), MLflow parses that env value as the deprecated UCSchemaLocation and populates the _MLFLOW_TRACE_USER_DESTINATION ContextVar accordingly. The ContextVar SHADOWS MLflow's auto-resolver from experiment tags, so the exporter targets mlflow_experiment_trace_otel_spans (the un-prefixed default) which doesn't exist on the prefixed schema — and every span export fails with TABLE_DOES_NOT_EXIST.
To close that gap, the App startup path (apps/handlers.py) and the MCP-server startup path (mcp/server.py) both call apply_runtime_trace_destination(config) from dao_ai.providers.databricks right after link_experiment_trace_location. The helper:
- When
trace_location.table_prefixis set: writes aUnityCatalog(catalog, schema, table_prefix)directly into_MLFLOW_TRACE_USER_DESTINATIONso the exporter picks<prefix>_otel_spans. - When
trace_locationis set buttable_prefixis unset: clears the ContextVar so MLflow's own_resolve_experiment_uc_locationreads the experiment-linkedUnityCatalog(with the backend-computed experiment-id prefix) from the tracking store. ConstructingUnityCatalog(catalog, schema)without a prefix raises at export time — clearing the ContextVar is the safe path. - When
config.app.trace_locationis None: no-op. Traces use the MLflow control-plane store.
The helper is only invoked from the two container entrypoints that HAVE ambient OAuth (Apps + MCP server). The Model Serving entrypoint (apps/model_serving.py) intentionally makes no in-container calls to MLflow — deploy-time agents.deploy() sets MLFLOW_EXPERIMENT_ID + MLFLOW_TRACING_DESTINATION + MLFLOW_TRACING_SQL_WAREHOUSE_ID on the endpoint, and the container relies on MLflow's env-driven routing (see the header comment in model_serving.py for the rationale — trying mlflow.set_experiment in the MS container hits an OAuth-config crash on any container whose model wasn't logged with the experiment as a resource dependency).
table_prefix is permanent per experiment¶
Once an experiment has been linked to a UC trace destination with a specific table_prefix, MLflow rejects any attempt to change it — you'll see already contains traces on the re-link. To change catalog / schema / table_prefix, provision a fresh experiment:
dao-ai trace create --name /Shared/my-app/dao-ai-fresh -p <profile>
# Then reference the new experiment id under `app.experiment.id` in the config,
# or rev `app.name` so the auto-declared experiment path is distinct.
Regenerating and Overwriting¶
The default staging dir (no -s) is ephemeral build output: build/up
regenerate it in place on every run (a default dir is wiped and rebuilt), so
there is nothing to hand-edit and nothing to lose. Add your own bundle resources
via a colocated resources/ dir or app.resource_paths (see Extending the bundle) rather than editing generated files.
For a user-supplied -s <dir>, existing generated files are skipped by
default; use --overwrite to rewrite them (and re-copy user-owned artifacts).
A -s <dir> is never auto-wiped. --overwrite is only valid on build/up.
Using a Databricks Profile¶
If your config references workspace resources (Genie rooms, warehouses, etc.), specify a profile so they can be resolved during generation:
Development Mode¶
Use --development to bundle a local build of dao-ai instead of pulling from PyPI. This is useful when testing unreleased dao-ai changes in a deployed app.
Development mode changes the generated bundle in several ways:
- Local wheel: Copies the dao-ai wheel from
dist/into the bundle. If no wheel exists, one is built automatically viauv build --wheel. - Path dependency: The generated
pyproject.tomluses a[tool.uv.sources]path dependency pointing at the local wheel instead of pinning a PyPI version. - No artifacts block: The
databricks.yamlomits theartifactssection so the wheel uploads as a regular source file rather than being intercepted by the artifact system. - Adjusted .gitignore: The
dist/directory is not ignored, since the wheel must be included in the bundle.
Next Steps¶
After building the bundle, the command prints the next steps. You can either drive Databricks directly, or use the sync/start verbs (which act on the staged dir without rebuilding):
# Option A — dao-ai verbs (deploy then start; or use `agent up` to do both at once)
dao-ai agent sync -c config/retail.yaml -p <profile>
dao-ai agent start -c config/retail.yaml -p <profile>
# Option B — drive databricks bundle directly
cd ./my-bundle
uv sync
databricks bundle deploy --target dev
databricks bundle run <app-name> --target dev
Trace Commands¶
The dao-ai trace group manages MLflow experiments and UC trace destinations.
dao-ai trace link¶
dao-ai trace link attaches an MLflow experiment to its Unity Catalog trace destination declared under app.trace_location. Run it as an explicit step between databricks bundle deploy and databricks bundle run — see the background above for why the app's runtime attempt is unreliable.
databricks bundle deploy --target dev -p <profile>
dao-ai trace link -c my_config.yaml -p <profile>
databricks bundle run <app-name> --target dev -p <profile>
databricks apps restart <app-name> -p <profile> # required — see below
Flags¶
| Flag | Purpose |
|---|---|
-c FILE, --config FILE |
Config file. Must set app.trace_location. |
-p PROFILE, --profile PROFILE |
Databricks profile for auth. |
--experiment-id ID |
Skip resolution and use this experiment id directly. |
--param KEY=VALUE / --var KEY=VALUE |
Config parameter overrides (repeatable). |
Experiment resolution¶
Tries in order:
--experiment-idexplicit override.config.app.experiment.resolved_idwhen the config sets an explicitexperiment:block.- Bundle-declared name lookup — tries both the plain
/Users/<user>/<app-name>name AND the DABs--target dev-prefixed variant/Users/<user>/[dev <sanitized-user>] <app-name>, so the same command works for prod deploys and personal dev deploys.
If none of the above resolves, the CLI prints the candidates and exits 1.
Two things that surprise operators¶
1. You must restart the app after linking. MLflow's OTEL exporter binds the trace destination at process startup. Running dao-ai trace link while the app is up does not retroactively route in-flight traces to the new location — the running exporter is already bound to whatever destination was in effect when it started. Trigger databricks apps restart <name> (or any bundle re-deploy) so the app picks up the fresh linkage.
2. A UC-linked experiment is permanently bound to that destination on Databricks. Verified against a live Databricks workspace (MLflow 3.11):
- Re-linking to the same destination — safe (idempotent, no error).
mlflow.tracing.unset_experiment_trace_location(...)— the OSS API exists (tracing/enablement.py:115-163), but the Databricks control plane explicitly rejects it:BAD_REQUEST: Unlinking an experiment from a Unity Catalog trace location is not allowed. Once linked, an experiment cannot be unlinked from its trace location.- Changing
table_prefix/catalog/schema— impossible, since you can't un-link first. Theunset → setswap that OSS MLflow supports does not work here.
There is no force, replace, or delete-and-recreate-linkage flag anywhere in the client or server API. The only recovery path is the fresh-experiment migration playbook below.
Migration playbook — moving traces to a new UC destination¶
When you actually need to change table_prefix, catalog, schema, or want traces to land somewhere new, you can't mutate the existing experiment — create a fresh one and re-point the app:
# 1. In your config, point at a new experiment. Two options:
#
# (a) Change the experiment name explicitly:
app:
experiment:
name: /Users/me@databricks.com/my-app-v2 # new path
# (b) Rename the app itself (auto-declared experiment path derives
# from app.name — a rename gives you a fresh experiment):
app:
name: my-app-v2 # was: my-app
# 2. (Optional) update trace_location. `table_prefix` is optional in
# dao-ai — if omitted, MLflow uses the experiment id as the prefix,
# which is fine (and often preferred) since a fresh experiment
# already gives you a fresh table namespace. Only set an explicit
# `table_prefix` when you want a human-readable name in the OTEL
# Delta tables (e.g. for dashboarding).
trace_location:
schema: *my_schema
warehouse: *my_warehouse
# table_prefix: my_app_v2_traces # optional
# 3. Deploy → link → run → restart.
dao-ai agent build -c my_config.yaml -s ./bundle --overwrite
cd ./bundle
databricks bundle deploy --target dev -p <profile>
dao-ai trace link -c ../my_config.yaml -p <profile>
databricks bundle run <new-app-name> --target dev -p <profile>
databricks apps restart <new-app-name> -p <profile>
The old experiment stays linked to its original destination — Databricks does not allow un-linking. If you no longer need the old data, delete the experiment outright via mlflow.delete_experiment(<old-id>) (or the workspace UI). That's a soft-delete; a hard purge is a workspace cleanup job. The OTEL Delta tables the old experiment wrote to are not affected by experiment deletion — drop them separately if you want the storage back.
Monitor¶
dao-ai monitor groups production observability for the deployed agent.
dao-ai monitor scorers enable|status|disable¶
Register, inspect, or stop MLflow monitoring scorers that continuously evaluate
production traces for quality, safety, and guideline compliance. Requires
app.monitoring in the YAML config.
dao-ai monitor scorers enable -c config/model_config.yaml # register + start
dao-ai monitor scorers status -c config/model_config.yaml # list active scorers
dao-ai monitor scorers disable -c config/model_config.yaml # stop all scorers
dao-ai monitor logs¶
Fetch or stream runtime logs for the deployed agent, to stdout. Provide either
-c/--config (derives the app/endpoint name from the YAML) or --name (an
explicit name, used literally) — the two are mutually exclusive.
# Databricks Apps (default mode) — last 200 lines, then last 500
dao-ai monitor logs -c config/model_config.yaml
dao-ai monitor logs -c config/model_config.yaml --lines 500
# Stream continuously until Ctrl-C (apps only)
dao-ai monitor logs -c config/model_config.yaml --follow
# Model Serving snapshot (no streaming)
dao-ai monitor logs -c config/model_config.yaml -m model_serving
# Explicit name instead of a config file
dao-ai monitor logs --name my-app -p fevm
Capability matrix — the two deployment targets expose logs differently:
| Capability | -m apps (default) |
-m model_serving |
|---|---|---|
Snapshot (last N via --lines) |
✅ | ✅ |
Streaming (--follow) |
✅ | ❌ (snapshot only — --follow is rejected) |
| Mechanism | databricks apps logs (CLI; requires the databricks CLI ≥ 1.3.0 on PATH) |
Databricks SDK serving_endpoints.logs |
The Apps path shells out to the databricks CLI because the Databricks Python
SDK exposes no Apps-logs API; the CLI streams the app's logz/stream websocket.
--lines 0 fetches all buffered lines (apps only).
Interactive Chat¶
Start an interactive chat session with your agent:
dao-ai chat -c config/my_config.yaml
# With parameter overrides
dao-ai chat -c config/my_config.yaml --param catalog=nfleming --param module_id=09
MCP Utilities¶
Inspect and test MCP (Model Context Protocol) servers and tools, grouped under
the dao-ai mcp noun. There are two distinct surfaces, told apart by their
flags:
-c/--config→ the MCP tools an agent config declares (what your agent sees)--url/--app→ a live MCP server (what a running server exposes)
To deploy a dao-ai agent as an MCP server, use
agent --as-mcp. Deployment is intentionally not part of this noun.
| Verb | Purpose |
|---|---|
dao-ai mcp tools |
List the MCP tools an agent config declares (with filter status) |
dao-ai mcp inspect |
Connect to a live MCP server and show its health + available tools |
dao-ai mcp call |
Invoke a single tool on a live MCP server and print the result |
mcp tools — inspect config-declared tools¶
List all MCP tools declared in a config with full descriptions and schemas:
dao-ai mcp tools -c config/my_config.yaml
# With parameter overrides
dao-ai mcp tools -c config/my_config.yaml --param catalog=main
Use --apply-filters to see only the tools that will actually be loaded
(respecting include_tools and exclude_tools configuration):
mcp inspect — introspect a live server¶
Connect to a running MCP server and show its health (best-effort /healthz)
plus the tools it exposes. Target any MCP server with --url, or a Databricks
App (e.g. a dao-ai agent deployed via agent --as-mcp) with --app:
# A deployed dao-ai MCP App, resolved by name via the SDK
dao-ai mcp inspect --app my-mcp-app -p fevm
# Any MCP server URL
dao-ai mcp inspect --url https://<host>/api/2.0/mcp/sql -p fevm
mcp call — smoke-test a single tool¶
Invoke one tool on a live MCP server and print its result — an end-to-end smoke
test of a deployed server. Arguments are passed as a JSON object via --args:
dao-ai mcp call ask --app my-mcp-app --args '{"input": "hello"}' -p fevm
dao-ai mcp call execute_sql \
--url https://<host>/api/2.0/mcp/sql \
--args '{"query": "SELECT 1"}' -p fevm
What It Shows¶
This command displays comprehensive information about each MCP server and its tools:
- Server Information: MCP server URL, transport type, and connection details
- Filter Configuration:
include_toolsandexclude_toolspatterns - Tool Statistics: Total available, included, and excluded tool counts
- Tool Details (for each included tool):
- Full description (no truncation)
- Parameters in readable format with:
- Parameter names and types
- Required vs optional indicators
- Inline enum values
- Parameter descriptions
- Nested object structures
- Exclusion Reasons: Why tools are excluded (pattern matches, not in include list)
Output Format¶
Default view (shows all tools with include/exclude status):
📦 Tool: search_tools
Server: http://mcp-server.example.com
Transport: stdio
Filters:
Include: search_*, query_*
Exclude: *_deprecated
Available Tools: 10 total
├─ ✓ Included: 7
└─ ✗ Excluded: 3
✓ Included Tools (7):
• search_web
Description: Search the web for information...
Parameters:
query: string (required)
└─ The search query to execute
max_results: integer (optional)
└─ Maximum number of results (default: 10)
language: string (one of: en, es, fr, de) (optional)
└─ Language for results
✗ Excluded Tools (3):
• internal_api (not in include list)
• legacy_search_deprecated (matches exclude pattern: *_deprecated)
With --apply-filters (shows only included tools):
📦 Tool: search_tools
Server: http://mcp-server.example.com
Available Tools: 7 (after filters)
Tools (7):
• search_web
Description: Search the web for information...
Parameters:
query: string (required)
└─ The search query to execute
Use Cases¶
- Discovery: Find available tools before configuring agents
- Documentation: Review tool descriptions and parameter schemas
- Debugging: Verify filter configuration is working correctly
- Validation: Ensure MCP server connectivity
- Planning: Determine which tools to include in agent configuration
Schema Format¶
Schemas are displayed in a concise, readable format (53% smaller than JSON):
- Type-first: Parameter types immediately visible
- Clear indicators: Required vs optional at a glance
- Inline enums: Allowed values shown directly
- Proper nesting: Hierarchical structure with indentation
- No boilerplate: Clean format without JSON syntax
Inspect Declared Parameters¶
Print every parameter declared in a config's parameters: block, its current resolved value, and where that value came from.
dao-ai parameters -c config/my_config.yaml # 'list' is the default action
# Explicit (equivalent) + overrides to see how they resolve
dao-ai parameters list -c dao_ai.yaml --param module_id=09
# Print ONE parameter's resolved value as a bare line (script-friendly)
CATALOG=$(dao-ai parameters get catalog -c config/my_config.yaml)
The action word is optional — dao-ai parameters -c <file> lists. dao-ai vars is kept as an alias, and --var works alongside --param.
Sample output:
NAME REQUIRED PROVIDED DEFAULT RESOLVED SOURCE DESCRIPTION
----------------------------------------------------------------------
catalog no no main main default Unity Catalog catalog name
module_id yes no - 09 --param Workshop module identifier
genie_id no yes - - provided Genie space id (provisioned at run time)
Source values: --param, env, default, inline-default, provided, MISSING. A provided: true parameter (see the configuration reference) reports source provided when unsupplied — its value is furnished at run time (e.g. by a workflow provisioning task), so it is not flagged MISSING or required.
get <name> prints the bare resolved value to stdout and exits non-zero (with a targeted message) when the name is undeclared, required-but-unset, or a provided param with no run-time value yet.
Exit code for list is 1 if any required parameter is MISSING, 0 otherwise. This makes it useful in CI pipelines to verify all overrides are wired up before deploying.
Any ${workspace.*} references in a parameter's default are resolved before the table is rendered, so the listed DEFAULT reflects the live workspace user / host.
Full reference: Parameters (Load-Time Substitution).
Verbose Output¶
Increase verbosity for debugging (use -v through -vvvv):
Command Options¶
Common Options¶
| Option | Description |
|---|---|
-c, --config FILE |
Path to configuration file (required) |
-p, --profile NAME |
Databricks CLI profile to use |
--param KEY=VALUE |
Override a ${param.KEY} / ${var.KEY} parameter in the config (repeatable). --var is kept as an alias. |
-v, --verbose |
Increase verbosity (can be repeated up to 4 times) |
--help |
Show help message |
Validate Options¶
Graph Options¶
| Option | Description |
|---|---|
-o, --output FILE |
Output file path (supports .png, .pdf, .svg) |
Workflow Options (dao-ai workflow up|build|sync|start|down)¶
dao-ai workflow up -c config/my_config.yaml [OPTIONS]
dao-ai workflow build -c config/my_config.yaml [OPTIONS]
dao-ai workflow sync -c config/my_config.yaml [OPTIONS]
dao-ai workflow start -c config/my_config.yaml [OPTIONS]
dao-ai workflow down -c config/my_config.yaml [OPTIONS]
up builds (if needed) → syncs → starts in one command. build stages the
bundle only; sync/start/down act on the already-built bundle and never
build — run build (or up) first, else they error with the next command. For
workflow, start is databricks bundle run deploy_job (the provisioning job).
| Option | Description | Verbs |
|---|---|---|
-c, --config FILE |
Path to the dao-ai configuration file (required) | all |
-s, --staging-dir DIR |
Bundle staging dir (default: $DAO_AI_BUNDLE_DIR/workflow/<app> or ./.dao-ai/bundle/workflow/<app>) |
all |
-p, --profile NAME |
Databricks CLI profile to use | all |
--param KEY=VALUE / --var KEY=VALUE |
Config parameter overrides (repeatable) | all |
--cloud {azure,aws,gcp} |
Cloud provider (auto-detected from the workspace URL; required only if detection fails) | all |
-t, --target NAME |
Bundle target name (auto-generated if not specified) | all |
--mode {apps,mcp,model_serving} |
Serving mode selector (default: apps; ms/model-serving accepted as aliases). Forwarded to the deploy-agent job step as a runtime var. |
all |
--as-mcp |
Serve the agent over MCP instead of the chat UI (requires --mode apps; deploys as mcp-<app>). |
all |
--with-connection |
After deploying the MCP server, create a UC MCP connection and register it with the Unity AI Gateway (requires --as-mcp). See MCP server → Genie One. |
all |
--dry-run |
Preview commands without executing | all |
--overwrite |
Overwrite copied-in files in the staging dir | up, build |
--development / --no-development |
Ship the local dao-ai wheel vs pin PyPI (default: auto-detect) | up, build |
--direct |
Go via SDK directly, no bundle on disk (apps/mcp) | up |
The flat generate-workflow command and the one-shot generate --deploy/--run
flags have been removed — use dao-ai workflow up (or build → sync → start).
Agent Options (dao-ai agent up|build|sync|start|down)¶
dao-ai agent up -c config/my_config.yaml [OPTIONS]
dao-ai agent build -c config/my_config.yaml [OPTIONS]
dao-ai agent sync -c config/my_config.yaml [OPTIONS]
dao-ai agent start -c config/my_config.yaml [OPTIONS]
dao-ai agent down -c config/my_config.yaml [OPTIONS]
# Use --as-mcp to build the MCP-server bundle instead of the chat-agent bundle
up builds (if needed) → syncs → starts in one command. build stages the
bundle only; sync/start/down act on the already-built bundle and never
build — run build (or up) first, else they error with the next command. For
agent, start is databricks bundle run <app>.
| Option | Description | Verbs |
|---|---|---|
-c, --config FILE |
Path to the dao-ai configuration file (required) | all |
-s, --staging-dir DIR |
Bundle staging dir (default: $DAO_AI_BUNDLE_DIR/<kind>/<app> or ./.dao-ai/bundle/<kind>/<app>, where <kind> is agent or workflow; the agent noun appends <platform>[/<protocol>]) |
all |
-p, --profile NAME |
Databricks profile for config loading and sync | all |
--param KEY=VALUE / --var KEY=VALUE |
Config parameter overrides (repeatable) | all |
--mode {apps,mcp,model_serving} |
Serving target (default: apps; ms/model-serving accepted as aliases) |
all |
--as-mcp |
Serve the agent over MCP instead of the chat UI (requires --mode apps; deploys as mcp-<app>). |
all |
--with-connection |
After deploying the MCP server, create a UC MCP connection and register it with the Unity AI Gateway (requires --as-mcp). See MCP server → Genie One. |
all |
--dry-run |
Preview commands without executing | all |
--direct |
Go via SDK directly, no bundle on disk (all modes) | up |
--overwrite |
Overwrite existing files in the output directory | up, build |
--development / --no-development |
Bundle a local dao-ai wheel vs pin PyPI (default: auto-detect) | up, build |
The flat generate-agent / generate-mcp commands and the one-shot
generate --deploy/--run flags have been removed — use dao-ai agent up (or
build → sync → start), with --as-mcp for the MCP-server bundle.
Chat Options¶
Starts an interactive REPL session where you can chat with your agent locally.
MCP Utilities Options¶
dao-ai mcp tools -c config/my_config.yaml [OPTIONS]
dao-ai mcp inspect (--url URL | --app NAME) [OPTIONS]
dao-ai mcp call TOOL (--url URL | --app NAME) [--args JSON] [OPTIONS]
mcp tools
| Option | Description |
|---|---|
-c, --config FILE |
Path to configuration file (default: ./config/model_config.yaml) |
--apply-filters |
Only show tools that pass include/exclude filters (hide excluded tools) |
Lists all MCP tools declared in a config with full descriptions and readable parameter schemas. Supports filtering to show only included tools.
mcp inspect / mcp call
| Option | Description |
|---|---|
--url URL |
Direct MCP server URL (e.g. https://<host>/.../mcp). Mutually exclusive with --app. |
--app NAME |
Databricks App name; its /mcp endpoint is resolved via the SDK. Mutually exclusive with --url. |
--args JSON |
(call only) JSON object of tool arguments (default: {}). |
inspect and call connect to a live MCP server and require valid auth (a -p/--profile or ambient credentials).
Multi-Cloud Support¶
DAO AI supports deploying to Azure, AWS, and GCP Databricks workspaces. The CLI handles cloud-specific configurations automatically.
How It Works¶
- Cloud Detection: When you specify a
--profile, the CLI detects the cloud provider from the workspace URL - Target Selection: The CLI uses the profile name as the deployment target for per-profile isolation
- Node Types: Cloud-appropriate compute node types are automatically selected:
- Azure:
Standard_D4ads_v5 - AWS:
i3.xlarge - GCP:
n1-standard-4
Profile Configuration¶
Profiles are configured in ~/.databrickscfg:
[aws-field-eng]
host = https://my-workspace.cloud.databricks.com
token = dapi...
[azure-retail]
host = https://adb-123456789.azuredatabricks.net
token = dapi...
[gcp-analytics]
host = https://my-workspace.gcp.databricks.com
token = dapi...
Deployment Isolation¶
Each profile gets its own isolated deployment state:
/.bundle/my_app/aws-field-eng/files # AWS deployment
/.bundle/my_app/azure-retail/files # Azure deployment
/.bundle/my_app/gcp-analytics/files # GCP deployment
This allows you to deploy the same application to multiple workspaces without conflicts.
Examples¶
Deploy to Multiple Clouds¶
# Deploy to AWS
dao-ai workflow up -c config/hardware_store.yaml --profile aws-prod
# Deploy same app to Azure
dao-ai workflow up -c config/hardware_store.yaml --profile azure-prod
# Deploy same app to GCP
dao-ai workflow up -c config/hardware_store.yaml --profile gcp-prod
Development vs Production¶
# Deploy to development workspace
dao-ai workflow up -c config/my_app.yaml --profile aws-dev
# Deploy to production workspace
dao-ai workflow up -c config/my_app.yaml --profile aws-prod
Full Deployment Pipeline¶
# Validate configuration
dao-ai validate -c config/my_app.yaml
# Generate workflow diagram
dao-ai graph -c config/my_app.yaml -o workflow.png
# Provision infra, deploy, and run
dao-ai workflow up -c config/my_app.yaml --profile aws-field-eng
Migration from pre-v2 CLI¶
The deploy-model v2 release removed several commands and renamed others. Use this table to update scripts and docs.
| Old command (removed) | New command |
|---|---|
dao-ai agent generate ... |
dao-ai agent build ... |
dao-ai agent deploy ... |
dao-ai agent sync ... |
dao-ai agent run ... |
dao-ai agent start ... |
dao-ai agent destroy ... |
dao-ai agent down ... |
dao-ai workflow generate\|deploy\|run\|destroy ... |
dao-ai workflow build\|sync\|start\|down ... |
dao-ai deploy -c ... --target model_serving |
dao-ai agent sync -c ... --mode model_serving |
dao-ai deploy -c ... --target apps |
dao-ai agent sync -c ... --mode apps |
dao-ai deploy -c ... --target both |
Run dao-ai agent sync --mode model_serving then dao-ai agent sync --mode apps |
dao-ai generate-agent ... |
dao-ai agent build ... |
dao-ai generate-mcp ... |
dao-ai agent build --as-mcp ... |
dao-ai generate-workflow ... |
dao-ai workflow build ... |
dao-ai mcp generate\|deploy\|run\|destroy |
dao-ai agent build\|sync\|start\|down --as-mcp |
dao-ai agent <verb> --mode mcp |
dao-ai agent <verb> --as-mcp (MCP is a protocol on the apps platform, not a --mode value) |
ServingMode.MCP (Python API) |
deploy_agent(mode=ServingMode.APPS, as_mcp=True) |
dao-ai agent generate --deploy --run ... |
dao-ai agent up ... (one command: build → sync → start) |
dao-ai agent generate --deploy ... |
dao-ai agent up ..., or build then sync for a staged/hand-editable bundle |
dao-ai agent deploy --run ... |
dao-ai agent up ..., or sync then start |
dao-ai workflow generate --deploy --run ... |
dao-ai workflow up ... |
dao-ai create-experiment ... |
dao-ai trace create ... |
dao-ai link-trace-destination ... |
dao-ai trace link ... |
dao-ai grant-trace-permissions ... |
dao-ai trace grant ... |
dao-ai list-mcp-tools ... |
dao-ai mcp tools ... |
--deployment-target <mode> flag |
--mode <mode> flag |
--deploy / --run one-shot flags on generate |
Removed — use the up verb |
app.deployment_target: config field |
Removed — serving mode is chosen at sync time via --mode (default apps) |
DeploymentTarget enum (Python API) |
Renamed ServingMode — from dao_ai.config import ServingMode; ServingMode.APPS / .MCP / .MODEL_SERVING |
DeploymentTarget.BOTH |
Removed — sync each mode separately |