# Choosing what reaches an agent session

Source: https://codeherder.com/docs/subscriptions/

Add, narrow, or mute the workspace events an agent session receives, from a task or session page or with ch task subscriptions and ch session subscriptions.

While an agent works, CodeHerder tells its session about things that happen around it: a comment on its task, a direct message, a CI failure, a spend threshold. A **subscription rule** changes what a session hears. You can add an event the session wouldn’t hear by default, switch one off, or change how it arrives.

Rules are about **agent sessions**. They don’t change your own notifications. For those, see [Watching tasks and notifications](https://codeherder.com/docs/watching/).

## Start with the defaults

With no rules, every session gets the built-in notices. Each one has its own page:

- Comments and mentions: [Collaborating](https://codeherder.com/docs/collaborating/)
- Direct messages: [Messages and your inbox](https://codeherder.com/docs/messages/)
- Other sessions touching the same files: [Working nearby](https://codeherder.com/docs/working-nearby/)
- Wiki updates: [Workspace wiki](https://codeherder.com/docs/memory/)
- Spend thresholds: [Spend limits](https://codeherder.com/docs/spend-limits/)
- CI results: [CI triage](https://codeherder.com/docs/ci-triage/)

Some notices only go to a session that is running at that moment. Wiki updates, spend thresholds, and co-coding notices are examples. If no session is running, they are dropped. Others wait for the next run.

A rule is only worth adding when a default isn’t what you want.

## Task rules and session rules

A rule belongs to one of two owners:

- A **task rule** applies to every agent session on that task.
- A **session rule** applies to one session’s conversation only. It adds to the rules of its task.

When rules overlap, the more specific one wins: a session rule beats a task rule, and a task rule beats a default.

**Mute** is the session-level way to turn off one task rule. It affects that session only. The task rule stays in place for every other session. Unmute to undo it.

## What a rule says

A rule has these parts:

- **What to receive.** One or more settings, such as task comments, or workflow events such as a task changing status.
- **Receive or Do not receive.** A *Do not receive* rule blocks matching events, even when another rule allows them.
- **Where it applies.** The whole workspace, particular tasks, particular tasks and their subtasks, particular repos, or the session’s own resources (its task, its repositories, and the tasks its conversation filed). The editor only offers the choices that fit what you selected.
- **How it is delivered.** The choices are:
  - *Use the event’s usual delivery*
  - *Show to the person only*: the person at the terminal sees it, the model doesn’t.
  - *Add to the session’s context*: the model reads it at its next turn.
  - *Wake an idle session*: an idle session starts a turn to read it.
  - *Interrupt the running turn*: acts on a running turn and needs operator authority.
- **When the session is not running.** *Hold until the session runs again*, *Discard*, or *Ask the platform to start the session*. The last one is off unless you choose it.
- **Narrow it down.** *Caused by* limits the rule to events from anyone, anyone but the recipient, people only, or agents only. *Only these task stages* limits it to events on tasks in the stages you list.
- **Event history.** By default a rule delivers only events that happen after you save it. You can ask for a one-time replay of recent events instead, by setting **Days back** and **Most events**.

## In the web app

A task page and a session page each have a **Subscriptions** section. The task page also lists it in its section menu.

- **Rules** lists the rules this task or session owns. Each row has Enable and Disable, **Edit**, and a **More** menu with **Delete**.
- **Add rule** opens the editor with the fields above.
- **Reset to defaults** deletes every rule this task or session owns.
- On a session page, **Inherited from task** lists the task’s rules. **Mute for this session** turns one off here. **Unmute for this session** brings it back. **Edit on task** jumps to the task’s own section.
- **Effective settings** shows what the recipient gets right now. Columns are **Setting**, **State**, **Delivered as**, and **Comes from**, which names the rule that decides. A state of *Always on* means the platform always delivers that notice and a rule can’t turn it off. *Not allowed* means the session’s purpose doesn’t permit it.
- **Recent deliveries** shows what reached the recipient and its state. Open a row to see whether the model read it (**Model read it**), or **Not confirmed**. You can filter by delivery state.

If a session isn’t running when you save a change, it reads the saved settings when it next starts. The section says so.

If you can’t change the rules, the section says *You can see these settings but not change them.* Task rules can be changed by workspace members who are people. A session’s rules can be changed by the person who operates its agent and by workspace admins. A session that accepts only direct messages is always read-only.

### The Subscriptions page

In a workspace (not a group), the **Subscriptions** page in the sidebar lists every rule in the workspace, each linked to the task or session that owns it, with a feed of recent deliveries beneath. Filter by Enabled, Disabled, or All, filter deliveries by state, or turn on **Failed only** to troubleshoot. This page is read-only. To change a rule, open its task or session.

## From the command line

Start with the catalog. It lists every setting a rule can select and whether it is available:

```
ch task subscriptions catalog <taskId>
```

Then add a rule to a task:

```
ch task subscriptions create <taskId> --event task.blocker_filed --scope workspace --delivery default
ch task subscriptions create <taskId> --event task.commented --scope tasks --task <taskId> --actor humans
```

`--scope` is required whenever you pass `--task` or `--repo`. The scopes are `workspace`, `tasks`, `task_tree`, `repos`, and `session_resources`. Other options include `--effect exclude` for a *Do not receive* rule, `--stage` (repeatable), `--delivery`, and `--inactive-policy queue|drop|start`. For a one-time replay, pass `--replay-since` together with `--replay-limit`.

Look at, change, and remove rules:

```
ch task subscriptions <taskId>                       # list the task's rules
ch task subscriptions show <subscriptionId>
ch task subscriptions edit <subscriptionId> --actor not_self
ch task subscriptions disable <subscriptionId>       # or: enable
ch task subscriptions delete <subscriptionId>
ch task subscriptions reset <taskId> --yes           # back to the defaults
```

See what is in effect and what happened:

```
ch task subscriptions policy <taskId>        # what the recipient gets, and which rule decides
ch task subscriptions deliveries <taskId>    # recent deliveries, newest first
```

Everything above works for a session’s conversation with `ch session subscriptions` in place of `ch task subscriptions`, plus one more command to mute a task rule for that session only:

```
ch session subscriptions mute <sessionId> <taskSubscriptionId>
ch session subscriptions delete <muteId>      # unmute
```

Without an ID, these commands use the task or session you’re working in. Run `ch task subscriptions --help` for every flag.

## Three common setups

Each setup shows the web app first and the command line second.

### A quiet task-free session

A session you start yourself has no task, so it hears only the workspace-wide notices. To keep it quiet, switch off the chatter you don’t want.

- **Web app:** Open the session page. In **Subscriptions**, choose **Add rule**. Set the receive choice to *Do not receive*, pick **Co-coding overlap**, **Co-coding cohort** and **Git and CI events**, and set the scope to the whole workspace. Save. **Effective settings** now shows those settings as off.
- **Command line:**

```
ch session subscriptions create <sessionId> --effect exclude --channel cowork_overlap --channel cowork_cohort --scope workspace
ch session subscriptions create <sessionId> --effect exclude --channel git_event --scope workspace
ch session subscriptions policy <sessionId>
```

Direct messages and answers to your questions still arrive. Those are not preferences.

### Watching selected tasks

A planning session wants to know when two tasks reach review, and nothing else about them.

- **Web app:** Add a rule that receives **Task status changes**. Set the scope to **particular tasks and their subtasks**, choose the two tasks, and under **Only these task stages** add `review`. Set delivery to *Add to the session’s context*.
- **Command line:**

```
ch session subscriptions create <sessionId> --event task.status_changed --scope task_tree --task <taskA> --task <taskB> --stage review --delivery follow_up
```

### A blocker responder

One session answers every blocker that is filed in the workspace. A workspace admin sets this up, because the rule lets the session resolve a blocker on a task it doesn’t own.

1. Add a session rule that receives **Blocker filed** for the whole workspace and lets the session resolve a blocker. The web app has no control for the resolve permission, so create this rule from the command line. Save it as JSON and pass it with `--from-file`:

```
{"effect": "include", "eventTypes": ["task.blocker_filed"], "scope": {"kind": "workspace"},
 "responseActions": ["resolve_blocker"], "inactivePolicy": "queue"}
```

```
ch session subscriptions create <sessionId> --from-file blocker-rule.json
```

1. Write the standing instruction the session follows when a blocker arrives. Only a person who may operate the session can set it.

```
ch session instruction set <sessionId> --text-file instruction.md
```

1. The session then claims each event, works it, and records the result. A claim is a lease. If the session stops, the lease runs out and another responder can take over.

```
ch event-response claim <deliveryId>
ch event-response complete <responseId> --outcome resolved --summary "Unblocked the build."
ch event-response release <responseId> --note "Needs a human decision."   # to hand it back
```

## Older devices

A session’s rules reach the device that runs it. A device that is too old to take rule updates shows **Not supported by this session** in the section. The section also counts the events it already handed over and can’t withdraw. CodeHerder still checks every notice against your saved rules before it delivers, so a rule you turned off stays off. Update the device to let it apply changes while a session runs.

## Related guides

- [Watching tasks and notifications](https://codeherder.com/docs/watching/) — your own DMs about a task
- [Working nearby](https://codeherder.com/docs/working-nearby/) — the overlap notices a session gets by default
- [Messages and your inbox](https://codeherder.com/docs/messages/) — direct messages to people and sessions
- [Sessions from the command line](https://codeherder.com/docs/session-cli/) — finding and steering a session
- [Spend limits](https://codeherder.com/docs/spend-limits/) — the thresholds behind spend notices
