← Back to Registry

approve_plan

Show a multi-step plan and ask the user to approve before execution.

confirmationpushAndWait
Display stack

Tokyo Weekend Itinerary

  1. 1Day 1: Arrival
    Check in at Shinjuku hotel, explore Shibuya
  2. 2Day 2: Culture
    Meiji Shrine, Harajuku, Akihabara
  3. 3Day 3: Food Tour
    Tsukiji market, ramen tasting, departure
approve-plan.tsxtsx
import { z } from "zod";
import type { ToolConfig, SlotRenderProps } from "glove-react";

export const approvePlan: ToolConfig = {
  name: "approve_plan",
  description:
    "Show a multi-step plan and ask the user to approve before execution. " +
    "Blocks until the user approves or rejects.",
  inputSchema: z.object({
    title: z.string().describe("Plan title"),
    steps: z
      .array(
        z.object({
          title: z.string().describe("Step title"),
          description: z.string().describe("Step details"),
        }),
      )
      .describe("Ordered list of plan steps"),
  }),
  async do(input, display) {
    const approved = await display.pushAndWait({ input });
    return approved ? "Plan approved by user." : "Plan rejected by user.";
  },
  render({ data, resolve }: SlotRenderProps) {
    const { title, steps } = data as {
      title: string;
      steps: { title: string; description: string }[];
    };
    return (
      <div
        style={{
          padding: 16,
          borderRadius: 12,
          border: "1px solid var(--accent, #9ED4B8)",
          background: "var(--surface, #141414)",
          fontFamily:
            '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
        }}
      >
        <p
          style={{
            fontSize: 14,
            fontWeight: 600,
            marginBottom: 12,
            color: "var(--text, #ededed)",
          }}
        >
          {title}
        </p>
        <ol
          style={{
            listStyle: "none",
            padding: 0,
            display: "flex",
            flexDirection: "column",
            gap: 8,
            counterReset: "step",
          }}
        >
          {steps.map((step, i) => (
            <li
              key={i}
              style={{
                display: "flex",
                flexDirection: "column",
                gap: 2,
                padding: "8px 10px",
                borderRadius: 6,
                background: "var(--bg, #0a0a0a)",
              }}
            >
              <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                <span
                  style={{
                    fontSize: 10,
                    fontWeight: 700,
                    color: "var(--accent, #9ED4B8)",
                  }}
                >
                  {i + 1}
                </span>
                <strong style={{ fontSize: 13, color: "var(--text, #ededed)" }}>
                  {step.title}
                </strong>
              </div>
              <span
                style={{
                  fontSize: 12,
                  color: "var(--text-muted, #888)",
                  paddingLeft: 18,
                }}
              >
                {step.description}
              </span>
            </li>
          ))}
        </ol>
        <div style={{ display: "flex", gap: 8, marginTop: 12 }}>
          <button
            onClick={() => resolve(true)}
            style={{
              padding: "8px 16px",
              border: "none",
              borderRadius: 6,
              background: "var(--success, #22c55e)",
              color: "#fff",
              fontSize: 13,
              fontWeight: 500,
              cursor: "pointer",
            }}
          >
            Approve Plan
          </button>
          <button
            onClick={() => resolve(false)}
            style={{
              padding: "8px 16px",
              border: "none",
              borderRadius: 6,
              background: "var(--border, #262626)",
              color: "var(--text-muted, #888)",
              fontSize: 13,
              fontWeight: 500,
              cursor: "pointer",
            }}
          >
            Reject
          </button>
        </div>
      </div>
    );
  },
};
tools.tstypescript
const tools: ToolConfig[] = [
  approve_plan,
  // ...other tools
];