# `A2UICore.Message`
[🔗](https://github.com/a2ui-elixir/a2ui/blob/v0.1.1/umbrella/apps/a2ui_core/lib/a2ui_core/message.ex#L1)

Wire messages: decode raw agent→renderer payloads into canonical
`A2UICore.Message.Operation` structs, and encode operations back to
wire-format maps.

`decode/2` accepts everything the transport contract allows — a
single message map, a bare JSON array of messages, a
`{"messages": [...]}` wrapper, or `nil` (no-op):

    {:ok, ops} = A2UICore.Message.decode(payload)

Decoding runs the full reference pipeline: payload sniffing
(`A2UICore.Message.AdapterRegistry`), recursion/pointer preflight
(`A2UICore.Validation.Integrity`), per-version envelope validation
against the vendored spec schemas with the active catalog bound to
the `catalog.json` placeholder, and canonical operation extraction
(`A2UICore.Message.Adapter`).

## Options

  * `:catalog` — the active catalog schema map for component
    validation (defaults to the shipped basic catalog of the
    message's protocol version).

## Examples

    iex> {:ok, [%A2UICore.Message.Operation.UpdateDataModel{} = op]} =
    ...>   A2UICore.Message.decode(%{
    ...>     "version" => "v1.0",
    ...>     "updateDataModel" => %{"surfaceId" => "main", "value" => %{"user" => "Ada"}}
    ...>   })
    iex> {op.path, op.value}
    {"/", %{"user" => "Ada"}}

# `opts`
*since 0.1.0* 

```elixir
@type opts() :: keyword()
```

Decode options (see module docs).

# `decode`
*since 0.1.0* 

```elixir
@spec decode(term(), opts()) ::
  {:ok, [A2UICore.Message.Operation.t()]} | {:error, A2UICore.Error.t()}
```

Decodes a raw payload into canonical operations.

Returns `{:ok, operations}` or `{:error, %A2UICore.Error{}}` (always
category `:validation` for wire problems).

`nil` is a no-op (`{:ok, []}`) — matching the TypeScript processor
and the reference adapter's own tolerance. (The Python factory
rejects `nil` instead; we choose the lenient behaviour, and the
registry retains the strict one for direct callers.)

# `decode!`
*since 0.1.0* 

```elixir
@spec decode!(term(), opts()) :: [A2UICore.Message.Operation.t()]
```

Like `decode/2`, raising `A2UICore.Error` on failure.

# `encode`
*since 0.1.0* 

```elixir
@spec encode(
  A2UICore.Message.Operation.t() | [A2UICore.Message.Operation.t()],
  keyword()
) ::
  map() | [map()]
```

Encodes canonical operations back into wire-format message maps.

`overrides` may pass `:version` to force a wire version (e.g.
`"v0.9.1"` instead of `"v0.9"`). Without it, `createSurface` and the
function-call operations use the version they carry, and
`updateComponents`, `updateDataModel` and `deleteSurface`, which carry
none, are encoded as `"v0.9"`.

    iex> A2UICore.Message.encode(
    ...>   %A2UICore.Message.Operation.DeleteSurface{surface_id: "main"},
    ...>   version: "v1.0"
    ...> )
    %{"version" => "v1.0", "deleteSurface" => %{"surfaceId" => "main"}}

---

*Consult [api-reference.md](api-reference.md) for complete listing*
