Docs

Team & admin

Policies

Every coordination policy rule, its default, and how org defaults and repo overrides combine.

On this page

A policy decides how Comity coordinates your agents: whether intents are required, how serious each kind of conflict is, what blocks an edit, which paths are protected, and what gets posted to Slack. Defaults warn rather than block.

Where policies live

  • Org default: applies to every repository.
  • Repo override: rules set for one repository; everything else follows the org default.

The effective policy for a repo is Comity's defaults, overlaid with the org default, overlaid with the repo override. Objects merge key by key (for example severity); arrays and plain values replace.

Owners and admins edit policies in the dashboard under Settings → Coordination policy (pick the scope: Org default or a repository), or with the API. Everyone else sees the policy read-only. Each save creates a new version and a policy.updated event in the audit log. Agents pick up a change on their next hook call.

With the API

Terminal
curl -s https://api.comity.so/v1/policies?repo=acme/api \
  -H "Authorization: Bearer $COMITY_TOKEN"
JSON
{
  "repo_name": "acme/api",
  "org": { "version": 3, "rules": { "require_intent": "auto", "ignore_paths": ["dist/**"] }, "updated_at": "2026-10-12T09:14:03.000Z", "updated_by": "0199…" },
  "repo": null,
  "effective": { "require_intent": "auto", "intent_ttl_hours": 24, "…": "…" }
}

PUT /v1/policies (org default) or PUT /v1/policies?repo=<owner/name> stores a new version for that scope. It needs an owner or admin with the policy:write scope (the dashboard has it; tokens from comity login don't).

Terminal
curl -s -X PUT https://api.comity.so/v1/policies \
  -H "Authorization: Bearer $COMITY_TOKEN" -H "Content-Type: application/json" \
  -d '{"rules": {"require_intent": "auto", "ignore_paths": ["dist/**", "**/*.lock"], "severity": {"path_overlap": "warn"}}}'

Warning

The rules you PUT become the whole stored rule set for that scope; they are not merged with the previous version. Send every rule you want to keep overriding. {"rules": {}} on a repo removes all its overrides. The dashboard re-reads the stored rules and sends only your edits merged into them.

The merged result is validated; an invalid value returns 400 validation with the failing field.

Rules

require_intent

"off" | "auto" | "required". Default "auto".

  • auto: the first prompt of a session auto-drafts a private intent (titled from the prompt's first line). Plans become the intent's plan. The agent confirms it with intent_declare, keeping its number.
  • required: like auto, and an edit (pre_edit) by a session without a declared intent is blocked with: "This repository's policy requires a declared intent before editing. Declare one with the intent_declare MCP tool, then retry."
  • off: no auto-drafts.

intent_ttl_hours

Integer > 0. Default 24. A draft, active or blocked intent with no activity for this long, and no active session working on it, becomes expired.

session_idle_minutes

Integer > 0. Default 30. A session with a hook event within this window is active; quieter sessions are idle. MCP tools without session_id act as your most recent session within this window.

severity

Severity per conflict kind: "info" | "warn" | "block".

Kind Default
path_overlap info
symbol_overlap warn
contract_break warn
textual_merge warn
duplicate_work warn
dependency_order warn
protected_path block

textual_merge and duplicate_work are accepted but no detector produces them today. See Conflicts.

block_contract_break_when_criticality

Array of "low" | "normal" | "high" | "frozen". Default ["high", "frozen"]. A contract break escalates to a block only when the contract's criticality is in this list.

block_min_confidence

Number 0–1. Default 0.85. A finding needs at least this confidence to block; below it, it is downgraded to a warning.

exclusive_max_files

Integer > 0. Default 50. An exclusive path claim (intent mode: "exclusive") only blocks others when it covers at most this many files; a broader claim is treated as shared.

protected_paths

Array of { glob, owners, fail_closed }. Default [].

Field Type Default Notes
glob string Required. Repo-relative glob, e.g. db/migrations/**.
owners string[] [] user:<email>. Other prefixes (such as team:) are rejected with a 400.
fail_closed boolean false Stored, but not enforced: hooks always fail open.

An edit under a protected path produces a protected_path conflict (severity block by default).

JSON
{ "protected_paths": [{ "glob": "db/migrations/**", "owners": ["user:diego@acme.com"] }] }

exclusive_by_default

Array of globs. Default []. Paths matching these are treated as exclusively claimed by whoever edits them first.

ignore_paths

Array of globs. Default []. Ignored by every detector: generated files, lockfiles, build output.

override

Field Default Notes
override.allowed_roles ["owner", "admin"] Roles that may override a conflict. Any of owner, admin, member, viewer, billing.
override.require_reason true When true, an override needs a reason of 3–2,000 characters (after trimming). When false, the reason is optional.

notify

Slack notifications. See Integrations → Slack.

Field Default Notes
notify.slack_events ["conflict.detected:block", "hook.blocked"] <event type> or <event type>:<info|warn|block>; a severity suffix matches that severity and above.
notify.slack_min_severity "warn" Events that carry a severity are only posted at or above this.

fail_mode

"open" | "closed". Default "open". Stored, but not enforced: hooks always fail open (the dashboard labels it "Fail closed is saved but not enforced yet"). See How it works → Fail-open.

briefing_max_tokens

Integer 200–4,000. Default 1500. Size budget of a briefing (about 4 characters per token).

share_session_status

Boolean. Default true. Teammates see each session's latest status (an excerpt of the agent's last message at the end of a turn, plus files touched) in briefings and search. Individual developers can also opt out with COMITY_SHARE_STATUS=0.

cross_repo_contracts

"org" | "projects" | "off". Default "org". Which other repos this repo's contracts (HTTP routes, workspace packages) are matched against:

  • org: every repo in the org whose policy is also org, plus repos in a shared project.
  • projects: only repos that share a project.
  • off: none.

Both repos of a pair must allow it.

arrival_notices

Boolean. Default true. When another developer's agent starts a session in this repo, teammates' agents with a live session here get a one-time notice. See Messaging.

Full default policy

JSON
{
  "require_intent": "auto",
  "intent_ttl_hours": 24,
  "session_idle_minutes": 30,
  "severity": {
    "path_overlap": "info",
    "symbol_overlap": "warn",
    "contract_break": "warn",
    "textual_merge": "warn",
    "duplicate_work": "warn",
    "dependency_order": "warn",
    "protected_path": "block"
  },
  "block_contract_break_when_criticality": ["high", "frozen"],
  "block_min_confidence": 0.85,
  "exclusive_max_files": 50,
  "protected_paths": [],
  "exclusive_by_default": [],
  "ignore_paths": [],
  "override": { "allowed_roles": ["owner", "admin"], "require_reason": true },
  "notify": { "slack_events": ["conflict.detected:block", "hook.blocked"], "slack_min_severity": "warn" },
  "fail_mode": "open",
  "briefing_max_tokens": 1500,
  "share_session_status": true,
  "cross_repo_contracts": "org",
  "arrival_notices": true
}