anthropic-a2ui 0.1.0__tar.gz
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.
- anthropic_a2ui-0.1.0/.gitignore +26 -0
- anthropic_a2ui-0.1.0/CHANGELOG.md +59 -0
- anthropic_a2ui-0.1.0/LICENSE +17 -0
- anthropic_a2ui-0.1.0/PKG-INFO +451 -0
- anthropic_a2ui-0.1.0/README.md +438 -0
- anthropic_a2ui-0.1.0/pyproject.toml +55 -0
- anthropic_a2ui-0.1.0/src/anthropic_a2ui/__init__.py +83 -0
- anthropic_a2ui-0.1.0/src/anthropic_a2ui/_internal/__init__.py +6 -0
- anthropic_a2ui-0.1.0/src/anthropic_a2ui/parts.py +108 -0
- anthropic_a2ui-0.1.0/src/anthropic_a2ui/prompt_builder.py +198 -0
- anthropic_a2ui-0.1.0/src/anthropic_a2ui/py.typed +0 -0
- anthropic_a2ui-0.1.0/src/anthropic_a2ui/repair.py +643 -0
- anthropic_a2ui-0.1.0/src/anthropic_a2ui/retry.py +877 -0
- anthropic_a2ui-0.1.0/src/anthropic_a2ui/stream_parser.py +233 -0
- anthropic_a2ui-0.1.0/src/anthropic_a2ui/tool.py +212 -0
- anthropic_a2ui-0.1.0/src/anthropic_a2ui/version.py +3 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
.venv/
|
|
9
|
+
venv/
|
|
10
|
+
|
|
11
|
+
# Tests
|
|
12
|
+
.pytest_cache/
|
|
13
|
+
.coverage
|
|
14
|
+
htmlcov/
|
|
15
|
+
|
|
16
|
+
# uv
|
|
17
|
+
.uv/
|
|
18
|
+
|
|
19
|
+
# Fire test results (generated, not committed)
|
|
20
|
+
fire_test/results/
|
|
21
|
+
fire_test/results_exhaustive/
|
|
22
|
+
fire_test/results_natural/
|
|
23
|
+
fire_test/viewer.html
|
|
24
|
+
|
|
25
|
+
# OS
|
|
26
|
+
.DS_Store
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `anthropic-a2ui` are documented here.
|
|
4
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
|
5
|
+
and the versioning follows [SemVer](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [0.1.0] - 2026-06-21
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **`generate_a2ui`**: high-level function that calls Claude, validates,
|
|
12
|
+
repairs, and retries on failure. Returns a `RetryResult` with the
|
|
13
|
+
validated A2UI payload.
|
|
14
|
+
- **`generate_a2ui_async`**: async version of `generate_a2ui` for
|
|
15
|
+
integration with async servers (FastAPI, Starlette, etc.).
|
|
16
|
+
- **`A2uiConversation`**: multi-turn conversation that maintains message
|
|
17
|
+
history across turns so the user can iterate ("make me a form" ->
|
|
18
|
+
"add a field" -> "change the color"). Claude generates a new A2UI
|
|
19
|
+
payload with all changes applied in each turn.
|
|
20
|
+
- **`A2uiConversationAsync`**: async version of `A2uiConversation`.
|
|
21
|
+
- **Prompt caching**: `use_cache=True` by default in `generate_a2ui` and
|
|
22
|
+
`A2uiConversation`. Adds `cache_control` to the system prompt to
|
|
23
|
+
reduce cost by ~80% on repeated calls.
|
|
24
|
+
- **Third mode `response_format`**: `create_a2ui_response_format` and
|
|
25
|
+
`parse_json_response` for forced JSON output without tools or tags.
|
|
26
|
+
- **Repair logging**: `log_repairs=True` records what was repaired
|
|
27
|
+
("Icon 'cloud' substituted with 'info'", etc.).
|
|
28
|
+
- **`py.typed`**: type marker for IDE support (autocompletion, type
|
|
29
|
+
checking).
|
|
30
|
+
- **`ClaudeA2uiPromptBuilder`**: constructs the system prompt with schema
|
|
31
|
+
+ few-shot examples + list of 59 valid icon names + list of 14 valid
|
|
32
|
+
catalog functions.
|
|
33
|
+
- **`create_a2ui_tool`**: defines the `send_a2ui_json_to_client` tool
|
|
34
|
+
with schema wrapped in `{"a2ui_json": [...]}` to avoid `oneOf` at the
|
|
35
|
+
root level (which the Anthropic API rejects).
|
|
36
|
+
- **`ClaudeStreamParser`**: parses the Anthropic stream and emits
|
|
37
|
+
`ResponsePart` objects (text + `<a2ui-json>` blocks and tool use).
|
|
38
|
+
Repairs and validates automatically.
|
|
39
|
+
- **`to_a2ui_part` / `A2uiPart`**: transport helpers with MIME
|
|
40
|
+
`application/a2ui+json`.
|
|
41
|
+
- **`validate_tool_input`**: validates A2UI payloads against the schema
|
|
42
|
+
with automatic repair.
|
|
43
|
+
- **Five automatic repairs**:
|
|
44
|
+
1. `patch_catalog_schema`: fixes `DateTimeInput.min/max` ambiguous
|
|
45
|
+
`oneOf` by changing it to `anyOf`.
|
|
46
|
+
2. `repair_orphans`: reconnects orphaned components to the `root`
|
|
47
|
+
tree.
|
|
48
|
+
3. `repair_icons`: maps 100+ common icon aliases to the 59 valid
|
|
49
|
+
catalog icons; unknown names become `info`.
|
|
50
|
+
4. `repair_functions`: replaces non-existent function calls
|
|
51
|
+
(`ternary`, `if`, `switch`) with literal values.
|
|
52
|
+
5. `repair_childlists`: converts dynamic child lists
|
|
53
|
+
(`{componentId, path}`) in `Row`/`Column` to static string arrays.
|
|
54
|
+
- **620 tests** covering: 19 cross-catalog components, 15 functions,
|
|
55
|
+
4 message types, optional properties, multi-catalog, multi-version,
|
|
56
|
+
5 repairs, multi-turn, async, caching, response_format.
|
|
57
|
+
- **Fire test**: 30 natural prompts x 3 models = 30/30 OK (Haiku 4.5,
|
|
58
|
+
Opus 4.7, Opus 4.8).
|
|
59
|
+
- **CI** with GitHub Actions (pytest + pyink on Python 3.10-3.13).
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
Copyright 2026
|
|
6
|
+
|
|
7
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
you may not use this file except in compliance with the License.
|
|
9
|
+
You may obtain a copy of the License at
|
|
10
|
+
|
|
11
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
|
|
13
|
+
Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
See the License for the specific language governing permissions and
|
|
17
|
+
limitations under the License.
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: anthropic-a2ui
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Que Claude genere interfaces de usuario con A2UI en sus respuestas.
|
|
5
|
+
License-Expression: Apache-2.0
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Keywords: a2ui,agent,anthropic,claude,generative-ui,ui
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Requires-Dist: a2ui-agent-sdk<0.3,>=0.2.4
|
|
10
|
+
Requires-Dist: anthropic<1,>=0.40
|
|
11
|
+
Requires-Dist: jsonschema>=4.0
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
___ _ _ _____
|
|
16
|
+
/\ |__ \ | | | | |_ _|
|
|
17
|
+
/ \ ) | | | | | | |
|
|
18
|
+
/ /\ \ / / | | | | | |
|
|
19
|
+
/ ____ \ / /_ | |__| | _| |_
|
|
20
|
+
/_/ \_\ |____| \____/ |_____|
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
# anthropic-a2ui
|
|
24
|
+
|
|
25
|
+
> Let Claude generate user interfaces with A2UI in its responses.
|
|
26
|
+
|
|
27
|
+
`anthropic-a2ui` bridges the A2UI protocol with the Anthropic SDK, enabling
|
|
28
|
+
Claude to emit declarative, interactive user interfaces as part of its
|
|
29
|
+
natural responses. Instead of returning plain text, Claude can now build
|
|
30
|
+
forms, dashboards, product cards, surveys, calendars, configuration panels,
|
|
31
|
+
modals, and any other UI composed from the A2UI component catalog — all
|
|
32
|
+
validated, repaired, and ready to render in any A2UI-compatible renderer
|
|
33
|
+
(Lit, React, Angular, Flutter, SwiftUI, and more).
|
|
34
|
+
|
|
35
|
+
The package does not wrap or replace the Anthropic SDK. It composes with
|
|
36
|
+
it: you use `anthropic` directly and plug in the A2UI pieces where they add
|
|
37
|
+
value. The system prompt, the tool definition, the stream parser, the
|
|
38
|
+
validator, the automatic repair layer, and the retry-with-feedback loop are
|
|
39
|
+
all designed to be transparent and composable.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## How it works
|
|
44
|
+
|
|
45
|
+
When a user asks Claude for an interface — "make me a contact form", "show
|
|
46
|
+
me a shopping cart", "build me a weather panel" — the following happens
|
|
47
|
+
behind the scenes:
|
|
48
|
+
|
|
49
|
+
1. **Prompt injection**: `ClaudeA2uiPromptBuilder` constructs a system
|
|
50
|
+
prompt containing the A2UI JSON Schema, few-shot examples, the list of
|
|
51
|
+
59 valid icon names, and the 14 catalog functions. Claude receives this
|
|
52
|
+
as its system context and knows how to speak A2UI.
|
|
53
|
+
|
|
54
|
+
2. **Tool definition**: `create_a2ui_tool` produces a tool definition
|
|
55
|
+
(`send_a2ui_json_to_client`) that Claude can invoke to deliver UI. The
|
|
56
|
+
schema is wrapped to comply with Anthropic's constraint against
|
|
57
|
+
`oneOf`/`allOf`/`anyOf` at the top level of `input_schema`.
|
|
58
|
+
|
|
59
|
+
3. **Streaming parse**: As Claude streams its response, `ClaudeStreamParser`
|
|
60
|
+
intercepts tool-use events (or `<a2ui-json>` text blocks) and emits
|
|
61
|
+
`ResponsePart` objects containing either conversational text or a
|
|
62
|
+
complete A2UI payload.
|
|
63
|
+
|
|
64
|
+
4. **Automatic repair**: Before validation, the payload passes through five
|
|
65
|
+
repair functions that fix known issues silently — invalid icon names,
|
|
66
|
+
non-existent catalog functions, orphaned components, ambiguous
|
|
67
|
+
DateTimeInput formats, and dynamic child lists in Row/Column.
|
|
68
|
+
|
|
69
|
+
5. **Validation**: The repaired payload is validated against the A2UI
|
|
70
|
+
schema. If it fails, the error is fed back to Claude as a tool result,
|
|
71
|
+
and Claude corrects itself on the next attempt (up to `max_retries`).
|
|
72
|
+
|
|
73
|
+
6. **Delivery**: The validated payload is wrapped in an `A2uiPart` with
|
|
74
|
+
MIME `application/a2ui+json`, ready to be sent to any A2UI renderer.
|
|
75
|
+
|
|
76
|
+
The user never mentions A2UI, components, functions, or schemas. They just
|
|
77
|
+
talk naturally, and Claude responds with a working interface.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Installation
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
uv add anthropic-a2ui
|
|
85
|
+
# or
|
|
86
|
+
pip install anthropic-a2ui
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Requires `ANTHROPIC_API_KEY` in the environment.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Quick start
|
|
94
|
+
|
|
95
|
+
The simplest way to use the package is `generate_a2ui`. One function call
|
|
96
|
+
handles everything: prompt construction, Claude invocation, streaming,
|
|
97
|
+
parsing, repair, validation, and retry-on-failure.
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
import anthropic
|
|
101
|
+
from anthropic_a2ui import generate_a2ui
|
|
102
|
+
|
|
103
|
+
client = anthropic.Anthropic()
|
|
104
|
+
|
|
105
|
+
result = generate_a2ui(
|
|
106
|
+
client,
|
|
107
|
+
"make me a registration form with name, email, and a submit button",
|
|
108
|
+
model="claude-haiku-4-5-20251001",
|
|
109
|
+
log_repairs=True,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
if result.success:
|
|
113
|
+
# result.a2ui_json is a validated list of A2UI messages
|
|
114
|
+
# ready to be rendered by any A2UI-compatible renderer
|
|
115
|
+
render(result.a2ui_json)
|
|
116
|
+
for repair in result.repairs:
|
|
117
|
+
print(f"Repaired: {repair}")
|
|
118
|
+
else:
|
|
119
|
+
print(f"Failed after {result.attempts} attempts: {result.error}")
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
An async version is also available for integration with async web
|
|
123
|
+
frameworks like FastAPI or Starlette:
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
import anthropic
|
|
127
|
+
from anthropic_a2ui import generate_a2ui_async
|
|
128
|
+
|
|
129
|
+
client = anthropic.AsyncAnthropic()
|
|
130
|
+
result = await generate_a2ui_async(
|
|
131
|
+
client,
|
|
132
|
+
"make me a registration form",
|
|
133
|
+
model="claude-haiku-4-5-20251001",
|
|
134
|
+
)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Usage modes
|
|
140
|
+
|
|
141
|
+
The package offers four complementary ways to generate A2UI, depending on
|
|
142
|
+
the level of control and the use case.
|
|
143
|
+
|
|
144
|
+
### Mode 1: Single call with `generate_a2ui`
|
|
145
|
+
|
|
146
|
+
Best for one-shot UI generation. The user asks for something, Claude
|
|
147
|
+
responds with a complete A2UI payload. If the payload is invalid, the
|
|
148
|
+
package automatically feeds the validation error back to Claude and
|
|
149
|
+
retries (up to `max_retries` times, default 2). Claude corrects itself
|
|
150
|
+
and resubmits.
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
result = generate_a2ui(
|
|
154
|
+
client,
|
|
155
|
+
"make me a contact form with name, email, subject, and message",
|
|
156
|
+
model="claude-opus-4-8",
|
|
157
|
+
max_retries=3,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
if result.success:
|
|
161
|
+
render(result.a2ui_json)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Key parameters:
|
|
165
|
+
|
|
166
|
+
- `builder`: custom `ClaudeA2uiPromptBuilder` (defaults to v0.9 Basic
|
|
167
|
+
Catalog).
|
|
168
|
+
- `model`: any Claude model that supports tool use.
|
|
169
|
+
- `max_tokens`: per-attempt token budget (default 8192).
|
|
170
|
+
- `max_retries`: how many times to retry on validation failure (default 2).
|
|
171
|
+
- `use_cache`: enable prompt caching to reduce cost ~80% on repeated calls
|
|
172
|
+
(default `True`).
|
|
173
|
+
- `log_repairs`: record what was repaired for debugging (default `False`).
|
|
174
|
+
|
|
175
|
+
### Mode 2: Multi-turn conversation with `A2uiConversation`
|
|
176
|
+
|
|
177
|
+
Best for iterative UI design. The user starts with a request, then refines
|
|
178
|
+
it across multiple turns: "make me a form" -> "add a phone field" ->
|
|
179
|
+
"change the button color to blue". Claude maintains the full conversation
|
|
180
|
+
context and generates a new A2UI payload with all changes applied in each
|
|
181
|
+
turn.
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
import anthropic
|
|
185
|
+
from anthropic_a2ui import A2uiConversation
|
|
186
|
+
|
|
187
|
+
client = anthropic.Anthropic()
|
|
188
|
+
conv = A2uiConversation(client, model="claude-haiku-4-5-20251001")
|
|
189
|
+
|
|
190
|
+
# Turn 1: create the initial form
|
|
191
|
+
r1 = conv.send("make me a contact form")
|
|
192
|
+
# r1.a2ui_json contains the form
|
|
193
|
+
# r1.success is True
|
|
194
|
+
|
|
195
|
+
# Turn 2: add a field
|
|
196
|
+
r2 = conv.send("add a phone number field")
|
|
197
|
+
# r2.a2ui_json contains the form + phone field
|
|
198
|
+
|
|
199
|
+
# Turn 3: change the styling
|
|
200
|
+
r3 = conv.send("make the submit button red")
|
|
201
|
+
# r3.a2ui_json contains the form + phone field + red button
|
|
202
|
+
|
|
203
|
+
# Access the full conversation history
|
|
204
|
+
print(f"Turns: {len(conv.turns)}")
|
|
205
|
+
print(f"Last valid A2UI: {conv.last_a2ui_json is not None}")
|
|
206
|
+
|
|
207
|
+
# Reset to start a new conversation
|
|
208
|
+
conv.reset()
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The async version works identically:
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
import anthropic
|
|
215
|
+
from anthropic_a2ui import A2uiConversationAsync
|
|
216
|
+
|
|
217
|
+
client = anthropic.AsyncAnthropic()
|
|
218
|
+
conv = A2uiConversationAsync(client)
|
|
219
|
+
|
|
220
|
+
r1 = await conv.send("make me a form")
|
|
221
|
+
r2 = await conv.send("add an email field")
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Mode 3: Forced JSON with `response_format`
|
|
225
|
+
|
|
226
|
+
Best when you want pure UI output with no conversational text. This mode
|
|
227
|
+
uses Anthropic's `response_format` parameter with `json_schema` to
|
|
228
|
+
guarantee that the response is parseable JSON. No tools, no tags — just a
|
|
229
|
+
structured payload.
|
|
230
|
+
|
|
231
|
+
```python
|
|
232
|
+
import anthropic
|
|
233
|
+
from anthropic_a2ui import (
|
|
234
|
+
ClaudeA2uiPromptBuilder,
|
|
235
|
+
create_a2ui_response_format,
|
|
236
|
+
parse_json_response,
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
builder = ClaudeA2uiPromptBuilder()
|
|
240
|
+
response_format = create_a2ui_response_format(builder.get_catalog())
|
|
241
|
+
|
|
242
|
+
client = anthropic.Anthropic()
|
|
243
|
+
response = client.messages.create(
|
|
244
|
+
model="claude-sonnet-4-5",
|
|
245
|
+
system=builder.build(role_description="You create user interfaces."),
|
|
246
|
+
response_format=response_format,
|
|
247
|
+
max_tokens=8192,
|
|
248
|
+
messages=[{"role": "user", "content": "make me a form"}],
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
# Extract, unwrap, validate, and repair the A2UI payload
|
|
252
|
+
a2ui_json = parse_json_response(response, builder.get_catalog())
|
|
253
|
+
render(a2ui_json)
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Mode 4: Manual streaming
|
|
257
|
+
|
|
258
|
+
Best when you need full control over the stream, token by token. You
|
|
259
|
+
construct the system prompt, define the tool, and process the stream
|
|
260
|
+
yourself. The parser handles unwrapping, repair, and validation.
|
|
261
|
+
|
|
262
|
+
```python
|
|
263
|
+
import anthropic
|
|
264
|
+
from anthropic_a2ui import (
|
|
265
|
+
ClaudeA2uiPromptBuilder,
|
|
266
|
+
create_a2ui_tool,
|
|
267
|
+
ClaudeStreamParser,
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
builder = ClaudeA2uiPromptBuilder()
|
|
271
|
+
tool = create_a2ui_tool(builder.get_catalog())
|
|
272
|
+
parser = ClaudeStreamParser(catalog=builder.get_catalog())
|
|
273
|
+
|
|
274
|
+
client = anthropic.Anthropic()
|
|
275
|
+
with client.messages.stream(
|
|
276
|
+
model="claude-sonnet-4-5",
|
|
277
|
+
system=builder.build(role_description="You create user interfaces."),
|
|
278
|
+
tools=[tool],
|
|
279
|
+
max_tokens=8192,
|
|
280
|
+
messages=[{"role": "user", "content": "make me a form"}],
|
|
281
|
+
) as stream:
|
|
282
|
+
for event in stream:
|
|
283
|
+
for part in parser.process_event(event):
|
|
284
|
+
if part.a2ui_json:
|
|
285
|
+
# A complete, validated, repaired A2UI payload
|
|
286
|
+
render(part.a2ui_json)
|
|
287
|
+
if part.text:
|
|
288
|
+
# Conversational text from Claude
|
|
289
|
+
print(part.text, end="")
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
The parser also supports the `<a2ui-json>` tag mode (no tool use), where
|
|
293
|
+
Claude embeds the JSON directly in its text response between
|
|
294
|
+
`<a2ui-json>` and `</a2ui-json>` tags.
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## Automatic repairs
|
|
299
|
+
|
|
300
|
+
Claude is remarkably good at generating valid A2UI, but it occasionally
|
|
301
|
+
makes mistakes — especially the smaller models. The package includes five
|
|
302
|
+
repair functions that fix these issues transparently before validation, so
|
|
303
|
+
the caller never sees a false rejection:
|
|
304
|
+
|
|
305
|
+
| Repair | What it fixes | Example |
|
|
306
|
+
|---|---|---|
|
|
307
|
+
| `patch_catalog_schema` | `DateTimeInput.min/max` uses `oneOf` of three date formats, which `jsonschema` rejects as ambiguous | Changes `oneOf` to `anyOf` in the schema |
|
|
308
|
+
| `repair_orphans` | Components created by Claude but not connected to the `root` tree | Reconnects orphans as children of the root container |
|
|
309
|
+
| `repair_icons` | Icon names that don't exist in the catalog enum (`cloud`, `sunny`, `trash`, ...) | Maps 100+ common aliases to the 59 valid icons; unknown names become `info` |
|
|
310
|
+
| `repair_functions` | `FunctionCall` with functions that don't exist in the catalog (`ternary`, `if`, `switch`) | Replaces with a literal value (`False` for boolean, `""` for string) or removes the check |
|
|
311
|
+
| `repair_childlists` | Dynamic child lists (`{componentId, path}`) used in `Row` or `Column`, which only accept static string arrays | Converts to a static array of component IDs |
|
|
312
|
+
|
|
313
|
+
All repairs are enabled by default in `generate_a2ui`, `A2uiConversation`,
|
|
314
|
+
and `ClaudeStreamParser`. They can be disabled with `repair=False` for
|
|
315
|
+
strict validation.
|
|
316
|
+
|
|
317
|
+
When `log_repairs=True`, the `RetryResult.repairs` list contains
|
|
318
|
+
human-readable descriptions of what was repaired:
|
|
319
|
+
|
|
320
|
+
```python
|
|
321
|
+
result = generate_a2ui(client, "make me a weather panel", log_repairs=True)
|
|
322
|
+
for r in result.repairs:
|
|
323
|
+
print(f"Repaired: {r}")
|
|
324
|
+
# Repaired: Icon 'sun_icon' substituted with 'info'
|
|
325
|
+
# Repaired: Text 'star1' emptied (possible function removed)
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Prompt caching
|
|
331
|
+
|
|
332
|
+
The A2UI system prompt is large: it includes the full JSON Schema, few-shot
|
|
333
|
+
examples, the list of 59 valid icon names, and the 14 catalog functions.
|
|
334
|
+
Sending this on every call would be expensive and slow.
|
|
335
|
+
|
|
336
|
+
`generate_a2ui` and `A2uiConversation` enable prompt caching by default
|
|
337
|
+
(`use_cache=True`). This adds `cache_control: {type: "ephemeral"}` to the
|
|
338
|
+
system prompt block, allowing Anthropic to cache it and reduce the cost by
|
|
339
|
+
approximately 80% on subsequent calls within the cache window.
|
|
340
|
+
|
|
341
|
+
To disable caching (for debugging or testing):
|
|
342
|
+
|
|
343
|
+
```python
|
|
344
|
+
result = generate_a2ui(client, "make me a form", use_cache=False)
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## Type safety
|
|
350
|
+
|
|
351
|
+
The package ships with a `py.typed` marker, so IDEs like VS Code (with
|
|
352
|
+
Pylance) and PyCharm provide full autocompletion, type checking, and
|
|
353
|
+
inline documentation for all public APIs.
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## Supported versions
|
|
358
|
+
|
|
359
|
+
A2UI is an evolving protocol. The package supports three versions:
|
|
360
|
+
|
|
361
|
+
| Version | Catalog | Components | Functions |
|
|
362
|
+
|---|---|---|---|
|
|
363
|
+
| v0.8 | standard (legacy) | 18 (includes `MultipleChoice`) | 0 |
|
|
364
|
+
| v0.9 | basic | 18 (includes `ChoicePicker`) | 14 |
|
|
365
|
+
| v0.9 | minimal | 5 (Text, Row, Column, Button, TextField) | 1 (`capitalize`) |
|
|
366
|
+
| v0.9.1 | basic | 18 | 14 |
|
|
367
|
+
|
|
368
|
+
The default is v0.9 with the Basic Catalog. To use a different version or
|
|
369
|
+
catalog:
|
|
370
|
+
|
|
371
|
+
```python
|
|
372
|
+
from anthropic_a2ui import ClaudeA2uiPromptBuilder
|
|
373
|
+
|
|
374
|
+
# v0.8 legacy
|
|
375
|
+
builder = ClaudeA2uiPromptBuilder(version="0.8")
|
|
376
|
+
|
|
377
|
+
# Pruned to specific components (saves tokens)
|
|
378
|
+
builder = ClaudeA2uiPromptBuilder()
|
|
379
|
+
prompt = builder.build(
|
|
380
|
+
role_description="You create simple forms.",
|
|
381
|
+
allowed_components=["Text", "TextField", "Button"],
|
|
382
|
+
)
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
## Tested models
|
|
388
|
+
|
|
389
|
+
The package has been tested with natural conversational prompts (no
|
|
390
|
+
mention of A2UI, components, or functions) across four Claude models. Each
|
|
391
|
+
model received 10 different prompts and was asked to generate a complete
|
|
392
|
+
A2UI interface:
|
|
393
|
+
|
|
394
|
+
| Model | Success rate | Avg. time |
|
|
395
|
+
|---|---|---|
|
|
396
|
+
| claude-haiku-4-5 | 10/10 (100%) | ~8s |
|
|
397
|
+
| claude-opus-4-7 | 10/10 (100%) | ~17s |
|
|
398
|
+
| claude-opus-4-8 | 10/10 (100%) | ~15s |
|
|
399
|
+
| claude-sonnet-4-5 | 8/8 (100%) | ~12s |
|
|
400
|
+
|
|
401
|
+
All 30 test cases (10 prompts x 3 models) passed validation after
|
|
402
|
+
automatic repair. The test prompts cover forms, dashboards, surveys,
|
|
403
|
+
calendars, profiles, configuration panels, task lists, product galleries,
|
|
404
|
+
and modal dialogs.
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## API reference
|
|
409
|
+
|
|
410
|
+
### High-level functions
|
|
411
|
+
|
|
412
|
+
- **`generate_a2ui(client, prompt, **kwargs) -> RetryResult`**: one-shot
|
|
413
|
+
generation with retries and caching.
|
|
414
|
+
- **`generate_a2ui_async(client, prompt, **kwargs) -> RetryResult`**:
|
|
415
|
+
async version.
|
|
416
|
+
- **`A2uiConversation(client, **kwargs)`**: multi-turn conversation.
|
|
417
|
+
`.send(prompt) -> ConversationTurn`, `.reset()`.
|
|
418
|
+
- **`A2uiConversationAsync(client, **kwargs)`**: async version.
|
|
419
|
+
- **`create_a2ui_response_format(catalog) -> dict`**: response_format for
|
|
420
|
+
forced JSON mode. Pair with `parse_json_response(message, catalog)`.
|
|
421
|
+
|
|
422
|
+
### Building blocks
|
|
423
|
+
|
|
424
|
+
- **`ClaudeA2uiPromptBuilder(version, catalogs)`**: constructs the system
|
|
425
|
+
prompt. `.build(role_description, ...)` returns the prompt string.
|
|
426
|
+
`.get_catalog()` returns the `A2uiCatalog`.
|
|
427
|
+
- **`create_a2ui_tool(catalog, **kwargs) -> dict`**: tool definition for
|
|
428
|
+
Anthropic.
|
|
429
|
+
- **`ClaudeStreamParser(catalog, **kwargs)`**: stream parser.
|
|
430
|
+
`.process_event(event) -> list[ResponsePart]`. `.parse_stream(stream)`
|
|
431
|
+
is an iterator shortcut.
|
|
432
|
+
- **`validate_tool_input(catalog, input_json, *, repair, strict_integrity)`**:
|
|
433
|
+
validates a payload against the schema.
|
|
434
|
+
- **`to_a2ui_part(payload) -> A2uiPart`**: wraps a payload for transport
|
|
435
|
+
with MIME `application/a2ui+json`.
|
|
436
|
+
|
|
437
|
+
### Repair functions
|
|
438
|
+
|
|
439
|
+
- **`repair_orphans(payload)`**: reconnects orphaned components.
|
|
440
|
+
- **`repair_icons(payload)`**: fixes invalid icon names.
|
|
441
|
+
- **`repair_functions(payload)`**: fixes non-existent function calls.
|
|
442
|
+
- **`repair_childlists(payload)`**: fixes dynamic child lists in
|
|
443
|
+
Row/Column.
|
|
444
|
+
- **`patch_catalog_schema(schema)`**: patches the DateTimeInput schema.
|
|
445
|
+
- **`find_orphans(payload) -> list[str]`**: diagnostic, returns orphan IDs.
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
449
|
+
## License
|
|
450
|
+
|
|
451
|
+
Apache-2.0.
|