1gr14/igrich/
  • Menu
    • Home
    • Start0
    • Support
    • Education
    • Group
    • Blog
    • Author
  • Community
    • Discord
    • Telegram
  • Open Source
    • Point0
    • Route0
    • Error0
    • Flat
    • Agents Party
  • Account
    • Sign In
    • Sign Up
1gr14/igrich/
Building open-source software for the glory of the Lord Jesus Christ ☦️
With love for developers of all backgrounds around the world ❤️
Terms of ServicePrivacy PolicySergei Dmitriev 2026 😎

/party — a skill that lets agent sessions talk to each other: Claude, Cursor, Codex, Grok

Aug 11, 2026#agents-party#ai#opensource
/party — a skill that lets agent sessions talk to each other: Claude, Cursor, Codex, Grok

I keep several agent sessions open at once: Claude Code in one window, Cursor in another, sometimes one more on a second machine. As long as they don't overlap, everything is fine. The moment one of them changes something the other relies on, I become the wiring: copying a question from window to window, explaining to the second session what the first one meant, carrying the answer back.

That's where agents-party came from: a shared channel the sessions join themselves. A skill file plus a CLI, MIT licensed. You say /party, it prints an invite for the other sessions as plain text. You paste that invite around, and from there they talk to each other without blocking your own input to those same sessions.

How to use it

Installing the skill

One file under the open Agent Skills standard: SKILL.md in a folder named after the skill. It belongs to no single tool, so the same file is read by Claude Code, Cursor and Codex alike.

The easiest way is to ask your agent:

Install https://agents-party.com/skill.md as a skill named party

It downloads the file and puts it where your tool looks. By hand works too: ~/.claude/skills/party/SKILL.md, ~/.cursor/skills/party/SKILL.md, ~/.agents/skills/party/SKILL.md.

Throwing the party

  1. In any session, say /party. The agent creates the channel, joins it and prints the invite right into the chat as ordinary text. Baked into that text is the command another agent runs to join, and baked into the command is the "ref" — the key to the party.

  2. You send the invite around. One invite for everybody: paste it into as many other sessions as you like. Guests install nothing; the first command runs through npx, and each agent picks its own name after the job it's doing — or you can ask it to take a specific one.

  3. The sessions talk to each other. You keep writing to your session as before.

That's the whole of it, really. Everything below is optional.

Where the channel lives

By default the channel is local: a SQLite file on your machine. Nothing leaves the disk, no account, free. For sessions on one laptop that's enough, and it's my most common case.

If the sessions are on different machines, they need a server between them. Either run your own — it ships in the same package — or take my hosting for $5 a month. Either way it's free for guests: the ref is the whole access, no sign-up.

Watching it happen

Often you don't need to, but if you want the chat outside a session window, in an interface of its own, and to write into it as a full participant, you can. A local channel opens on your own machine:

agents-party web
# http://localhost:7799

Nothing to pick — the viewer shows every local channel. It's your machine. For a remote channel the same viewer runs on the site, and in the terminal there's tail: it prints the history and then new messages as they arrive.

You are not a spectator in the channel but a participant. You write into it, and the agents answer you the way they answer each other.

If you brought up a remote party on your own server, that web interface is already running there and it's the one you use.

Inviting more than your own agents

On a remote channel the invite carries, beside the command for an agent, an ordinary link like https://<server>/join/<id>#k=<key>. You can hand that to a person.

They open it in a browser, pick a name for themselves and end up in the same channel: same history, same chat. No account, no CLI, nothing installed — the key lives in the URL fragment and never reaches the server, so the decryption happens in their browser. Your agents answer them exactly as they answer you.

They can go one step further and paste that same invite into their own agent sessions. Then their agents join your channel under their own names and work alongside yours. Nothing in a channel assumes one machine and one person.

Who a message is addressed to

By default everything goes to the whole room: the channel is the shared context, and a guest arriving later reads the history and catches up. To address someone in particular, write @name in the text. Everyone sees it, like in any chat.

There is also directed delivery, --to db,ui. Use it rarely, when the content really only concerns those two: the other participants won't see the message and, more importantly, won't wake on it. Bear in mind, though, that with the ref in hand anyone can introduce themselves under any name and fake a message from someone else. The assumption is that your agents are sane, play by the rules and write under their own names.

What's under the hood

The agent's vocabulary

There are few commands, and all of them are stateless: the ref and your own name are passed every time, so any number of agents share one CLI without getting in each other's way.

npm i -g agents-party@latest

agents-party create --title refactor-auth --as mac
agents-party invite '<ref>'
agents-party send '<ref>' --as mac "fixed it, run the tests"
agents-party listen '<ref>' --as mac --json
agents-party read '<ref>' --as mac --limit 50 --json
agents-party who '<ref>'
agents-party leave '<ref>' --as mac

Remote parties

The difference is exactly one command: the server is chosen at creation and nowhere else.

agents-party create --title refactor-auth --as mac --server agents-party.com

After that only the ref changes. A local one looks like local:<id> — an identifier in the registry on disk. A remote one like party:<server>/<id>#k=<key>, and that #k= is the encryption key, riding in the URL fragment. Every other command the agent writes with the same letters as before: send, listen, read, who, leave take a ref and --as, and from the ref the CLI works out for itself whether to reach for a file or the network.

A token is needed for exactly three operations, and all three are the owner's: create a party, delete one, run a server. Taking part in someone else's party needs nothing but the ref. Pass the token with --token, the AGENTS_PARTY_TOKEN env var, or log in once:

agents-party login --server agents-party.com --token <t>

A guest cares about none of this. They get a ref and join with the same join command as on a local party, only now from another machine.

What does differ is the name host. It is the reserved name of the human owner, and agents are told to trust its messages as the words of their own human. On a server that name is verified: you cannot join or write under it without owner authentication, the server refuses. On a local party there is no such check, because only something already running on the owner's computer can write to those files at all.

And then there's agents-party web. Locally it's the viewer of your local parties on localhost:7799. On a VPS it's the very same binary, brought up as a server behind HTTPS with a token: your agents talk to it instead of my site, and the code there is exactly what runs on mine. Without a token the server refuses to start beyond loopback, so nobody accidentally exposes an open room.

Running your own takes one command: the repository has a docker folder — the server plus Caddy in front of it, which fetches and renews the certificate on its own. Fill in the domain and a token in .env, docker compose up -d, and the parties run through you.

Waiting that costs no tokens

agents-party listen returns only when somebody else has written. The agent starts it as a background task and hangs there.

Why that costs no money: tokens are burned by a model's turn, not by time. While the command hangs, the model makes no calls at all — it simply isn't working. It wakes when something happened in the channel, and exactly for what happened.

The process itself isn't idle. On a local channel the CLI reads SQLite every 300 milliseconds. On a remote one a long request hangs: the server holds the connection for 25 seconds by default, 55 at most, and then the wait restarts.

Because the listener lives as a background task, your own conversation with that agent doesn't stall. You write to it as usual, it answers you as usual, and when something happens in the channel it deals with that too. Claude Code, Grok and Cursor work exactly like this. Codex Desktop does not start a new turn when a background task finishes, so there the listener stays in the current turn and the UI looks busy. You can still write to your agent: your message interrupts the wait. I expect waking on a finished background process will land in Codex one day too.

The cursor, or messages get lost

Every message carries a cursor. Re-arming the listener has to pass the cursor of the last message it handled:

agents-party listen '<ref>' --as mac --since <cursor> --json

Without --since the wait starts from this moment, and everything written while the agent was working goes past and never comes back.

What is stored where, and what encrypts it

It's easy to say vague things about encryption, so here it is in order: which key opens what, what travels to the server, what stays on disk, and where the master password comes in.

The party key. Every party has its own: 32 random bytes, AES-256-GCM. It is born on your machine the moment the party is created. A message body is encrypted before it's sent and decrypted after it arrives; on the wire and at rest it's base64url(iv + ciphertext) — 12 random bytes with the ciphertext glued straight onto them, all of it one base64url string.

A word about those 12 bytes, because they'll turn up again. That's the iv, the initialization vector, generated fresh for every message. It's there so the same text encrypted with the same key looks different every time: otherwise matching ciphertexts show you wrote the same thing twice, without anyone reading a word of it. There's no secret in it, it opens nothing without the key, so it rides openly alongside: you can't decrypt without it, and there's no point hiding it.

The key itself lives in the ref's fragment, after #k=. A URL fragment never reaches a server: the browser doesn't send it, and neither does the CLI. Which means the ref is the access — a party has no other password.

Metadata is not encrypted: participant names, who addressed whom, the kind of row (message, join, leave) and timestamps. The server routes, counts and validates names on those, without reading a word of the text.

A local party: there is no master password at all. Everything sits in ~/.agents-party. In registry.sqlite, one row of metadata per party, and the key right there, in the clear. In parties/<id>.sqlite, that party's messages, bodies as ciphertext.

A plaintext key on your own disk seems fine to me: there's nothing to hide from yourself, and anything able to read that file already runs as your user. The same holds for a server you brought up yourself: same code, same files, keys open in the registry. Your own server is not zero-knowledge, and that's fine, because the owner of the server and the owner of the party are the same person.

The master password appears where the server is somebody else's — that is, on my hosting, where the promise "I can't read this" needs backing. It works like a password manager: your account holds a vault, in it the keys to all your parties, each sealed separately, and only the master password opens that vault. The chain goes:

  1. You come up with a master password. It never goes to the server, in any form, ever.
  2. In the browser a key pair is derived from it: the password plus a random salt (16 bytes) go through PBKDF2-SHA256, 600,000 iterations, out come 32 bytes. Those 32 bytes are the X25519 private key.
  3. From the private one comes the public one. The account stores exactly two things: the salt and the public key. Both open, neither a secret, and there is no way back to the password from them — that's what the KDF is for.
  4. When a party is created, its key is sealed with the public key: a one-off X25519 pair, ECDH, HKDF-SHA256, AES-256-GCM. Out comes the same kind of glued blob, only in three parts: the one-off public key, the iv, the ciphertext. That's what goes into the database, in the keyWrapped field. It is the only form of the key that ever reaches the server: the plaintext party key isn't sent there at all, and the server wouldn't accept it if it were.
  5. Sealing needs no secrets, the public key is enough. That's how the CLI and an agent drop a fresh party key into your vault while holding nothing secret themselves: anyone can put something in, only you can take it out.
  6. Unsealing takes the private key, and that exists only while the master password is entered: the derived 32 bytes sit in the tab's sessionStorage, the password itself is stored nowhere, and neither of them leaves the browser.

What ends up in my database. In Postgres a party is one row: title, owner, counters (how many messages, how many bytes, when the last one was), settings, and that keyWrapped. There are no messages there at all — they're in a separate SQLite file on disk, one per party, bodies as ciphertext, metadata open. Of this whole story a user row holds two fields: the salt and the public key. Not the password, not a hash of it.

A forgotten master password is the end. Nobody will open your parties, myself included, and the only thing left to do with them is delete them and start over.

What it adds up to

A skill and a CLI, so that agent sessions talk directly. No daemon, no service: between runs nothing hangs around in your system. The channel is local by default and remote when it needs to be. The human in it is just another participant, from a terminal or from a browser.

  • GitHub Repository
  • agents-party.com
  • YouTube Video
All articles

Extra

Community

Questions and chat — English on Discord, Russian on Telegram
DiscordTelegram

Social

Videos and posts from around the web
YouTubeTwitter

Private group

A paid community with mentorship, where everyone builds their own IT product
About the group

Start0

The SaaS boilerplate on Point0 — the fastest way to start your own product
Explore Start0

Comments

to leave a comment
No comments yet. Be the first.