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,349 @@
1
+ """Terminal presentation layer for the Agent Bricks CLI.
2
+
3
+ Rendering is centralized so every `list`/`get`/`create` command looks consistent.
4
+ Functions accept an optional `console` for testability; default is stdout.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import json
10
+ from contextlib import contextmanager
11
+ from typing import Any, Iterable, Iterator, Literal, Optional, Sequence
12
+
13
+ import click
14
+ from rich import box
15
+ from rich.console import Console, Group, RenderableType
16
+ from rich.panel import Panel
17
+ from rich.syntax import Syntax
18
+ from rich.table import Table
19
+ from rich.text import Text
20
+
21
+ from databricks_agentbricks import theme
22
+
23
+ # Semantic styles from the facelift palette (see `theme.py`). Color carries meaning, never
24
+ # decoration: LINK (blue) for URLs, COMMAND (cyan) for the actionable next step, SUCCESS (green)
25
+ # for the ✔ and success boxes, and the mid-tone greys for descriptions/metadata. There is no
26
+ # decorative brand accent — the design reserves every color for a signal. These are raw hex/style
27
+ # strings, not themed names, so they render on any `Console` a caller passes in — not just the
28
+ # module's own themed stdout.
29
+ SECONDARY = theme.SECONDARY # descriptions, section labels
30
+ DIM = theme.DIM # metadata: timestamps, key labels, breadcrumbs
31
+ FAINT = theme.FAINT # tree branches, placeholders
32
+ SUCCESS = theme.GREEN
33
+ LINK = theme.BLUE
34
+ COMMAND = theme.CYAN
35
+ WARNING = theme.AMBER
36
+ ERROR = theme.RED
37
+
38
+ # Severity-keyword styles for `diagnostic`: error=red, warning=amber, note=blue.
39
+ _SEVERITY_STYLE = {
40
+ "error": f"bold {theme.RED}",
41
+ "warning": f"bold {theme.AMBER}",
42
+ "note": f"bold {theme.BLUE}",
43
+ }
44
+
45
+ _stdout = Console(theme=theme.AGENTBRICKS_THEME)
46
+
47
+
48
+ def console() -> Console:
49
+ return _stdout
50
+
51
+
52
+ @contextmanager
53
+ def status(message: str, con: Optional[Console] = None) -> Iterator[None]:
54
+ """Show an animated spinner with ``message`` while a slow call runs, then clear it.
55
+
56
+ Wraps ``rich``'s console status; a no-op spinner (no TTY) still runs the body. Use around
57
+ network work like store provisioning so the CLI doesn't look hung. Under ``-o json`` the spinner
58
+ is skipped so no control characters leak into machine-readable output.
59
+ """
60
+ from databricks_agentbricks import errors # local import avoids a cycle at module load
61
+
62
+ con = con or _stdout
63
+ if errors._OUTPUT_MODE == "json":
64
+ yield
65
+ return
66
+ with con.status(message, spinner="dots"):
67
+ yield
68
+
69
+
70
+ @contextmanager
71
+ def progress(message: str, con: Optional[Console] = None) -> Iterator[None]:
72
+ """Like ``status``, but first prints a persistent line so feedback survives the spinner.
73
+
74
+ ``status`` clears itself on exit and only animates on a TTY, so a long, silent wait (e.g. waiting
75
+ for app compute) can look like a hang in terminals where the spinner doesn't render. This prints
76
+ a durable "• message" line up front, then runs a bare spinner (no repeated text) beneath it.
77
+ Skipped under ``-o json`` so machine output stays clean.
78
+ """
79
+ from databricks_agentbricks import errors # local import avoids a cycle at module load
80
+
81
+ con = con or _stdout
82
+ if errors._OUTPUT_MODE == "json":
83
+ yield
84
+ return
85
+ con.print(f"[{DIM}]•[/] {message}")
86
+ # Empty status text: the persistent line above already carries the message, so the spinner
87
+ # underneath is just the animated glyph — no duplicated sentence.
88
+ with con.status("", spinner="dots"):
89
+ yield
90
+
91
+
92
+ # --- small helpers -----------------------------------------------------------
93
+
94
+
95
+ def field(obj: dict, name: str) -> Any:
96
+ """Read a field tolerating snake_case or camelCase JSON keys."""
97
+ if name in obj:
98
+ return obj[name]
99
+ parts = name.split("_")
100
+ camel = parts[0] + "".join(p.title() for p in parts[1:])
101
+ return obj.get(camel)
102
+
103
+
104
+ def emit_json(data: Any) -> None:
105
+ """Print raw JSON for `--output json` (stable, pipe-friendly)."""
106
+ click.echo(json.dumps(data, indent=2, default=str))
107
+
108
+
109
+ def confirm_destroy(target: str, *, assume_yes: bool) -> None:
110
+ """Guard a destructive action with a confirmation prompt.
111
+
112
+ No-op when `assume_yes` is set (the `--yes/-y` flag, for scripts). Otherwise prompts
113
+ on the terminal and aborts unless the user answers yes. A non-interactive stdin (a
114
+ pipe with no `--yes`) answers no and aborts, which is the safe default.
115
+ """
116
+ if assume_yes:
117
+ return
118
+ if not click.confirm(f"Delete {target}? This cannot be undone.", default=False):
119
+ raise click.Abort()
120
+
121
+
122
+ def status_pill(status: Optional[str]) -> Text:
123
+ """Create a colored ●/○ status indicator, using the palette's semantic colors."""
124
+ value = (status or "").strip().upper()
125
+ if value in {"ACTIVE", "RUNNING", "READY"}:
126
+ return Text("● ", style=SUCCESS) + Text(value.title(), style=SUCCESS)
127
+ if value in {"PENDING", "CREATING", "STARTING", "DEPLOYING"}:
128
+ return Text("○ ", style=WARNING) + Text(value.title(), style=WARNING)
129
+ if value in {"DISABLED", "DELETED", "STOPPED", "ERROR", "FAILED"}:
130
+ return Text("⨯ ", style=ERROR) + Text(value.title(), style=ERROR)
131
+ return Text("● ", style=DIM) + Text(value.title() or "Unknown", style=DIM)
132
+
133
+
134
+ def warning(message: str, con: Optional[Console] = None) -> None:
135
+ """Print a yellow ⚠ warning line (non-fatal; the command keeps running)."""
136
+ (con or _stdout).print(Text("⚠ ", style="yellow") + Text(message, style="yellow"))
137
+
138
+
139
+ def hyperlink(text: str, url: Optional[str]) -> Text:
140
+ """A terminal hyperlink (OSC 8): renders `text`, opens `url` on click; plain text if no url.
141
+
142
+ Blue + underline, because the palette reserves blue for links/URLs. Supported terminals show
143
+ `text` as clickable so the full URL needn't fit on screen; others fall back to the plain text.
144
+ Use `-o json` for the raw URL where a terminal lacks OSC 8.
145
+ """
146
+ if not url:
147
+ return Text(text)
148
+ return Text(text, style=f"{LINK} underline link {url}")
149
+
150
+
151
+ def diagnostic(
152
+ severity: Literal["error", "warning", "note"],
153
+ message: str,
154
+ *,
155
+ code: Optional[str] = None,
156
+ help: Optional[str] = None,
157
+ con: Optional[Console] = None,
158
+ ) -> None:
159
+ """Render one cargo/uv-style diagnostic.
160
+
161
+ A color-coded severity keyword, a plain-language message, and an optional indented ``help:``
162
+ line carrying the fix::
163
+
164
+ warning: active virtualenv ignored — `VIRTUAL_ENV` doesn't match `.venv`
165
+ help: pass --active to target the active environment
166
+
167
+ ``code`` renders cargo's ``error[CODE]:`` form (errors only). The severity keyword is colored
168
+ (error=red, warning=amber, note=blue); the message and fix use the default foreground so they
169
+ stay readable on any terminal background.
170
+ """
171
+ con = con or _stdout
172
+ keyword = f"{severity}[{code}]" if code and severity == "error" else severity
173
+ # `Text.assemble` styles each span independently; `Text(a, style=s) + Text(b)` would instead make
174
+ # `s` the whole line's container style, coloring the message/fix too (and dimming the fix so far
175
+ # it's hard to read). Only the severity keyword and the `help:` label carry weight/color; the
176
+ # message and the fix stay at the terminal's default foreground so they're fully legible.
177
+ con.print(Text.assemble((keyword, _SEVERITY_STYLE[severity]), (f": {message}", "")))
178
+ if help:
179
+ con.print(Text.assemble((" help:", "bold"), (f" {help}", "")))
180
+
181
+
182
+ # --- list view ---------------------------------------------------------------
183
+
184
+
185
+ def resource_table(
186
+ title: str,
187
+ columns: Sequence[tuple[str, Literal["default", "left", "center", "right", "full"]]],
188
+ rows: Iterable[Sequence[Any]],
189
+ *,
190
+ subtitle: Optional[str] = None,
191
+ con: Optional[Console] = None,
192
+ no_wrap: Optional[Sequence[int]] = None,
193
+ ) -> None:
194
+ """Render a titled list table.
195
+
196
+ `columns` is a sequence of (header, justify) where justify is left/right/center.
197
+ `no_wrap` column indexes are kept full-width; the rest narrow to fit the terminal.
198
+ """
199
+ con = con or _stdout
200
+ rows = list(rows)
201
+ no_wrap_cols = set(no_wrap or ())
202
+
203
+ con.print()
204
+ con.print(Text(title, style="bold"))
205
+ if subtitle:
206
+ con.print(Text(subtitle, style=SECONDARY))
207
+
208
+ # Dim, uppercase headers; columns size to content so they always line up.
209
+ table = Table(box=box.SIMPLE_HEAD, expand=False, pad_edge=False, show_edge=False)
210
+ for i, (header, justify) in enumerate(columns):
211
+ # Reserve a no_wrap column's full content width so Rich narrows the others instead.
212
+ min_width = (
213
+ max([len(header)] + [_cell_len(row[i]) for row in rows], default=0)
214
+ if i in no_wrap_cols
215
+ else None
216
+ )
217
+ table.add_column(
218
+ header.upper(),
219
+ justify=justify,
220
+ header_style=f"bold {DIM}",
221
+ no_wrap=i in no_wrap_cols,
222
+ min_width=min_width,
223
+ )
224
+ for row in rows:
225
+ table.add_row(*[_cell(v) for v in row])
226
+ con.print(table)
227
+
228
+ con.print(Text(f"{len(rows)} item{'s' if len(rows) != 1 else ''}", style=DIM))
229
+
230
+
231
+ def _cell_len(value: Any) -> int:
232
+ if value is None:
233
+ return 1 # em-dash placeholder
234
+ return len(value.plain if isinstance(value, Text) else str(value))
235
+
236
+
237
+ def _cell(value: Any) -> Any:
238
+ if isinstance(value, Text):
239
+ return value
240
+ if value is None:
241
+ return Text("—", style=DIM)
242
+ return str(value)
243
+
244
+
245
+ # --- detail view (aig-endpoint.png) ------------------------------------------
246
+
247
+
248
+ def detail(
249
+ breadcrumb: str,
250
+ name: str,
251
+ fields: dict[str, Any],
252
+ *,
253
+ status: Optional[str] = None,
254
+ snippets: Optional[Sequence[tuple[str, str, str]]] = None,
255
+ con: Optional[Console] = None,
256
+ ) -> None:
257
+ """Render a resource detail page.
258
+
259
+ `breadcrumb` is the section label ("Agent Memory"); `fields` is an ordered
260
+ key -> value map for the details rail. `snippets` is a sequence of
261
+ (label, lexer, code) blocks shown under a "Starter code" panel.
262
+ """
263
+ con = con or _stdout
264
+
265
+ con.print()
266
+ con.print(Text(f"{breadcrumb} › ", style=DIM) + Text(name, style="bold"))
267
+ if status is not None:
268
+ con.print(status_pill(status))
269
+ con.print()
270
+
271
+ grid = Table.grid(padding=(0, 3))
272
+ grid.add_column(style=DIM, justify="left")
273
+ grid.add_column(justify="left")
274
+ for key, value in fields.items():
275
+ grid.add_row(key, _cell(value))
276
+ con.print(grid)
277
+
278
+ if snippets:
279
+ con.print()
280
+ con.print(
281
+ Panel(
282
+ _snippet_group(snippets),
283
+ title="Starter code",
284
+ title_align="left",
285
+ border_style=DIM,
286
+ box=box.ROUNDED,
287
+ )
288
+ )
289
+
290
+
291
+ def _snippet_group(snippets: Sequence[tuple[str, str, str]]) -> RenderableType:
292
+ parts: list[RenderableType] = []
293
+ for i, (label, lexer, code) in enumerate(snippets):
294
+ if i:
295
+ parts.append(Text())
296
+ parts.append(Text(label, style=f"bold {DIM}"))
297
+ parts.append(Syntax(code.strip(), lexer, background_color="default", word_wrap=True))
298
+ return Group(*parts)
299
+
300
+
301
+ # --- success / next steps (the "Set up" cards) -------------------------------
302
+
303
+
304
+ def success(
305
+ title: str,
306
+ *,
307
+ fields: Optional[dict[str, Any]] = None,
308
+ next_steps: "Optional[Sequence[str | tuple[str, str]]]" = None,
309
+ con: Optional[Console] = None,
310
+ ) -> None:
311
+ """A green success panel with optional details and a Next step(s) list.
312
+
313
+ Each next step is either a ``(command, description)`` pair — the command is shown in cyan (the
314
+ actionable accent) with the description in secondary — or a bare string for a non-command
315
+ instruction (e.g. ``"Open http://localhost:8000"``), rendered as prose. Commands are
316
+ **copy-safe**: no ``$`` prompt prefix, so they paste straight into a shell. The heading is
317
+ "Next step" or "Next steps", chosen automatically from the count.
318
+ """
319
+ con = con or _stdout
320
+ body: list[RenderableType] = [Text("✔ ", style=SUCCESS) + Text(title, style="bold")]
321
+
322
+ if fields:
323
+ grid = Table.grid(padding=(0, 3))
324
+ grid.add_column(style=DIM)
325
+ grid.add_column()
326
+ for key, value in fields.items():
327
+ grid.add_row(key, _cell(value))
328
+ body.append(grid)
329
+
330
+ if next_steps:
331
+ # Singular vs plural from the count, per the design.
332
+ heading = "Next step" if len(next_steps) == 1 else "Next steps"
333
+ body.append(Text(heading, style=SECONDARY))
334
+ # A two-column grid aligns every command's description at the same offset.
335
+ steps = Table.grid(padding=(0, 2))
336
+ steps.add_column()
337
+ steps.add_column(style=SECONDARY)
338
+ for step in next_steps:
339
+ if isinstance(step, tuple):
340
+ # The actionable command is cyan; its description trails in secondary.
341
+ command, description = step
342
+ steps.add_row(Text(command, style=COMMAND), description)
343
+ else:
344
+ # Prose (e.g. "Open <url>") renders plainly — no command accent, no prompt marker.
345
+ steps.add_row(Text(step), "")
346
+ body.append(steps)
347
+
348
+ con.print()
349
+ con.print(Panel(Group(*body), border_style=SUCCESS, box=box.ROUNDED))
@@ -0,0 +1,101 @@
1
+ ---
2
+ name: agent-bricks-migrate
3
+ description: Adapt an existing LangGraph or OpenAI Agents SDK agent project to use Agent Bricks CLI (`ab`) development, tools, managed state, tracing, recovery, and deployment commands. Use with the migration bundle generated by `ab init --existing`.
4
+ ---
5
+
6
+ # Migrate an existing LangGraph or OpenAI Agents SDK agent to the managed runtime
7
+
8
+ Integrate the managed runtime so Agent Bricks CLI commands work through the same integration points
9
+ as the bundled template for the project's framework. Preserve the existing agent and application
10
+ contracts. Configuration alone does not complete migration.
11
+
12
+ ## Inspect the project and reference
13
+
14
+ Read `references/migration.json` for the server, bundled template version, chat-app choice, and
15
+ optional profile. It names the `framework` the reference was generated for; the migration follows
16
+ that framework's runtime semantics. `references/template/` is a candidate project generated
17
+ from the templates shipped with the installed CLI. Use it as migration evidence, not an importable
18
+ application dependency.
19
+
20
+ Read [the shared runtime contract](references/template/AGENTKIT_CONTRACT.md). It is written for the
21
+ named framework — LangGraph or OpenAI Agents — and its runtime requirements apply as written.
22
+ Then inspect adjacent template code for the integration points being adapted. If the chat app is
23
+ enabled, also read `references/template/CHAT_APP.md` and inspect `runtime/ui.py`. The contract owns
24
+ runtime requirements; this skill owns migration decisions.
25
+
26
+ Locate agent construction, state and history handling, model/tool wiring, persistence, invocation
27
+ config, interrupt/resume handling, HTTP serving, authentication, and tests. Identify
28
+ package/import conflicts with the reference. Explain the concrete changes, then implement them.
29
+ Preserve the agent's model, prompts, structure, tools, routing, and approval policy unless a
30
+ change is required and accepted.
31
+
32
+ ## Explicitly handle existing state and contracts
33
+
34
+ State and durability semantics differ by framework; handle the ones that apply:
35
+
36
+ - **LangGraph:** checkpointer, thread IDs, checkpoint namespaces, graph state, reducers,
37
+ subgraphs, and pending interrupts. Runtime recovery may resume a checkpoint belonging to the
38
+ current invocation; otherwise original input replays.
39
+ - **OpenAI Agents SDK:** the `Session` transcript is the persistent conversation state. There is
40
+ no checkpoint continuation; recovery replays the persisted application input against the same
41
+ session. HITL `RunState` is process-local and does not survive worker loss even with a Session
42
+ Store bound.
43
+
44
+ - **Persistence and history:** Identify the current checkpointer or session store, memory store,
45
+ thread/session IDs, actor/tenant mapping, and pending interrupts or approvals. Switching stores
46
+ does not migrate checkpoints, transcripts, or memories. Preserve access to existing history
47
+ until the transition is decided. Do not silently reset state, delete storage, or claim old
48
+ conversations were migrated. Surface choices about copying history, starting new threads or
49
+ sessions, or retiring storage.
50
+ - **Custom state and outputs:** Preserve fields, reducers and subgraphs where the framework has
51
+ them, structured inputs/outputs, streaming events, and interrupts or approval flows. The
52
+ reference assumes message-oriented events and is not a generic serializer. Implement explicit
53
+ mappings without discarding custom results to fit the reference UI.
54
+ - **Identity and sessions:** Preserve authentication, actor/tenant isolation, and session/thread
55
+ identity. The reference separates invocation UUIDs, application session IDs, and the routing
56
+ cookie. Map existing IDs explicitly, including reopening sessions. Derive actor identity from
57
+ the trusted application context; do not blindly trust a caller field or adopt a shared
58
+ fallback. If the existing server used a different request/response shape (e.g. a
59
+ `{conversation_id, message}` body), map it explicitly in `runtime/adapter.py` to the runtime's
60
+ `input.session_id` / `input.messages`, and preserve response fields clients depend on.
61
+ - **Recovery and durability:** Distinguish Runtime Store invocation recovery from Session Store
62
+ persistence. Address at-least-once side effects and retain stronger existing guarantees. Do not
63
+ silently enable replay of non-idempotent tools.
64
+
65
+ ## Implement the shared contract
66
+
67
+ Implement the command requirements in `references/template/AGENTKIT_CONTRACT.md`, using the template
68
+ as an example. Merge candidate `agent.toml`, the existing `.agentbricks/project.toml` marker, dependencies, and startup config
69
+ without overwriting existing choices. `ab init --existing` writes these manifests only inside
70
+ `references/template/`, not into the project, so copy or merge them to the project root; default
71
+ store names come from the reference's generated `agent.toml`. Candidate stores are migration
72
+ intent, not authorization to provision resources or switch live state. Use `uv` and the bundled
73
+ template's current `databricks-agentbricks` dependency. Migration may raise the project's minimum Python version:
74
+ the templates require `>=3.11` (the runtime uses 3.11+ features such as `asyncio.timeout`). Check
75
+ and bump `requires-python` and CI accordingly.
76
+
77
+ Keep framework-native execution independent of runtime request/context types. Adapt package
78
+ conflicts and preserve tool execution and approval logic. Merge run configuration without losing
79
+ callbacks, run limits, configurable fields, or session/checkpoint settings. Preserve existing
80
+ tracing when composing Agent Bricks CLI tracing.
81
+
82
+ Reuse the HTTP server where feasible. Follow the contract's distinction between basic CLI launch
83
+ requirements, managed `DurableAgentServer` hooks, and optional chat UI mappings. Adapt the UI only when
84
+ selected. Do not copy sample tools, models, prompts, or business logic into the application.
85
+ Model provider is a migration decision: keep the existing one or adopt the gateway; the
86
+ reference example is not mandatory.
87
+
88
+ ## Verify and hand off
89
+
90
+ Run existing tests and relevant lint/type checks. Add focused offline regression tests for custom
91
+ inputs/outputs, streaming, remote and local tool wiring, store selection, actor/session isolation,
92
+ interrupt/resume and approval flows, and invocation recovery where used. Use fakes for remote
93
+ services. Confirm the configured entrypoint starts with the project's test setup.
94
+
95
+ Do not provision, deploy, make live model/tool calls, or run integration tests unless authorized.
96
+ `ab doctor` is a separate planned feature; do not implement it here.
97
+
98
+ Report changes, validation, unresolved state or client-contract decisions, and readiness for
99
+ `dev`, `tools add`, `sessions bind`, `memory bind`, tracing, `endpoint`, and `deploy`. Distinguish
100
+ local wiring from live validation. Exclude the reference snapshot from application packaging and
101
+ test discovery if the project would otherwise collect it.
@@ -0,0 +1,36 @@
1
+ # Copy to .env for local development: cp .env.example .env
2
+ #
3
+ # The only required setting for local dev is a Databricks auth profile (used to call the model).
4
+ # Everything else — MLflow tracing, long-term memory — is optional and off by default. Invocation
5
+ # durability uses an in-memory store locally; conversation history uses an in-process checkpointer.
6
+
7
+ # Databricks auth profile (from `databricks auth profiles`). Used to call the model endpoint.
8
+ DATABRICKS_CONFIG_PROFILE=DEFAULT
9
+ # Or use explicit host/token instead of a profile:
10
+ # DATABRICKS_HOST=https://<your-workspace>.databricks.com
11
+ # DATABRICKS_TOKEN=dapi...
12
+
13
+ # --- Optional: MLflow tracing ---
14
+ # Leave UNSET to skip tracing (local dev). To enable, set a destination AND an experiment (either
15
+ # form of each works): destination = MLFLOW_TRACKING_URI or MLFLOW_TRACING_DESTINATION;
16
+ # experiment = MLFLOW_EXPERIMENT_ID or MLFLOW_EXPERIMENT_NAME.
17
+ # MLFLOW_TRACKING_URI="databricks"
18
+ # MLFLOW_EXPERIMENT_ID=
19
+ # MLFLOW_EXPERIMENT_NAME=
20
+ # For fully-local tracing (no workspace), point MLFLOW_TRACKING_URI at a local OSS MLflow server
21
+ # (`mlflow server`), e.g. MLFLOW_TRACKING_URI="http://localhost:5000".
22
+
23
+ # --- Optional: long-term memory tools ---
24
+ # Leave UNSET to skip. Set to a managed memory store ID to register the remember/recall tools
25
+ # (persist/search facts across conversations); see databricks_agentkit/langgraph/memory.py. Memory is
26
+ # partitioned per user: the agent uses the signed-in user as the actor (falls back to "agent"
27
+ # locally); edit `_actor` in agent/agent.py to change that.
28
+ # AGENT_MEMORY_STORE=<memory-store-id>
29
+
30
+ # --- Optional: durable state (managed Session Store) ---
31
+ # Leave UNSET to keep the in-process LangGraph checkpointer (InMemorySaver): multi-turn and HITL
32
+ # pauses work within one process but don't survive restarts/replicas. Set to an existing managed
33
+ # Session Store name to persist checkpoints through its REST API (DatabricksSessionStoreSaver) —
34
+ # durable graph state incl. paused HITL runs, over RPCs (no DB connection). Access uses your normal
35
+ # Databricks auth (must have access to the store). See databricks_agentkit/langgraph/session_store.py.
36
+ # AGENT_SESSION_STORE=my-agent-sessions
@@ -0,0 +1,199 @@
1
+ # Created by https://www.toptal.com/developers/gitignore/api/python
2
+ # Edit at https://www.toptal.com/developers/gitignore?templates=python
3
+
4
+ ### Python ###
5
+ # Byte-compiled / optimized / DLL files
6
+ __pycache__/
7
+ *.py[cod]
8
+ *$py.class
9
+
10
+ # C extensions
11
+ *.so
12
+
13
+ # Distribution / packaging
14
+ .Python
15
+ build/
16
+ develop-eggs/
17
+ dist/
18
+ downloads/
19
+ eggs/
20
+ .eggs/
21
+ lib64/
22
+ parts/
23
+ sdist/
24
+ var/
25
+ wheels/
26
+ share/python-wheels/
27
+ *.egg-info/
28
+ .installed.cfg
29
+ *.egg
30
+ MANIFEST
31
+
32
+ # PyInstaller
33
+ # Usually these files are written by a python script from a template
34
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
35
+ *.manifest
36
+ *.spec
37
+
38
+ # Installer logs
39
+ pip-log.txt
40
+ pip-delete-this-directory.txt
41
+
42
+ # Unit test / coverage reports
43
+ htmlcov/
44
+ .tox/
45
+ .nox/
46
+ .coverage
47
+ .coverage.*
48
+ .cache
49
+ nosetests.xml
50
+ coverage.xml
51
+ *.cover
52
+ *.py,cover
53
+ .hypothesis/
54
+ .pytest_cache/
55
+ cover/
56
+
57
+ # Translations
58
+ *.mo
59
+ *.pot
60
+
61
+ # Django stuff:
62
+ *.log
63
+ local_settings.py
64
+ db.sqlite3
65
+ db.sqlite3-journal
66
+
67
+ # Flask stuff:
68
+ instance/
69
+ .webassets-cache
70
+
71
+ # Scrapy stuff:
72
+ .scrapy
73
+
74
+ # Sphinx documentation
75
+ docs/_build/
76
+
77
+ # PyBuilder
78
+ .pybuilder/
79
+ target/
80
+
81
+ # Jupyter Notebook
82
+ .ipynb_checkpoints
83
+
84
+ # IPython
85
+ profile_default/
86
+ ipython_config.py
87
+
88
+ # pyenv
89
+ # For a library or package, you might want to ignore these files since the code is
90
+ # intended to run in multiple environments; otherwise, check them in:
91
+ # .python-version
92
+
93
+ # pipenv
94
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
95
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
96
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
97
+ # install all needed dependencies.
98
+ #Pipfile.lock
99
+
100
+ # poetry
101
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
102
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
103
+ # commonly ignored for libraries.
104
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
105
+ #poetry.lock
106
+
107
+ # pdm
108
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
109
+ #pdm.lock
110
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
111
+ # in version control.
112
+ # https://pdm.fming.dev/#use-with-ide
113
+ .pdm.toml
114
+
115
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
116
+ __pypackages__/
117
+
118
+ # Celery stuff
119
+ celerybeat-schedule
120
+ celerybeat.pid
121
+
122
+ # SageMath parsed files
123
+ *.sage.py
124
+
125
+ # Environments
126
+ .env
127
+ .venv
128
+ env/
129
+ venv/
130
+ ENV/
131
+ env.bak/
132
+ venv.bak/
133
+
134
+ # Spyder project settings
135
+ .spyderproject
136
+ .spyproject
137
+
138
+ # Rope project settings
139
+ .ropeproject
140
+
141
+ # mkdocs documentation
142
+ /site
143
+
144
+ # mypy
145
+ .mypy_cache/
146
+ .dmypy.json
147
+ dmypy.json
148
+
149
+ # Pyre type checker
150
+ .pyre/
151
+
152
+ # pytype static type analyzer
153
+ .pytype/
154
+
155
+ # Cython debug symbols
156
+ cython_debug/
157
+
158
+ # PyCharm
159
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
160
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
161
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
162
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
163
+ #.idea/
164
+
165
+ # VS Code
166
+ .vscode/
167
+
168
+ ### Python Patch ###
169
+ # Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
170
+ poetry.toml
171
+
172
+ # ruff
173
+ .ruff_cache/
174
+
175
+ # LSP config files
176
+ pyrightconfig.json
177
+
178
+ # End of https://www.toptal.com/developers/gitignore/api/python
179
+
180
+ .DS_*
181
+
182
+ # Databricks / MLflow local artifacts
183
+ **/mlruns/
184
+ mlflow.db
185
+ **/.databricks
186
+ .claude/
187
+
188
+ # Environment files
189
+ **/.env
190
+ **/.env.local
191
+
192
+ # Local (Lakebase-free) SQLite session store
193
+ local_agent_sessions.db
194
+ local_agent_sessions.db-*
195
+ *.db-journal
196
+
197
+ # Agent Bricks local dev artifacts (`agentbricks dev`)
198
+ .agentbricks/
199
+ app.agentbricksdev.yaml