Opengram

(Coming Soon) Interactive Requests

Let agents ask users for structured input through choice buttons, text inputs, and multi-field forms.

Interactive requests allow agents to collect structured input from users. Instead of parsing free-text replies, agents create a typed request and receive a clean, validated response.

Request Types

There are three request types. Each request requires a type, title, and a config object with type-specific configuration. An optional body provides additional descriptive text shown below the title.

Choice

Presents the user with a set of buttons to pick from.

{
  "type": "choice",
  "title": "How would you like to proceed?",
  "body": "Pick one of the options below.",
  "config": {
    "options": [
      { "id": "approve", "label": "Approve", "variant": "primary" },
      { "id": "reject", "label": "Reject", "variant": "danger" },
      { "id": "changes", "label": "Ask for changes" }
    ]
  }
}

Each option requires an id (returned in the resolution payload) and a label (displayed to the user). An optional variant controls the button style: "primary", "secondary", or "danger".

By default the user picks exactly one option. To allow multi-select, set maxSelections in the config:

{
  "type": "choice",
  "title": "Which toppings?",
  "config": {
    "options": [
      { "id": "cheese", "label": "Cheese" },
      { "id": "pepperoni", "label": "Pepperoni" },
      { "id": "mushrooms", "label": "Mushrooms" }
    ],
    "minSelections": 1,
    "maxSelections": 3
  }
}
Config PropertyDefaultDescription
options(required)Array of { id, label, variant? } objects
maxSelections1Maximum number of options the user can select
minSelections0Minimum number of options required

Text Input

Asks the user for a single free-text response.

{
  "type": "text_input",
  "title": "What is the project name?",
  "config": {
    "placeholder": "Enter a name..."
  }
}

The config supports optional validation constraints:

{
  "type": "text_input",
  "title": "Enter a version number",
  "config": {
    "placeholder": "e.g. 1.2.3",
    "validation": {
      "minLength": 1,
      "maxLength": 20,
      "pattern": "^\\d+\\.\\d+\\.\\d+$"
    }
  }
}
Config PropertyDescription
placeholderPlaceholder text shown in the input
validation.minLengthMinimum character length
validation.maxLengthMaximum character length
validation.patternRegex pattern the response must match

Form

Collects multiple fields at once.

{
  "type": "form",
  "title": "Deployment details",
  "config": {
    "fields": [
      {
        "name": "environment",
        "label": "Environment",
        "type": "select",
        "options": ["staging", "production"],
        "required": true
      },
      {
        "name": "version",
        "label": "Version",
        "type": "text",
        "required": true
      },
      {
        "name": "notes",
        "label": "Release notes",
        "type": "textarea"
      },
      {
        "name": "notify",
        "label": "Send notification",
        "type": "checkbox"
      }
    ],
    "submitLabel": "Deploy"
  }
}

How It Works

  1. The agent creates a request by calling POST /api/v1/chats/:chatId/requests with the request body.
  2. A floating widget appears above the composer in the user's chat, showing the request.
  3. The user fills in or selects their answer and submits it.
  4. The request is resolved, and the agent receives the result either through the dispatch system or via webhook.

Widget Behavior

The request widget floats above the message composer so it stays visible while the user scrolls through the conversation. Users can collapse the widget if they want to continue reading before responding.

If multiple requests are pending, they stack in the widget and the user can resolve them in any order.

Form Field Types

When using the form request type, each field in config.fields has a type property:

Field TypeDescriptionExtra Properties
textSingle-line text input
textareaMulti-line text input
selectDropdown selectoptions (string array, required)
multiselectMulti-select listoptions (string array, required)
checkboxBoolean toggle
dateDate picker

All field types support these common properties:

PropertyTypeDescription
namestringUnique field identifier (required)
labelstringDisplay label
requiredbooleanWhether the field must be filled before submitting

The form config also supports a submitLabel property to customize the submit button text (defaults to "Submit").

Resolution Payloads

When a request is resolved, the resolution payload varies by type:

Request TypeResolution Payload
choice{ "selectedOptionIds": ["approve"] }
text_input{ "text": "The user's response" }
form{ "values": { "environment": "production", "version": "1.2.3", "notify": true } }

When a request is cancelled, the resolution payload is null and the status changes to "cancelled".

The resolve endpoint also accepts an optional resolvedBy field set to "user" (default) or "backend", which controls how the resolution is routed through dispatch.

Trace

Requests support an optional trace field — a freeform JSON object that agents can use to attach tracking metadata. The trace is stored with the request and included in resolution events and dispatch inputs, making it useful for correlating requests back to a specific workflow step.

{
  "type": "choice",
  "title": "Approve deployment?",
  "config": {
    "options": [
      { "id": "yes", "label": "Yes" },
      { "id": "no", "label": "No" }
    ]
  },
  "trace": { "workflow": "deploy", "step": 3 }
}

API Reference

See the full API details at:

On this page