Skip to content
GitHub

Response Components API

Read and set how often an agent answers with an interactive response component, and which components it may use, over the agents REST API. The frequency is the same dial as the dashboard's Component frequency select.


On this page

An agent can attach a response component to its reply in the Web SDK — a clickable confirm, a select list, a formatted card, or a list of results. How often it reaches for one is a per-agent setting, responseComponents.frequency, carried on the public agents API. The same setting is the Component frequency select under Choice buttons in the dashboard's agent settings; either path writes the one value, and this page covers the API. Which components the agent may use at all is a second per-agent setting on the same field, the per-component switches in responseComponents.components — see Choosing components.

Authenticate with a bearer API key, created under Settings → API keys (where available). If your organization doesn't show that item, open Settings → Members, which opens your organization's account page, and manage keys in its API Keys section; see API keys. Full request and response schemas live in the OpenAPI reference.

Endpoints#

EndpointPurpose
GET /v1/agents?ids=…Read the level for several agents. ids is required — a comma-separated list of up to 100 agent ids; omitting it is a 400
GET /v1/agents/{id}Read the level for one agent
PATCH /v1/agents/{id}Set the level, the per-component switches, or both

PATCH requires an API key with the manageAgents capability. Reads do not. That capability is the public-surface equivalent of the dashboard's feature:write permission, which is a per-user dashboard permission with no representation on an API key — so do not look for feature:write on a key, and do not expect a key to inherit the dashboard permissions of whoever created it. Keys are issued from the dashboard by an organization admin or owner.

The dashboard is the second write path. There the dial is gated by feature:write itself, and it applies the same rule as the 422 below: a non-off level is refused on an agent type that cannot emit components.

POST /v1/agents does not accept responseComponents; the field is ignored rather than rejected, so a create carrying it still returns 201 with the dial at off. Create the agent, then set the dial with a follow-up PATCH.

Reading the level#

responseComponents is a required field on every agent payload — GET /v1/agents, GET /v1/agents/{id}, and the create and update responses. Abridged to the relevant fields:

{
  "id": "0f2b7d1e-9c34-4a5b-8f61-2ad0c5e7b913",
  "name": "Support agent",
  "longTermMemory": { "enabled": true },
  "responseComponents": {
    "frequency": "medium",
    "components": { "choiceButtons": true, "card": true, "list": false, "table": false, "chart": false }
  }
}

An agent that has never had the dial set reads back as "off". components is always the complete map: every switch, with its default filled in where nothing was set. New switches may be added to it later, so treat a key you do not recognize as one more switch rather than an error.

Setting the level#

curl -X PATCH https://api.runbear.io/v1/agents/0f2b7d1e-9c34-4a5b-8f61-2ad0c5e7b913 \
  -H "Authorization: Bearer $RUNBEAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"responseComponents":{"frequency":"medium"}}'

The response is the full agent, with responseComponents.frequency reflecting the write. frequency is optional: a request can carry only components (see Choosing components), and an omitted frequency keeps its stored value.

The levels#

LevelWhat it does
offThe agent is not offered the components at all on this channel. This is the default, and the value an unset or unrecognized stored level reads back as.
lowOffer buttons sparingly: only when the next reply is unambiguously one of a few concrete options, and at most once per turn.
mediumThe balanced setting. Offer buttons whenever the next reply is plausibly one of a few concrete options; answer in prose when the question is genuinely open-ended.
highOffer buttons at every reasonable opportunity — whenever the turn would end in a question, a list of suggestions, or any choice the visitor could type back.

Choosing components#

The per-component switches choose which components the agent may use on the Web SDK. Each switch covers one or more components:

SwitchComponentsDefault
choiceButtonsconfirm, selectOn
cardcardOn
listlistOff
tabletableOff
chartchartOff

Turn a switch on or off with a PATCH carrying only the switches you change:

curl -X PATCH https://api.runbear.io/v1/agents/0f2b7d1e-9c34-4a5b-8f61-2ad0c5e7b913 \
  -H "Authorization: Bearer $RUNBEAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"responseComponents":{"components":{"list":true}}}'
  • Only the switches you send change. The rest keep their stored value, and a switch you never set keeps following its default.
  • The request is strict. An unknown switch, or a value that is not true or false, is rejected with 400 bad_request before anything is stored.
  • Turning on a component the agent's type cannot emit is refused with 422 unsupported_for_agent_type, and the message names the refused switches. A claude-agent-sdk agent supports only the choiceButtons switch, and a gemini agent supports none. Sending true for a switch that already reads back as true is accepted, so a map you read can be sent back unchanged.
  • Turning a switch off is always accepted, on every agent type.

The switches choose among components only while the dial is on. frequency set to "off" still withholds every component on the Web SDK, whatever the switches say. With the choiceButtons switch off, the low, medium and high levels read the same: their guidance is about the choice buttons.

The choiceButtons switch is not the agent's Choice Buttons setting (disableInteractivePrompts). The setting is the agent-wide opt-out: turning it off withdraws every component on every surface, whatever the switches say. The choiceButtons switch only decides whether confirm and select are offered on the Web SDK, and it never affects Slack.

A switch for a component that is not yet available (table, chart) stores and reads back like any other and produces nothing until it is. list, table and chart render on @runbear-io/react 0.5.0 or newer.

What else has to be true#

The dial is necessary but not sufficient. A non-off level produces components in the Web SDK only when all of these also hold:

  • Response components are enabled for your organization. They are in limited availability, and Runbear turns them on per organization (see the callout at the top of this page). Until then a non-off level stores and reads back correctly and produces nothing.
  • The agent's Choice Buttons setting is on. Turning it off withdraws interactive prompts on every surface, and it is checked before this dial. An agent opted out there never gains web components, whatever the level says.
  • The run has someone waiting on it. Scheduled and other automated runs never offer components, whatever the level says.
  • Your widget is on an SDK release that carries the renderers. That is @runbear-io/react 0.3.0 or newer for confirm and select, 0.4.0 or newer for card, and 0.5.0 or newer for list and for a card's image and links. On an earlier release the component arrives on the wire and the widget shows its prose fallback — see Web SDK response components.

Which components the agent can reach for also depends on its type. anthropic and openai-responses agents can emit every built-in component, and so can mastra agents — their dial is set from the dashboard, because mastra is not exposed on /v1/agents. A claude-agent-sdk agent emits confirm and select only, and never a card or a list, at any level. gemini emits none, which is why the dial refuses to leave off there at all.

Because the per-organization switch and the Choice Buttons setting are separate, a GET returning "frequency": "high" is a statement about this agent's configuration, not a promise that a visitor will see a button.

Errors#

StatusBodyCause
400{ "error": "bad_request", … }frequency is not one of off, low, medium, high.
400{ "error": "bad_request", … }components names an unknown switch, or a switch's value is not true or false.
422{ "error": "unsupported_for_agent_type", "message": … }A non-off level was written to an agent whose type cannot emit response components, or components turned on a switch the agent's type cannot emit. The message names the refused switches.

The 422 is terminal for that agent: the dial is only meaningful on a type that supports the components, and no retry changes that. On the public agents API this is refused for gemini, which registers no tools at all. The agent types that predate this API — perplexity, upstage and openai-assistant — also cannot emit components, but they are not exposed on /v1/agents and so cannot be reached to be refused.

Writing "off" is accepted on every type, so an agent can always be returned to the default even if it could not be given a level in the first place.

  • Web SDK response components — the rendering contract: the wire event, the props shapes, the server limits, and what a click does
  • Choice buttons — the dashboard section that holds this dial as Component frequency, and the switch that is checked before it
  • API keys — creating the key that carries manageAgents
  • OpenAPI reference — exact schemas for the agents endpoints