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

# ChannelContext

> Abstract base class for channel execution contexts. Handles incoming events and transforms them into Claude Code notifications.

## Overview

`ChannelContext` extends `ExecutionContextBase` and provides the foundation for all channel implementations. It handles event transformation via `onEvent()` and optional reply handling via `onReply()`.

## Class Hierarchy

```
ExecutionContextBase<ChannelNotification>
  └── ChannelContext (abstract)
        ├── Your @Channel class
        └── FunctionChannelContext (internal, for channel() builder)
```

## Abstract Methods

### onEvent

Transform an incoming event payload into a channel notification.

```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
abstract onEvent(payload: unknown): Promise<ChannelNotification>;
```

| Parameter | Type      | Description                                                      |
| --------- | --------- | ---------------------------------------------------------------- |
| `payload` | `unknown` | Raw event payload from the source. Shape depends on source type. |

**Returns:** `Promise<ChannelNotification>` — the notification to push to Claude Code sessions.

### Payload Shapes by Source

| Source             | Payload Shape                                                                         |
| ------------------ | ------------------------------------------------------------------------------------- |
| `webhook`          | `WebhookPayload { body, headers, method, query }`                                     |
| `app-event`        | Whatever was passed to `eventBus.emit(event, payload)`                                |
| `agent-completion` | `AgentCompletionEvent { agentId, agentName, status, durationMs, output, error }`      |
| `job-completion`   | `JobCompletionEvent { jobName, jobId, status, durationMs, output, error, sessionId }` |
| `service`          | Whatever `pushIncoming(payload)` receives from your connection listener               |
| `file-watcher`     | Whatever `pushIncoming(payload)` receives from your file watcher                      |
| `manual`           | Whatever was passed to `handleEvent(payload)`                                         |

## Optional Methods

### onReply

Handle a reply from Claude Code. Only called when the channel has `twoWay: true`.

```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
async onReply(reply: string, meta?: Record<string, string>): Promise<void>
```

| Parameter | Type                     | Description                                                   |
| --------- | ------------------------ | ------------------------------------------------------------- |
| `reply`   | `string`                 | The reply text from Claude                                    |
| `meta`    | `Record<string, string>` | Metadata from the `channel-reply` tool call (e.g., `chat_id`) |

Default implementation logs a warning. Override to forward replies to external systems.

## Lifecycle Hooks (Service Connectors)

For channels with `source: { type: 'service' }` or `source: { type: 'file-watcher' }`, these lifecycle hooks manage persistent connections.

### onConnect

Establish a persistent connection to an external service. Called during scope initialization after the notification service is wired.

```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
async onConnect(): Promise<void>
```

Use this to set up WebSocket connections, API clients, polling loops, or file watchers. Call `pushIncoming()` inside event listeners to feed incoming events into the notification pipeline.

```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
async onConnect(): Promise<void> {
  this.client = new WhatsAppClient(process.env['WA_TOKEN']);
  this.client.on('message', (msg) => {
    this.pushIncoming({ sender: msg.from, text: msg.body, chatId: msg.chatId });
  });
  await this.client.connect();
}
```

### onDisconnect

Tear down the persistent connection. Called during scope shutdown.

```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
async onDisconnect(): Promise<void>
```

```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
async onDisconnect(): Promise<void> {
  await this.client?.disconnect();
  this.watcher?.close();
}
```

### pushIncoming

Push an incoming event from a service connection into the notification pipeline. Triggers `onEvent()` → notification push to subscribed sessions.

```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
protected pushIncoming(payload: unknown): void
```

| Parameter | Type      | Description                                      |
| --------- | --------- | ------------------------------------------------ |
| `payload` | `unknown` | Raw event payload to process through `onEvent()` |

<Warning>
  Only call `pushIncoming()` inside `onConnect()` event listeners. Calling it before `onConnect()` completes will log a warning since the handler is not yet wired.
</Warning>

## Inherited Properties

From `ExecutionContextBase`:

| Property      | Type              | Description                      |
| ------------- | ----------------- | -------------------------------- |
| `logger`      | `FrontMcpLogger`  | Scoped logger for this channel   |
| `metadata`    | `ChannelMetadata` | The channel's decorator metadata |
| `channelName` | `string`          | The channel name (from metadata) |

## Inherited Methods

From `ExecutionContextBase`:

| Method             | Description                                |
| ------------------ | ------------------------------------------ |
| `get<T>(token)`    | Resolve a dependency from the DI container |
| `tryGet<T>(token)` | Resolve or return `undefined` if not found |
| `scope`            | Access the parent scope                    |
| `fail(error)`      | Throw an MCP error                         |

## Examples

### Webhook Channel

```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
@Channel({
  name: 'monitoring',
  source: { type: 'webhook', path: '/hooks/monitor' },
  twoWay: true,
})
class MonitoringChannel extends ChannelContext {
  async onEvent(payload: unknown): Promise<ChannelNotification> {
    const { body } = payload as { body: { alert: string; severity: string } };
    return { content: `Alert: ${body.alert}`, meta: { severity: body.severity } };
  }

  async onReply(reply: string, meta?: Record<string, string>): Promise<void> {
    const messenger = this.get(MessengerServiceToken);
    await messenger.send(meta?.chat_id, reply);
  }
}
```

### Service Connector (Full Lifecycle)

```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
@Channel({
  name: 'whatsapp',
  source: { type: 'service', service: 'whatsapp-business' },
  tools: [SendWhatsAppTool],  // Claude calls this to send outbound messages
  twoWay: true,
})
class WhatsAppChannel extends ChannelContext {
  private client: WhatsAppClient;

  async onConnect(): Promise<void> {
    // Called during scope initialization
    this.client = new WhatsAppClient(process.env['WA_TOKEN']);
    this.client.on('message', (msg) => {
      // Feed incoming messages into the notification pipeline
      this.pushIncoming({ from: msg.sender, text: msg.body, chatId: msg.chatId });
    });
    await this.client.connect();
  }

  async onDisconnect(): Promise<void> {
    // Called during scope teardown
    await this.client.disconnect();
  }

  async onEvent(payload: unknown): Promise<ChannelNotification> {
    // Transform incoming service event → notification for Claude
    const msg = payload as { from: string; text: string; chatId: string };
    return {
      content: `${msg.from}: ${msg.text}`,
      meta: { chat_id: msg.chatId, sender: msg.from },
    };
  }

  async onReply(reply: string, meta?: Record<string, string>): Promise<void> {
    // Forward Claude's reply back through the service
    await this.client.sendMessage(meta?.chat_id, reply);
  }
}
```

## Related

* [@Channel Decorator](/frontmcp/sdk-reference/decorators/channel) — decorator configuration options
* [Channels Guide](/frontmcp/servers/channels) — full documentation
* [ExecutionContextBase](/frontmcp/sdk-reference/contexts/execution-context-base) — base class reference
