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.
- databricks_agentbricks/__init__.py +1 -0
- databricks_agentbricks/_group.py +217 -0
- databricks_agentbricks/agent_project.py +657 -0
- databricks_agentbricks/app_resources.py +139 -0
- databricks_agentbricks/cli/__init__.py +12 -0
- databricks_agentbricks/cli/app.py +108 -0
- databricks_agentbricks/cli/app_auth.py +198 -0
- databricks_agentbricks/cli/auth.py +142 -0
- databricks_agentbricks/cli/deploy.py +954 -0
- databricks_agentbricks/cli/dev.py +310 -0
- databricks_agentbricks/cli/endpoint.py +145 -0
- databricks_agentbricks/cli/endpoint_examples.py +33 -0
- databricks_agentbricks/cli/endpoint_output.py +53 -0
- databricks_agentbricks/cli/endpoint_request.py +71 -0
- databricks_agentbricks/cli/endpoint_transport.py +148 -0
- databricks_agentbricks/cli/help.py +467 -0
- databricks_agentbricks/cli/init.py +496 -0
- databricks_agentbricks/cli/mcp.py +75 -0
- databricks_agentbricks/cli/memory.py +520 -0
- databricks_agentbricks/cli/sandbox.py +823 -0
- databricks_agentbricks/cli/sessions.py +588 -0
- databricks_agentbricks/cli/tools.py +456 -0
- databricks_agentbricks/cli/tracing.py +724 -0
- databricks_agentbricks/databricks_cli.py +38 -0
- databricks_agentbricks/errors.py +114 -0
- databricks_agentbricks/lakebase_runtime_store.py +107 -0
- databricks_agentbricks/legacy_lakebase_runtime_store.py +74 -0
- databricks_agentbricks/project_config.py +157 -0
- databricks_agentbricks/project_types.py +55 -0
- databricks_agentbricks/py.typed +0 -0
- databricks_agentbricks/render.py +349 -0
- databricks_agentbricks/templates/agent-bricks-migrate/SKILL.md +101 -0
- databricks_agentbricks/templates/agent-langgraph/.env.example +36 -0
- databricks_agentbricks/templates/agent-langgraph/.gitignore +199 -0
- databricks_agentbricks/templates/agent-langgraph/AGENTKIT_CONTRACT.md +95 -0
- databricks_agentbricks/templates/agent-langgraph/AGENTS.md +31 -0
- databricks_agentbricks/templates/agent-langgraph/CLAUDE.md +1 -0
- databricks_agentbricks/templates/agent-langgraph/README.md +141 -0
- databricks_agentbricks/templates/agent-langgraph/agent/__init__.py +0 -0
- databricks_agentbricks/templates/agent-langgraph/agent/agent.py +177 -0
- databricks_agentbricks/templates/agent-langgraph/agent/mcps.py +27 -0
- databricks_agentbricks/templates/agent-langgraph/agent/tools/__init__.py +24 -0
- databricks_agentbricks/templates/agent-langgraph/agent/tools/sample_tool.py +15 -0
- databricks_agentbricks/templates/agent-langgraph/agent/tools/send_message.py +17 -0
- databricks_agentbricks/templates/agent-langgraph/app.yaml +15 -0
- databricks_agentbricks/templates/agent-langgraph/pyproject.toml +42 -0
- databricks_agentbricks/templates/agent-langgraph/runtime/__init__.py +0 -0
- databricks_agentbricks/templates/agent-langgraph/runtime/adapter.py +144 -0
- databricks_agentbricks/templates/agent-langgraph/runtime/main.py +25 -0
- databricks_agentbricks/templates/agent-langgraph/tests/__init__.py +0 -0
- databricks_agentbricks/templates/agent-langgraph/tests/test_agent.py +211 -0
- databricks_agentbricks/templates/agent-langgraph/tests/test_runtime.py +19 -0
- databricks_agentbricks/templates/agent-langgraph/tests/test_workspace.py +28 -0
- databricks_agentbricks/templates/agent-openai/.env.example +37 -0
- databricks_agentbricks/templates/agent-openai/.gitignore +199 -0
- databricks_agentbricks/templates/agent-openai/AGENTKIT_CONTRACT.md +107 -0
- databricks_agentbricks/templates/agent-openai/AGENTS.md +76 -0
- databricks_agentbricks/templates/agent-openai/CLAUDE.md +1 -0
- databricks_agentbricks/templates/agent-openai/README.md +143 -0
- databricks_agentbricks/templates/agent-openai/agent/__init__.py +0 -0
- databricks_agentbricks/templates/agent-openai/agent/agent.py +205 -0
- databricks_agentbricks/templates/agent-openai/agent/mcps.py +28 -0
- databricks_agentbricks/templates/agent-openai/agent/tools/__init__.py +24 -0
- databricks_agentbricks/templates/agent-openai/agent/tools/sample_tool.py +15 -0
- databricks_agentbricks/templates/agent-openai/agent/tools/send_message.py +18 -0
- databricks_agentbricks/templates/agent-openai/app.yaml +15 -0
- databricks_agentbricks/templates/agent-openai/pyproject.toml +42 -0
- databricks_agentbricks/templates/agent-openai/runtime/__init__.py +0 -0
- databricks_agentbricks/templates/agent-openai/runtime/adapter.py +188 -0
- databricks_agentbricks/templates/agent-openai/runtime/main.py +25 -0
- databricks_agentbricks/templates/agent-openai/tests/__init__.py +0 -0
- databricks_agentbricks/templates/agent-openai/tests/test_agent.py +326 -0
- databricks_agentbricks/templates/agent-openai/tests/test_runtime.py +19 -0
- databricks_agentbricks/templates/agent-openai/tests/test_workspace.py +28 -0
- databricks_agentbricks/templates/custom-agent-langgraph/.env.example +1 -0
- databricks_agentbricks/templates/custom-agent-langgraph/.gitignore +11 -0
- databricks_agentbricks/templates/custom-agent-langgraph/README.md +22 -0
- databricks_agentbricks/templates/custom-agent-langgraph/agent/__init__.py +0 -0
- databricks_agentbricks/templates/custom-agent-langgraph/agent/agent.py +27 -0
- databricks_agentbricks/templates/custom-agent-langgraph/app.yaml +1 -0
- databricks_agentbricks/templates/custom-agent-langgraph/pyproject.toml +38 -0
- databricks_agentbricks/templates/custom-agent-langgraph/runtime/__init__.py +0 -0
- databricks_agentbricks/templates/custom-agent-langgraph/runtime/main.py +31 -0
- databricks_agentbricks/templates/custom-agent-langgraph/tests/test_runtime.py +29 -0
- databricks_agentbricks/templates/custom-agent-openai/.env.example +1 -0
- databricks_agentbricks/templates/custom-agent-openai/.gitignore +11 -0
- databricks_agentbricks/templates/custom-agent-openai/README.md +22 -0
- databricks_agentbricks/templates/custom-agent-openai/agent/__init__.py +0 -0
- databricks_agentbricks/templates/custom-agent-openai/agent/agent.py +29 -0
- databricks_agentbricks/templates/custom-agent-openai/app.yaml +1 -0
- databricks_agentbricks/templates/custom-agent-openai/pyproject.toml +38 -0
- databricks_agentbricks/templates/custom-agent-openai/runtime/__init__.py +0 -0
- databricks_agentbricks/templates/custom-agent-openai/runtime/main.py +31 -0
- databricks_agentbricks/templates/custom-agent-openai/tests/test_runtime.py +29 -0
- databricks_agentbricks/templates/sandbox_mcp.py +39 -0
- databricks_agentbricks/templates/sandbox_mcp_langgraph.py +39 -0
- databricks_agentbricks/templates/ui/agent-langgraph/CHAT_APP.md +49 -0
- databricks_agentbricks/templates/ui/agent-langgraph/runtime/main.py +26 -0
- databricks_agentbricks/templates/ui/agent-langgraph/runtime/ui.py +528 -0
- databricks_agentbricks/templates/ui/agent-langgraph/tests/test_demo_ui.py +542 -0
- databricks_agentbricks/templates/ui/agent-langgraph/ui/agentbricks-mark.png +0 -0
- databricks_agentbricks/templates/ui/agent-langgraph/ui/app.js +1464 -0
- databricks_agentbricks/templates/ui/agent-langgraph/ui/index.html +281 -0
- databricks_agentbricks/templates/ui/agent-langgraph/ui/styles.css +1913 -0
- databricks_agentbricks/templates/ui/agent-openai/CHAT_APP.md +54 -0
- databricks_agentbricks/templates/ui/agent-openai/runtime/main.py +26 -0
- databricks_agentbricks/templates/ui/agent-openai/runtime/ui.py +521 -0
- databricks_agentbricks/templates/ui/agent-openai/tests/test_demo_ui.py +512 -0
- databricks_agentbricks/templates/ui/agent-openai/ui/agentbricks-mark.png +0 -0
- databricks_agentbricks/templates/ui/agent-openai/ui/app.js +1428 -0
- databricks_agentbricks/templates/ui/agent-openai/ui/index.html +281 -0
- databricks_agentbricks/templates/ui/agent-openai/ui/styles.css +1913 -0
- databricks_agentbricks/theme.py +72 -0
- databricks_agentbricks-0.2.0.dist-info/METADATA +897 -0
- databricks_agentbricks-0.2.0.dist-info/RECORD +159 -0
- databricks_agentbricks-0.2.0.dist-info/WHEEL +4 -0
- databricks_agentbricks-0.2.0.dist-info/entry_points.txt +2 -0
- databricks_agentbricks-0.2.0.dist-info/licenses/NOTICE +39 -0
- databricks_agentkit/__init__.py +67 -0
- databricks_agentkit/_api_client.py +673 -0
- databricks_agentkit/_pagination.py +25 -0
- databricks_agentkit/client.py +31 -0
- databricks_agentkit/langgraph/__init__.py +98 -0
- databricks_agentkit/langgraph/genie.py +50 -0
- databricks_agentkit/langgraph/mcp.py +216 -0
- databricks_agentkit/langgraph/memory.py +67 -0
- databricks_agentkit/langgraph/session_store.py +485 -0
- databricks_agentkit/memory_store.py +371 -0
- databricks_agentkit/models.py +330 -0
- databricks_agentkit/openai/__init__.py +93 -0
- databricks_agentkit/openai/genie.py +50 -0
- databricks_agentkit/openai/mcp.py +189 -0
- databricks_agentkit/openai/memory.py +67 -0
- databricks_agentkit/openai/sessions.py +157 -0
- databricks_agentkit/py.typed +0 -0
- databricks_agentkit/runtime/ARCHITECTURE.md +64 -0
- databricks_agentkit/runtime/README.md +184 -0
- databricks_agentkit/runtime/__init__.py +69 -0
- databricks_agentkit/runtime/app.py +316 -0
- databricks_agentkit/runtime/auth.py +149 -0
- databricks_agentkit/runtime/durability/__init__.py +1 -0
- databricks_agentkit/runtime/durability/execution.py +133 -0
- databricks_agentkit/runtime/durability/heartbeat.py +64 -0
- databricks_agentkit/runtime/durability/lakebase_runtime_store.py +648 -0
- databricks_agentkit/runtime/durability/recovery.py +70 -0
- databricks_agentkit/runtime/durability/store.py +33 -0
- databricks_agentkit/runtime/execution.py +160 -0
- databricks_agentkit/runtime/genie.py +224 -0
- databricks_agentkit/runtime/mcp_auth.py +114 -0
- databricks_agentkit/runtime/model_services.py +90 -0
- databricks_agentkit/runtime/runtime.py +273 -0
- databricks_agentkit/runtime/session_store_client.py +120 -0
- databricks_agentkit/runtime/store.py +287 -0
- databricks_agentkit/runtime/tool_manifest.py +223 -0
- databricks_agentkit/runtime/tracing.py +71 -0
- databricks_agentkit/runtime/types.py +118 -0
- databricks_agentkit/runtime/workspace.py +27 -0
- databricks_agentkit/session_store.py +434 -0
- databricks_agentkit/timefmt.py +85 -0
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
"""Discover available integrations and manage manifest-backed tool bindings."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import pathlib
|
|
6
|
+
import re
|
|
7
|
+
from typing import Any, Literal
|
|
8
|
+
|
|
9
|
+
import click
|
|
10
|
+
|
|
11
|
+
from databricks_agentbricks import render
|
|
12
|
+
from databricks_agentbricks.agent_project import AgentProject, Scope, ToolSpec
|
|
13
|
+
from databricks_agentbricks.cli.help import _example_epilog
|
|
14
|
+
from databricks_agentbricks.cli.mcp import _add_command, _list_services, _validate_schema
|
|
15
|
+
from databricks_agentbricks.errors import AgentCliError
|
|
16
|
+
from databricks_agentbricks.project_config import require_managed_tool_support
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _identifier(value: str) -> str:
|
|
20
|
+
normalized = re.sub(r"[^A-Za-z0-9_]", "_", value.strip()).strip("_").lower()
|
|
21
|
+
if not normalized or normalized[0].isdigit():
|
|
22
|
+
raise AgentCliError(f"Could not derive a Python identifier from {value!r}.")
|
|
23
|
+
return normalized
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _default_id(resource: str) -> str:
|
|
27
|
+
return _identifier(resource.rsplit(".", 1)[-1])
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _require_arg(value: str, label: str) -> str:
|
|
31
|
+
"""Reject an empty/whitespace positional argument with a clear message."""
|
|
32
|
+
if value is None or not value.strip():
|
|
33
|
+
raise AgentCliError(f"A {label} is required.")
|
|
34
|
+
return value
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _source_value(spec: ToolSpec) -> str:
|
|
38
|
+
# For a sandbox tool, the useful detail is the allowed scopes, not the (constant)
|
|
39
|
+
# 'system.ai.sandbox' service name that duplicates the KIND column.
|
|
40
|
+
if spec.source.kind == "sandbox" and spec.policy.downscope:
|
|
41
|
+
return ", ".join(s.resource for s in spec.policy.downscope)
|
|
42
|
+
return spec.source.service or spec.source.function or spec.source.space_id or spec.source.kind
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _tool_record(spec: ToolSpec) -> dict[str, str]:
|
|
46
|
+
record = {
|
|
47
|
+
"id": spec.id,
|
|
48
|
+
"kind": spec.source.kind,
|
|
49
|
+
"source": _source_value(spec),
|
|
50
|
+
}
|
|
51
|
+
if spec.source.kind in ("mcp", "sandbox", "uc_function", "genie_one", "genie_agent"):
|
|
52
|
+
record["auth"] = spec.auth or (
|
|
53
|
+
"app/default" if spec.source.kind == "uc_function" else "unspecified"
|
|
54
|
+
)
|
|
55
|
+
return record
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _emit_change(
|
|
59
|
+
obj: Any, project: AgentProject, spec: ToolSpec, changed_files: list[pathlib.Path]
|
|
60
|
+
) -> None:
|
|
61
|
+
payload = {
|
|
62
|
+
"schema_version": 1,
|
|
63
|
+
"changed": bool(changed_files),
|
|
64
|
+
"changed_files": [str(path) for path in changed_files],
|
|
65
|
+
"manifest": str(project.path),
|
|
66
|
+
"tool": _tool_record(spec),
|
|
67
|
+
}
|
|
68
|
+
if getattr(obj, "output", "text") == "json":
|
|
69
|
+
render.emit_json(payload)
|
|
70
|
+
return
|
|
71
|
+
if changed_files:
|
|
72
|
+
render.success(
|
|
73
|
+
f"Added {spec.id}",
|
|
74
|
+
fields={"Kind": spec.source.kind, "Manifest": str(project.path)},
|
|
75
|
+
)
|
|
76
|
+
else:
|
|
77
|
+
click.echo(f"Tool {spec.id!r} is already configured in {project.path}")
|
|
78
|
+
click.echo(f"Review {project.path} to check configured managed tools and MCP bindings.")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _add_spec(obj: Any, source: pathlib.Path, spec: ToolSpec) -> None:
|
|
82
|
+
# Managed bindings are framework-neutral agent.toml entries. Both Agent Bricks server runtime
|
|
83
|
+
# adapters read them; custom-server projects wire tools directly in agent code.
|
|
84
|
+
project = AgentProject.load(source)
|
|
85
|
+
require_managed_tool_support(project.root)
|
|
86
|
+
changed = project.add_tool(spec)
|
|
87
|
+
if spec.source.kind == "mcp":
|
|
88
|
+
service = spec.source.service
|
|
89
|
+
try:
|
|
90
|
+
obj.client().get_mcp_service(service)
|
|
91
|
+
except AgentCliError as exc:
|
|
92
|
+
raise AgentCliError(
|
|
93
|
+
f"Could not validate MCP service {service!r}: {exc.message}",
|
|
94
|
+
error_code=exc.error_code,
|
|
95
|
+
hint=exc.hint
|
|
96
|
+
or "Run `ab tools list --kind mcp` with the same --profile to find "
|
|
97
|
+
"available services.",
|
|
98
|
+
) from exc
|
|
99
|
+
changed_files = [project.write()] if changed else []
|
|
100
|
+
_emit_change(obj, project, spec, changed_files)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def add_sandbox_to_manifest(
|
|
104
|
+
obj: Any,
|
|
105
|
+
source: pathlib.Path,
|
|
106
|
+
scopes: tuple[str, ...],
|
|
107
|
+
permission: str,
|
|
108
|
+
*,
|
|
109
|
+
tool_id: str = "sandbox",
|
|
110
|
+
auth: Literal["user", "app"] = "user",
|
|
111
|
+
) -> None:
|
|
112
|
+
"""Shared implementation for the nested command and compatibility alias."""
|
|
113
|
+
parsed: list[Scope] = []
|
|
114
|
+
seen: set[tuple[str, str]] = set()
|
|
115
|
+
for value in scopes:
|
|
116
|
+
scope = Scope.parse(value, permission)
|
|
117
|
+
identity = (scope.kind, scope.value)
|
|
118
|
+
if identity not in seen:
|
|
119
|
+
parsed.append(scope)
|
|
120
|
+
seen.add(identity)
|
|
121
|
+
_add_spec(obj, source, ToolSpec.sandbox(tool_id, scopes=parsed, auth=auth))
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@click.group()
|
|
125
|
+
def tools() -> None:
|
|
126
|
+
"""Discover available integrations and manage an agent's tool bindings.
|
|
127
|
+
|
|
128
|
+
Tools are what let an agent act beyond the language model itself — query governed data, call a
|
|
129
|
+
service, or run a function — and each one is recorded in agent.toml so `ab dev` / `ab deploy`
|
|
130
|
+
wire it in. `ab tools add` manages these Databricks-managed tool types:
|
|
131
|
+
|
|
132
|
+
\b
|
|
133
|
+
sandbox Query Unity Catalog data via system.ai.sandbox, scoped
|
|
134
|
+
to the tables, volumes, or paths you choose.
|
|
135
|
+
mcp A Databricks-managed MCP service (see `ab tools list --kind mcp`),
|
|
136
|
+
e.g. system.ai.web_search.
|
|
137
|
+
uc-function An existing Unity Catalog function (catalog.schema.function).
|
|
138
|
+
genie-one Workspace-wide Genie One MCP tools.
|
|
139
|
+
genie-agent Native Genie conversation tools for a configured space ID.
|
|
140
|
+
|
|
141
|
+
Browse available integrations with `ab tools list`, add one with `ab tools add <type>`,
|
|
142
|
+
and drop a binding with `ab tools remove`. Review agent.toml for configured managed tools
|
|
143
|
+
and MCP bindings. The list shows addable integrations, not configured bindings or individual
|
|
144
|
+
operations inside an MCP service. Custom Python tools are code-first — write them directly
|
|
145
|
+
in your project's code rather than through the CLI.
|
|
146
|
+
"""
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
@tools.group("add")
|
|
150
|
+
def add() -> None:
|
|
151
|
+
"""Add a managed sandbox, MCP service, UC function, or Genie tool binding.
|
|
152
|
+
|
|
153
|
+
Subcommands target the current directory by default.
|
|
154
|
+
|
|
155
|
+
Pass --source PATH to target another project.
|
|
156
|
+
|
|
157
|
+
Review that project's agent.toml to check configured managed tools and MCP bindings.
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _source_option(function):
|
|
162
|
+
return click.option(
|
|
163
|
+
"--source",
|
|
164
|
+
type=click.Path(exists=True, file_okay=False, path_type=pathlib.Path),
|
|
165
|
+
default=pathlib.Path("."),
|
|
166
|
+
show_default=True,
|
|
167
|
+
help="Agent Bricks project containing agent.toml.",
|
|
168
|
+
)(function)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
@add.command("sandbox")
|
|
172
|
+
@click.option(
|
|
173
|
+
"--scope",
|
|
174
|
+
"scopes",
|
|
175
|
+
multiple=True,
|
|
176
|
+
required=True,
|
|
177
|
+
help="Allowed table:, volume:, or workspace: resource. Repeat for multiple scopes.",
|
|
178
|
+
)
|
|
179
|
+
@click.option(
|
|
180
|
+
"--permission",
|
|
181
|
+
type=click.Choice(["read_only", "read_write"]),
|
|
182
|
+
default="read_only",
|
|
183
|
+
show_default=True,
|
|
184
|
+
)
|
|
185
|
+
@click.option("--name", "tool_id", default="sandbox", show_default=True)
|
|
186
|
+
@click.option("--auth", type=click.Choice(["user", "app"]), default="user", show_default=True)
|
|
187
|
+
@_source_option
|
|
188
|
+
@click.pass_obj
|
|
189
|
+
def add_sandbox(
|
|
190
|
+
obj: Any,
|
|
191
|
+
scopes: tuple[str, ...],
|
|
192
|
+
permission: str,
|
|
193
|
+
tool_id: str,
|
|
194
|
+
source: pathlib.Path,
|
|
195
|
+
auth: Literal["user", "app"],
|
|
196
|
+
) -> None:
|
|
197
|
+
"""Add a data sandbox tool (system.ai.sandbox), scoped to specific Unity Catalog resources.
|
|
198
|
+
|
|
199
|
+
Review the target project's agent.toml to check configured managed tools and MCP bindings.
|
|
200
|
+
"""
|
|
201
|
+
add_sandbox_to_manifest(obj, source.resolve(), scopes, permission, tool_id=tool_id, auth=auth)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
@add.command("mcp")
|
|
205
|
+
@click.argument("service")
|
|
206
|
+
@click.option("--name", "tool_id", default=None)
|
|
207
|
+
@click.option("--auth", type=click.Choice(["user", "app"]), default="user", show_default=True)
|
|
208
|
+
@_source_option
|
|
209
|
+
@click.pass_obj
|
|
210
|
+
def add_mcp(
|
|
211
|
+
obj: Any,
|
|
212
|
+
service: str,
|
|
213
|
+
tool_id: str | None,
|
|
214
|
+
source: pathlib.Path,
|
|
215
|
+
auth: Literal["user", "app"],
|
|
216
|
+
) -> None:
|
|
217
|
+
"""Validate and add a Databricks-managed MCP service as a tool.
|
|
218
|
+
|
|
219
|
+
Use `ab tools list --kind mcp` for available services. Review the target project's
|
|
220
|
+
agent.toml to check configured managed tools and MCP bindings.
|
|
221
|
+
"""
|
|
222
|
+
_require_arg(service, "managed MCP service name (e.g. system.ai.web_search)")
|
|
223
|
+
_add_spec(
|
|
224
|
+
obj,
|
|
225
|
+
source.resolve(),
|
|
226
|
+
ToolSpec.mcp(tool_id or _default_id(service), service=service, auth=auth),
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
@add.command("uc-function")
|
|
231
|
+
@click.argument("function_name")
|
|
232
|
+
@click.option("--name", "tool_id", default=None)
|
|
233
|
+
@_source_option
|
|
234
|
+
@click.pass_obj
|
|
235
|
+
def add_uc_function(
|
|
236
|
+
obj: Any,
|
|
237
|
+
function_name: str,
|
|
238
|
+
tool_id: str | None,
|
|
239
|
+
source: pathlib.Path,
|
|
240
|
+
) -> None:
|
|
241
|
+
"""Add an existing Unity Catalog function (catalog.schema.function) as a tool.
|
|
242
|
+
|
|
243
|
+
Review the target project's agent.toml to check configured managed tools and MCP bindings.
|
|
244
|
+
"""
|
|
245
|
+
_require_arg(function_name, "Unity Catalog function name (catalog.schema.function)")
|
|
246
|
+
_add_spec(
|
|
247
|
+
obj,
|
|
248
|
+
source.resolve(),
|
|
249
|
+
ToolSpec.uc_function(
|
|
250
|
+
tool_id or _default_id(function_name),
|
|
251
|
+
function=function_name,
|
|
252
|
+
),
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
@add.command("genie-one", epilog=_example_epilog(("ab tools add genie-one",)))
|
|
257
|
+
@click.option("--name", "tool_id", default="genie_one", show_default=True)
|
|
258
|
+
@click.option("--auth", type=click.Choice(["user", "app"]), default="user", show_default=True)
|
|
259
|
+
@_source_option
|
|
260
|
+
@click.pass_obj
|
|
261
|
+
def add_genie_one(
|
|
262
|
+
obj: Any, tool_id: str, auth: Literal["user", "app"], source: pathlib.Path
|
|
263
|
+
) -> None:
|
|
264
|
+
"""Add workspace-wide Genie One MCP tools."""
|
|
265
|
+
_add_spec(obj, source.resolve(), ToolSpec.genie_one(tool_id, auth=auth))
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
@add.command(
|
|
269
|
+
"genie-agent",
|
|
270
|
+
epilog=_example_epilog(
|
|
271
|
+
("ab tools add genie-agent 0123456789abcdef0123456789abcdef --name sales",)
|
|
272
|
+
),
|
|
273
|
+
)
|
|
274
|
+
@click.argument("space_id")
|
|
275
|
+
@click.option("--name", "tool_id", default="genie_agent", show_default=True)
|
|
276
|
+
@click.option("--auth", type=click.Choice(["user", "app"]), default="user", show_default=True)
|
|
277
|
+
@_source_option
|
|
278
|
+
@click.pass_obj
|
|
279
|
+
def add_genie_agent(
|
|
280
|
+
obj: Any,
|
|
281
|
+
space_id: str,
|
|
282
|
+
tool_id: str,
|
|
283
|
+
auth: Literal["user", "app"],
|
|
284
|
+
source: pathlib.Path,
|
|
285
|
+
) -> None:
|
|
286
|
+
"""Add native Genie conversation tools for a 32-character lowercase hexadecimal SPACE_ID."""
|
|
287
|
+
_add_spec(
|
|
288
|
+
obj,
|
|
289
|
+
source.resolve(),
|
|
290
|
+
ToolSpec.genie_agent(tool_id, space_id=space_id, auth=auth),
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
@tools.command("list")
|
|
295
|
+
@click.option(
|
|
296
|
+
"--kind",
|
|
297
|
+
type=click.Choice(["sandbox", "mcp", "uc-function", "genie-one", "genie-agent"]),
|
|
298
|
+
help=(
|
|
299
|
+
"Show one integration kind. Sandbox, uc-function, genie-one, and genie-agent show local "
|
|
300
|
+
"add recipes only."
|
|
301
|
+
),
|
|
302
|
+
)
|
|
303
|
+
@click.option(
|
|
304
|
+
"--schema",
|
|
305
|
+
help="Two-part UC schema: catalog.schema (default: system.ai). Requires --kind mcp.",
|
|
306
|
+
)
|
|
307
|
+
@click.pass_obj
|
|
308
|
+
def list_tools(obj: Any, kind: str | None, schema: str | None) -> None:
|
|
309
|
+
"""List available integrations to add, not configured agent bindings.
|
|
310
|
+
|
|
311
|
+
By default, show built-in add recipes plus caller-visible MCP Services in system.ai.
|
|
312
|
+
--kind mcp limits discovery to MCP Services; --schema catalog.schema replaces system.ai.
|
|
313
|
+
Sandbox recipes require scopes; UC-function and Genie Agent recipes require concrete resource
|
|
314
|
+
identifiers. Genie One needs no additional argument.
|
|
315
|
+
|
|
316
|
+
No agent project is required. MCP discovery uses your Databricks profile; local recipes do
|
|
317
|
+
not authenticate. This does not scan every workspace schema or list individual MCP operations.
|
|
318
|
+
API failures return a nonzero exit status and mark discovery incomplete, not empty.
|
|
319
|
+
|
|
320
|
+
Review agent.toml to check configured managed tools and MCP bindings. The former configured
|
|
321
|
+
list and --source option are removed. JSON discovery uses schema_version 2 and available_tools.
|
|
322
|
+
"""
|
|
323
|
+
if schema is not None and kind != "mcp":
|
|
324
|
+
raise AgentCliError("--schema requires --kind mcp.")
|
|
325
|
+
mcp_schema = (
|
|
326
|
+
_validate_schema("system.ai" if schema is None else schema)
|
|
327
|
+
if kind in (None, "mcp")
|
|
328
|
+
else None
|
|
329
|
+
)
|
|
330
|
+
sandbox_command = _add_command("system.ai.sandbox")
|
|
331
|
+
recipes = [
|
|
332
|
+
{"name": "sandbox", "kind": "sandbox", "add_command": sandbox_command},
|
|
333
|
+
{
|
|
334
|
+
"name": "uc-function",
|
|
335
|
+
"kind": "uc-function",
|
|
336
|
+
"add_command": "ab tools add uc-function catalog.schema.function",
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
"name": "genie-one",
|
|
340
|
+
"kind": "genie-one",
|
|
341
|
+
"add_command": "ab tools add genie-one",
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
"name": "genie-agent",
|
|
345
|
+
"kind": "genie-agent",
|
|
346
|
+
"add_command": "ab tools add genie-agent SPACE_ID",
|
|
347
|
+
},
|
|
348
|
+
]
|
|
349
|
+
rows = [recipe for recipe in recipes if kind is None or recipe["kind"] == kind]
|
|
350
|
+
discovery_error = None
|
|
351
|
+
if mcp_schema is not None:
|
|
352
|
+
try:
|
|
353
|
+
services = _list_services(obj.client(), mcp_schema)
|
|
354
|
+
except AgentCliError as exc:
|
|
355
|
+
discovery_error = exc
|
|
356
|
+
else:
|
|
357
|
+
for service in services:
|
|
358
|
+
name = service["name"]
|
|
359
|
+
if name == "system.ai.sandbox" and kind is None:
|
|
360
|
+
continue
|
|
361
|
+
rows.append(
|
|
362
|
+
{
|
|
363
|
+
"name": name,
|
|
364
|
+
"kind": "mcp",
|
|
365
|
+
"add_command": _add_command(name),
|
|
366
|
+
}
|
|
367
|
+
)
|
|
368
|
+
if getattr(obj, "output", "text") == "json":
|
|
369
|
+
errors = []
|
|
370
|
+
if discovery_error is not None:
|
|
371
|
+
error = {"message": discovery_error.message}
|
|
372
|
+
if discovery_error.error_code:
|
|
373
|
+
error["code"] = discovery_error.error_code
|
|
374
|
+
if discovery_error.hint:
|
|
375
|
+
error["hint"] = discovery_error.hint
|
|
376
|
+
errors.append(error)
|
|
377
|
+
render.emit_json(
|
|
378
|
+
{
|
|
379
|
+
"schema_version": 2,
|
|
380
|
+
"available_tools": rows,
|
|
381
|
+
"mcp_schema": mcp_schema,
|
|
382
|
+
"complete": discovery_error is None,
|
|
383
|
+
"errors": errors,
|
|
384
|
+
}
|
|
385
|
+
)
|
|
386
|
+
else:
|
|
387
|
+
if kind != "mcp":
|
|
388
|
+
render.resource_table(
|
|
389
|
+
"Built-in add recipes",
|
|
390
|
+
[("Kind", "left"), ("Add command (replace example resources)", "left")],
|
|
391
|
+
[(row["kind"], row["add_command"]) for row in rows if row["kind"] != "mcp"],
|
|
392
|
+
)
|
|
393
|
+
if mcp_schema is not None:
|
|
394
|
+
render.resource_table(
|
|
395
|
+
"Available MCP Services",
|
|
396
|
+
[("Service", "left"), ("Add command", "left")],
|
|
397
|
+
[(row["name"], row["add_command"]) for row in rows if row["kind"] == "mcp"],
|
|
398
|
+
subtitle=f"Caller-visible in {mcp_schema}"
|
|
399
|
+
+ (" — discovery incomplete" if discovery_error is not None else ""),
|
|
400
|
+
)
|
|
401
|
+
click.echo("Tip: focus on MCP services with `ab tools list --kind mcp`.")
|
|
402
|
+
click.echo(
|
|
403
|
+
"Discover services in another UC schema with "
|
|
404
|
+
"`ab tools list --kind mcp --schema catalog.schema`."
|
|
405
|
+
)
|
|
406
|
+
click.echo("Review agent.toml to check configured managed tools and MCP bindings.")
|
|
407
|
+
if discovery_error is not None:
|
|
408
|
+
discovery_error.show()
|
|
409
|
+
if discovery_error is not None:
|
|
410
|
+
raise click.exceptions.Exit(1)
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
@tools.command("remove")
|
|
414
|
+
@click.argument("tool_id")
|
|
415
|
+
@click.argument("mcp_service", required=False)
|
|
416
|
+
@_source_option
|
|
417
|
+
@click.pass_obj
|
|
418
|
+
def remove_tool(
|
|
419
|
+
obj: Any,
|
|
420
|
+
tool_id: str,
|
|
421
|
+
mcp_service: str | None,
|
|
422
|
+
source: pathlib.Path,
|
|
423
|
+
) -> None:
|
|
424
|
+
"""Remove a managed tool binding from this agent."""
|
|
425
|
+
project = AgentProject.load(source)
|
|
426
|
+
if mcp_service is not None:
|
|
427
|
+
if tool_id != "mcp":
|
|
428
|
+
raise AgentCliError("A second argument is supported only for `tools remove mcp`.")
|
|
429
|
+
ToolSpec.mcp(_default_id(mcp_service), service=mcp_service)
|
|
430
|
+
matches = [
|
|
431
|
+
tool
|
|
432
|
+
for tool in project.tools
|
|
433
|
+
if tool.source.kind == "mcp" and tool.source.service == mcp_service
|
|
434
|
+
]
|
|
435
|
+
if len(matches) > 1:
|
|
436
|
+
raise AgentCliError(
|
|
437
|
+
f"Multiple bindings use MCP service {mcp_service!r}.",
|
|
438
|
+
hint=f"Review {project.path}, then remove the intended binding by ID.",
|
|
439
|
+
)
|
|
440
|
+
tool_id = matches[0].id if matches else _default_id(mcp_service)
|
|
441
|
+
changed = project.remove_tool(tool_id)
|
|
442
|
+
changed_files = [project.write()] if changed else []
|
|
443
|
+
if getattr(obj, "output", "text") == "json":
|
|
444
|
+
render.emit_json(
|
|
445
|
+
{
|
|
446
|
+
"schema_version": 1,
|
|
447
|
+
"changed": changed,
|
|
448
|
+
"changed_files": [str(path) for path in changed_files],
|
|
449
|
+
"tool_id": tool_id,
|
|
450
|
+
}
|
|
451
|
+
)
|
|
452
|
+
return
|
|
453
|
+
if changed:
|
|
454
|
+
render.success("Removed " + tool_id, fields={"Manifest": str(project.path)})
|
|
455
|
+
else:
|
|
456
|
+
click.echo(f"Tool {tool_id!r} is not configured in {project.path}")
|