Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.charmos.io/llms.txt

Use this file to discover all available pages before exploring further.

How to Render Rich UI

The Charm Store features a Universal Renderer that can automatically transform your agent’s data into beautiful, interactive React components—like charts, data grids, and metric cards—without you needing to write any frontend code. This guide will show you how to structure your agent’s return values to trigger these components. For a full list of supported UI schemas, please refer to the UI Protocol Reference.

Returning Explicit UI Components

To guarantee that the Store renders a specific component, your agent should return a Python dictionary containing the special key _charm_render_type.

Using the Custom Adapter

If you are writing a standard Python function agent, you can simply return the dictionary:
def agent(inputs):
    # Perform your agent logic here...
    
    # Return a structured dictionary instead of a string
    return {
        "_charm_render_type": "bar_chart",
        "title": "Quarterly Sales",
        "data": [
            {"name": "Q1", "value": 15000},
            {"name": "Q2", "value": 22000},
            {"name": "Q3", "value": 31000}
        ]
    }

Using Framework Adapters (LangChain, CrewAI, OpenClaw)

If you are using a framework, you can configure your LLM to output a JSON string that matches the required schema. The Charm adapters will automatically detect the JSON, parse it, and forward the structure to the UI. For example, using OpenClaw:
# Inside charm.yaml
runtime:
  adapter:
    type: openclaw
  config:
    system_prompt: |
      You are a data analysis agent. 
      You MUST return your final answer as a JSON object containing a pie chart.
      Format:
      {
        "_charm_render_type": "pie_chart",
        "title": "Data Distribution",
        "data": [{"name": "A", "value": 50}, {"name": "B", "value": 50}]
      }

Rendering Custom UI with HTML/SVG

If the built-in components do not meet your needs, you can return raw HTML or SVG strings. The Store’s Markdown renderer safely sanitizes HTML (stripping <script> tags) and renders it directly.
def agent(inputs):
    # Dynamically generate an SVG badge
    status = "Operational"
    color = "#4CAF50"
    
    svg_badge = f"""
    <svg width="150" height="30" xmlns="http://www.w3.org/2000/svg">
      <rect width="150" height="30" rx="5" fill="{color}"/>
      <text x="75" y="20" font-family="sans-serif" font-size="14" fill="white" text-anchor="middle">
        {status}
      </text>
    </svg>
    """
    
    # You can mix SVG with standard Markdown
    return f"### System Status\n\n{svg_badge}"

Mixing Text and UI

In most conversational agents, you want to stream thoughts and text before showing the final chart. To achieve this, use the CharmEmitter to stream markdown text during the execution, and then return the rich JSON object as the final result:
from charm.core.io import CharmEmitter

def agent(inputs):
    CharmEmitter.emit_delta("Analyzing the dataset...\n")
    # ... logic ...
    CharmEmitter.emit_delta("Generating the chart...\n")
    
    return {
        "_charm_render_type": "metric_card",
        "title": "Analysis Results",
        "metrics": [
            {"label": "Confidence", "value": "98.5", "unit": "%"}
        ]
    }

Next Steps