# `Raxol.AgentClientProtocol.Schema.AgentTypes`
[🔗](https://github.com/DROOdotFOO/raxol-agent/blob/raxol_agent_client_protocol-v0.1.0/packages/raxol_agent_client_protocol/lib/raxol/agent_client_protocol/schema/agent_types.ex#L1)

Agent-side types for the Agent Client Protocol: the `initialize`/
`authenticate` handshake, session lifecycle (`session/new`, `session/load`,
`session/set_mode`, `session/prompt`, `session/cancel`), capability
negotiation, and MCP server descriptors.

Every struct here carries an `_meta` map (default `%{}`) that is total on
decode: unrecognized top-level wire keys, plus the contents of an explicit
`"_meta"` wire object, are folded into it (via `extract_meta/2`) and
re-emitted nested under the wire `"_meta"` key on encode (via
`put_meta/2`, matching every sibling schema module's
`WireFields.emit_meta/2` convention), so round-tripping an object this
library doesn't fully understand never loses data. `from_json/1` never
raises; it always returns `{:ok, t}` or `{:error, reason}`.

Known load-bearing string fields (`cwd`, `sessionId`, `modeId`,
`methodId`) are type-checked via `fetch/3`, not just presence-checked via
`fetch/2`: a wrong-typed value returns `{:error, {:invalid_field, key,
value}}` rather than decoding the raw value through. A lenient
presence-only decode on these fields would let e.g. a non-string
`sessionId` reach a handler, changing the error class from `-32602
Invalid params` at decode to whatever the handler's own lookup produced.
Unknown wire keys are unaffected -- they still fold into `_meta` via
`extract_meta/2` -- so this does not narrow forward-compat, only rejects
nonsense on fields this module already claims to understand.

## Cross-module references

`PromptRequest.prompt` is a list of
`Raxol.AgentClientProtocol.Schema.ContentBlock`;
`InitializeRequest.client_capabilities` / `InitializeResponse` reference
`Raxol.AgentClientProtocol.Schema.ClientTypes.ClientCapabilities`;
`ClientRequest`/`ClientNotification` reference
`Raxol.AgentClientProtocol.Schema.Ext.{ExtRequest, ExtNotification,
ExtResponse}`; protocol version decode uses
`Raxol.AgentClientProtocol.Schema.Version.coerce/1`.

Note: `ACP.SessionUpdate` (the `session/update` notification's
`sessionUpdate`-discriminated union) lives in upstream's
`lib/acp/client_types.ex`, not `agent_types.ex` — it is intentionally NOT
ported here. It lives as `Raxol.AgentClientProtocol.Schema.SessionUpdate`
in its own file, `session_update.ex`, together with its variant payload
structs (`ContentChunk`, `CurrentModeUpdate`,
`AvailableCommandsUpdate`/`AvailableCommand`/`AvailableCommandInput`/
`UnstructuredCommandInput`). The `{sessionId, update, _meta}` envelope
that wraps it for the wire is
`Raxol.AgentClientProtocol.Schema.LifecycleExtras.SessionNotification`;
this package has no `AgentNotification` routing union -- the
`session/update` method is routed by its `MethodTable` row.

Ported from the MIT `f1729/agent_client_protocol` (c) 2025 f1729; see NOTICE.md.

# `put_meta`

```elixir
@spec put_meta(map(), map()) :: map()
```

Re-emit a struct's `_meta` bucket under the wire `"_meta"` key, omitted
when empty -- matches the internal `WireFields.emit_meta/2` helper (not
part of the public docs; `@moduledoc false`), the convention every
sibling module in this package (`content.ex`,
`plan.ex`, `tool_call.ex`, `client_types.ex`) follows. The bucket is
nested, never flattened onto the top-level wire object, so encode is
symmetric with `extract_meta/2`, which folds an explicit `"_meta"`
object on decode: a round trip preserves nested `_meta` content instead
of promoting it to top-level fields.

---

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