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

# Channel Router and Inbound Pipeline

<details>
  <summary>Relevant source files</summary>

  The following files were used as context for generating this wiki page:

  * crates/palyra-cli/src/args/message.rs
  * crates/palyra-cli/src/client/message.rs
  * crates/palyra-cli/src/commands/approvals.rs
  * crates/palyra-cli/src/commands/channels/connectors/discord/setup.rs
  * crates/palyra-cli/src/commands/channels/connectors/discord/verify.rs
  * crates/palyra-cli/src/commands/channels/mod.rs
  * crates/palyra-cli/src/commands/channels/router.rs
  * crates/palyra-cli/src/commands/message.rs
  * crates/palyra-connectors/src/lib.rs
  * crates/palyra-connectors/tests/simulator\_harness.rs
  * crates/palyra-daemon/src/channel\_router.rs
  * crates/palyra-daemon/src/channels.rs
  * crates/palyra-daemon/src/channels/attachments.rs
  * crates/palyra-daemon/src/channels/defaults.rs
  * crates/palyra-daemon/src/channels/discord.rs
  * crates/palyra-daemon/src/channels/gateway\_auth.rs
  * crates/palyra-daemon/src/channels/media.rs
  * crates/palyra-daemon/src/channels/proto.rs
  * crates/palyra-daemon/src/delegation.rs
  * crates/palyra-daemon/src/transport/http/handlers/admin/channels/mod.rs
  * crates/palyra-daemon/src/transport/http/handlers/console/channels/mod.rs
</details>

The Channel Router and Inbound Pipeline constitute the entry point for all external messaging traffic into the Palyra daemon. This subsystem is responsible for normalizing messages from diverse platforms (Discord, Slack, etc.), applying routing policies, managing conversation state, and coalescing rapid-fire messages into logical "turns" for the agent loop.

## Inbound Message Lifecycle

The inbound pipeline follows a strict progression from raw connector event to a dispatched agent run.

### 1. Admission and Matching

When a connector (e.g., Discord) receives a message, it is passed to the `ChannelRouter::route_inbound` function [crates/palyra-daemon/src/channel\_router.rs#1-10](http://crates/palyra-daemon/src/channel_router.rs#1-10). The router evaluates the message against `ChannelRoutingRule` sets [crates/palyra-daemon/src/channel\_router.rs#195-210](http://crates/palyra-daemon/src/channel_router.rs#195-210).

* **Mention Matching**: The router checks if the message matches defined `mention_patterns` [crates/palyra-daemon/src/channel\_router.rs#198](http://crates/palyra-daemon/src/channel_router.rs#198).
* **Sender Filtering**: `allow_from` and `deny_from` lists are checked to permit or block specific identities [crates/palyra-daemon/src/channel\_router.rs#200-201](http://crates/palyra-daemon/src/channel_router.rs#200-201).
* **DM Policy**: Direct messages are gated by `DirectMessagePolicy`, which can be `Deny`, `Allow`, or `Pairing` [crates/palyra-daemon/src/channel\_router.rs#74-78](http://crates/palyra-daemon/src/channel_router.rs#74-78).

### 2. Session Resolution

Once admitted, the router determines the `session_id`. If `isolate_session_by_sender` is true, a unique session is created per user; otherwise, the conversation ID from the platform is used [crates/palyra-daemon/src/channel\_router.rs#204](http://crates/palyra-daemon/src/channel_router.rs#204).

### 3. Inbound Coalescing

To prevent "message storms" from triggering excessive runs, the pipeline uses an `InboundCoalescer` (logic managed within the gateway runtime). This component merges multiple rapid-fire messages from the same conversation into a single buffer before dispatching a "Channel Turn."

### 4. Dispatch

Accepted messages result in a `RouteInboundResult` [crates/palyra-connectors/tests/simulator\_harness.rs#53-77](http://crates/palyra-connectors/tests/simulator_harness.rs#53-77). This result contains the `route_key` and `session_id` required by the `GatewayRuntime` to initiate an agent run.

**Inbound Data Flow Diagram**

```mermaid theme={null}
graph TD
    subgraph "External Platforms"
        Discord["Discord Gateway"]
        Slack["Slack Webhook"]
    end

    subgraph "palyra-daemon (Channel Subsystem)"
        ConnectorSupervisor["ConnectorSupervisor"]
        ChannelRouter["ChannelRouter"]
        InboundCoalescer["InboundCoalescer"]
    end

    subgraph "Core Runtime"
        GatewayRuntime["GatewayRuntime"]
        AgentLoop["AgentRunLoop"]
    end

    Discord -->|"InboundMessageEvent"| ConnectorSupervisor
    Slack -->|"InboundMessageEvent"| ConnectorSupervisor
    ConnectorSupervisor -->|"route_inbound()"| ChannelRouter
    ChannelRouter -->|"RouteInboundResult"| InboundCoalescer
    InboundCoalescer -->|"Channel Turn"| GatewayRuntime
    GatewayRuntime -->|"Start Run"| AgentLoop
```

Sources: [crates/palyra-daemon/src/channel\_router.rs#1-210](http://crates/palyra-daemon/src/channel_router.rs#1-210), [crates/palyra-connectors/tests/simulator\_harness.rs#47-78](http://crates/palyra-connectors/tests/simulator_harness.rs#47-78), [crates/palyra-daemon/src/channels.rs#1-175](http://crates/palyra-daemon/src/channels.rs#1-175)

## Channel Router Implementation

The `ChannelRouter` is a policy-driven engine that manages in-memory state for routing decisions, including rate limiting and quarantine for "poison" messages [crates/palyra-daemon/src/channel\_router.rs#1-10](http://crates/palyra-daemon/src/channel_router.rs#1-10).

### Key Structures

| Class/Struct          | Responsibility                                                    |
| :-------------------- | :---------------------------------------------------------------- |
| `ChannelRouter`       | Primary entry point for routing logic and policy enforcement.     |
| `ChannelRoutingRule`  | Defines how a specific channel behaves (mentions, targets, etc.). |
| `DirectMessagePolicy` | Enum defining `Deny`, `Pairing`, or `Allow` for DMs.              |
| `BroadcastStrategy`   | Controls how fan-out requests are handled per channel.            |

### Direct Message Pairing

For channels using `DirectMessagePolicy::Pairing`, the router manages a "handshake" flow:

1. **Code Generation**: An operator generates a `PairingCodeRecord` [crates/palyra-daemon/src/channel\_router.rs#107-113](http://crates/palyra-daemon/src/channel_router.rs#107-113).
2. **Consumption**: The user sends the code via DM. The router creates a `PairingPendingRecord` [crates/palyra-daemon/src/channel\_router.rs#118-125](http://crates/palyra-daemon/src/channel_router.rs#118-125).
3. **Approval**: An operator approves the request, creating a `PairingGrantRecord` [crates/palyra-daemon/src/channel\_router.rs#129-135](http://crates/palyra-daemon/src/channel_router.rs#129-135).

**Code Entity Mapping: Routing and Pairing**

```mermaid theme={null}
classDiagram
    class ChannelRouter {
        +route_inbound(event) RouteInboundResult
        +consume_pairing_code(code) PairingConsumeOutcome
    }
    class ChannelRoutingRule {
        +String channel
        +Vec~String~ mention_patterns
        +DirectMessagePolicy direct_message_policy
    }
    class PairingCodeRecord {
        +String code
        +i64 expires_at_unix_ms
    }
    class PairingGrantRecord {
        +String sender_identity
        +Option~i64~ expires_at_unix_ms
    }

    ChannelRouter "1" *-- "many" ChannelRoutingRule : enforces
    ChannelRouter "1" *-- "many" PairingCodeRecord : manages
    ChannelRouter "1" *-- "many" PairingGrantRecord : tracks
```

Sources: [crates/palyra-daemon/src/channel\_router.rs#38-144](http://crates/palyra-daemon/src/channel_router.rs#38-144), [crates/palyra-daemon/src/channel\_router.rs#195-210](http://crates/palyra-daemon/src/channel_router.rs#195-210)

## Outbound Lifecycle

Outbound messages follow a "Delivery Intent" pattern to ensure reliability across unstable network conditions.

1. **Enqueue**: The agent or a tool requests an outbound send. This is captured as an `OutboundMessageRequest` [crates/palyra-daemon/src/channels/discord.rs#150-165](http://crates/palyra-daemon/src/channels/discord.rs#150-165).
2. **Persistence**: The request is stored in the outbox via the `ConnectorSupervisor` [crates/palyra-daemon/src/channels/discord.rs#166](http://crates/palyra-daemon/src/channels/discord.rs#166).
3. **Drain**: A background worker or immediate trigger calls `drain_due_outbox_for_connector` [crates/palyra-daemon/src/channels/discord.rs#168-173](http://crates/palyra-daemon/src/channels/discord.rs#168-173).
4. **Delivery**: The specific adapter (e.g., Discord) executes the HTTPS/WebSocket request.
5. **Receipt**: If successful, a `native_message_id` is returned and associated with the internal `envelope_id` [crates/palyra-daemon/src/channels/discord.rs#174-177](http://crates/palyra-daemon/src/channels/discord.rs#174-177).

### Outbound Mutation and Approval

Mutations (Edit, Delete, Reactions) are subject to `ApprovalRiskLevel` checks [crates/palyra-daemon/src/channels/discord.rs#15](http://crates/palyra-daemon/src/channels/discord.rs#15).

* **Preflight**: The system checks if the connector supports the action [crates/palyra-cli/src/client/message.rs#4-6](http://crates/palyra-cli/src/client/message.rs#4-6).
* **Governance**: `classify_discord_message_mutation_governance` determines if a mutation requires manual operator approval based on the target channel and message age [crates/palyra-daemon/src/channels.rs#69-72](http://crates/palyra-daemon/src/channels.rs#69-72).

**Outbound Delivery Flow**

```mermaid theme={null}
sequenceDiagram
    participant A as Agent Loop
    participant S as ConnectorSupervisor
    participant D as DiscordAdapter
    participant P as Discord API

    A->>S: enqueue_outbound(OutboundMessageRequest)
    S->>S: Persist DeliveryIntent
    A->>S: drain_due_outbox()
    S->>D: send_outbound(request)
    D->>P: POST /channels/{id}/messages
    P-->>D: 200 OK (message_id)
    D-->>S: DeliveryOutcome::Delivered
    S->>S: Update DeliveryIntentStatus::Delivered
```

Sources: [crates/palyra-daemon/src/channels/discord.rs#150-188](http://crates/palyra-daemon/src/channels/discord.rs#150-188), [crates/palyra-connectors/tests/simulator\_harness.rs#129-170](http://crates/palyra-connectors/tests/simulator_harness.rs#129-170), [crates/palyra-daemon/src/channels.rs#27-31](http://crates/palyra-daemon/src/channels.rs#27-31)

## Conversation Bindings

Palyra maintains a mapping between external platform entities and internal agent constructs.

* **Principal**: The identity of the Palyra instance on the platform (e.g., the Bot User ID) [crates/palyra-daemon/src/channels.rs#45](http://crates/palyra-daemon/src/channels.rs#45).
* **Connector ID**: A unique string identifying a specific account/token (e.g., `discord:my-server`) [crates/palyra-daemon/src/channels/discord.rs#20](http://crates/palyra-daemon/src/channels/discord.rs#20).
* **Route Key**: A deterministic string combining connector and conversation IDs used to serialize access to session state [crates/palyra-connectors/tests/simulator\_harness.rs#68-71](http://crates/palyra-connectors/tests/simulator_harness.rs#68-71).

### Implementation Reference

| Feature             | Code Entity                    | File Path                                                                                                                                                           |
| :------------------ | :----------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Routing Entry**   | `ChannelRouter::route_inbound` | [crates/palyra-daemon/src/channel\_router.rs#1-10](http://crates/palyra-daemon/src/channel_router.rs#1-10)                                                          |
| **Platform Facade** | `ChannelPlatform`              | [crates/palyra-daemon/src/channels.rs#169-174](http://crates/palyra-daemon/src/channels.rs#169-174)                                                                 |
| **Outbound Send**   | `submit_discord_test_send`     | [crates/palyra-daemon/src/channels/discord.rs#99-103](http://crates/palyra-daemon/src/channels/discord.rs#99-103)                                                   |
| **Mutation Risk**   | `ApprovalRiskLevel`            | [crates/palyra-daemon/src/channels/discord.rs#15](http://crates/palyra-daemon/src/channels/discord.rs#15)                                                           |
| **Admin API**       | `admin_channels_list_handler`  | [crates/palyra-daemon/src/transport/http/handlers/admin/channels/mod.rs#26-30](http://crates/palyra-daemon/src/transport/http/handlers/admin/channels/mod.rs#26-30) |

Sources: [crates/palyra-daemon/src/channel\_router.rs#1-210](http://crates/palyra-daemon/src/channel_router.rs#1-210), [crates/palyra-daemon/src/channels.rs#1-175](http://crates/palyra-daemon/src/channels.rs#1-175), [crates/palyra-daemon/src/channels/discord.rs#1-188](http://crates/palyra-daemon/src/channels/discord.rs#1-188)
