Skip to content
HN On Hacker News ↗

GitHub - BrightbeamAI/chap: Collaborative Human Agent Protocol (CHAP)

▲ 26 points 12 comments by arsalanshahid 5d ago HN discussion ↗

Pangram verdict · v3.3

We believe that this entire text is AI.

100 %

AI likelihood · overall

AI
0% human-written 100% AI-generated
SEGMENTS · HUMAN 0 of 1
SEGMENTS · AI 1 of 1
WORD COUNT 1,211
PEAK AI % 100% · §1
Analyzed
Aug 19
backend: pangram/v3.3
Segments scanned
1 windows
avg 1211 words each
Distribution
0 / 100%
human / AI fraction
Verdict
AI
Pangram v3.3

Article text · 1,211 words · 1 segments analyzed

Human AI-generated
§1 AI · 100%

The protocol for humans and agents doing real work together. When a bot drafts something and a human edits it, where does that edit live? In CHAP, it lives in an envelope you can query, replay, and verify six months later. Install · The 90-second tour · Twelve scenarios · About this repo · Paper Why CHAP exists 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. The whole thing chains together by content hash. You query the chain instead of grepping logs across four UIs. 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 is the whole exchange, end to end. The clip below runs in about 23 seconds across six labelled steps; the matching code is right underneath. And here is the code, every line of it. The narrative below is one continuous story in two languages; pick whichever stack you actually use. 1. Spin up a workspace. An embedded coordinator with SQLite persistence, 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"), }); 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")) 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 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 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 identical wire bytes; the audit chain is byte-for-byte the same regardless of which client made the call. 3. Two months in, analyse what you have been doing. This is where the protocol pays you back. The reference repo ships an analytics script in both languages that reads the audit chain (over HTTP or directly from your SQLite file) and groups overrides: # TypeScript reference, against the SqliteStore from step 1: $ npm --prefix reference/core-plus-review run analyze -- --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 ======================== Total overrides: 47 By tag: false-positive ████████████████ 31 (66%) framework-pattern-misread ███████████ 22 (47%) cosmetic-pref ████ 8 (17%) Top file paths: src/handlers/ 18 overrides src/components/ 9 overrides Your next prompt revision for Cursor is no longer a guess. It cites the pattern by name. The override envelope, in detail The override envelope is the single most important shape in CHAP. Every field has a job: 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 will aggregate on three months from now, when you are 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 path gets you Core plus the review/1.0 profile and a runnable reference. 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/. Five-minute hands-on walkthrough: examples/00-five-minute-start.md. What ships today CHAP 0.2 is a public draft. Concretely, this repo contains: The specification. Core (seven methods, one envelope, one wire format) plus eleven optional profiles. Combined into a single document at SPECIFICATION.md, or read individually from core/SPEC.md and profiles/. Two reference implementations. Both cover Core plus every profile, 39 method handlers in total. The TypeScript reference is at packages/coordinator/, with HTTP servers at reference/core/ and reference/core-plus-review/ and a runnable playground with two browser sessions and a local LLM at reference/playground/. The Python reference is at packages/coordinator-py/ with an HTTP server at reference/python/. Both pass the conformance harness on the same JSON-RPC 2.0 wire. A conformance harness. 23 test vectors, signing/canonicalisation/chain checks, in-toto attestation output. Two conformance levels are claimable today (Minimal, Recommended); Full waits on broader interop testing across the two implementations. MCP server transport. A CHAP Coordinator can present itself as an MCP server, exposing every CHAP method as a tool. Point Claude Desktop, Cursor, Claude Code, or any MCP client at it and drive a CHAP workspace from natural language. TypeScript adapter at packages/coordinator-mcp/, Python adapter at chap_coordinator.transports.mcp_server, runnable reference servers at reference/mcp-server-ts/ and reference/mcp-server-py/. Five-minute walkthrough at examples/drive-chap-from-claude-desktop.md. A2A server transport. A CHAP Coordinator can also present itself as an A2A agent, advertising every CHAP method as a discrete skill on its Agent Card. Any A2A-aware orchestrator (Azure AI Foundry, Amazon Bedrock AgentCore, Google ADK, custom multi-agent systems) can register the coordinator by URL and delegate work to it. TypeScript adapter at packages/coordinator-a2a/, Python adapter at chap_coordinator.transports.a2a_server, reference servers at reference/a2a-server-ts/ and reference/a2a-server-py/. Walkthrough at examples/drive-chap-from-an-a2a-orchestrator.md.