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

# The Streams

```bash theme={null}
telnyx-acp invoke support-agent --conversation alice --stream "hi"
```

```text {5,13} theme={null}
support-agent/
├── agent.json
├── instructions.md
└── .telnyx/                        written by deploy
    ├── index.ts                                       ◀
    ├── telnyx.toml
    ├── telnyx-env.d.ts
    └── package.json

@telnyx/acp/                      the package
├── managed/
│   ├── index.ts
│   ├── agent.ts                                       ◀
│   ├── model.ts
│   ├── memory.ts
│   ├── tools.ts
│   ├── mcp.ts
│   ├── voice.ts
│   ├── direct-turn.ts
│   └── filler.ts
├── channels/
│   ├── index.ts
│   ├── phone.ts
│   ├── email.ts
│   ├── web.ts
│   └── wire.ts
├── synth/
│   ├── index.ts
│   ├── code-entry.ts
│   └── vendor.ts
└── spec/
    ├── schema.ts
    ├── model.ts
    ├── phone.ts
    ├── project.ts
    └── io.ts
```

A WebSocket upgrade, or `GET …?subscribe=state`, on a conversation's address opens the stream of its state and messages. No turn runs. [`mountAgents`](/docs/agent-sdk/internals/mount/mountAgents) hands the upgrade to the runtime's default [`webSocket()`](/docs/agent-sdk/interface/webSocket), and the GET, like an RPC's POST, to the class's `fetch`:

```ts theme={null}
// managed/agent.ts
fetch(req) {
  return (this.door ??= new AgentHttpServer(this.connectionEngine)).fetch(req);
}
```

`fetch(req)` overrides the runtime SDK's [`fetch()`](/docs/agent-sdk/interface/fetch) with an [`AgentHttpServer`](/docs/agent-sdk/internals/the-http-server) over [`connectionEngine`](/docs/agent-sdk/interface/connectionEngine).

* The server answers a GET with Server-Sent Events, and a POST to `…/rpc/<method>` with one RPC call.
* `connectionEngine` is the engine the default `webSocket()` runs every socket through, so both transports serve the same streams under the same `authorize`.
* The server is built on the first request and kept for the activation.

`authorize` decides who may read the streams and who may call the [`@rpc`](/docs/agent-sdk/interface/rpc) methods:

```ts theme={null}
// managed/agent.ts
authorize(token, req) {
  return this.host.authorize ? this.host.authorize(token, req) : ["read", "rpc"];
}
```

`authorize(token, req)` overrides the runtime SDK's [`authorize()`](/docs/agent-sdk/interface/authorize).

* `token` is the credential the caller presented, or `undefined` without one.
* `req` is the request, with any identity headers a front door stamped on it.
* The returned claims are the caller's grants, and a throw rejects the caller. The runtime acts on `"rpc"` alone, which admits the `@rpc` methods.
* The runtime's own default returns `["read"]`, which admits the streams and no RPC.

The voice class overrides `webSocket()` to answer calls, so on a voice agent an upgrade is a call, as [The Call Webhook](/docs/agent-sdk/inside/request-handling/call-webhook) shows.

> [!WARNING]
>
> **Beta.** Without a host `authorize`, every caller is granted read and RPC.
