databricks-agentbricks 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. databricks_agentbricks/__init__.py +1 -0
  2. databricks_agentbricks/_group.py +217 -0
  3. databricks_agentbricks/agent_project.py +657 -0
  4. databricks_agentbricks/app_resources.py +139 -0
  5. databricks_agentbricks/cli/__init__.py +12 -0
  6. databricks_agentbricks/cli/app.py +108 -0
  7. databricks_agentbricks/cli/app_auth.py +198 -0
  8. databricks_agentbricks/cli/auth.py +142 -0
  9. databricks_agentbricks/cli/deploy.py +954 -0
  10. databricks_agentbricks/cli/dev.py +310 -0
  11. databricks_agentbricks/cli/endpoint.py +145 -0
  12. databricks_agentbricks/cli/endpoint_examples.py +33 -0
  13. databricks_agentbricks/cli/endpoint_output.py +53 -0
  14. databricks_agentbricks/cli/endpoint_request.py +71 -0
  15. databricks_agentbricks/cli/endpoint_transport.py +148 -0
  16. databricks_agentbricks/cli/help.py +467 -0
  17. databricks_agentbricks/cli/init.py +496 -0
  18. databricks_agentbricks/cli/mcp.py +75 -0
  19. databricks_agentbricks/cli/memory.py +520 -0
  20. databricks_agentbricks/cli/sandbox.py +823 -0
  21. databricks_agentbricks/cli/sessions.py +588 -0
  22. databricks_agentbricks/cli/tools.py +456 -0
  23. databricks_agentbricks/cli/tracing.py +724 -0
  24. databricks_agentbricks/databricks_cli.py +38 -0
  25. databricks_agentbricks/errors.py +114 -0
  26. databricks_agentbricks/lakebase_runtime_store.py +107 -0
  27. databricks_agentbricks/legacy_lakebase_runtime_store.py +74 -0
  28. databricks_agentbricks/project_config.py +157 -0
  29. databricks_agentbricks/project_types.py +55 -0
  30. databricks_agentbricks/py.typed +0 -0
  31. databricks_agentbricks/render.py +349 -0
  32. databricks_agentbricks/templates/agent-bricks-migrate/SKILL.md +101 -0
  33. databricks_agentbricks/templates/agent-langgraph/.env.example +36 -0
  34. databricks_agentbricks/templates/agent-langgraph/.gitignore +199 -0
  35. databricks_agentbricks/templates/agent-langgraph/AGENTKIT_CONTRACT.md +95 -0
  36. databricks_agentbricks/templates/agent-langgraph/AGENTS.md +31 -0
  37. databricks_agentbricks/templates/agent-langgraph/CLAUDE.md +1 -0
  38. databricks_agentbricks/templates/agent-langgraph/README.md +141 -0
  39. databricks_agentbricks/templates/agent-langgraph/agent/__init__.py +0 -0
  40. databricks_agentbricks/templates/agent-langgraph/agent/agent.py +177 -0
  41. databricks_agentbricks/templates/agent-langgraph/agent/mcps.py +27 -0
  42. databricks_agentbricks/templates/agent-langgraph/agent/tools/__init__.py +24 -0
  43. databricks_agentbricks/templates/agent-langgraph/agent/tools/sample_tool.py +15 -0
  44. databricks_agentbricks/templates/agent-langgraph/agent/tools/send_message.py +17 -0
  45. databricks_agentbricks/templates/agent-langgraph/app.yaml +15 -0
  46. databricks_agentbricks/templates/agent-langgraph/pyproject.toml +42 -0
  47. databricks_agentbricks/templates/agent-langgraph/runtime/__init__.py +0 -0
  48. databricks_agentbricks/templates/agent-langgraph/runtime/adapter.py +144 -0
  49. databricks_agentbricks/templates/agent-langgraph/runtime/main.py +25 -0
  50. databricks_agentbricks/templates/agent-langgraph/tests/__init__.py +0 -0
  51. databricks_agentbricks/templates/agent-langgraph/tests/test_agent.py +211 -0
  52. databricks_agentbricks/templates/agent-langgraph/tests/test_runtime.py +19 -0
  53. databricks_agentbricks/templates/agent-langgraph/tests/test_workspace.py +28 -0
  54. databricks_agentbricks/templates/agent-openai/.env.example +37 -0
  55. databricks_agentbricks/templates/agent-openai/.gitignore +199 -0
  56. databricks_agentbricks/templates/agent-openai/AGENTKIT_CONTRACT.md +107 -0
  57. databricks_agentbricks/templates/agent-openai/AGENTS.md +76 -0
  58. databricks_agentbricks/templates/agent-openai/CLAUDE.md +1 -0
  59. databricks_agentbricks/templates/agent-openai/README.md +143 -0
  60. databricks_agentbricks/templates/agent-openai/agent/__init__.py +0 -0
  61. databricks_agentbricks/templates/agent-openai/agent/agent.py +205 -0
  62. databricks_agentbricks/templates/agent-openai/agent/mcps.py +28 -0
  63. databricks_agentbricks/templates/agent-openai/agent/tools/__init__.py +24 -0
  64. databricks_agentbricks/templates/agent-openai/agent/tools/sample_tool.py +15 -0
  65. databricks_agentbricks/templates/agent-openai/agent/tools/send_message.py +18 -0
  66. databricks_agentbricks/templates/agent-openai/app.yaml +15 -0
  67. databricks_agentbricks/templates/agent-openai/pyproject.toml +42 -0
  68. databricks_agentbricks/templates/agent-openai/runtime/__init__.py +0 -0
  69. databricks_agentbricks/templates/agent-openai/runtime/adapter.py +188 -0
  70. databricks_agentbricks/templates/agent-openai/runtime/main.py +25 -0
  71. databricks_agentbricks/templates/agent-openai/tests/__init__.py +0 -0
  72. databricks_agentbricks/templates/agent-openai/tests/test_agent.py +326 -0
  73. databricks_agentbricks/templates/agent-openai/tests/test_runtime.py +19 -0
  74. databricks_agentbricks/templates/agent-openai/tests/test_workspace.py +28 -0
  75. databricks_agentbricks/templates/custom-agent-langgraph/.env.example +1 -0
  76. databricks_agentbricks/templates/custom-agent-langgraph/.gitignore +11 -0
  77. databricks_agentbricks/templates/custom-agent-langgraph/README.md +22 -0
  78. databricks_agentbricks/templates/custom-agent-langgraph/agent/__init__.py +0 -0
  79. databricks_agentbricks/templates/custom-agent-langgraph/agent/agent.py +27 -0
  80. databricks_agentbricks/templates/custom-agent-langgraph/app.yaml +1 -0
  81. databricks_agentbricks/templates/custom-agent-langgraph/pyproject.toml +38 -0
  82. databricks_agentbricks/templates/custom-agent-langgraph/runtime/__init__.py +0 -0
  83. databricks_agentbricks/templates/custom-agent-langgraph/runtime/main.py +31 -0
  84. databricks_agentbricks/templates/custom-agent-langgraph/tests/test_runtime.py +29 -0
  85. databricks_agentbricks/templates/custom-agent-openai/.env.example +1 -0
  86. databricks_agentbricks/templates/custom-agent-openai/.gitignore +11 -0
  87. databricks_agentbricks/templates/custom-agent-openai/README.md +22 -0
  88. databricks_agentbricks/templates/custom-agent-openai/agent/__init__.py +0 -0
  89. databricks_agentbricks/templates/custom-agent-openai/agent/agent.py +29 -0
  90. databricks_agentbricks/templates/custom-agent-openai/app.yaml +1 -0
  91. databricks_agentbricks/templates/custom-agent-openai/pyproject.toml +38 -0
  92. databricks_agentbricks/templates/custom-agent-openai/runtime/__init__.py +0 -0
  93. databricks_agentbricks/templates/custom-agent-openai/runtime/main.py +31 -0
  94. databricks_agentbricks/templates/custom-agent-openai/tests/test_runtime.py +29 -0
  95. databricks_agentbricks/templates/sandbox_mcp.py +39 -0
  96. databricks_agentbricks/templates/sandbox_mcp_langgraph.py +39 -0
  97. databricks_agentbricks/templates/ui/agent-langgraph/CHAT_APP.md +49 -0
  98. databricks_agentbricks/templates/ui/agent-langgraph/runtime/main.py +26 -0
  99. databricks_agentbricks/templates/ui/agent-langgraph/runtime/ui.py +528 -0
  100. databricks_agentbricks/templates/ui/agent-langgraph/tests/test_demo_ui.py +542 -0
  101. databricks_agentbricks/templates/ui/agent-langgraph/ui/agentbricks-mark.png +0 -0
  102. databricks_agentbricks/templates/ui/agent-langgraph/ui/app.js +1464 -0
  103. databricks_agentbricks/templates/ui/agent-langgraph/ui/index.html +281 -0
  104. databricks_agentbricks/templates/ui/agent-langgraph/ui/styles.css +1913 -0
  105. databricks_agentbricks/templates/ui/agent-openai/CHAT_APP.md +54 -0
  106. databricks_agentbricks/templates/ui/agent-openai/runtime/main.py +26 -0
  107. databricks_agentbricks/templates/ui/agent-openai/runtime/ui.py +521 -0
  108. databricks_agentbricks/templates/ui/agent-openai/tests/test_demo_ui.py +512 -0
  109. databricks_agentbricks/templates/ui/agent-openai/ui/agentbricks-mark.png +0 -0
  110. databricks_agentbricks/templates/ui/agent-openai/ui/app.js +1428 -0
  111. databricks_agentbricks/templates/ui/agent-openai/ui/index.html +281 -0
  112. databricks_agentbricks/templates/ui/agent-openai/ui/styles.css +1913 -0
  113. databricks_agentbricks/theme.py +72 -0
  114. databricks_agentbricks-0.2.0.dist-info/METADATA +897 -0
  115. databricks_agentbricks-0.2.0.dist-info/RECORD +159 -0
  116. databricks_agentbricks-0.2.0.dist-info/WHEEL +4 -0
  117. databricks_agentbricks-0.2.0.dist-info/entry_points.txt +2 -0
  118. databricks_agentbricks-0.2.0.dist-info/licenses/NOTICE +39 -0
  119. databricks_agentkit/__init__.py +67 -0
  120. databricks_agentkit/_api_client.py +673 -0
  121. databricks_agentkit/_pagination.py +25 -0
  122. databricks_agentkit/client.py +31 -0
  123. databricks_agentkit/langgraph/__init__.py +98 -0
  124. databricks_agentkit/langgraph/genie.py +50 -0
  125. databricks_agentkit/langgraph/mcp.py +216 -0
  126. databricks_agentkit/langgraph/memory.py +67 -0
  127. databricks_agentkit/langgraph/session_store.py +485 -0
  128. databricks_agentkit/memory_store.py +371 -0
  129. databricks_agentkit/models.py +330 -0
  130. databricks_agentkit/openai/__init__.py +93 -0
  131. databricks_agentkit/openai/genie.py +50 -0
  132. databricks_agentkit/openai/mcp.py +189 -0
  133. databricks_agentkit/openai/memory.py +67 -0
  134. databricks_agentkit/openai/sessions.py +157 -0
  135. databricks_agentkit/py.typed +0 -0
  136. databricks_agentkit/runtime/ARCHITECTURE.md +64 -0
  137. databricks_agentkit/runtime/README.md +184 -0
  138. databricks_agentkit/runtime/__init__.py +69 -0
  139. databricks_agentkit/runtime/app.py +316 -0
  140. databricks_agentkit/runtime/auth.py +149 -0
  141. databricks_agentkit/runtime/durability/__init__.py +1 -0
  142. databricks_agentkit/runtime/durability/execution.py +133 -0
  143. databricks_agentkit/runtime/durability/heartbeat.py +64 -0
  144. databricks_agentkit/runtime/durability/lakebase_runtime_store.py +648 -0
  145. databricks_agentkit/runtime/durability/recovery.py +70 -0
  146. databricks_agentkit/runtime/durability/store.py +33 -0
  147. databricks_agentkit/runtime/execution.py +160 -0
  148. databricks_agentkit/runtime/genie.py +224 -0
  149. databricks_agentkit/runtime/mcp_auth.py +114 -0
  150. databricks_agentkit/runtime/model_services.py +90 -0
  151. databricks_agentkit/runtime/runtime.py +273 -0
  152. databricks_agentkit/runtime/session_store_client.py +120 -0
  153. databricks_agentkit/runtime/store.py +287 -0
  154. databricks_agentkit/runtime/tool_manifest.py +223 -0
  155. databricks_agentkit/runtime/tracing.py +71 -0
  156. databricks_agentkit/runtime/types.py +118 -0
  157. databricks_agentkit/runtime/workspace.py +27 -0
  158. databricks_agentkit/session_store.py +434 -0
  159. databricks_agentkit/timefmt.py +85 -0
@@ -0,0 +1,27 @@
1
+ from typing import Any
2
+
3
+ from databricks_langchain import ChatDatabricks
4
+ from langchain.agents import create_agent
5
+
6
+ from databricks_agentkit import workspace_client, workspace_headers
7
+
8
+ MODEL = "databricks-gpt-5-2"
9
+
10
+
11
+ class _RoutedChatDatabricks(ChatDatabricks):
12
+ def _get_client_kwargs(self) -> dict[str, Any]:
13
+ kwargs = super()._get_client_kwargs()
14
+ if headers := workspace_headers():
15
+ kwargs["default_headers"] = headers
16
+ return kwargs
17
+
18
+
19
+ async def invoke(messages: list[dict[str, Any]]) -> dict[str, Any]:
20
+ agent = create_agent(
21
+ model=_RoutedChatDatabricks(endpoint=MODEL, workspace_client=workspace_client()),
22
+ tools=[],
23
+ )
24
+ result = await agent.ainvoke({"messages": messages})
25
+ message = result["messages"][-1]
26
+ output = message.model_dump() if hasattr(message, "model_dump") else message
27
+ return {"output": [output]}
@@ -0,0 +1 @@
1
+ command: ["uv", "run", "start-server"]
@@ -0,0 +1,38 @@
1
+ [project]
2
+ name = "custom-agent-langgraph"
3
+ version = "0.1.0"
4
+ description = "LangGraph agent with a custom FastAPI server"
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ dependencies = [
8
+ "databricks-agentbricks>=0.2.0",
9
+ "databricks-langchain>=0.17.0",
10
+ "databricks-sdk>=0.124.0",
11
+ "fastapi>=0.129.0",
12
+ "langchain>=1.0.0",
13
+ "python-dotenv>=1.2.1",
14
+ "uvicorn>=0.41.0",
15
+ ]
16
+
17
+ [build-system]
18
+ requires = ["hatchling"]
19
+ build-backend = "hatchling.build"
20
+
21
+ [tool.hatch.build.targets.wheel]
22
+ packages = ["agent", "runtime"]
23
+
24
+ [dependency-groups]
25
+ dev = [
26
+ "hatchling>=1.28.0",
27
+ "httpx>=0.28.1",
28
+ "pytest>=9.0.2",
29
+ ]
30
+
31
+ [tool.uv]
32
+ default-groups = ["dev"]
33
+
34
+ [tool.pytest.ini_options]
35
+ testpaths = ["tests"]
36
+
37
+ [project.scripts]
38
+ start-server = "runtime.main:main"
@@ -0,0 +1,31 @@
1
+ import os
2
+ from pathlib import Path
3
+ from typing import Any
4
+
5
+ import uvicorn
6
+ from agent.agent import invoke
7
+ from dotenv import load_dotenv
8
+ from fastapi import FastAPI
9
+ from pydantic import BaseModel, ConfigDict, Field
10
+
11
+ # override=False so injected DATABRICKS_* (from `ab dev -p` or the deploy platform) win over a
12
+ # checked-in .env.
13
+ load_dotenv(dotenv_path=Path(__file__).parent.parent / ".env", override=False)
14
+
15
+
16
+ class InvocationRequest(BaseModel):
17
+ model_config = ConfigDict(extra="forbid")
18
+
19
+ input: list[dict[str, Any]] = Field(default_factory=list)
20
+
21
+
22
+ app = FastAPI(title="Custom LangGraph Agent")
23
+
24
+
25
+ @app.post("/invocations")
26
+ async def invocations(body: InvocationRequest) -> dict[str, Any]:
27
+ return await invoke(body.input)
28
+
29
+
30
+ def main() -> None:
31
+ uvicorn.run("runtime.main:app", host="0.0.0.0", port=int(os.getenv("PORT", "8000")))
@@ -0,0 +1,29 @@
1
+ from unittest.mock import AsyncMock
2
+
3
+ from fastapi.testclient import TestClient
4
+
5
+ import runtime.main as runtime
6
+
7
+
8
+ def test_foreground_invocation(monkeypatch) -> None:
9
+ invoke = AsyncMock(return_value={"output": [{"role": "assistant", "content": "hello"}]})
10
+ monkeypatch.setattr(runtime, "invoke", invoke)
11
+
12
+ response = TestClient(runtime.app).post(
13
+ "/invocations",
14
+ json={"input": [{"role": "user", "content": "hi"}]},
15
+ )
16
+
17
+ assert response.status_code == 200
18
+ assert response.json()["output"][0]["content"] == "hello"
19
+ invoke.assert_awaited_once_with([{"role": "user", "content": "hi"}])
20
+
21
+
22
+ def test_custom_server_rejects_runtime_transport_fields() -> None:
23
+ response = TestClient(runtime.app).post(
24
+ "/invocations",
25
+ json={"input": [], "background": True},
26
+ )
27
+
28
+ assert response.status_code == 422
29
+ assert "/api/invocations" not in runtime.app.openapi()["paths"]
@@ -0,0 +1 @@
1
+ DATABRICKS_CONFIG_PROFILE=DEFAULT
@@ -0,0 +1,11 @@
1
+ .env
2
+ .venv/
3
+ __pycache__/
4
+ *.py[cod]
5
+ .pytest_cache/
6
+ dist/
7
+ *.egg-info/
8
+
9
+ # Agent Bricks local dev artifacts (`agentbricks dev`)
10
+ .agentbricks/
11
+ app.agentbricksdev.yaml
@@ -0,0 +1,22 @@
1
+ # Custom OpenAI Agents server
2
+
3
+ This template shows how to serve an OpenAI Agents SDK agent with an ordinary FastAPI application.
4
+ It does not use the managed `DurableAgentServer` HTTP server or durable runtime.
5
+
6
+ This template does not load managed tool bindings from `agent.toml`, so `ab tools add` is not
7
+ supported. Wire framework-native Python tools and MCP servers directly in `agent/agent.py`.
8
+
9
+ ```bash
10
+ ab dev
11
+ ```
12
+
13
+ Call its single foreground endpoint:
14
+
15
+ ```bash
16
+ curl -sS http://localhost:8000/invocations \
17
+ -H 'Content-Type: application/json' \
18
+ -d '{"input":[{"role":"user","content":"Hello"}]}'
19
+ ```
20
+
21
+ Edit `runtime/main.py` to define your own HTTP contract. Edit `agent/agent.py` to change the model
22
+ or agent behavior. Deploy with `ab --profile <profile> deploy custom-agent-openai`.
@@ -0,0 +1,29 @@
1
+ from typing import Any
2
+
3
+ from agents import Agent, Runner, set_default_openai_api, set_default_openai_client
4
+ from databricks_openai import AsyncDatabricksOpenAI
5
+
6
+ from databricks_agentkit import workspace_client, workspace_headers
7
+
8
+ MODEL = "databricks-gpt-5-2"
9
+
10
+
11
+ def _configure_client() -> None:
12
+ headers = workspace_headers()
13
+ workspace = workspace_client()
14
+ client = (
15
+ AsyncDatabricksOpenAI(workspace_client=workspace, default_headers=headers)
16
+ if headers
17
+ else AsyncDatabricksOpenAI(workspace_client=workspace)
18
+ )
19
+ set_default_openai_client(client)
20
+ set_default_openai_api("chat_completions")
21
+
22
+
23
+ async def invoke(messages: list[dict[str, Any]]) -> dict[str, Any]:
24
+ _configure_client()
25
+ result = await Runner.run(
26
+ Agent(name="Agent", instructions="You are a helpful assistant.", model=MODEL),
27
+ messages,
28
+ )
29
+ return {"output": [{"role": "assistant", "content": str(result.final_output)}]}
@@ -0,0 +1 @@
1
+ command: ["uv", "run", "start-server"]
@@ -0,0 +1,38 @@
1
+ [project]
2
+ name = "custom-agent-openai"
3
+ version = "0.1.0"
4
+ description = "OpenAI Agents SDK agent with a custom FastAPI server"
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ dependencies = [
8
+ "databricks-agentbricks>=0.2.0",
9
+ "databricks-openai>=0.13.0",
10
+ "databricks-sdk>=0.124.0",
11
+ "fastapi>=0.129.0",
12
+ "openai-agents>=0.8.0",
13
+ "python-dotenv>=1.2.1",
14
+ "uvicorn>=0.41.0",
15
+ ]
16
+
17
+ [build-system]
18
+ requires = ["hatchling"]
19
+ build-backend = "hatchling.build"
20
+
21
+ [tool.hatch.build.targets.wheel]
22
+ packages = ["agent", "runtime"]
23
+
24
+ [dependency-groups]
25
+ dev = [
26
+ "hatchling>=1.28.0",
27
+ "httpx>=0.28.1",
28
+ "pytest>=9.0.2",
29
+ ]
30
+
31
+ [tool.uv]
32
+ default-groups = ["dev"]
33
+
34
+ [tool.pytest.ini_options]
35
+ testpaths = ["tests"]
36
+
37
+ [project.scripts]
38
+ start-server = "runtime.main:main"
@@ -0,0 +1,31 @@
1
+ import os
2
+ from pathlib import Path
3
+ from typing import Any
4
+
5
+ import uvicorn
6
+ from agent.agent import invoke
7
+ from dotenv import load_dotenv
8
+ from fastapi import FastAPI
9
+ from pydantic import BaseModel, ConfigDict, Field
10
+
11
+ # override=False so injected DATABRICKS_* (from `ab dev -p` or the deploy platform) win over a
12
+ # checked-in .env.
13
+ load_dotenv(dotenv_path=Path(__file__).parent.parent / ".env", override=False)
14
+
15
+
16
+ class InvocationRequest(BaseModel):
17
+ model_config = ConfigDict(extra="forbid")
18
+
19
+ input: list[dict[str, Any]] = Field(default_factory=list)
20
+
21
+
22
+ app = FastAPI(title="Custom OpenAI Agent")
23
+
24
+
25
+ @app.post("/invocations")
26
+ async def invocations(body: InvocationRequest) -> dict[str, Any]:
27
+ return await invoke(body.input)
28
+
29
+
30
+ def main() -> None:
31
+ uvicorn.run("runtime.main:app", host="0.0.0.0", port=int(os.getenv("PORT", "8000")))
@@ -0,0 +1,29 @@
1
+ from unittest.mock import AsyncMock
2
+
3
+ from fastapi.testclient import TestClient
4
+
5
+ import runtime.main as runtime
6
+
7
+
8
+ def test_foreground_invocation(monkeypatch) -> None:
9
+ invoke = AsyncMock(return_value={"output": [{"role": "assistant", "content": "hello"}]})
10
+ monkeypatch.setattr(runtime, "invoke", invoke)
11
+
12
+ response = TestClient(runtime.app).post(
13
+ "/invocations",
14
+ json={"input": [{"role": "user", "content": "hi"}]},
15
+ )
16
+
17
+ assert response.status_code == 200
18
+ assert response.json()["output"][0]["content"] == "hello"
19
+ invoke.assert_awaited_once_with([{"role": "user", "content": "hi"}])
20
+
21
+
22
+ def test_custom_server_rejects_runtime_transport_fields() -> None:
23
+ response = TestClient(runtime.app).post(
24
+ "/invocations",
25
+ json={"input": [], "stream": True},
26
+ )
27
+
28
+ assert response.status_code == 422
29
+ assert "/api/invocations" not in runtime.app.openapi()["paths"]
@@ -0,0 +1,39 @@
1
+ from typing import Any
2
+
3
+ from databricks.sdk import WorkspaceClient
4
+ from databricks_openai.agents import McpServer # ty: ignore[unresolved-import]
5
+
6
+ # BEGIN: agentbricks add-sandbox
7
+ # The downscope is fixed when this file is generated. It is sent as MCP metadata,
8
+ # outside model-controlled tool arguments, on every sandbox call.
9
+ _SANDBOX_DOWNSCOPE: dict[str, list[dict[str, str]]] = {} # __AGENTBRICKS_SANDBOX_DOWNSCOPE__
10
+
11
+
12
+ class _SandboxMcpServer(McpServer):
13
+ async def call_tool(
14
+ self,
15
+ tool_name: str,
16
+ arguments: dict[str, Any] | None,
17
+ **kwargs: Any,
18
+ ) -> Any:
19
+ incoming_meta = kwargs.pop("meta", None)
20
+ meta = dict(incoming_meta) if isinstance(incoming_meta, dict) else {}
21
+ meta["downscope"] = _SANDBOX_DOWNSCOPE
22
+ return await super().call_tool(tool_name, arguments, meta=meta, **kwargs)
23
+
24
+
25
+ def _build_sandbox_mcp_server() -> McpServer:
26
+ workspace_client = WorkspaceClient()
27
+ return _SandboxMcpServer(
28
+ url=(
29
+ f"{workspace_client.config.host.rstrip('/')}/ai-gateway/mcp-services/system.ai.sandbox"
30
+ ),
31
+ workspace_client=workspace_client,
32
+ timeout=120.0,
33
+ name="system.ai.sandbox",
34
+ # Production advertises ``sandbox``; older preview workspaces use ``run_code``.
35
+ tool_filter={"allowed_tool_names": ["sandbox", "run_code"]},
36
+ )
37
+
38
+
39
+ # END: agentbricks add-sandbox
@@ -0,0 +1,39 @@
1
+ from typing import Any
2
+
3
+ from databricks.sdk import WorkspaceClient
4
+ from databricks_langchain import DatabricksMCPServer # ty: ignore[unresolved-import]
5
+ from langchain_mcp_adapters.sessions import create_session # ty: ignore[unresolved-import]
6
+
7
+ # BEGIN: agentbricks add-sandbox
8
+ # The downscope is fixed when this file is generated. It is sent as MCP metadata,
9
+ # outside model-controlled tool arguments, on every sandbox call.
10
+ _SANDBOX_DOWNSCOPE: dict[str, list[dict[str, str]]] = {} # __AGENTBRICKS_SANDBOX_DOWNSCOPE__
11
+
12
+
13
+ def _build_sandbox_mcp_server() -> DatabricksMCPServer:
14
+ workspace_client = WorkspaceClient()
15
+ return DatabricksMCPServer(
16
+ name="system.ai.sandbox",
17
+ url=(
18
+ f"{workspace_client.config.host.rstrip('/')}/ai-gateway/mcp-services/system.ai.sandbox"
19
+ ),
20
+ workspace_client=workspace_client,
21
+ timeout=120.0,
22
+ )
23
+
24
+
25
+ async def _sandbox_tool_interceptor(request: Any, handler: Any) -> Any:
26
+ if request.server_name != "system.ai.sandbox":
27
+ return await handler(request)
28
+
29
+ connection = _build_sandbox_mcp_server().to_connection_dict()
30
+ async with create_session(connection) as session:
31
+ await session.initialize()
32
+ return await session.call_tool(
33
+ request.name,
34
+ request.args,
35
+ meta={"downscope": _SANDBOX_DOWNSCOPE},
36
+ )
37
+
38
+
39
+ # END: agentbricks add-sandbox
@@ -0,0 +1,49 @@
1
+ # LangGraph Chat App Overlay
2
+
3
+ `ab init --framework langgraph` copies this framework-specific overlay after the base
4
+ `agent-langgraph` template (it is included by default; `--disable-chat-app` opts out). It is
5
+ intentionally not a post-generation mutation command.
6
+
7
+ ## Installed files
8
+
9
+ - `ui/` contains the zero-build chat client.
10
+ - `runtime/ui.py` serves the assets and exposes demo APIs for memory and sessions.
11
+ - `runtime/main.py` installs the chat routes on the base FastAPI runtime.
12
+ - `tests/test_demo_ui.py` verifies the browser-facing routes.
13
+
14
+ ## Behavior
15
+
16
+ The capability indicators are automatic. Streaming and background reflect the runtime contract;
17
+ Session reflects checkpoint history; Memory requires `AGENT_MEMORY_STORE`; Traces reflects the MLflow
18
+ tracing config (destination + experiment). Selecting Memory opens a pane for browsing the store's
19
+ entries (searchable, filterable by actor, with a modal for each entry); the other indicators expand
20
+ in place, and Traces links out to the MLflow experiment. The transport selector is the only manual
21
+ capability choice.
22
+
23
+ The composer's model picker lists the workspace's Unity Catalog AI Gateway chat model services — the
24
+ `system.ai.*` model services from `GET /api/2.1/unity-catalog/model-services?parent=schemas/system.ai`
25
+ (embeddings-only services filtered out), exposed as `GET /api/demo/models` and pinned to
26
+ `agent.agent.MODEL` as the default. Each request sends the selected model as `model` in the
27
+ invocation body; the agent is rebuilt per turn, so the picker changes the model for the next turn
28
+ without a restart. Discovery is best-effort: if listing is unavailable (e.g. `system.ai` isn't
29
+ readable), the picker falls back to just the default. Omitting `model` uses `MODEL`.
30
+
31
+ The agent calls the chosen model through the gateway (`<host>/ai-gateway/mlflow/v1`) rather than
32
+ `/serving-endpoints`, so `MODEL` is a `system.ai.*` model service name. The picker is capped
33
+ (`_MODEL_LIMIT`, 20) with the default pinned first and the rest alphabetical, so truncation never
34
+ drops the configured default. Transient list failures are retried in
35
+ `databricks_agentkit.runtime.model_services` before the fallback applies.
36
+
37
+ The UI reads local history from the LangGraph checkpoint and managed history from Session Store
38
+ items. It keeps a stable application session UUID in browser local storage and includes it inside
39
+ every durable invocation's `input`; each turn gets a separate invocation UUID. The router cookie is
40
+ independent and may still provide sticky replica routing.
41
+
42
+ The Sessions card creates new session UUIDs in the browser. With a managed Session Store,
43
+ `GET /api/demo/sessions` lists the most recent sessions for the signed-in actor and each Open action
44
+ calls `POST /api/demo/sessions/{session_id}/open`. Opening a session verifies ownership and reloads
45
+ its transcript and pending LangGraph state. In local in-memory mode only the current browser session
46
+ can be listed because there is no shared session index.
47
+
48
+ Transcript responses include only user, assistant, tool, system, and human-decision message items;
49
+ checkpoint fragments remain in Session Store but are never returned to the chat UI.
@@ -0,0 +1,26 @@
1
+ """Run the LangGraph agent with the optional Agent Bricks chat app."""
2
+
3
+ import os
4
+ from pathlib import Path
5
+
6
+ import uvicorn
7
+ from agent.agent import configure
8
+ from dotenv import load_dotenv
9
+ from runtime.adapter import invoke, recover
10
+ from runtime.ui import install_ui
11
+
12
+ from databricks_agentkit import DurableAgentServer
13
+
14
+ # override=False so injected DATABRICKS_* (from `ab dev -p` or the deploy platform) win over a
15
+ # checked-in .env.
16
+ load_dotenv(dotenv_path=Path(__file__).parent.parent / ".env", override=False)
17
+ configure()
18
+
19
+ app = DurableAgentServer()
20
+ app.invoke(invoke)
21
+ app.recover(recover)
22
+ install_ui(app)
23
+
24
+
25
+ def main() -> None:
26
+ uvicorn.run("runtime.main:app", host="0.0.0.0", port=int(os.getenv("PORT", "8000")))