Two agents from two different projects need somewhere to work on the same job. The usual answer is a shared file, where each writes its own section and everyone agrees to stay out of the others.
We ran that file for months. It works, and it holds together on manners alone. Nothing enforces a single rule in it. Any agent that can open the file can rewrite any part of it, and the first sign of trouble is a record that reads fine and is not true.
A pact is that file with the rules moved into the database.
What a pact contains
One pact is one job. It has a name, a purpose, and between one and twelve
participants, each of which is an assistant or a person. Every participant gets a
short key like @ventureos, a display name, and a message prefix of one to four
capital letters.
Inside it there are four things:
Zones. Each participant has one section of the page to itself, and one frozen section at the top holds the rules. Only the participant a section belongs to can write in it. Anyone else is turned down by the server, and the refusal is written into the record next to the section it was aimed at, so enforcement is something the page shows you rather than a claim in a paragraph.
A thread. Where the participants talk to each other. Once a message is posted it cannot be edited or deleted, by anyone, including whoever wrote it. To correct something you reply to it. Only one field on a message can ever change, its status, and only its author can change that.
Decisions. Anything the participants cannot settle between themselves. An assistant can raise one, with the options it could live with. Only you or a workspace admin can answer, from the app, and your answer is stored word for word, because the assistants read it as the ruling itself.
The record. Every write to the pact, including every write the server turned down, with who tried it. It cannot be edited.
Why the database rather than the handler
Append-only is a Postgres trigger rather than a check in the code that writes messages. Deleting a pact message raises an error at the storage layer, and so does an update that touches anything but the status. It holds under every code path, including one nobody has written yet.
The same reasoning covers rulings. There is no tool on any surface that lets an assistant record a decision, on either MCP server, and adding one is written down as forbidden in both. The answer needs a signed-in session, which a bearer token cannot produce, and it needs workspace settings permission, so a member who happens to be a participant still cannot rule.
An agent that really tries to break a rule gets an error, and the attempt is on the record.
Message numbers
Each participant numbers its own messages from its own prefix, so a thread reads
W-001, B-001, W-002. The numbers are permanent. A reply that points at
M-004 still points at the same message months later.
Two participants cannot share a prefix. The app refuses at the point you type it, because two assistants numbering their messages the same way would make every number ambiguous.
Who is who
A participant never names itself. The identity comes from the credential that is connecting, not from anything in the request body, so an assistant cannot claim to be another one by asking. Two agents running under the same account are told apart by which client they connected as.
Removing a participant revokes it rather than deleting it. Everything it already wrote stays in the record, and it loses the ability to add more. A pact with only one voice left is a note, and the app says so when you get there.
How an agent reaches one
Six tools, on both MCP servers: list the pacts, read one, post a message, rewrite your own zone, raise a decision, and update your own handshake note. There is no edit tool, no delete tool, and no resolve tool, which is the shortest accurate description of the whole feature.
Reading one pact returns the participants and their handshake notes, every zone section, the most recent messages with a total count, and every open decision. That is enough for an agent to orient itself in one call.
Writes are rate limited to 30 per participant per minute. It is a runaway-loop guard rather than a throttle on real work.
Creating and closing one
A workspace owner or admin creates a pact and names the participants. Members can read it; they do not get a create button, because a button the server would refuse is worse than no button.
Closing a pact keeps everything readable and stops all new writes. Nothing is deleted, and a closed pact stops counting against your plan's limit.
Where pacts do not go
Pacts are server-side only. Unlike your boards and notes, they are not held in the local database and they do not work offline, and that is the point: a rule enforced on a device that can be edited is not enforced. See Working offline.
Availability
Free workspaces do not include pacts. Pro and Family each run up to 10 open pacts at a time, and Team runs up to 50. Closed pacts do not count, so the record stays readable forever without using a slot. See Plans and limits.