RobotRock

Actions

actions define what decisions a human can take on a task.

Actions can work in two modes:

  • Button-only action: no schema, just a decision button (for example Approve/Reject).
  • Form action: add schema (and optional ui) when you need structured input from the reviewer.

JSON Forms foundation

Action forms are based on JSON Forms concepts:

  • schema (JSON Schema) defines response shape and validation.
  • ui (UI schema) controls how fields render in the form.

Action shape

actions: [
  {
    id: "approve", // required
    title: "Approve", // required
    description: "Optional helper text",
    schema: {}, // optional JSON Schema
    ui: {}, // optional UI schema
    data: {}, // optional action metadata
  },
];

Webhooks are configured on the RobotRock client (webhook: { url, headers? }), not on individual actions. See Webhooks.

Button-only vs form actions

Use button-only actions for simple yes/no flows:

actions: [
  { id: "approve", title: "Approve" },
  { id: "reject", title: "Reject" },
];

Use form actions when you need extra input with the decision:

actions: [
  {
    id: "approve",
    title: "Approve",
    schema: {
      type: "object",
      required: ["comment"],
      properties: {
        comment: { type: "string", title: "Approval comment" },
      },
    },
    ui: {
      comment: { "ui:widget": "textarea" },
    },
  },
];

Full action example

actions: [
  {
    id: "approve",
    title: "Approve",
    description: "Approve and provide accounting code",
    schema: {
      type: "object",
      required: ["accountingCode", "comment"],
      properties: {
        accountingCode: {
          type: "string",
          title: "Accounting code",
        },
        comment: {
          type: "string",
          title: "Approval comment",
        },
        notifyTeams: {
          type: "array",
          title: "Notify teams",
          uniqueItems: true,
          items: {
            type: "string",
            enum: ["finance", "ops", "security"],
          },
        },
      },
    },
    ui: {
      accountingCode: { "ui:placeholder": "e.g. ACCT-2026-44" },
      comment: {
        "ui:widget": "textarea",
        "ui:options": { rows: 4 },
      },
      notifyTeams: {
        "ui:widget": "checkboxes",
      },
    },
    data: {
      severity: "normal",
      approvalPath: "finance-lead",
    },
  },
  {
    id: "reject",
    title: "Reject",
    description: "Reject and provide reason",
    schema: {
      type: "object",
      required: ["reason"],
      properties: {
        reason: { type: "string", title: "Reason for rejection" },
        retryAfterDays: { type: "number", title: "Suggest retry in days" },
      },
    },
    ui: {
      reason: { "ui:widget": "textarea" },
    },
    data: {
      severity: "high",
      escalationChannel: "#finance-escalations",
    },
  },
];

Field details

id and title

  • id: machine-readable action key
  • title: label shown in the UI

description

Optional helper copy for reviewers.

schema

JSON Schema that defines the response payload for this action.

schema: {
  type: "object",
  required: ["reason"],
  properties: {
    reason: { type: "string", title: "Reason" },
    retry: { type: "boolean", title: "Retry later?" },
  },
}

ui

UI schema for rendering/action form behavior.

ui: {
  reason: {
    "ui:widget": "textarea",
    "ui:placeholder": "Explain the decision",
  },
  retry: {
    "ui:title": "Allow retry",
  },
}

data

Custom metadata attached to the action definition.

data: {
  internalCode: "FIN-REJECT",
  severity: "high",
}

Form widget reference (grouped by widget type)

When you provide an action schema, form controls are chosen from schema type by default. You can override rendering with ui:widget.

Default widget mapping (no ui:widget needed)

schema: {
  type: "object",
  properties: {
    comment: { type: "string" }, // text input
    retries: { type: "number" }, // number input
    dryRun: { type: "boolean" }, // checkbox
    priority: {
      type: "string",
      enum: ["low", "medium", "high"], // select/radio-style choice input
    },
  },
}

textarea

  • use when: you want multi-line text input
  • ui:options: no RobotRock-specific options; standard RJSF options are passed through
ui: {
  comment: {
    "ui:widget": "textarea",
    "ui:placeholder": "Explain your decision",
  },
}

radio

  • use when: single choice from enum values
  • ui:options:
    • inline: true | false (layout as multi-column cards on wider screens)
schema: {
  type: "object",
  properties: {
    decision: {
      type: "string",
      enum: ["approve", "reject", "needs_changes"],
    },
  },
}
ui: {
  decision: {
    "ui:widget": "radio",
    "ui:options": { inline: true },
  },
}

checkboxes

  • use when: multiple selections from enum values (type: "array" + items.enum)
  • ui:options:
    • inline: true | false (layout as multi-column cards on wider screens)
schema: {
  type: "object",
  properties: {
    notifyTeams: {
      type: "array",
      uniqueItems: true,
      items: {
        type: "string",
        enum: ["finance", "ops", "security"],
      },
    },
  },
}
ui: {
  notifyTeams: {
    "ui:widget": "checkboxes",
    "ui:options": { inline: true },
  },
}

Notes on action ui:options

  • ui:options values are passed through to the underlying RJSF widgets.
  • RobotRock currently adds custom behavior for:
    • radio (inline)
    • checkboxes (inline)
  • For other widgets, options are handled by the default @rjsf/shadcn widget behavior.

Notes

  • You must provide at least one action.
  • Configure webhooks on the client; see Webhooks.

On this page