Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions CONTRACT.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# HexaUI Developer Contract (v1)
# HexKit Developer Contract (v1)

> The contract between a **developer's agent backend** and the **HexaUI proxy**.
> The contract between a **developer's agent backend** and the **HexKit proxy**.
> It imposes only the **shape of the API** (five endpoints) and that each stream
> frame is **tagged with the framework that produced it**. You do *not* rewrite
> your agent's events: you forward your framework's **native** events, tagged,
Expand All @@ -15,7 +15,7 @@
## 1. Roles

```
browser ──HTTP/SSE──▶ HexaUI proxy ──HTTP/SSE──▶ your agent backend
browser ──HTTP/SSE──▶ HexKit proxy ──HTTP/SSE──▶ your agent backend
(this platform) (you implement this)
```

Expand Down Expand Up @@ -65,16 +65,16 @@ previous revision; see those sections at the end.)

- `run_id` — opaque id the proxy assigns; accept it on `cancel`.
- `input.messages` — the chat transcript.
- **Provider API keys are *not* in the context.** HexUI does not store or forward
- **Provider API keys are *not* in the context.** HexKit does not store or forward
them — your backend reads its own provider keys (OpenAI, Google, …) from its
own environment. The platform never holds your model credentials.
- `context.files` — files the user attached to the conversation (persist across
turns; forwarded every run). `content` is the decoded text for text mimes,
`null` for binary (fetch by `id` is post-v1). Inline them into the prompt /
provider content blocks as your framework needs.
- `context.user` — caller identity. Always exactly three keys: `id` (the HexUI
- `context.user` — caller identity. Always exactly three keys: `id` (the HexKit
user uuid), `name` (display name or `null`), and `role` (free-text string or
`null`). HexUI does not interpret `role`; it's there so policy-aware runtimes
`null`). HexKit does not interpret `role`; it's there so policy-aware runtimes
(hexgate, etc.) can scope per-call decisions to the calling user.
**NEVER** includes email, password hash, or any internal identifier. An agent
backend that doesn't use this can ignore the block.
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# HexaUI dev Makefile — see QUICKSTART.md for prerequisites (uv + Node 18+).
# HexKit dev Makefile — see QUICKSTART.md for prerequisites (uv + Node 18+).
#
# Common flow on a fresh clone:
#
Expand Down
6 changes: 3 additions & 3 deletions QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Without API keys the agents reply with an echo placeholder. That's fine for a fi

## One-time setup

From the repo root (`HexUI/`):
From the repo root (`HexKit/`):

```bash
make setup
Expand Down Expand Up @@ -58,7 +58,7 @@ To enable real LLM replies (instead of echo), prepend the env var:
AGENT_ENABLE_LLM=1 bash demo/scripts/run-backends.sh
```

Provider keys live in the **agent backend's** environment, not the app — set `OPENAI_API_KEY` (Probe + healthcare/devops) and/or `GOOGLE_API_KEY` (Orbit) in your shell or in `demo/agent-server/.env` before starting the backends. HexUI never holds your model keys.
Provider keys live in the **agent backend's** environment, not the app — set `OPENAI_API_KEY` (Probe + healthcare/devops) and/or `GOOGLE_API_KEY` (Orbit) in your shell or in `demo/agent-server/.env` before starting the backends. HexKit never holds your model keys.

#### Terminal 2 — frontend

Expand Down Expand Up @@ -88,7 +88,7 @@ Open <http://localhost:8873>.
startup when `PLATFORM_DEMO_USERS_FILE` is set (the `make dev` launcher sets
it for you). Or sign up a fresh account at **/signup**.
3. The chat shell loads with an empty greeting.
4. Click the agent picker in the top bar and choose **Probe** (or any of the six demo agents — Probe, Orbit, Atlas, Forge, Healthcare, DevOps).
4. Click the agent picker in the top bar and choose **Probe** (or any of the eight demo agents — Probe, Orbit, Atlas, Forge, Healthcare, DevOps, ITSM, HR).
5. Type a message and send.
6. With `AGENT_ENABLE_LLM=1` and a provider key in the agent backend's env → a real LLM reply.
Without → an echo of your message (this confirms the full pipeline works).
Expand Down
169 changes: 161 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
<div align="center">

# HexUI
<img src="assets/hexkit-mark.svg" width="72" height="72" alt="HexKit">

# HexKit

</div>

A **UI/UX-first multi-agent chat platform**. Developers bring their own
streaming agent backend (any framework); HexaUI provides the chat experience —
streaming agent backend (any framework); HexKit provides the chat experience —
a configurable, YAML-driven UI, conversation history, folders, file attachments
— and a thin proxy that normalizes any framework's event stream into one schema
the UI renders.

<p align="center">
<img src="assets/hero.png" alt="HexaUI — the DevOps agent: a YAML-driven dashboard (service metrics + table) above a streaming chat, themed by the active agent's accent color." width="100%">
<img src="assets/hero.png" alt="HexKit — the DevOps agent: a YAML-driven dashboard (service metrics + table) above a streaming chat, themed by the active agent's accent color." width="100%">
</p>

<p align="center">
<a href="https://github.com/HexamindOrganisation/HexUI/actions/workflows/ci.yml"><img src="https://github.com/HexamindOrganisation/HexUI/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
<a href="https://github.com/HexamindOrganisation/hexkit/actions/workflows/ci.yml"><img src="https://github.com/HexamindOrganisation/hexkit/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
<img src="https://img.shields.io/badge/python-3.11+-3776AB?logo=python&logoColor=white" alt="Python 3.11+">
<img src="https://img.shields.io/badge/node-18+-339933?logo=node.js&logoColor=white" alt="Node 18+">
Expand Down Expand Up @@ -67,10 +69,10 @@ events; the **proxy translates** and the **UI renders from YAML**. See
| Path | Purpose |
|---|---|
| [custom-UI/](custom-UI/) | The product's heart: a React + TS library that renders a configurable agent UI from YAML (`<AgentUI>` + 12 built-in widgets). Theme bridge, streaming chat, the actions/`data_source` system. |
| [front-app/](front-app/) | The HexaUI shell that consumes `custom-UI` and talks to the proxy. |
| [front-app/](front-app/) | The HexKit shell that consumes `custom-UI` and talks to the proxy. |
| [proxy-server/](proxy-server/) | The platform backend (FastAPI): JWT auth, conversations, folders, files, and the per-framework translators that normalize native events into the hexa SSE schema. Import package stays `platform_backend`. |
| [packages/hexa-events/](packages/hexa-events/) | The internal event schema package consumed by the proxy (a local path dependency). |
| [demo/](demo/) | The runnable reference backends: [`agent-server/`](demo/agent-server/) (a contract-conformant developer backend with 6 sample agents), [`hexgate-agent/`](demo/hexgate-agent/) (a standalone hexgate-wrapped backend), [`starter-agent/`](demo/starter-agent/) (a minimal **copy-me** backend — the whole contract in one file), and [`scripts/`](demo/scripts/) (run + smoke checks, incl. the `verify_backend.py` conformance CLI). |
| [demo/](demo/) | The runnable reference backends: [`agent-server/`](demo/agent-server/) (a contract-conformant developer backend with 8 sample agents — Probe, Orbit, Atlas, Forge, Healthcare, DevOps, ITSM, HR), [`hexgate-agent/`](demo/hexgate-agent/) (a standalone hexgate-wrapped backend), [`starter-agent/`](demo/starter-agent/) (a minimal **copy-me** backend — the whole contract in one file), and [`scripts/`](demo/scripts/) (run + smoke checks, incl. the `verify_backend.py` conformance CLI). |
| [legacy/](legacy/) | The dropped unified-runtime backend (`backend-runtime`), kept for reference. Not part of the live product. |
| [CONTRACT.md](CONTRACT.md) | The developer contract — the one document an integrator reads. |

Expand Down Expand Up @@ -103,8 +105,8 @@ To get real model replies rather than the deterministic echo/canned fallback,
put your provider keys in the **agent backend's environment** (`OPENAI_API_KEY`
for Probe + the healthcare/devops agents, `GOOGLE_API_KEY` for Orbit) and start
it with `AGENT_ENABLE_LLM=1` — see [`demo/agent-server/.env.sample`](demo/agent-server/.env.sample).
HexUI never holds your model keys. The **Settings** page carries only your
display name and a free-text `role`; if you point HexUI at a `hexgate`-wrapped
HexKit never holds your model keys. The **Settings** page carries only your
display name and a free-text `role`; if you point HexKit at a `hexgate`-wrapped
agent, that role is forwarded to the agent and drives hexgate's per-tool policy
+ audit pipeline.

Expand All @@ -122,10 +124,161 @@ The bundled agents demonstrate the contract end to end:
| **Forge** | `openai-agents` | the OpenAI Agents translator (canned native events) |
| **Healthcare** | `openai-agents` (OpenAI) | a real clinical-assistant agent; HexGate-gated when `HEXGATE_KEY` is set, scoping per-tool policy to the caller's `context.user` role |
| **DevOps** | `google-adk` (OpenAI via LiteLLM) | a real infra-assistant agent; HexGate-gated when `HEXGATE_KEY` is set, scoping per-tool policy to the caller's `context.user` role |
| **ITSM** | `langchain` (deepagents) | a change-request assistant with a live lifecycle dashboard (refresh button → funnel metrics + change table updates as the agent's tools run) |
| **HR** | `langchain` (deepagents) | an internal HR assistant; demonstrates stateful per-user data (`hr_state.py`) and role-gated tools when HexGate is wired |
| **Hexgate Guard** | `hexgate` | a hexgate-wrapped agent that opens `User(user_id, role)` per run and emits audit decisions to the hexgate cloud (separate backend at [`demo/hexgate-agent/`](demo/hexgate-agent/)) |

---

## Components

Every agent UI is built out of these widgets. You compose them in a `ui.yaml` —
`type` picks the widget, `position` + `size` lay it out on the grid,
`data_source` wires it to one of your `/actions/{name}` endpoints. No React,
no CSS.

<table>
<tr>
<td width="50%">

**`ai-response`** — streaming chat surface

The flagship widget. Renders the assistant's turn as it streams; embeds tool calls, markdown, code blocks, files inline.

```yaml
- name: transcript
type: ai-response
position: { horizontal: left, vertical: high }
size: { width: 8, height: 520 }
empty_text: "Ask something…"
thinking_indicator: dots
```

</td>
<td width="50%">

**`ai-chat-input`** — composer with attachments

Text input + file attach + keyboard send. Forwards the composed turn through `POST /conversations/{id}/messages`.

```yaml
- name: chat-input
type: ai-chat-input
position: { horizontal: left, vertical: low }
size: { width: 12, height: auto }
placeholder: "Message Hexgate Guard…"
rows: 2
```

</td>
</tr>
<tr>
<td>

**`metrics`** — KPI strip

A row of labeled stat tiles. Pulls its values from a `data_source` action; auto-refreshes when a button-group action lists it in `refresh:`.

```yaml
- name: kpis
type: metrics
size: { width: 12, height: auto }
columns: 4
data_source: { action: change_summary }
metrics:
- { id: new, label: "New", format: number }
```

</td>
<td>

**`table`** — scrollable data grid

Header row + virtualized rows. Sourced from an action that returns rows; can be refreshed by a button.

```yaml
- name: changes
type: table
size: { width: 12, height: auto }
data_source: { action: change_table }
has_header: true
empty_text: "No changes yet."
```

</td>
</tr>
<tr>
<td>

**`tool-calls`** — live tool log

Shows each tool the agent calls in real time, with arguments, status, and result. Default landing surface for any unaddressed tool call.

```yaml
- name: tools
type: tool-calls
position: { horizontal: right, vertical: high }
size: { width: 4, height: 520 }
empty_text: "Tool calls will appear here."
```

</td>
<td>

**`markdown`** — rich text + code

Static markdown sourced from a string, or live markdown that the agent updates via a data source (e.g. a runbook the agent edits).

```yaml
- name: runbook
type: markdown
size: { width: 8, height: auto }
data_source: { action: get_runbook }
```

</td>
</tr>
<tr>
<td>

**`form`** — structured input

Labeled fields the user submits as one payload to an action. Each field declares its type; submit fires `POST /actions/{name}`.

```yaml
- name: deploy
type: form
size: { width: 6, height: auto }
action: deploy_service
fields:
- { name: env, label: Environment, type: text }
- { name: replicas, label: Replicas, type: number }
```

</td>
<td>

**`button-group`** — actions row

A row of buttons, each tied to an action. Optional `refresh:` list re-pulls the named widgets after the action completes — the basis for the lifecycle dashboards in ITSM / DevOps.

```yaml
- name: ops
type: button-group
size: { width: 12, height: auto }
buttons:
- { label: "Refresh", action: refresh_changes,
refresh: [change-metrics, change-table] }
```

</td>
</tr>
</table>

Four more widgets ship for layout and inputs: `dropdown`, `page-header`, `page-footer`, `spacer`. See [`custom-UI/src/registry/builtin.ts`](custom-UI/src/registry/builtin.ts) for the canonical registry and [demo/agent-server/src/agent_server/ui/](demo/agent-server/src/agent_server/ui/) for complete `ui.yaml` examples (the ITSM and DevOps agents stitch most of the widgets together into a live ops dashboard).

---

## The two things a developer configures

1. **`ui.yaml`** — which widgets, where, and the accent color. Placed/served by
Expand Down
7 changes: 7 additions & 0 deletions assets/hexkit-mark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion custom-UI/src/lib/context-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useAgentUIContext } from "../runtime/context.js";

/**
* Frame for a display widget (table / markdown) that can toggle its content
* into the conversation's model context. Ported from the HexaUI "Context Toggle"
* into the conversation's model context. Ported from the HexKit "Context Toggle"
* design: a header (icon + caption + the pill switch) over the widget body; when
* on, the card lights to the agent accent with a one-shot scan/glow.
*
Expand Down
2 changes: 1 addition & 1 deletion custom-UI/src/registry/builtin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export const builtinWidgets: AnyWidgetDefinition[] = [
schema: AiChatInputWidgetSchema,
component: AiChatInputWidgetComponent,
chromeless: true,
// HexaUI: the composer is constant chrome pinned to the bottom of the chat
// HexKit: the composer is constant chrome pinned to the bottom of the chat
// area (the transcript scrolls above it), not a widget in the content flow.
slot: "footer",
}),
Expand Down
2 changes: 1 addition & 1 deletion custom-UI/src/schema/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const PageSchema = {
layout_type: { enum: ["grid", "flex"] },
/**
* The active agent's signature color — the ONE variable that recolors the
* whole page (HexaUI's core principle). Bridges to shadcn `--primary` /
* whole page (HexKit's core principle). Bridges to shadcn `--primary` /
* `--ring` (and the legacy `--accent` agent usage). Takes precedence over
* `theme.accent`. Hex (`#RGB`, `#RRGGBB`, `#RRGGBBAA`).
*/
Expand Down
14 changes: 7 additions & 7 deletions custom-UI/src/shadcn.css
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
/*
* agent-ui shadcn base layer — themed to HexaUI.
* agent-ui shadcn base layer — themed to HexKit.
*
* Consumer usage (from your app's CSS entry):
* @import "agent-ui/shadcn.css";
*
* Pair with the Tailwind preset:
* presets: [require("agent-ui/tailwind-preset")]
*
* The shadcn HSL tokens are mapped onto the HexaUI neutral scale (Spec §2), so
* every native widget inherits the HexaUI look automatically. The ONE color in
* The shadcn HSL tokens are mapped onto the HexKit neutral scale (Spec §2), so
* every native widget inherits the HexKit look automatically. The ONE color in
* the product is the active agent's hue: `page.main_color` → `--primary` /
* `--ring` (set inline at the page root by the theme bridge) and a raw hex
* `--accent-color` for links / carets / status dots. Chrome stays monochrome —
Expand All @@ -20,7 +20,7 @@

@layer base {
:root {
/* ----- HexaUI light neutral scale (Spec §2) ----- */
/* ----- HexKit light neutral scale (Spec §2) ----- */
--background: 0 0% 100%; /* --bg #ffffff */
--foreground: 216 14% 11%; /* --text #191c21 */

Expand Down Expand Up @@ -52,7 +52,7 @@

--radius: 0.6875rem; /* --r-md 11px */

/* ----- HexaUI raw tokens (for widget chrome that needs them) ----- */
/* ----- HexKit raw tokens (for widget chrome that needs them) ----- */
--hx-bg: #ffffff;
--hx-bg-2: #f5f6f7;
--hx-surface: #ffffff;
Expand All @@ -78,7 +78,7 @@
}

.dark {
/* ----- HexaUI dark neutral scale (Spec §2) ----- */
/* ----- HexKit dark neutral scale (Spec §2) ----- */
--background: 240 2% 12%; /* --bg #1e1e1f */
--foreground: 220 9% 93%; /* --text #ecedef */

Expand Down Expand Up @@ -106,7 +106,7 @@
--input: 240 3% 22%;
--ring: 174 43% 47%;

/* ----- HexaUI raw tokens (dark) ----- */
/* ----- HexKit raw tokens (dark) ----- */
--hx-bg: #1e1e1f;
--hx-bg-2: #181819;
--hx-surface: #282829;
Expand Down
4 changes: 2 additions & 2 deletions custom-UI/src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@
}

/* ============================================================
* HexaUI chat — metaball thinking loader, streaming caret, status shimmer.
* HexKit chat — metaball thinking loader, streaming caret, status shimmer.
* All tint from the agent color via --accent-color (set by the theme bridge),
* falling back to the shadcn primary.
* ============================================================ */
Expand Down Expand Up @@ -386,7 +386,7 @@

/* ============================================================
File handling — composer attach popover + attached pills.
Ported from the HexaUI design handoff; tokens scoped to `.hxf`
Ported from the HexKit design handoff; tokens scoped to `.hxf`
and mapped onto the shadcn palette + the active agent accent.
The agent stays the only color; glyphs are neutral.
============================================================ */
Expand Down
Loading
Loading