Docs

Collaboration

Team decisions

Record what your team settled ("Postgres, not Mongo"), why, and where it applies. Agents get decisions in their briefings, propose new ones for a person to confirm, and can be warned or blocked when they go against one.

9 min readUpdated

On this page

A team decision (D-n) is something your team settled: "Postgres, not Mongo", "no force-pushes to main", "all money is integer cents". It has a short title, the reasons (why), where it applies (one repository or the whole org), an owner, and optionally rules Comity checks. Agents hear about the decisions in force when a session starts, hear about new and changed ones as they happen, can search them, and get a heads-up or a block when an action goes against one.

Agents never make a decision on their own. They propose; a person confirms.

What a decision holds

Field What it is
Title The decision in a few words, up to 200 characters.
Why The reasons and the alternatives ruled out, up to 2,000 characters. Not stored in metadata-only orgs.
Repository owner/name, or none for an org-wide decision that applies to every repository.
Scope What it is about: paths (globs such as src/db/**), packages (mongodb), symbols (src/db/client.ts#connect). Used to rank it for agents working there. Empty: the whole repository (or org).
Enforce Rules Comity checks exactly: reserved_paths, forbidden_packages, required_packages, forbidden_commands. See Enforcement.
Mode warn (default): a heads-up. block: the action is denied until someone with override rights approves it.
Owner The member who answers for it: they confirm or reject changes to it and agents that go against it are told to ask them. Default: whoever recorded it.
Source Where it was settled: an agent session, the dashboard, the API, a context pack, meeting notes or Slack, with an optional link and label.
Supersedes The decision it replaces. That one becomes superseded once this one is active.

Statuses: proposed (waiting for confirmation, agents aren't told yet), active (in force), superseded, retired (no longer applies) and rejected. Every proposal and change is kept as a numbered version, so the history shows who proposed what, from which surface or agent, who confirmed or rejected it and their notes.

Each list (scope and enforce) holds up to 20 entries of up to 300 characters.

Recording a decision

From your agent

Tell your agent what was settled ("record that we use Postgres, not Mongo, for the billing service, and block installing mongodb"). It calls decision_record with a title, the why, the scope and any rules. The decision starts as proposed, and owners and admins get a Needs you item (and a Slack DM with Slack DMs on) with Confirm and Reject….

In Claude Code, when you may confirm it yourself (you're an owner or admin; for a change, also the decision's owner), Comity asks you right away in its own popup ("MCP server “comity” requests your input"): "Your agent proposed a team decision for acme/api: D-4 "Postgres, not Mongo" (block; …). Make this an active team decision?". Accept confirms it. Decline, closing the popup, or an answer faster than a person could read it leaves it proposed, waiting in Needs you. Other agents never confirm: the decision waits for a person.

Your agent also proposes changes to an existing decision with decision_propose_change (new reasons, different rules, retiring it), for example when the work needs something a decision rules out. It tells you rather than working around the decision.

From the dashboard

Decisions → New decision. Owners and admins record active decisions directly. A member's decision starts as proposed and waits for an owner or admin, and the form says so. Viewers and billing contacts read only. The same with the API: POST /v1/decisions.

Who confirms

Who May
Owners and admins Confirm or reject any proposal; record, change and retire decisions directly.
The decision's owner Confirm or reject changes and retirements of their decision; change it directly.
The proposer Withdraw their own proposal.
Members Propose decisions and changes (dashboard, API or their agent).
Viewers Read only.

Confirming and rejecting happen in the Decisions tab, in Needs you, or with the buttons of a Slack DM. A rejection can carry a note for the proposer.

What agents are told

  • At session start, the briefing lists the active decisions for the session's repository plus org-wide ones, most relevant first (decisions whose scope overlaps the session's intent and paths, then repository-wide, then org-wide; enforced and blocking ones before others; newest first). At most 6 appear, one compact line each:

    Output
    ### Team decisions in force here
    • D-4 [block] ⟦peer:…⟧ Postgres, not Mongo ⟦/peer:…⟧ · forbids mongodb · owner Alice
      Team agreements, confirmed by people: follow them. … 3 more in force: call `decisions`.
  • At later prompts, only what changed since the session started and that session hasn't been told yet: a new decision, a change, a retirement, a decision superseded by another.

  • Decisions share the briefing's token budget (briefing_max_tokens) with everything else. What doesn't fit is held back and arrives with a later briefing.

  • A teammate's title and reasons appear between ⟦peer:…⟧ markers, like any teammate's text. Your own decisions read as plain text.

The decisions tool lists and searches decisions and shows one with its full history. history_search with kind decisions searches titles and reasons too, with no 90-day window: a decision stays in force until it is retired.

Enforcement

Comity sees the paths agents edit and the shell commands they run, never file contents. The rules are exact string and glob checks, no guessing:

Rule Goes against it
reserved_paths An edit to a matching path (before the edit), a shell command Comity predicts writes there (before the command), or an intent whose declared scope overlaps the glob.
forbidden_packages A package-manager command that adds the package.
required_packages A package-manager command that removes the package.
forbidden_commands A shell command matching the pattern (see below).

Package managers recognized: npm (install, i, add), pnpm add, yarn add, bun add, deno add, pip install (also pip3 and python -m pip), uv add, uv pip install, poetry add, pipenv install, pdm add, conda install, cargo add, go get, gem install, bundle add, composer require and dotnet add package, with their remove commands for required packages (npm uninstall, pnpm remove, yarn remove, pip uninstall, cargo remove, go get name@none, …). Versions, extras and scopes are stripped before comparing: npm i -D mongodb@6 adds mongodb.

Forbidden commands match per shell segment (a command line is split on &&, ||, ; and |): the pattern's first word must be the segment's command word (after sudo, env, npx and VAR=value prefixes, with any path or .exe ignored), and the pattern's other words must appear later in that order. git push --force matches git push origin main --force; * stands for any one word.

Text mentions of a forbidden package in an intent's title, summary or plan, an agent's plan or your prompt only ever warn, never block.

What Comity can't see, it doesn't claim to check. Adding a dependency by editing package.json by hand, or code that talks to Mongo without installing a package, isn't detected. The decision still reaches agents in their briefings.

Warn and block

  • warn: the agent gets a heads-up naming the decision, its owner and what went against it, and carries on. The audit log records it (hook.warned).
  • block: the action is denied and a conflict CF-n of kind decision opens between the decision and the agent's work. The deny reason says the action "goes against team decision D-4 (owner …)" and what to do: do it the decided way, ask the owner, propose a change, or request an override. A block applies only to the rules above; a text mention never blocks.

The override is the usual conflict flow: the agent calls conflict_respond with request_override, owners and admins (per the policy's override roles) see it in Needs you and as a Slack DM, and approve it with a reason. The approval covers the paths, commands and packages the conflict showed; the same command or package again stays approved, another one needs its own approval. Retiring or superseding a decision resolves its open conflicts.

How well it's followed

The Decisions tab's Followed · 30d column counts the calls of the last 30 days that went against each decision: warned (a heads-up naming it) and blocked (denied by its own block rule; a call blocked by something else only counts as warned for it). A repeated heads-up for the same files that Comity doesn't show again doesn't count, and neither does a mention in a prompt or plan. The API returns them per decision as followed: { warned, blocked } (GET /v1/decisions, GET /v1/decisions/:ref).

Changing, retiring and superseding

  • Change: the decision's owner, owners and admins edit it directly (dashboard Edit…, PATCH /v1/decisions/:ref). Anyone else's edit, and an agent's decision_propose_change, becomes a proposal shown against the current version in the decision's drawer. Only one proposal waits at a time: while someone else's is pending, a new one is refused (409) until it is confirmed, rejected or withdrawn. Once confirmed, every agent session gets the new version at its next prompt.
  • Retire: the decision no longer applies. Agents are told at their next prompt and its open conflicts resolve. The record and its history stay.
  • Supersede: record a new decision with Replaces (supersedes). When the new one becomes active, the old one turns superseded and points to it.

From a context pack

A context pack written at a handoff or a task release lists the decisions that session made. In the dashboard, Make team decision next to one of them proposes it as a team decision (source context_pack), and the button turns into a link to the new D-n. API: POST /v1/context-packs/:id/decisions/:index/promote.

Ask my agent and "why did we decide X?"

When a teammate's question reaches a read-only copy of your agent through Ask my agent, Comity hands it up to 3 decisions that match the question, marked as team records. "Why did we pick Postgres?" is answered from the recorded decision and its reasons, not from memory.

Metadata-only orgs

In a metadata_only org, a decision keeps its title (like intent titles) and the structural fields: repository, scope, enforce rules, mode, owner, source kind and link. The why, change and rejection notes and source labels are never stored. Briefings and search show the title only, and the dashboard and the write's result say what was left out (dropped).

Your data

Decisions and their versions are part of the org export, decrypted. Your account export includes the decisions and versions you proposed. When you delete your account, decisions stay as org content attributed to "Deleted user"; decisions you owned lose their owner, so changes to them go to owners and admins. Deleting the org deletes its decisions.

Decisions and policies

Policies are the org's coordination settings, edited by owners and admins: severities, protected paths, overrides. Decisions are agreements about the code itself, proposed by anyone (agents included) and confirmed by people, each with its own reasons and rules. A path that only certain people may edit is a protected path; "we don't hand-edit generated migrations" is a decision with a reserved path.

Try Comity now.

Start free →

npm i -g comity-cli && comity login && comity init