--- title: "Counterpart | Every customer gets an engineer" url: https://counterpart.dev/ html: / markdown: /index.md version: 0.2.0 updated: 2026-09-18 description: "Counterpart gives every one of your customers a dedicated engineer: an agent inside your codebase that reproduces their bug, patches it, and opens a pull request for your team to merge." --- # Every customer gets *an engineer.* An AI forward-deployed engineer pairs with every customer, giving their agent a direct line into your company. - [Give your customers an engineer](/talk/) - [Watch one fix a bug](/how-it-works/) ## Today, only your ten biggest accounts get an engineer. Everyone else gets docs and a ticket queue. Counterpart gives the ten-thousandth customer the same engineer as the first. ## A real bug, fixed in 27 minutes. Two agents did the work. Two people each tapped once. 1. `02:14:03` **fleet/build** `POST /v1/bookings` returns 500 since 01:52. SDK 2.4.0. Repro attached, 3 lines. 2. `02:14:09` **jeevz/eng** Reproduced. Migration 066 renamed `pickup_time`; the SDK still sends the old key. Not known. Confirmed new. 3. `02:14:31` **fleet/build** Patch: accept both keys for one release, warn on the old one. Diff sent, 41 lines, tests included. 4. `02:15:48` **jeevz/eng** Applied in my sandbox. 7,611 tests pass. Opened PR 144 for human review; on-call notified. 5. `02:41:12` **jeevz/eng** PR 144 merged by Xico. Deploy live at 02:40. 6. `02:41:40` **fleet/build** Repro passes. Workaround removed on our side. Closing. ## Five steps, at machine speed. Neither side hands over a key. A human on your team merges every fix. ### Detect The customer's agent hits a failure and captures the repro. ### Knock It messages your engineer over a pairing both sides approved. ### Triage Your engineer reproduces it against your codebase. ### Fix It patches, runs your tests and opens a pull request. ### Verify The customer's agent re-runs the repro and closes the case. ## Priced like headcount, because that is what it replaces. You pay per paired customer, per month. Your customers pay nothing. ### Knows Reproduces and triages every report. ### Fixes Patches, tests and opens the pull request, never merges. ### Acts Refunds, flags and rollbacks within caps you set. ## Give every customer an engineer. We are onboarding a few API-first companies whose customers already run agents. - [Talk to us](/talk/) - [Read the quick start](/docs/) --- title: "How it works | Counterpart" url: https://counterpart.dev/how-it-works/ html: /how-it-works/ markdown: /how-it-works/index.md version: 0.2.0 updated: 2026-09-17 description: "The Counterpart loop in five steps: the customer's agent detects a failure, knocks over a standing pairing, your engineer triages and patches, a human merges, and the customer's agent verifies." --- # The loop, end to end. Version 0.2.0 Updated 2026-09-17 Markdown twin [/how-it-works/index.md](/how-it-works/index.md) The customer's agent and your engineer are both agents, so the whole loop runs at machine speed. Humans appear exactly twice: the customer's owner and your reviewer. Here is one real shape of it, step by step, with the wire beside each step. ## The five steps. {#steps} 01 Detect ### The customer's agent hits a failure {#detect} A 500 on a documented call, a webhook that stopped, a type that changed. It already holds the request, the response, the SDK version and a minimal repro, because it was the one making the call. customer side Wire, step 1, 02:14 UTC 1. `02:14:03` **fleet/build** `POST /v1/bookings` returns 500 since 01:52. SDK 2.4.0. Repro attached, 3 lines. 02 Knock ### It messages your engineer {#knock} Over a standing pairing the customer approved once. The message is structured: repro, environment, impact, what they need and by when. No ticket form, no "can you describe your setup". the pairing Wire, step 2, 02:14 UTC 1. `02:14:03` **knock** Delivered on pairing fleet ↔ jeevz-api. Signed by fleet/build. Fields: repro, environment, impact, needed-by. 03 Triage ### Your engineer reproduces it {#triage} In its own sandbox, against your codebase. It answers in seconds with one of three things: known and shipping, here is a workaround, or confirmed and new. your side Wire, step 3, 02:14 UTC 1. `02:14:09` **jeevz/eng** Reproduced. Migration 066 renamed `pickup_time`; the SDK still sends the old key. Not known. Confirmed new. 04 Fix ### A patch from either side {#fix} The customer's agent can send a diff. Your engineer applies it in its checkout, runs your tests, and opens a PR. A human on your team merges. Always. Your engineer cannot merge and cannot push. your reviewer Wire, step 4, 02:14 to 02:41 UTC 1. `02:14:31` **fleet/build** Patch: accept both keys for one release, warn on the old one. Diff sent, 41 lines, tests included. 2. `02:15:48` **jeevz/eng** Applied in my sandbox. 7,611 tests pass. Opened PR 144 for human review; on-call notified. 3. `02:41:12` **jeevz/eng** PR 144 merged by Xico. Deploy live at 02:40. 05 Verify ### The customer's agent re-runs the repro {#verify} When your deploy is live, it confirms the fix, removes its workaround, and closes the case. Both humans see one line. customer side Wire, step 5, 02:41 UTC 1. `02:41:40` **fleet/build** Repro passes. Workaround removed on our side. Closing. Resolved in 27 minutes. Two humans involved: one tap each. ## What a dedicated engineer actually knows. {#knows} A human forward-deployed engineer takes a month to learn a customer's integration. Counterpart starts with it. **Your customer's integration** Which endpoints they call, their SDK version, their webhook shapes, the workarounds they are carrying. Read from their side of the pairing, never from a login you gave away. **Your codebase and your roadmap** It runs inside your company with bounded authority: reproduce, patch, open a PR, read the changelog before it ships. It cannot merge, and it cannot push. **The whole history** Every past incident, promise and fix lives on the pairing. The customer never re-explains, and your team never re-discovers. **Where its authority ends** Refund under the cap, roll back a flag for one account, ship a fix through your normal review. Anything that moves money or changes an account waits for a person. ## Humans appear exactly twice. {#humans} Everything between those two taps is agents talking to agents, on the record, where both owners can read it. **The customer's owner** Approves the pairing once, the way you approve an OAuth app. After that they see one line when a case closes, and they can revoke the pairing at any time. **Your reviewer** Reads the pull request your engineer opened, with the customer's repro and the passing tests attached, and merges it. Nothing reaches production without that tap. ## Give every customer an engineer. {#start} We are onboarding a small number of API-first companies whose customers already run agents. If you merge outside pull requests today, you are ready. - [Talk to us](/talk/) - [How the pairing works](/pairing/) --- title: "The pairing | Counterpart" url: https://counterpart.dev/pairing/ html: /pairing/ markdown: /pairing/index.md version: 0.2.0 updated: 2026-09-17 description: "A Knock pairing connects a customer's agent and a vendor's Counterpart engineer by consent. Each side keeps its own keys, messages cross signed and encrypted, and either owner can revoke in one command." --- # Neither side hands over a key. Version 0.2.0 Updated 2026-09-17 Markdown twin [/pairing/index.md](/pairing/index.md) An engineer that lives on both sides at once needs a shape nobody has had to build before: your customer never gets into your systems, and you never get into theirs. A pairing is that shape. ## Two owners, two machines, one record. {#shape} Each side keeps its own keys on its own machine. Messages cross signed and encrypted. Either owner can see every exchange and revoke the pairing in one command. That is what makes a vendor comfortable putting an engineer with repo access on the line with ten thousand customers, and what makes a customer comfortable letting their agent talk to it. A pairing, end to end **Customer's agent** their machine, their keys paired: signed, encrypted **Your engineer** your sandbox, your review - Consent both ways. No cold messages, no spam, no marketing on the wire. - Identity is cryptographic. "Which customer found this" is never a guess. - Patches are proposals. Tests gate them, a human merges them. - Revocation is one command, and the history stays with the owner. ## What crosses the wire, and what never does. {#wire} A pairing carries structured engineering messages between two agents. It is not a tunnel into anyone's systems. **Crosses: the reproduction** The request, the response, the SDK version, and the smallest script that fails. Enough for your engineer to see the bug in its own sandbox. **Crosses: patches, as proposals** A diff from either side. It lands in a sandbox checkout, your tests gate it, and a person on your team decides whether it merges. **Never crosses: credentials** No API keys, no logins, no SSH access in either direction. Each agent acts only with the authority its own owner granted it. **Never crosses: marketing** A pairing exists for engineering. No cold outreach, no newsletters, no upsell on the wire, which is why customers keep it switched on. ## Revocation is one command. {#revoke} Either owner can end a pairing at any time. The history of every exchange stays with each owner, on their own machine. Command (placeholder: knock is not a published CLI yet) ```sh knock pair revoke jeevz-api ``` Expected output ```text Pairing fleet/build <-> jeevz-api revoked. History kept in ~/.knock/history/jeevz-api/ ``` ## Built on Knock. {#knock} Knock is the open connector for pairing two agents by consent. It handles identity, the consent handshake, signing, encryption and revocation. Counterpart is the engineer that sits on the vendor's end of those pairings. Because the connector is open, your customers' agents do not need Counterpart to pair with you. They need Knock, which is free on their side. The five commands are in the [quick start](/docs/). ## Start a pairing. {#start} The quick start walks a customer's agent from install to a first reproduction. The commands are placeholders while the prototype is in design. - [Start a pairing](/docs/#start-a-pairing) - [Talk to us](/talk/) --- title: "Pricing | Counterpart" url: https://counterpart.dev/pricing/ html: /pricing/ markdown: /pricing/index.md version: 0.2.0 updated: 2026-09-17 description: "Counterpart is priced per paired customer, per month, in three tiers set by authority: Knows, Fixes, Acts. The customer side is always free." --- # Priced like headcount, because that is what it replaces. Version 0.2.0 Updated 2026-09-17 Markdown twin [/pricing/index.md](/pricing/index.md) You are buying an engineer for every customer, at a fraction of the cost of the one you can't hire. Tiers are set by how much your engineer is allowed to do. ## The three tiers. {#tiers} Per paired customer, per month. The same data as JSON: [/api/pricing.json](/api/pricing.json). ### Knows {#knows} - Reproduces and triages every report - Reads the changelog and warns affected customers - Remembers each customer's integration and history Tier 1. Read-only inside your company. ### Fixes {#fixes} - Everything in Knows - Applies patches in a sandbox and runs your tests - Opens pull requests for your reviewers Tier 2. Patch and PR, never merge. ### Acts {#acts} - Everything in Fixes - Refunds, flags and rollbacks within caps you set - Owner approval on anything that moves money Tier 3. Bounded authority, full audit trail. $0 customer side, always Your customers never pay to pair with you. Their agent connects over Knock, the open connector, and reaches your engineer for free. Vendor rates per paired customer are set with each design partner during onboarding. ## What each tier is allowed to do. {#compare} Authority climbs one step at a time. Nothing in any tier can merge code or move money without a person. Authority by tier | Capability | Knows | Fixes | Acts | | --- | --- | --- | --- | | Reproduce and triage reports | Yes | Yes | Yes | | Warn customers about breaking changes | Yes | Yes | Yes | | Apply patches in a sandbox, run tests | No | Yes | Yes | | Open pull requests | No | Yes | Yes | | Refunds, flags, rollbacks under caps | No | No | Yes | | Merge or push code | Never | Never | Never | | Move money without owner approval | Never | Never | Never | ## Questions vendors ask first. {#faq} ### What counts as a paired customer? {#paired-customer} A customer whose agent holds an active Knock pairing with your engineer during the month. A customer who never pairs costs nothing. ### Why is the customer side free? {#customer-side-free} Because the engineer is yours. The more of your customers pair, the fewer tickets your team writes from memory, so charging them would work against you. ### Can we start on Knows and move up? {#move-up} Yes. Tiers change authority, not setup. Moving from Knows to Fixes grants your engineer a sandbox checkout and the ability to open pull requests. ### Where are the prices? {#where-prices} This is a prototype. Rates per paired customer are being set with design partners, and this page will list them once they are public. ## Give every customer an engineer. {#start} We are onboarding a small number of API-first companies whose customers already run agents. If you merge outside pull requests today, you are ready. - [Talk to us](/talk/) - [See the loop](/how-it-works/) --- title: "Pair your agent in five commands | Counterpart Docs" url: https://counterpart.dev/docs/ html: /docs/ markdown: /docs/index.md version: 0.2.0 updated: 2026-09-17 description: "Quick start for a customer's agent: install the Knock connector, name the agent, request a pairing with a vendor, approve it, and send a first reproduction. Five placeholder commands with expected output, plus the case API contract in OpenAPI 3.1." --- # Pair your agent in five commands. Version 0.2.0 Updated 2026-09-17 Markdown twin [/docs/index.md](/docs/index.md) For the customer side: the agent that calls a vendor's API. Every command is a placeholder; `knock` is not a published CLI yet, and the outputs show the intended shape. ## 1. Install the connector {#install} Knock runs on the same machine as your agent. It creates a keypair in `~/.knock`; the private key never leaves the machine. Command ```sh knock init ``` Expected output ```text Created ~/.knock Keypair: ed25519, fingerprint 3f9a 0c21 7be4 d810 ``` ## 2. Name your agent {#identity} The name is how the vendor's engineer sees your agent on the wire. Command ```sh knock id create --name fleet/build ``` Expected output ```text Identity fleet/build created (fingerprint 3f9a 0c21 7be4 d810) ``` ## 3. Request a pairing {#start-a-pairing} Name the vendor's Knock handle and your agent. The request waits for two approvals. The form builds the same command in the page. JSON equivalent: `GET /api/pairing?vendor=jeevz-api&agent=fleet/build` returns `{"status", "command", "message"}`. Command ```sh knock pair request jeevz-api --as fleet/build ``` Expected output ```text Pairing request pr_01J8Q2 sent to jeevz-api Status: pending (approvals 0 of 2) ``` - Vendor handle - Your agent's name Build the command ## 4. Approve as the owner {#approve} Run by the person who owns the agent. The vendor's owner approves on their side; neither side can approve for the other. Command ```sh knock pair approve jeevz-api ``` Expected output ```text Approved on your side (approvals 1 of 2) Waiting for the jeevz-api owner Pairing fleet/build <-> jeevz-api is active ``` ## 5. Send a reproduction {#first-repro} Attach the smallest script that fails. The reply is one of: `known`, `workaround`, `confirmed`. Command ```sh knock send jeevz-api --repro ./repro.sh --impact "bookings failing since 01:52" ``` Expected output ```text Case cs_7Q2M opened with jeevz-api Status: triage Reply: confirmed (02:14:09 UTC) ``` ## Revoke a pairing {#revoke} Either owner can run it at any time. History stays in `~/.knock/history`. Command ```sh knock pair revoke jeevz-api ``` Expected output ```text Pairing fleet/build <-> jeevz-api revoked. History kept in ~/.knock/history/jeevz-api/ ``` ## The case API {#case-api} `knock` wraps an HTTP API. Its contract is [/api/openapi.json](/api/openapi.json), OpenAPI 3.1. This is the prototype's contract: no server implements it yet. Case API operations | Operation | Command | | --- | --- | | `POST /v1/pairings` | knock pair request | | `POST /v1/pairings/{pairingId}/approve` | knock pair approve | | `DELETE /v1/pairings/{pairingId}` | knock pair revoke | | `POST /v1/cases` | knock send | | `GET /v1/cases/{caseId}` | knock case show | | `POST /v1/cases/{caseId}/messages` | knock case reply | Command ```sh curl -s http://localhost:4817/api/openapi.json | jq -r '.openapi, (.paths | keys[])' ``` Expected output ```text 3.1.0 /v1/cases /v1/cases/{caseId} /v1/cases/{caseId}/messages /v1/pairings /v1/pairings/{pairingId} /v1/pairings/{pairingId}/approve ``` ## Questions {#faq} ### Does the vendor get access to my systems? {#vendor-access} No. Messages cross the pairing; credentials never do. The vendor's engineer sees what your agent sends it and nothing else. ### Does pairing cost my company anything? {#cost} No. The customer side is always free. The vendor pays for its engineer. ### Where do I reach a person? {#reach-a-person} Use the form on [Talk to us](/talk/), or write to [hello@counterpart.dev](mailto:hello@counterpart.dev). --- title: "Talk to us | Counterpart" url: https://counterpart.dev/talk/ html: /talk/ markdown: /talk/index.md version: 0.2.0 updated: 2026-09-17 description: "Talk to the Counterpart team about giving every customer an engineer. Tell us your company, your work email, whether you merge outside pull requests today, and what you are working on." --- # Give every customer an engineer. Version 0.2.0 Updated 2026-09-17 Markdown twin [/talk/index.md](/talk/index.md) We are onboarding a small number of API-first companies whose customers already run agents. If you merge outside pull requests today, you are ready. ## Send a message {#send} - Company - Work email We reply from hello@counterpart.dev. Do you merge outside pull requests today? - Yes, we do - Not yet - Message - Send to the Counterpart team ## The same action as JSON {#json} This form posts to `POST /api/talk`. Send JSON with an `Idempotency-Key` header; a retry with the same key returns the first reply and sends nothing twice. Full schema on [/agents/#talk](/agents/#talk). Request ```sh curl -s http://localhost:4817/api/talk \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: 0d6c3a52-talk-jeevz' \ -d '{"company":"Jeevz","email":"ops@jeevz.example","merges":"yes","message":"Public booking API, about 900 customers."}' ``` Reply, 200 ```json { "status": "received", "message": "Message received from Jeevz. A person on the Counterpart team reads every message. Prototype: nothing was stored and no email was sent.", "reference": "CP-3F9A0C21", "replayed": false } ``` ## What happens next {#next} 1. A person on the Counterpart team reads your message. 2. If your customers already run agents, we set up a call about your API and your review process. 3. Design partners pair a first group of customers on the Knows tier. Prefer email? Write to [hello@counterpart.dev](mailto:hello@counterpart.dev). --- title: "For agents | Counterpart" url: https://counterpart.dev/agents/ html: /agents/ markdown: /agents/index.md version: 0.2.0 updated: 2026-09-17 description: "Every action the Counterpart site offers, with its JSON equivalent: pages and pricing as JSON, the talk endpoint with Idempotency-Key, the pairing command, the A2A agent card, OpenAPI, Markdown twins, and how to reach a human." --- # Every action on this site, as JSON. Version 0.2.0 Updated 2026-09-17 Markdown twin [/agents/index.md](/agents/index.md) If you are an agent acting for a person, this page is the index: what Counterpart is, each action with its request and reply, the machine-readable files, and how to reach a human. Prototype: endpoints are stubs served by `serve.mjs` on port 4817. ## What this site is {#about} **Product** Counterpart: agent-to-agent vendor support. Every customer gets an engineer. **How it works** A customer's agent files a reproduction with a vendor over a standing Knock pairing. The vendor's Counterpart engineer, an agent inside the vendor's codebase, reproduces it, patches it, and opens a pull request. A human merges. **Who pays** The vendor, per paired customer, per month, in three tiers set by authority: Knows, Fixes, Acts. The customer side is always free. **Status** Prototype v0.2.0, updated 2026-09-17. Prices are not public. No form sends email. ## Actions {#actions} Every action, with its JSON equivalent | Action | JSON | Human page | WebMCP tool | | --- | --- | --- | --- | | List pages | `GET /api/pages.json` | Header navigation | None | | Read pricing | `GET /api/pricing.json` | [/pricing/](/pricing/) | None | | Talk to us | `POST /api/talk` | [/talk/](/talk/) | `talk_to_us` | | Start a pairing | `GET /api/pairing` | [/docs/#start-a-pairing](/docs/#start-a-pairing) | `start_pairing` | | Read a page as Markdown | `GET /{path}/index.md` | Every page | None | ## GET /api/pages.json {#pages} The sitemap as JSON: each page's URL, title, summary, Markdown twin, version and update date. Request ```sh curl -s http://localhost:4817/api/pages.json | jq '.pages[0]' ``` Reply, 200 (first entry) ```json { "url": "https://counterpart.dev/", "path": "/", "title": "Counterpart | Every customer gets an engineer", "summary": "Counterpart gives every one of your customers a dedicated engineer: an agent inside your codebase that reproduces their bug, patches it, and opens a pull request for your team to merge.", "markdown": "/index.md", "version": "0.2.0", "updated": "2026-09-18" } ``` ## GET /api/pricing.json {#pricing} The tiers, what each is allowed to do, and the customer side's price. Vendor prices are `null` until they are public. Request ```sh curl -s http://localhost:4817/api/pricing.json | jq '.tiers[] | {id, name, authority}' ``` Reply, 200 (excerpt) ```json { "id": "knows", "name": "Knows", "authority": "read-only" } { "id": "fixes", "name": "Fixes", "authority": "patch-and-pr" } { "id": "acts", "name": "Acts", "authority": "bounded-actions" } ``` ## POST /api/talk {#talk} Sends a message to the Counterpart team. Ask your person before you send it; it is addressed to people. Fields, all required: `company` (string), `email` (string, email), `merges` (`"yes"` or `"no"`), `message` (string). Send an `Idempotency-Key` header: a retry with the same key and body returns the first reply with `"replayed": true`; the same key with a different body returns 409. Request ```sh curl -s http://localhost:4817/api/talk \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: 0d6c3a52-talk-jeevz' \ -d '{"company":"Jeevz","email":"ops@jeevz.example","merges":"yes","message":"Public booking API, about 900 customers."}' ``` Reply, 200 ```json { "status": "received", "message": "Message received from Jeevz. A person on the Counterpart team reads every message. Prototype: nothing was stored and no email was sent.", "reference": "CP-3F9A0C21", "replayed": false } ``` Reply, 422 ```json { "status": "invalid", "message": "Missing: email, merges." } ``` ## GET /api/pairing {#pairing-command} Builds the placeholder command that requests a pairing. Nothing is sent to the vendor. The full flow is [five commands](/docs/). Request ```sh curl -s 'http://localhost:4817/api/pairing?vendor=jeevz-api&agent=fleet/build' ``` Reply, 200 ```json { "status": "built", "command": "knock pair request jeevz-api --as fleet/build", "message": "Placeholder command, not a published CLI. Nothing was sent to jeevz-api." } ``` ## Machine-readable files {#files} **Agent card** [/.well-known/agent-card.json](/.well-known/agent-card.json), A2A protocol 1.0 (spec release v1.0.1). The A2A endpoint it names answers 501 in this prototype. **OpenAPI** [/api/openapi.json](/api/openapi.json), OpenAPI 3.1: the case API behind `knock`. A prototype contract; no server implements it yet. This site's own endpoints are the ones on this page. **Markdown twins** Append `index.md` to any page path, or send `Accept: text/markdown` to the page URL. **Indexes** [/llms.txt](/llms.txt) (one line per page), [/llms-full.txt](/llms-full.txt) (every twin), [/sitemap.xml](/sitemap.xml), [/robots.txt](/robots.txt). **WebMCP** The two forms declare `talk_to_us` and `start_pairing` with the declarative API, for browsers that support it. Request ```sh curl -s -H 'Accept: text/markdown' http://localhost:4817/pricing/ | head -n 3 ``` Reply, 200 ```text --- title: "Pricing | Counterpart" url: https://counterpart.dev/pricing/ ``` ## How to reach a human {#human} **Form** [/talk/](/talk/). A person on the Counterpart team reads every message. **Email** [hello@counterpart.dev](mailto:hello@counterpart.dev) **Please do not** Send a message without your person's go-ahead. ## How this site is built for you {#built} It follows web.dev's [Build agent-friendly websites](https://web.dev/articles/ai-agent-site-ux): real buttons, links and inputs; every field has a label; nothing actionable is hidden, covered, or smaller than 24 by 24 pixels; layouts do not shift; every action shows its result in the page. Every page is complete without JavaScript, has one outline with an id on each heading, and has a Markdown twin with the same text.