Simplify Mason agent demo with SDK durable runtime - #479
Draft
shivam5 wants to merge 18 commits into
Draft
Conversation
Sparse-clones a basic template (--framework openai|langgraph) out of the app-templates repo into a local directory, ready for `mason deploy --source`. Repo/ref are overridable so a template can be fetched from a fork/branch before it merges to the canonical repo. Co-authored-by: Isaac <no-reply@databricks.com>
A from-scratch FastAPI LangGraph agent backend for Databricks Apps: native LangGraph wire on both ends, in-memory checkpointer, streaming + background, MCP loading, and human-in-the-loop tool approval (HumanInTheLoopMiddleware). Co-authored-by: Isaac <no-reply@databricks.com>
This scratch template uses an in-process LangGraph checkpointer; durability is a code swap (PostgresSaver in session_store.py), not an env var. Remove the unused AGENT_SESSION_STORE / LOCAL_SESSION_DB_PATH references from .env.example and app.yaml. Co-authored-by: Isaac <no-reply@databricks.com>
…tely Without a profile, the scaffolded template has no .env (it's gitignored) and `uv run start-server` fails on missing model auth. --profile (or the -p / `mason login` default) copies .env.example -> .env with DATABRICKS_CONFIG_PROFILE set, making the project runnable out of the box. Never clobbers an existing .env. Co-authored-by: Isaac <no-reply@databricks.com>
…ssing configure() now resolves a WorkspaceClient at startup, so a missing/invalid profile raises an actionable RuntimeError (naming the profile tried + how to fix) instead of a generic SDK error buried in the first request's traceback. Co-authored-by: Isaac <no-reply@databricks.com>
…le was set Co-authored-by: Isaac <no-reply@databricks.com>
Apply James's PR databricks#265 review: - Move template under integrations/mason/templates/. - Rename server/ -> runtime/ (start_server.py -> main.py, app.py -> runtime.py). - Drop the /responses route + alias; keep only /invocations, and rename the background poll route to /invocations/{invocation_id} (resp_ -> inv_ ids) to decouple from the Responses API. - Read the session id from the X-Routing-Key header instead of the request body. - Remove the thin mason/wire/ module (a misnomer); inline session-id + event serialization into agent.py, keeping runtime.py SDK-agnostic. - Rename BackgroundRuns.create() -> start(); drop the stray mlflow.message.format "openai" attribute (this template is LangChain-native). - Trim the tutorial-style runtime docstring; point deploy docs at `mason deploy`. - Note the local OSS MLflow tracking-server option in .env.example. Co-authored-by: Isaac <no-reply@databricks.com>
invoke_handler generated a fresh session id for the checkpointer thread (via stream_handler) and a *different* one for the returned session_id, so a request without a session id got back an id that was never persisted — the client couldn't resume the paused run. Pin the id into the request once, up front. Co-authored-by: Isaac <no-reply@databricks.com>
When AGENT_SESSION_STORE names a managed Session Store, checkpointer() now returns a DatabricksMemorySaver — LangGraph's PostgresSaver over the store's service-managed Lakebase — so full graph state, including paused HITL runs, survives restarts and replicas. Unset keeps the in-process InMemorySaver. checkpointer() is now async (opens/caches the Lakebase pool once). Resolving a Session Store name to its backing Lakebase instance is a pending fast-follow in the Session Store API; until then LAKEBASE_INSTANCE_NAME supplies it, and the saver raises a clear error if the store is set without it. Co-authored-by: Isaac <no-reply@databricks.com>
Switch the durable path from AsyncCheckpointSaver to the sync CheckpointSaver (both databricks-langchain[memory]; the sync one runs fine under astream via LangGraph's threadpool). checkpointer() is sync again — no async ripple into create_agent_graph or the tests — and the lru_cache reuses one saver/pool. Co-authored-by: Isaac <no-reply@databricks.com>
Use the verified Session Store provisioning convention (shared per-workspace project databricks-internal-lakebase-agent-session-store, default "production" branch, autoscaling) so the durable CheckpointSaver is built from the store name with no extra connection config — drops LAKEBASE_INSTANCE_NAME. Known gap, documented in session_store.py: databricks-langchain's pool hardcodes the default database, so checkpoints land in the project's default DB, not the per-store database that holds the session's message items. Co-locate once the pool supports selecting a database. Co-authored-by: Isaac <no-reply@databricks.com>
… is deployed-app-only Add the [memory] extra to databricks-langchain so the durable checkpointer's Lakebase pool (langgraph-checkpoint-postgres + psycopg) is installed. The managed Session Store's Lakebase grants the deployed app's service principal, not human users, so the durable path fails under local user credentials. Wrap the Postgres auth failure in a clear RuntimeError explaining this and pointing to the in-process default for local dev; document it in README / AGENTS / .env.example. Co-authored-by: Isaac <no-reply@databricks.com>
The agent drives the graph with astream (async), but the durable path used the sync CheckpointSaver, whose aget_tuple/aput/aput_writes are unimplemented on the base class — so an async run raised NotImplementedError. Switch to AsyncCheckpointSaver (AsyncPostgresSaver) and make checkpointer() async again; open/cache one saver per process. InMemorySaver already implements both, so the local default was unaffected. Co-authored-by: Isaac <no-reply@databricks.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
This is the end-to-end Mason + Agent Platform demo built from #474, #478, and the SDK-owned entrypoint idea in #476.
DatabricksDurableApp, which owns/invocations, background execution, polling, recovery heartbeats, and durable SSE replay.Idempotency-Keyfor the durable invocation ID.X-Routing-Keyfor the agent session ID.AGENT_SESSION_STOREis wired at deploy time.mason dev.mason deployinfer the current project directory, deployment name, and the profile seeded bymason init.Compared with the current #478 template, this removes 1,041 lines and adds 256 lines.
Demo
Durable deployed state remains opt-in for the demo:
Validation
Validated on August 27, 2026:
32focused durable runtime/app/store tests pass.53Mason unit tests pass.ty checkpasses for the runtime and app code.8hermetic tests.[DONE];409on conflicting reuse of an idempotency key.Remaining live check
The selected
e2-dogfoodprofile currently has an invalid OAuth refresh token, so a freshmason devstartup andmason deploycannot complete until running:A model-backed sync invocation succeeded earlier from the already-running current template, before the cached credential expired.
Draft note
The generated template temporarily installs
databricks-ai-bridge[agent-server]from this fork branch so the end-to-end demo can consume the runtime before it is released. Replace that direct reference with the merged/released package before landing.