# How to Customize A2UI Outputs: Schema Management, Prompt Engineering, and Response Parsing

> Learn how to customize A2UI outputs by mastering schema management, prompt engineering, and response parsing. Control A2UI components for tailored results.

- Repository: [Google/A2UI](https://github.com/google/A2UI)
- Tags: how-to-guide
- Published: 2026-03-13

---

**Customize A2UI outputs by controlling the component schema catalog, pruning allowed components in system prompts, and parsing LLM responses into structured A2A parts using `A2uiSchemaManager` and `parse_response_to_parts`.**

A2UI (Agent-to-UI) enables large language models to drive rich, component-based user interfaces by returning JSON payloads wrapped in special delimiters. When you customize A2UI outputs in the `google/A2UI` repository, you manipulate three distinct layers: the **schema catalog** defining available UI components, the **prompt generation** controlling which components the LLM may use, and the **response parsing** converting raw text into typed A2A parts. This guide demonstrates the specific SDK classes, configuration options, and source file locations required to tailor these outputs for specialized use cases.

## The Three Layers of Output Customization

A2UI customization operates across three architectural layers defined in the source code:

- **Schema / Catalog**: The JSON contracts describing UI components (cards, charts, maps), managed through `A2uiSchemaManager` in [`agent_sdks/python/src/a2ui/core/schema/manager.py`](https://github.com/google/A2UI/blob/main/agent_sdks/python/src/a2ui/core/schema/manager.py). You control this by loading bundled catalogs, registering custom catalogs, or accepting inline catalogs from clients.

- **Prompt Generation**: The assembly of system instructions via `generate_system_prompt`, which injects schema definitions and examples into the LLM context. You customize this through parameters like `allowed_components`, `include_schema`, and `ui_description`.

- **Response Parsing**: The transformation of delimited LLM output (`<|A2UI|>`...`</|A2UI|>`) into A2A protocol parts. You handle this using `parse_response_to_parts` and `create_a2ui_part` in [`agent_sdks/python/src/a2ui/a2a.py`](https://github.com/google/A2UI/blob/main/agent_sdks/python/src/a2ui/a2a.py).

## Loading and Extending Component Catalogs

The **catalog** is a JSON document describing every renderable component and its properties. A2UI ships with a default standard catalog at [`catalogs/standard.json`](https://github.com/google/A2UI/blob/main/catalogs/standard.json), but you must extend or replace this to customize available outputs.

### Registering Server-Side Catalogs

Register custom catalogs by passing a `CatalogConfig` to the `A2uiSchemaManager` constructor. The manager loads schemas via `_load_schemas` and selects the active catalog through `_select_catalog` logic:

```python
from a2ui.core.schema.manager import A2uiSchemaManager
from a2ui.basic_catalog.provider import BasicCatalog
from a2ui.core.schema.constants import VERSION_0_9

schema_manager = A2uiSchemaManager(
    version=VERSION_0_9,
    catalogs=[
        BasicCatalog.get_config(
            version=VERSION_0_9,
            examples_path="examples",
        )
    ],
    accepts_inline_catalogs=False,
)

```

For complete custom schemas, reference [`samples/agent/adk/component_gallery/a2ui_schema.py`](https://github.com/google/A2UI/blob/main/samples/agent/adk/component_gallery/a2ui_schema.py), which demonstrates how to define component fields like `outputFormat` for `DateTimeInput` inputs.

### Accepting Inline Catalogs from Clients

To allow dynamic customization without server redeployment, enable `accepts_inline_catalogs=True`. Clients then submit their own catalogs in the `client_ui_capabilities` payload:

```json
{
  "client_ui_capabilities": {
    "inlineCatalogs": [
      { "$ref": "https://my.cdn/custom_catalog.json" }
    ]
  }
}

```

The manager automatically selects the first inline catalog entry when processing the request.

## Pruning Components for Targeted Outputs

Restrict which components the LLM can emit by passing an `allowed_components` list to `generate_system_prompt`. This is essential for channel-specific customization, such as hiding `GoogleMap` for text-only interfaces:

```python
prompt = schema_manager.generate_system_prompt(
    role_description="You are a helpful travel assistant.",
    ui_description="Render results using cards and lists.",
    allowed_components=["Card", "Text", "DateTimeInput"],
    include_schema=True,
    include_examples=True,
)

```

Internally, the manager calls `catalog.with_pruned_components(allowed_components)` to filter the schema before injection into the prompt, as implemented in [`agent_sdks/python/src/a2ui/core/schema/manager.py`](https://github.com/google/A2UI/blob/main/agent_sdks/python/src/a2ui/core/schema/manager.py).

## Engineering the System Prompt

The `generate_system_prompt` method assembles the final LLM instructions by concatenating:

1. Your `role_description` (static persona text)
2. The `ui_description` (human-readable UI hints)
3. The catalog schema JSON (if `include_schema=True`)
4. Example UI snippets (if `include_examples=True` and `examples_path` is configured)

A typical implementation from [`samples/agent/adk/restaurant_finder/agent.py`](https://github.com/google/A2UI/blob/main/samples/agent/adk/restaurant_finder/agent.py) demonstrates conditional prompt creation:

```python
instruction = (
    schema_manager.generate_system_prompt(
        role_description=ROLE_DESCRIPTION,
        ui_description=UI_DESCRIPTION,
        include_schema=True,
        include_examples=True,
        validate_examples=True,
    )
    if use_ui
    else get_text_prompt()
)

```

Set `validate_examples=True` to ensure included snippets conform to the active catalog schema.

## Parsing LLM Responses into A2A Parts

LLM responses contain A2UI JSON wrapped in `<|A2UI|>` and `</|A2UI|>` delimiters. The SDK provides two primary methods for converting this raw output into structured parts for the A2A protocol.

### Extracting JSON from Delimited Responses

Use `parse_response_to_parts` from [`agent_sdks/python/src/a2ui/a2a.py`](https://github.com/google/A2UI/blob/main/agent_sdks/python/src/a2ui/a2a.py) to separate plain text from UI JSON and optionally validate against the catalog:

```python
from a2ui.a2a import parse_response_to_parts

parts = parse_response_to_parts(
    content=llm_raw_output,
    validator=schema_manager.get_selected_catalog().validator,
    fallback_text="Sorry, I couldn't generate a UI response."
)

```

This function returns a list of `Part` objects ready for inclusion in the A2A response.

### Manual Part Creation

For programmatic UI generation or post-processing, construct parts manually using `create_a2ui_part`:

```python
from a2ui.a2a import create_a2ui_part

a2ui_json = {
    "beginRendering": {
        "surfaceId": "main",
        "components": [
            {"id": "c1", "component": {"Text": {"text": {"literalString": "Hello"}}}}
        ],
    }
}
a2ui_part = create_a2ui_part(a2ui_json)

```

This returns a `Part` containing a `DataPart` with the specified JSON payload.

## Configuring Output Modes and MIME Types

Agents declare supported content types via `AgentCard` fields `default_input_modes` and `default_output_modes`. While standard samples use `["text", "text/plain"]`, A2UI parts carry the MIME type defined by `A2UI_MIME_TYPE` in [`agent_sdks/python/src/a2ui/a2a.py`](https://github.com/google/A2UI/blob/main/agent_sdks/python/src/a2ui/a2a.py).

To support proprietary clients or custom media types, modify the constant:

```python
A2UI_MIME_TYPE = "application/vnd.myapp+a2ui"

```

All parts created via `create_a2ui_part` will now carry this type, allowing clients to differentiate A2UI payloads from standard text responses.

## Complete Customization Example

The following end-to-end demonstration shows loading a custom catalog, pruning components, and parsing responses:

```python
import json
from a2ui.core.schema.manager import A2uiSchemaManager
from a2ui.core.schema.catalog import CatalogConfig
from a2ui.core.schema.constants import VERSION_0_9
from a2ui.a2a import parse_response_to_parts

# 1. Load custom catalog from JSON file

custom_schema = json.load(open("my_catalogs/custom_v0_9.json"))
catalog_config = CatalogConfig(
    name="my_custom",
    provider=lambda: custom_schema,
    examples_path="my_catalogs/examples",
)

schema_manager = A2uiSchemaManager(
    version=VERSION_0_9,
    catalogs=[catalog_config],
    accepts_inline_catalogs=False,
)

# 2. Generate constrained prompt

system_prompt = schema_manager.generate_system_prompt(
    role_description="You are a finance assistant.",
    ui_description="Show results using Cards and Tables only.",
    allowed_components=["Card", "Table"],
    include_schema=True,
    include_examples=False,
)

# 3. Process LLM response with validation

llm_response = llm.generate(system_prompt, user_query="Show last 5 months revenue.")
parts = parse_response_to_parts(
    content=llm_response,
    validator=schema_manager.get_selected_catalog().validator,
    fallback_text="I couldn't render the UI."
)

```

## Summary

- **Catalog Management**: Customize available UI components by registering custom JSON catalogs via `CatalogConfig` in `A2uiSchemaManager`, either server-side or through inline client capabilities.
- **Component Filtering**: Restrict LLM output options using the `allowed_components` parameter in `generate_system_prompt`, which internally calls `with_pruned_components` to filter the schema.
- **Response Processing**: Convert delimited LLM outputs to A2A parts using `parse_response_to_parts` for automatic extraction and validation, or `create_a2ui_part` for manual construction.
- **Protocol Configuration**: Adjust MIME types in [`agent_sdks/python/src/a2ui/a2a.py`](https://github.com/google/A2UI/blob/main/agent_sdks/python/src/a2ui/a2a.py) and output modes in `AgentCard` declarations to match specific client requirements.

## Frequently Asked Questions

### How do I add a custom property to an existing A2UI component?

Edit your custom catalog JSON to extend the component schema. For example, adding an `outputFormat` field to `DateTimeInput` allows the LLM to specify date formatting strings:

```json
{
  "components": {
    "DateTimeInput": {
      "properties": {
        "outputFormat": {
          "type": "string",
          "description": "Desired string format (e.g., YYYY-MM-DD)."
        }
      }
    }
  }
}

```

Register this catalog with `A2uiSchemaManager` and set `include_schema=True` when generating prompts to expose the new property to the LLM.

### What is the difference between inline catalogs and server-side catalogs?

**Server-side catalogs** are registered when initializing `A2uiSchemaManager` via the `catalogs` parameter, giving you full control over available components through the `_load_schemas` mechanism. **Inline catalogs** are sent by the client in the `client_ui_capabilities` payload and loaded dynamically when `accepts_inline_catalogs=True`. Use server-side catalogs for consistent, controlled UI experiences; use inline catalogs to support diverse client capabilities without redeploying the agent.

### How does `parse_response_to_parts` handle invalid JSON from the LLM?

The function extracts content between `<|A2UI|>` and `</|A2UI|>` delimiters and attempts JSON parsing. If you provide a `validator` parameter (typically from `schema_manager.get_selected_catalog().validator`), it validates the structure against the active catalog schema. When parsing or validation fails, the function returns a text part containing your `fallback_text` instead of crashing, ensuring graceful degradation in production environments.

### Can I use A2UI with plain text outputs only?

Yes. Set `include_schema=False` in `generate_system_prompt` to omit the JSON schema from the LLM context, or provide an empty `allowed_components` list to prevent UI generation entirely. The `parse_response_to_parts` function will return the raw text content as a text part without attempting JSON extraction, allowing you to support text-only channels while maintaining the same agent architecture and response parsing pipeline.