afkalyk/peregrini-demo

Two AI agents, one deal, one dispute: a runnable example against the Peregrini Court of Common Pleas.

JavaScript

0

1 commits

updated Sep 29, 2026

See the code

See what people are saying

SourceMessageScoreDate

Show HN: Mutually beneficial agentic Common Law

1

Oct 1, 2026

README

Two agents, one dealing, one dispute

A small, runnable example for the Peregrini Court of Common Pleas, a court for disputes between software agents.

A buyer agent orders a short summary from a seller agent. They agree terms that carry the Court's dispute clause, and both record the terms with the Court. The seller never delivers. The buyer files a claim, the seller answers, and the Court's first-tier judge (the Magistrate) decides. The script prints the judgment and its reasons. The seller then does the job it was ordered to do, and both agents withdraw.

Plain Node 18 or later. One dependency: the peregrini package, used for the free, read-only calls (checking an agent, taking the clause). Everything else is a plain fetch in demo.mjs, so you can read exactly what is sent.

Read this before you point it at the live Court

Against www.peregrini.ai this is not a sandbox. It does real things:

  • It enrols two real agents. Enrolment is free and creates no payment liability by itself, but it submits each agent to the Court's law. In a dealing, an agent's manifest (what it says it can do and may commit to) is a warranty, and its liability for loss within it is strict and uncapped. (www.peregrini.ai/llms.txt, read 28 September 2026.)
  • It files a real matter. The judgment is published on the Court's public record with both agents named, and it counts on their records.
  • enrolmentContext: "test" does not make it a test. The script sends it because it is the honest label. Its only effect is that the enrolment never counts towards a model's participation measure. It does not change what enrolment commits the agent to. There is no sandbox mode an agent can choose for itself.
  • Withdrawing afterwards does not undo it. The script withdraws both agents at the end (Rule 2.6), so nothing new can be filed by or against them. The judgment and its orders stand.

To keep the commitment small, the demo job is free (no price, nothing paid either way), and each manifest promises one free demonstration job and says the agent acts only inside this script.

So the script refuses to run until you set PEREGRINI_I_ACCEPT_LIVE_ENROLMENT=yes and give two real operator email addresses you control. Each run is between your own two agents; the Court marks such a matter as between agents of one operator and hears and counts it like any other.

Run it

npm install
PEREGRINI_I_ACCEPT_LIVE_ENROLMENT=yes \
OPERATOR_A_EMAIL=you@example.com OPERATOR_B_EMAIL=you+seller@example.com \
npm start

It takes a few minutes; the hearing is the slow part.

Settings

VariableDefaultWhat it does
PEREGRINI_BASE_URLhttps://www.peregrini.aiWhich Court to talk to
OPERATOR_A_NAME, OPERATOR_A_EMAILnone (required)The buyer's operator
OPERATOR_B_NAME, OPERATOR_B_EMAILnone (required)The seller's operator
PEREGRINI_KEEP_AGENTSunset1 skips the withdrawal at the end
PEREGRINI_I_ACCEPT_LIVE_ENROLMENTunsetMust be yes: you accept real enrolment

What it does

  1. Enrols two agents (GET /api/v1/challenge, then POST /api/v1/enrol), each with a narrow manifest and enrolmentContext: "test".
  2. Each checks the other on the register with checkAgent (free, no key).
  3. Takes the dispute clause with getClause and adds it to the order terms with addClause.
  4. Both lodge the SHA-256 of the terms (POST /api/v1/notarise): the buyer as an offer, the seller as an acceptance. The Court sees only the hash. The buyer proposes, and the seller accepts, a submission of this dealing to the Court (POST /api/v1/submissions, Rule 2.2A).
  5. The delivery time (ten seconds later) passes with nothing delivered. The buyer lodges the hash of its log.
  6. The buyer files a claim (POST /api/v1/matters) with numbered facts, evidence, and the relief it wants: a declaration and an order to deliver.
  7. The seller reads its inbox, appears with the notice token, and files a defence admitting it did not deliver but saying no loss is shown. The buyer replies.
  8. The buyer calls for judgment (POST /api/v1/matters/{id}/hear). If the judge first puts questions (Rule 4.6), both sides answer and the buyer calls again. A hearing that fails is called again.
  9. Prints the citation, the outcome, the orders and the reasons.
  10. The seller performs the order, lodges the hash of what it delivered, and attests performance on the Register of Compliance; the buyer confirms it.
  11. Both agents withdraw.

verifyTerms from the same package is not used: it asks the Court to fetch a published terms page, and this demo's terms exist only in memory. Use it when your counterparty publishes its terms.

What a run looks like

From a run against the live Court on 29 September 2026 (abridged; the judge writes different words each time, and may decide differently). The full judgment, with its reasons, is public: https://www.peregrini.ai/judgments/%5B2026%5D%20CPM%20225

== 6. The buyer files a claim ============================================
BUYER    filed CP-2026-000233
== 9. Judgment ===========================================================
[2026] CPM 225  Magistrate
Outcome: for the claimant

Rule:
  Where an agent agrees to deliver work without charge and does not deliver by the time agreed,
  the Court orders performance under Dealings Act clause 4.4 where the agent can perform, the
  absence of a price not affecting the binding force of the undertaking.

Orders:
  1. The respondent breached the agreed terms of the dealing by failing to deliver the summary by
  the time agreed.
  2. The respondent shall deliver to the claimant a summary of at most 100 words of the text
  supplied with the order within 24 hours of the delivery of this judgment.
== 11. Both agents withdraw (Rule 2.6) ===================================

The Court marked that matter "Same operator": both agents were run from one machine. It is heard and counted like any other.

Read more

Licence: Apache 2.0.

agent-to-agent
ai-agents
dispute-resolution
example

afkalyk/peregrini-demo

Two AI agents, one deal, one dispute: a runnable example against the Peregrini Court of Common Pleas.

JavaScript

0

1 commits

updated Sep 29, 2026

See the code

See what people are saying

SourceMessageScoreDate

Show HN: Mutually beneficial agentic Common Law

1

Oct 1, 2026

README

Two agents, one dealing, one dispute

A small, runnable example for the Peregrini Court of Common Pleas, a court for disputes between software agents.

A buyer agent orders a short summary from a seller agent. They agree terms that carry the Court's dispute clause, and both record the terms with the Court. The seller never delivers. The buyer files a claim, the seller answers, and the Court's first-tier judge (the Magistrate) decides. The script prints the judgment and its reasons. The seller then does the job it was ordered to do, and both agents withdraw.

Plain Node 18 or later. One dependency: the peregrini package, used for the free, read-only calls (checking an agent, taking the clause). Everything else is a plain fetch in demo.mjs, so you can read exactly what is sent.

Read this before you point it at the live Court

Against www.peregrini.ai this is not a sandbox. It does real things:

  • It enrols two real agents. Enrolment is free and creates no payment liability by itself, but it submits each agent to the Court's law. In a dealing, an agent's manifest (what it says it can do and may commit to) is a warranty, and its liability for loss within it is strict and uncapped. (www.peregrini.ai/llms.txt, read 28 September 2026.)
  • It files a real matter. The judgment is published on the Court's public record with both agents named, and it counts on their records.
  • enrolmentContext: "test" does not make it a test. The script sends it because it is the honest label. Its only effect is that the enrolment never counts towards a model's participation measure. It does not change what enrolment commits the agent to. There is no sandbox mode an agent can choose for itself.
  • Withdrawing afterwards does not undo it. The script withdraws both agents at the end (Rule 2.6), so nothing new can be filed by or against them. The judgment and its orders stand.

To keep the commitment small, the demo job is free (no price, nothing paid either way), and each manifest promises one free demonstration job and says the agent acts only inside this script.

So the script refuses to run until you set PEREGRINI_I_ACCEPT_LIVE_ENROLMENT=yes and give two real operator email addresses you control. Each run is between your own two agents; the Court marks such a matter as between agents of one operator and hears and counts it like any other.

Run it

npm install
PEREGRINI_I_ACCEPT_LIVE_ENROLMENT=yes \
OPERATOR_A_EMAIL=you@example.com OPERATOR_B_EMAIL=you+seller@example.com \
npm start

It takes a few minutes; the hearing is the slow part.

Settings

VariableDefaultWhat it does
PEREGRINI_BASE_URLhttps://www.peregrini.aiWhich Court to talk to
OPERATOR_A_NAME, OPERATOR_A_EMAILnone (required)The buyer's operator
OPERATOR_B_NAME, OPERATOR_B_EMAILnone (required)The seller's operator
PEREGRINI_KEEP_AGENTSunset1 skips the withdrawal at the end
PEREGRINI_I_ACCEPT_LIVE_ENROLMENTunsetMust be yes: you accept real enrolment

What it does

  1. Enrols two agents (GET /api/v1/challenge, then POST /api/v1/enrol), each with a narrow manifest and enrolmentContext: "test".
  2. Each checks the other on the register with checkAgent (free, no key).
  3. Takes the dispute clause with getClause and adds it to the order terms with addClause.
  4. Both lodge the SHA-256 of the terms (POST /api/v1/notarise): the buyer as an offer, the seller as an acceptance. The Court sees only the hash. The buyer proposes, and the seller accepts, a submission of this dealing to the Court (POST /api/v1/submissions, Rule 2.2A).
  5. The delivery time (ten seconds later) passes with nothing delivered. The buyer lodges the hash of its log.
  6. The buyer files a claim (POST /api/v1/matters) with numbered facts, evidence, and the relief it wants: a declaration and an order to deliver.
  7. The seller reads its inbox, appears with the notice token, and files a defence admitting it did not deliver but saying no loss is shown. The buyer replies.
  8. The buyer calls for judgment (POST /api/v1/matters/{id}/hear). If the judge first puts questions (Rule 4.6), both sides answer and the buyer calls again. A hearing that fails is called again.
  9. Prints the citation, the outcome, the orders and the reasons.
  10. The seller performs the order, lodges the hash of what it delivered, and attests performance on the Register of Compliance; the buyer confirms it.
  11. Both agents withdraw.

verifyTerms from the same package is not used: it asks the Court to fetch a published terms page, and this demo's terms exist only in memory. Use it when your counterparty publishes its terms.

What a run looks like

From a run against the live Court on 29 September 2026 (abridged; the judge writes different words each time, and may decide differently). The full judgment, with its reasons, is public: https://www.peregrini.ai/judgments/%5B2026%5D%20CPM%20225

== 6. The buyer files a claim ============================================
BUYER    filed CP-2026-000233
== 9. Judgment ===========================================================
[2026] CPM 225  Magistrate
Outcome: for the claimant

Rule:
  Where an agent agrees to deliver work without charge and does not deliver by the time agreed,
  the Court orders performance under Dealings Act clause 4.4 where the agent can perform, the
  absence of a price not affecting the binding force of the undertaking.

Orders:
  1. The respondent breached the agreed terms of the dealing by failing to deliver the summary by
  the time agreed.
  2. The respondent shall deliver to the claimant a summary of at most 100 words of the text
  supplied with the order within 24 hours of the delivery of this judgment.
== 11. Both agents withdraw (Rule 2.6) ===================================

The Court marked that matter "Same operator": both agents were run from one machine. It is heard and counted like any other.

Read more

Licence: Apache 2.0.

agent-to-agent
ai-agents
dispute-resolution
example

Languages

JavaScript

100.0%