@intui/core · protocol v1

IntUI

Interactive answers from agents, drawn on any surface.

An agent answers with a component tree (charts, tables, flows, buttons, forms) instead of only text. A renderer for each surface draws it: a terminal, a web page, an email, later native apps. Every tree also has a Markdown text form, so the model can read back what it showed, and every surface has a fallback.

How it fits together

tool call ──► Tree.parse ──► component tree ──► renderer: Claude Code
 or code       (validate,     (Chart, Table,     ├─► renderer: web
 Tree.of        check who      Flow, Choice…)    ├─► renderer: email
                wrote it)            │           └─► later: Swift, Kotlin
                                     └──► toText(): what the model reads back

Use it

import { Tree, IntuiEvent, core } from "@intui/core";

// A tool's input schema: only what the model may write.
const inputSchema = core.writableBy("model").jsonSchema();

// Validate what the model sent. Throws IntuiError listing every problem.
const tree = Tree.parse(input, { author: "model" });

tree.toText();   // Markdown, returned as the tool result

// When the person presses a button:
const event = IntuiEvent.press(toolUseId, "next", "park");
tree.verify(event);
tree.describe(event);   // 'Pressed "Park" in next (from toolu_1).'

Not on npm yet. For now, clone the repo.

Components

Text

model or code

Markdown text. The default, and what every other component falls back to.

Tree
{
  "type": "Text",
  "markdown": "Traffic was **normal** this week."
}
Text form
Traffic was **normal** this week.

Group

model or code

Holds other components in a row or a column.

Tree
{
  "type": "Group",
  "direction": "row",
  "children": [
    {
      "type": "Text",
      "markdown": "**Ideas inbox**"
    },
    {
      "type": "Label",
      "text": "3 open",
      "tone": "neutral"
    }
  ]
}
Text form
**Ideas inbox** · [3 open]

Label

model or code

A short tag with a tone, such as a status.

Tree
{
  "type": "Label",
  "text": "parked",
  "tone": "muted"
}
Text form
[parked]

Table

model or code

Rows and columns of short values. For comparisons and lists of records.

Tree
{
  "type": "Table",
  "columns": [
    {
      "key": "option",
      "label": "Option"
    },
    {
      "key": "streams",
      "label": "Streams?"
    }
  ],
  "rows": [
    {
      "option": "Tool calls",
      "streams": "No"
    },
    {
      "option": "Markup in text",
      "streams": "Yes"
    }
  ]
}
Text form
| Option | Streams? |
| --- | --- |
| Tool calls | No |
| Markup in text | Yes |

Chart

built by code

A line or bar chart of one or more series, with optional markers.

Tree
{
  "type": "Chart",
  "kind": "line",
  "title": "Visitors",
  "unit": "visitors",
  "series": [
    {
      "label": "This week",
      "role": "primary",
      "points": [
        {
          "x": "Mon",
          "y": 120
        },
        {
          "x": "Tue",
          "y": 180
        },
        {
          "x": "Wed",
          "y": 90
        }
      ]
    },
    {
      "label": "Usual",
      "role": "baseline",
      "points": [
        {
          "x": "Mon",
          "y": 110
        },
        {
          "x": "Tue",
          "y": 115
        },
        {
          "x": "Wed",
          "y": 105
        }
      ]
    }
  ],
  "annotations": [
    {
      "at": "Tue",
      "label": "New pricing page"
    }
  ]
}
Text form
**Visitors** (line chart, visitors)

|  | This week | Usual (baseline) |
| --- | --- | --- |
| Mon | 120 | 110 |
| Tue | 180 | 115 |
| Wed | 90 | 105 |

Markers: Tue: New pricing page

Stat

built by code

One number with a label, and optionally its change.

Tree
{
  "type": "Stat",
  "label": "Visitors",
  "value": 1204,
  "change": {
    "value": 18,
    "as": "percent"
  },
  "tone": "positive"
}
Text form
**Visitors:** 1,204 (+18%)

Flow

model or code

Steps joined by arrows: a process, a pipeline, how parts of a system connect.

Tree
{
  "type": "Flow",
  "steps": [
    {
      "id": "model",
      "label": "Model tokens"
    },
    {
      "id": "tree",
      "label": "Component tree",
      "detail": "Validated against the core schemas"
    },
    {
      "id": "render",
      "label": "Renderer",
      "detail": "One per surface"
    }
  ],
  "links": []
}
Text form
Model tokens → Component tree → Renderer

- **Component tree:** Validated against the core schemas
- **Renderer:** One per surface

Choice

model or code

Buttons. Pressing one sends an event back to the agent.

Tree
{
  "type": "Choice",
  "id": "next-step",
  "prompt": "What next?",
  "options": [
    {
      "id": "explore",
      "label": "Start exploring",
      "emphasis": "primary"
    },
    {
      "id": "park",
      "label": "Park"
    }
  ],
  "repeat": "once"
}
Text form
What next?

[Start exploring] [Park]

Form

model or code

A few inputs and a submit button. Submitting sends the values back to the agent.

Tree
{
  "type": "Form",
  "id": "new-idea",
  "fields": [
    {
      "id": "title",
      "label": "Title",
      "input": "text",
      "required": true
    },
    {
      "id": "source",
      "label": "Source",
      "input": "select",
      "options": [
        "self",
        "client"
      ],
      "required": false
    }
  ],
  "submitLabel": "Add idea"
}
Text form
Form:
- Title (text, required)
- Source (select: self, client)

[Add idea]

Rules for core

Agents add to IntUI while working on specific products. These rules keep core general.

Roadmap

  1. Core: schemas, text forms, events.
  2. Claude Code plugin: a show tool that draws trees in the transcript.
  3. Web renderer, responsive from phone to desktop.
  4. The same tree drawn in Claude Code and on the web, with working buttons.
  5. Email renderer.