Skip to content
BrightbeamAIPublic

About

CHAP, the Collaborative Human Agent Protocol, is a MCP/A2A-compatible runtime for auditable human-agent work: approvals, overrides, handoffs, escalation and verifiable evidence logs.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

106 stars

Watchers

1 watching

Forks

Latest commit

 

History

186 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Collaborative Human-Agent Protocol (CHAP)

Latest release PyPI package npm package CI status Specification licensed CC BY 4.0 Code licensed Apache 2.0

The open protocol for humans and agents doing accountable work together.

CHAP gives approvals, overrides, handoffs and escalations a shared, auditable shape across MCP and A2A.

Start here · Install · MCP quickstart · 90-second tour · Scenarios · Implementations · Wiki · Discussions · Paper

Star CHAP on GitHub to help more implementers find and test the protocol


Same scenario, two stacks. Without CHAP: six tools holding fragments of one decision (OpenAI logs expired, Zendesk thread, Slack scrolled past, Linear comments, webhook tail, Notion runbook), 45 minutes across four UIs to answer 'what did the agent draft and why did we approve it?'. With CHAP and its hash chain switched on: three hash-linked envelopes (task.create → artefact → decide.override) joined by prev_hash, one audit.read call, 30 seconds.


You have agents doing real work. Drafting code reviews, triaging tickets, suggesting settlements, reviewing contracts. A human approves, edits, or rejects each one. Right now, that decision lives in your application code, your chat threads, your ticket comments, and your head. When something goes wrong six weeks later, reconstructing what happened costs you forty-five minutes and is half guesswork.

CHAP gives you one place to put those decisions and one shape to put them in. The agent's draft is an artefact. The human's edit is a structured override with a diff, a rationale, and tags you control. Switch the hash chain on, as the tour below does, and each entry carries a hash of the one before it, so audit.verify_chain detects an altered entry as long as you keep a recent chain head where the coordinator's operator cannot change it (SECURITY.md §5). One query over the log replaces grepping across four UIs.

The record survives key rotation, expiring vendor logs, and people leaving; one audit.read call returns the whole thing. The overrides your reviewers were already making accumulate into supervision data you'd otherwise have to commission. When approvals must be non-repudiable, security-signed/1.0, switched on by the requireSignatures option (require_signatures in Python), refuses calls without a valid Ed25519 signature apart from workspace.create and participant.join, and identity-oidc/1.0 can bind the key to a verified identity. Under audit-scitt/1.0, calling audit.submit_to_scitt hands a SCITT statement for each entry to a transparency service through a submitter you supply. And CHAP sits beside MCP and A2A and replaces neither: MCP for tools, A2A for other agents, CHAP for the shared work with humans.

That's the whole pitch.

The 90-second tour

A solo developer using Cursor to review pull requests. The bot flags a "warning" the developer disagrees with. Here's the whole exchange, end to end. The clip below runs in about 23 seconds across six labelled steps; the matching code is right underneath.

Six-step CHAP Core+Review walkthrough with a progress bar and step indicator across the top. Step 1: Setup (workspace, two participants, a task). Step 2: Drafting (agent drafts a response). Step 3: Pending review (review.request with the draft artefact). Step 4: Override (human disagrees: diff, rationale, tags). Step 5: Audit chain (hash-linked replay, prev_hash continuous). Step 6: Two months in (override learning report shows framework-pattern as the top tag, pointing the next prompt revision at the right problem).

And here's the code, every line of it. One continuous story in two languages; pick whichever stack you actually use.

1. Spin up a workspace. An embedded coordinator with SQLite persistence and the hash chain switched on, two participants, a workspace:

TypeScriptPython
import { Coordinator } from "@brightbeamai/chap-coordinator";
import { SqliteStore } from
  "@brightbeamai/chap-coordinator/storage/sqlite";

const coord = new Coordinator({
  store: new SqliteStore("./chap.db"),
  enableChain: true,
});

coord.api.workspace.create({
  workspace: "wsp_pr_reviews",
  profiles:  ["core/1.0", "review/1.0"],
});

coord.api.participant.join({
  workspace: "wsp_pr_reviews",
  from:      "human:me@local",
  type:      "human",
});

coord.api.participant.join({
  workspace: "wsp_pr_reviews",
  from:      "agent:cursor#v1",
  type:      "agent",
});
from chap_coordinator import Coordinator
from chap_coordinator.storage.sqlite \
    import SqliteStore

coord = Coordinator(
    store=SqliteStore("./chap.db"),
    enable_chain=True,
)

def send(method, params):
    return coord.dispatch({
        "jsonrpc": "2.0", "id": method,
        "method": method, "params": params,
    })

send("workspace.create", {
    "workspace": "wsp_pr_reviews",
    "profiles":  ["core/1.0", "review/1.0"],
})

send("participant.join", {
    "workspace": "wsp_pr_reviews",
    "from":      "human:me@local",
    "type":      "human",
})

send("participant.join", {
    "workspace": "wsp_pr_reviews",
    "from":      "agent:cursor#v1",
    "type":      "agent",
})

2. The bot drafts, you override. Wire your existing Cursor integration to emit envelopes:

TypeScriptPython
// The review Cursor returned.
const cursorReview = {
  comments: [{ severity: "warning",
               body: "Unused parameter." }],
};

// The bot's review is the output of a task.
const { task_id } = coord.api.task.create({
  workspace: "wsp_pr_reviews",
  from:      "agent:cursor#v1",
  assignee:  "agent:cursor#v1",
  kind:      "code_review",
  input:     { pr_id: "PR-482" },
});

coord.api.task.complete({
  workspace: "wsp_pr_reviews",
  from:      "agent:cursor#v1",
  task_id,
  output:    cursorReview,
});

coord.api.review.request({
  workspace: "wsp_pr_reviews",
  from:      "agent:cursor#v1",
  task_id,
  artefact:  cursorReview,
  to:        "human:me@local",
});

// You disagree with one comment. Override it.
coord.api.decide.override({
  workspace:        "wsp_pr_reviews",
  from:             "human:me@local",
  task_id,
  intent_preserved: true,
  diff: [{ op: "replace",
           path: "/comments/0/severity",
           value: "info" }],
  rationale: "False positive. Framework " +
             "convention, not a bug.",
  tags: ["false-positive",
         "framework-pattern-misread"],
});
# The review Cursor returned.
cursor_review = {
    "comments": [{"severity": "warning",
                  "body": "Unused parameter."}],
}

# The bot's review is the output of a task.
r = send("task.create", {
    "workspace": "wsp_pr_reviews",
    "from":      "agent:cursor#v1",
    "assignee":  "agent:cursor#v1",
    "kind":      "code_review",
    "input":     {"pr_id": "PR-482"},
})
task_id = r["result"]["task_id"]

send("task.complete", {
    "workspace": "wsp_pr_reviews",
    "from":      "agent:cursor#v1",
    "task_id":   task_id,
    "output":    cursor_review,
})

send("review.request", {
    "workspace": "wsp_pr_reviews",
    "from":      "agent:cursor#v1",
    "task_id":   task_id,
    "artefact":  cursor_review,
    "to":        "human:me@local",
})

# You disagree with one comment. Override it.
send("decide.override", {
    "workspace":        "wsp_pr_reviews",
    "from":             "human:me@local",
    "task_id":          task_id,
    "intent_preserved": True,
    "diff": [{"op":    "replace",
              "path":  "/comments/0/severity",
              "value": "info"}],
    "rationale": "False positive. Framework "
                 "convention, not a bug.",
    "tags": ["false-positive",
             "framework-pattern-misread"],
})

About the surfaces. TypeScript ships a typed facade (coord.api.*) so every method gets full autocomplete and compile-time checks. Python keeps the JSON-RPC envelope shape on the surface (coord.dispatch({...})) and consumers wrap it however suits the call site; a send() helper is the idiom the Python tests use. Both paths emit the same params and the same envelope shape, so the audit chain reads the same whichever client made the call.

3. Two months in, analyse what you've been doing. The reference repo ships an analytics script in both languages that reads the audit chain (over HTTP or straight from your SQLite file) and groups overrides:

# TypeScript reference, against the SqliteStore from step 1:
$ npx tsx reference/core-plus-review/analyze-overrides.ts --db ./chap.db wsp_pr_reviews

# Python reference, same idea:
$ python3 reference/python/analyze_overrides.py --db ./chap.db wsp_pr_reviews

Override Learning Report
========================================
Workspace:       wsp_pr_reviews
Total overrides: 47

By tag:
  false-positive                       ████████████████████   31  (66%)
  framework-pattern-misread            ██████████████          22  (47%)
  cosmetic-pref                        █████                    8  (17%)

Intent breakdown:
  refining (same decision, better wording)   41
  substituting (different decision)          6

Top reviewers:
  human:me@local                            47

Hint: the most common tags are your next prompt revision targets.

Your next prompt revision for Cursor cites the pattern by name instead of guessing at it.

For the full picture, chap-analytics (pip install chap-analytics) projects the whole chain into documented pandas tables, from a SQLite file, a JSON export, a live coordinator or a plain audit.read. The overrides, decisions, reviewers, whispers and handoffs can then be analysed as the supervision dataset they are. A notebook walks a week of review work from the raw envelopes to the tables. The plan for what sits above the tables is in ANALYTICS_ROADMAP.md.


The override envelope, in detail

If you read one shape closely, make it the override envelope. Every field has a job:

Anatomy of a decide.override envelope, with each field annotated: task_id links to the review chain, from carries queryable identity, logical_id survives revision, intent_preserved separates refining from substituting overrides, diff is RFC 6902 JSON Patch, rationale is the 'why' alongside the 'what', tags are structured supervision data.

The two fields most people miss on first read are intent_preserved and tags.

intent_preserved distinguishes a refining override (the human agreed with the agent's decision but rewrote how it was expressed) from a substituting override (the human reached a different decision). These are two different failure modes and they want different fixes. A high refining rate around one policy clause means the agent's retrieval is off; a high substituting rate on the same clause means the policy itself is ambiguous, or the agent's task context is wrong.

tags is the controlled vocabulary your team agrees on. Keep it small. Whatever you put there is the dimension you'll aggregate on three months from now, when you're answering questions like which prompts need work? or which paths is the bot getting consistently wrong?

Install

TypeScript / Node:

npm install @brightbeamai/chap-coordinator

Python:

pip install chap-coordinator

Either package gives you Core and every profile; a new workspace advertises core/1.0 and review/1.0 unless you name others. The TypeScript reference is in reference/; the Python reference is in reference/python/. The TypeScript library lives at packages/coordinator/; the Python library at packages/coordinator-py/.

New here? START_HERE.md gets you to one real decision in about two minutes, with Python and nothing else:

git clone https://github.com/BrightbeamAI/chap.git && cd chap
python3 start-here/start.py

Five-minute hands-on walkthrough with the envelopes in view: examples/00-five-minute-start.md.

Status

CHAP 0.3 is a public draft: a small Core and optional profiles (SPECIFICATION.md). Two reference coordinators, in TypeScript and Python, implement the same methods, and a differential fuzzer checks that they answer and log alike. The conformance harness covers Core and review/1.0 and runs against the Python coordinator and a standalone TypeScript server. A coordinator can present itself as an MCP server or an A2A agent, and five framework bridges put LangGraph, Pydantic AI, AG2, LlamaIndex Workflows, and Google ADK human-in-the-loop decisions on the audit log. The full inventory, the repository layout, and how CHAP relates to MCP and A2A are in ABOUT.md.

Before 1.0 a minor release may break things, and its changelog lists each break with a migration. From 1.0 the specification follows Semantic Versioning (ROADMAP.md, Version numbers). If you need strict stability, wait for 1.0. ROADMAP.md sets out what 1.0 will promise and the milestones that lead to it.

Read this next

If you have not run anything yet, START_HERE.md takes about two minutes. After that, IN_PRACTICE.md, twelve scenarios from a solo developer with Cursor up to GMP-regulated manufacturing; it's the most useful next read. ABOUT.md covers what's in the repo, how CHAP relates to MCP and A2A, the standards it reuses, and how to contribute. core/SPEC.md fits Core on one screen. And the technical report on arXiv grounds the design choices: architecture, profile semantics, threat model, and the twelve scenarios as JSON traces in a worked appendix.

Cite

If you reference CHAP in academic or technical work, please cite the technical report:

@techreport{chap2026,
  author      = {Shahid, Arsalan and Suttie, Gordon and Black, Philip},
  title       = {Collaborative Human-Agent Protocol (CHAP): An open protocol for auditable, structured multi-human and multi-agent collaboration},
  institution = {Brightbeam AI},
  year        = {2026},
  type        = {Technical Report},
  number      = {arXiv:2606.09751},
  url         = {https://arxiv.org/abs/2606.09751}
}

CC BY 4.0 (specification text, see LICENSE-SPEC.md) · Apache 2.0 (everything else) · Any language, any deployment.

About

CHAP, the Collaborative Human Agent Protocol, is a MCP/A2A-compatible runtime for auditable human-agent work: approvals, overrides, handoffs, escalation and verifiable evidence logs.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

106 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages