> ## Documentation Index
> Fetch the complete documentation index at: https://docs.widgentic.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Actions and secrets

> Make a widget interactive with prompt and http actions declared as data, and give http actions credentials that are never displayed.

A widget can carry actions: buttons and links that do something when the person viewing it activates them. Actions are declared as data, never as code, so a template never gains a way to run anything. The exact grammar is in the [Action definition reference](/reference/action-definition).

## Two kinds of action

**`prompt`** proposes a message. Its `text` is a sequence of literals and `{ "bind" }` segments that resolves at render time to one plain-text message. Activating the element places that text in the user's composer; the user decides whether to send it. No server call is made, and prompt actions work with any key.

**`http`** calls a URL server-side. The definition carries `method` (`GET` or `POST`), a fixed absolute `https` `url` (no userinfo, fragment or bindings), an `input` JSON Schema of type `object` for the arguments, an `output` schema the response must satisfy, and optional `headers` and `query` maps whose values are literal strings or `{ "secret": "<name>" }` references. `GET` sends the validated arguments as query parameters, `POST` as a JSON body. Header names the transport owns (`host`, `content-length`, `transfer-encoding`, `connection`) are refused.

A shared action is an entry `{ name, label?, description?, definition }`:

```json theme={null}
{
  "name": "refresh",
  "label": "Refresh weather",
  "definition": {
    "kind": "http",
    "method": "GET",
    "url": "https://api.example.com/weather",
    "input": { "type": "object", "properties": { "city": { "type": "string" } }, "required": ["city"] },
    "output": { "type": "object", "properties": { "current_weather": { "type": "object" } }, "required": ["current_weather"] },
    "headers": { "Authorization": { "secret": "weather-token" } }
  }
}
```

## Binding an action to an element

Put `action` on a `button` or an `a` element; an element carries `action` or `href`, never both (`CONFLICTING_ATTRIBUTES`). The binding names its action by reference, `{ "ref": "refresh" }`, or inline under `definition`, and may add:

* `input`: one entry per input-schema field, a template path or a `{ "const": ... }` literal, resolved at render time in the element's scope (`$root`, `$parent` and `$index` available), so a button inside `each` can name its own row. Arguments must be declared in the input schema and must not share a name with a fixed `query` parameter.
* `output`: how the validated response merges into the widget's data. `mode` is `merge` (the default: top-level keys over `data`), `replace` (the response becomes `data`) or `patch` (written at a required `path`); an optional `map` of target path to source path projects the response first. The result is re-validated as a payload of the widget's kind; a response that breaks the schema fails with `INVALID_ACTION_OUTPUT` and the previous data stands.

<CodeGroup>
  ```json Shared http action theme={null}
  {
    "tag": "button",
    "action": {
      "ref": "refresh",
      "input": { "city": "location.city" },
      "output": { "mode": "patch", "path": "reading", "map": { ".": "current_weather" } }
    },
    "children": ["Refresh"]
  }
  ```

  ```json Inline prompt theme={null}
  {
    "tag": "button",
    "action": { "definition": { "kind": "prompt", "text": ["Show the 7-day forecast for ", { "bind": "city" }] } },
    "children": ["7-day forecast"]
  }
  ```
</CodeGroup>

A widget may also declare one `load` binding beside its template, a top-level `load` field with the same keys. It accepts only `http` `GET` actions and runs once when the widget first renders in an Apps host.

In the widget designer the add menu offers `action` on `button` and `a` elements only, with an editor for the mapping and output mode; the preview renders bound elements with an inert badge, and nothing executes from a preview.

## The action designer and the Test control

Shared actions live in the **Actions** section, managed like widgets, themes and schemas. The action designer edits a prompt's text segments or an http action's method, URL, schemas, headers and query, with `{ "secret" }` references chosen from your secret names; a shared schema can be copied into an input or output schema, and the control says so, because an action's contract never references one. Import and Export sections accept and produce the entry JSON above.

An http action is savable only after a **Test call** succeeds: the app builds a form from the input schema, runs the call through the same server-side path production uses (never from the browser), requires the response to validate against the output schema, and shows the result with secret values redacted. Test calls share the per-principal execution limit. Saving a prompt action asks you to acknowledge that the proposed message is your responsibility. Deleting an action that widgets still bind is refused with `ACTION_IN_USE`, naming them.

## Execution gates

An http action leaves the server only when three gates pass:

1. **The host proxies widget tool calls.** The frame calls `execute_action` itself, which needs an MCP Apps host advertising `serverTools`; elsewhere http elements render disabled with an explanatory title, and prompt elements stay enabled.
2. **The key carries `execute`.** The scope is an opt-in at key creation and fixed afterwards. Under a read-only key the widget renders with its http descriptors marked `disabled: "scope"` and no `load` fires. See [Keys and scopes](/get-started/keys-and-scopes).
3. **The definition comes from your store.** A request names a widget and a binding identifier; the server resolves the definition from your stored template or shared action and ignores any URL, method, headers or schema in the request. A binding to an action you have not saved renders `disabled: "unresolved"`.

The fetch is guarded: `https` only, private, loopback, link-local and metadata targets refused, no redirects, a total deadline, a response size cap and JSON content only ([the values](/reference/action-definition)); a `204` or empty body arrives as `null` for the output schema to judge. After a successful action the widget re-renders in place and posts one model-context update with its new payload, so the agent and the visual never disagree. See [Trust model](/how-it-works/trust-model).

## Action notes

The model never sees the frame, so every `render_widget` and `execute_action` text output ends with an `Action notes:` tail whenever the widget carries actions: how many http and prompt actions it has (per binding; a button repeated by `each` counts once), how they behave, whether the widget loads data on first render, why any http action is disabled (`scope` or `unresolved`), and that the agent does not call `execute_action` itself.

## Secrets

The **Secrets** section is write-only. You set, replace and delete named secrets through a password-style field; after entry the app never shows a value, a preview or a length, and the list offers **Replace** and **Delete**, never Show or Copy. A name matches `^[a-z][a-z0-9-]{0,63}$`. At rest each secret is envelope-encrypted: a fresh data key encrypts the value with AES-256-GCM and is itself wrapped by a key-encryption key held in a vault, so only ciphertext is persisted.

An http action references a secret only as `{ "secret": "<name>" }` in a header or query value; references in the URL, body or input mapping are refused. At execution the server resolves each reference from your own secrets and injects the value; a missing secret fails with `UNKNOWN_SECRET` before any network activity. Values never appear in rendered output, `structuredContent`, tool text or model-context updates, and every diagnostic, including errors echoed by the remote service, has each value replaced by `***` in its raw, percent-encoded and JSON-escaped forms. A secret an action still references cannot be deleted (`SECRET_IN_USE`, naming the actions).
