# Channels — External Connection Points

Each subdirectory here is a **channel instance**: a persistent connection
surface (Feishu chat, ACP client, stdio terminal, etc.) with its own
inbox, outbox, sessions, and configuration.

## Layout

```
channels/
├── <channel_id>/
│   ├── descriptor.md     # Instance Descriptor (config + prompt)
│   ├── inbox/             # Pending inbound messages
│   ├── outbox/            # Pending outbound messages
│   └── sessions/          # Session attachments
└── ...
```

## Instance Descriptor (`descriptor.md`)

The instance descriptor is a Markdown file with YAML frontmatter.
It configures how sessions on this specific channel instance behave.

### System Fields (daemon-managed, do not edit)

```yaml
schema_version: 1
revision: 3
channel_id: my-channel
channel_kind: acp
```

### User-Configurable Fields

```yaml
---
# Human-readable name (optional)
display_name: "Research Assistant"

# Default workspace for new sessions (optional, supports ~/)
new_session_workspace: /workspace/research

# System prompt mode (optional)
#   append   (default): keep Claude Code preset, append channel prompts
#   override          : skip preset, use only assembled prompts
prompt_mode: append

# SDK tool configuration (optional)
allowedTools: ["Read", "Edit", "Bash"]
disallowedTools: ["EnterPlanMode"]

# Additional directories whose CLAUDE.md files are loaded into context (optional)
# Use this to give sessions access to reference docs, knowledge bases, etc.
additionalDirectories:
  - /refs
  - ~/shared-docs

# Enable/disable streaming (optional, default: true)
# When false, output is buffered until the turn completes.
# Useful for group chats where streaming typing indicators are noise.
stream: false
---
You are a research assistant specialized in financial analysis.
Use the reference documents in /refs/ for evidence-based answers.
```

### Config Merge Order

Instance descriptors override kind descriptors:

```
Kind Descriptor (kernel/config/<kind>.md)    ← defaults for all instances of this kind
  └─ Instance Descriptor (this file)         ← overrides for this specific instance
```

For `additionalDirectories`, `allowedTools`, and `disallowedTools`:
instance values **replace** (not merge with) kind values.

### Prompt Assembly

```
[Identity]        bootstrap/meta-prompt.md
[Kind Prompt]     kernel/config/<kind>.md body
[Instance Prompt] descriptor.md body            ← this file's Markdown body
```

## How Channels Get Created

1. **Automatically** — when the daemon receives the first message for an
   unknown `channel_id`, it creates a descriptor with system defaults.
2. **By adapters** — channel adapters (ACP, Feishu) create descriptors
   during ingress processing via `ensureChannelDescriptor()`.

## Configuring Channels as an Integrator

To customize channel behavior at deployment time:

1. **Kind-level defaults** — edit `kernel/config/<kind>.md` to set
   defaults for all channels of a kind (e.g., all ACP channels).
   See `kernel/config/stdio.md` for a fully documented template.

2. **Instance-level overrides** — edit the `descriptor.md` of a specific
   channel to override kind defaults for that instance only.

3. **At channel creation** — pass frontmatter fields when creating a
   channel via the daemon API or adapter.
