# `T3.RPC`
[🔗](https://github.com/dl-alexandre/t3-elixir/blob/main/lib/t3/rpc.ex#L1)

Supervised WebSocket client for T3's Effect RPC protocol (`/ws`).

This is a separate authentication audience from MCP. Supply an environment
access token (`:token`) or an RPC WebSocket ticket (`:ticket`), not an MCP OAuth
token. T3 rejects MCP client credentials on this surface. `:dpop` accepts a
caller-created proof for a proof-bound credential (token headers then use the
`DPoP` authorization scheme; `:auth_scheme` can explicitly select it). Credentials
never persist. `:max_pending` defaults to 128 and `:max_message_bytes` to 16 MiB.

Obtain a route-bound ticket with an environment HTTP credential:

    http = T3.HTTP.new(base_url: "http://127.0.0.1:3773", token: environment_token)
    {:ok, response} = T3.HTTP.Auth.web_socket_ticket_for(http, "rpc")
    {:ok, rpc} = T3.RPC.start_link(
      url: "ws://127.0.0.1:3773/ws", ticket: response.body["ticket"]
    )

For proof-bound tickets supply a new DPoP proof that hashes that ticket. The SDK
transports caller-created proofs; it does not generate or manage signing keys.

    {:ok, rpc} = T3.RPC.start_link(url: "ws://127.0.0.1:3773/ws", token: token)
    {:ok, config} = T3.RPC.call(rpc, "server.getConfig", %{})
    {:ok, subscription} = T3.RPC.subscribe(rpc, "orchestration.subscribeShell", %{})
    receive do
      {:t3_rpc, ^subscription, {:chunk, values}} ->
        IO.inspect(values)
        :ok = T3.RPC.ack(rpc, subscription)
      {:t3_rpc, ^subscription, {:done, _}} -> :ok
      {:t3_rpc, ^subscription, {:error, error}} -> IO.puts(Exception.message(error))
    after
      5_000 -> :ok
    end
    :ok = T3.RPC.unsubscribe(rpc, subscription)
    :ok = T3.RPC.close(rpc)

Subscriptions use explicit acknowledgements: acknowledge each chunk after
consuming it. This retains the server's back-pressure instead of buffering an
unbounded event queue. Terminal messages are `{:t3_rpc, id, {:done, value}}` or
`{:t3_rpc, id, {:error, error}}`. Subscriber death cancels its request.

`call/4` defaults to a 30-second deadline. Subscription `:timeout` defaults to
`:infinity`; pass milliseconds for a total deadline. No operation is replayed or
retried after disconnect. Use `T3.RPC.Reader` for opt-in supervised read
subscription recovery and `T3.LocalAuth` for local service credentials. Payloads and results retain the upstream string keys;
`T3.RPC.Catalog` lists the pinned upstream methods and streaming flags.

# `result`

```elixir
@type result() :: {:ok, term()} | {:error, T3.Error.t()}
```

# `subscription`

```elixir
@type subscription() :: String.t()
```

# `ack`

Acknowledge the outstanding chunk of a subscription.

# `call`

```elixir
@spec call(GenServer.server(), String.t(), term(), keyword()) :: result()
```

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `close`

# `ping`

# `respond`

Reply to a server-originated request delivered to the configured :owner.

# `start_link`

# `subscribe`

```elixir
@spec subscribe(GenServer.server(), String.t(), term(), keyword()) ::
  {:ok, subscription()} | {:error, T3.Error.t()}
```

# `unsubscribe`

Interrupt a subscription and release its local state. Idempotent.

---

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