Get started

Quickstart

Pick the API path, drop a canvas into a page, and react to events.

tsx
"use client";

import {
  WireProvider,
  WireCanvas,
  type WireDiagram
} from "@aigentive/wire-react";

const diagram: WireDiagram = {
  version: 1,
  id: "agent-chain",
  layout: "LR",
  nodes: [
    { id: "in",  kind: "trigger", title: "Webhook" },
    { id: "ai",  kind: "ai",      title: "Plan answer", from: "in", model: "gpt-5.4-mini" },
    { id: "out", kind: "action",  title: "Send reply",  from: "ai", tone: "success" }
  ],
  edges: []
};

export function AgentDiagram() {
  return (
    <div style={{ height: 320 }}>
      <WireProvider defaultDiagram={diagram}>
        <WireCanvas
          mode="view"
          fitView
          fitViewPadding={0.2}
          showControls={false}
          showMiniMap={false}
        />
      </WireProvider>
    </div>
  );
}
tsx
"use client";

import { useCallback, useState } from "react";
import {
  WireProvider,
  WireCanvas,
  WireOptionPanel,
  type WireEvent,
  type WireOptionCatalog
} from "@aigentive/wire-react";

const options: WireOptionCatalog = {
  ai: [
    { key: "model", storage: "node", type: "select",
      options: ["gpt-5.4-mini", "gpt-4.1-mini", "o4-mini"] },
    { key: "temperature", type: "number", min: 0, max: 2, step: 0.1 }
  ],
  action: [
    { key: "channel", type: "select",
      options: ["email", "chat", "ticket", "slack"] }
  ]
};

export function AgentEditor({ diagram }) {
  const [openId, setOpenId] = useState<string>();

  const onEvent = useCallback((event: WireEvent) => {
    if (event.type === "node.click") setOpenId(event.nodeId);
    else if (event.type === "pane.click") setOpenId(undefined);
  }, []);

  return (
    <WireProvider defaultDiagram={diagram} validateOnChange onEvent={onEvent}>
      <div className="grid grid-cols-[1fr_320px]">
        <WireCanvas mode="view" fitView />
        {openId ? (
          <aside className="border-l p-4">
            <WireOptionPanel catalog={options} nodeId={openId} />
          </aside>
        ) : null}
      </div>
    </WireProvider>
  );
}
tsx
"use client";

import { useState } from "react";
import {
  WireWorkspace,
  type WireDiagram,
  type WireOptionCatalog
} from "@aigentive/wire-react";

export function FullEditor({ initial, options }: {
  initial: WireDiagram;
  options: WireOptionCatalog;
}) {
  const [diagram, setDiagram] = useState(initial);

  return (
    <WireWorkspace
      diagram={diagram}
      onChange={setDiagram}
      optionCatalog={options}
      onEvent={(e) => console.log(e.source, e.type)}
    />
  );
}
tsx
import {
  Flow,
  TriggerNode,
  AINode,
  ActionNode
} from "@aigentive/wire-react";

export function AgentDiagram() {
  return (
    <Flow layout="LR">
      <TriggerNode id="in"  title="Webhook" />
      <AINode      id="ai"  title="Plan answer" from="in"  model="gpt-5.4-mini" />
      <ActionNode  id="out" title="Send reply"  from="ai"  tone="success" />
    </Flow>
  );
}
tsx
import {
  Flow,
  TriggerNode,
  AINode,
  ActionNode,
  type WireDiagram
} from "@aigentive/wire-react";

export function CompileOnly({ onSave }: { onSave: (d: WireDiagram) => void }) {
  return (
    <Flow mode="json" onCompile={onSave}>
      <TriggerNode id="in"  title="Webhook" />
      <AINode      id="ai"  title="Plan answer" from="in"  model="gpt-5.4-mini" />
      <ActionNode  id="out" title="Send reply"  from="ai"  tone="success" />
    </Flow>
  );
}
NextHow Wire thinks