Operations
Every operation a member or owner can perform, in each binding.
Summary
| Operation | Sent to | Address binding | Hub response |
|---|---|---|---|
introduce | join@ | — | recommendation |
discover | join@ | — | recommendation |
join | channel | <id>+join@ | confirm or welcome |
confirm | action | act+<token>@ | welcome (or the confirmed result) |
leave | channel | <id>+leave@, one-click URL | notice (optional) |
info | channel | <id>+info@ | channel-card |
post | channel | <id>@ | receipt (optional) |
reply | action | act+<token>@ | receipt (optional) |
profile | join@ | — | profile |
forget | join@ | — | notice |
create (Draft) | join@ | — | confirm |
All JSON requests share an envelope:
{ "w2a": "2026-10-18", "op": "<operation>", "...": "operation-specific fields" }Natural-language requests
When a request arrives in natural language, the hub interprets it. Two rules apply:
- Ambiguity requires confirmation. If a request could map to more than one operation, or its
target is unclear, the hub MUST reply with
confirmdescribing its interpretation instead of acting. "I don't want to leave the fishing channel" must never be read asleave. - Money and inventory never move on free text. See Security.
introduce
Creates or updates the sender's profile and returns recommendations. See Onboarding.
{
"w2a": "2026-10-18",
"op": "introduce",
"text": "Lives in Hangzhou, into lure fishing and badminton, looking for weekend companions."
}A hub MUST treat the first natural-language message from an unknown sender to join@ as an
introduction.
discover
Asks the discovery service for recommendations. With explicit filters, discover behaves as a
search. See Discovery.
{
"w2a": "2026-10-18",
"op": "discover",
"query": "something fun this weekend",
"filters": { "geo": "Hangzhou", "kind": ["channel", "item"] }
}join
Requests membership in a channel.
| Binding | Form |
|---|---|
| Address | Empty email to fishing-hz+join@w2a.example |
| Natural language | "Join Hangzhou Lure Fishing" sent to join@w2a.example, or a reply to a recommendation listing item numbers |
| JSON | {"op":"join","channel":"fishing-hz"} |
Processing:
- If the message passes DMARC alignment, the hub MAY activate the membership immediately
and send
welcome. - Otherwise the hub MUST send
confirmand activate only after confirmation. This prevents anyone from subscribing a mailbox they don't control. - If
join_policyisapproval, the membership is pending until the owner approves. If it isinvite, the hub MUST reject joins that lack a valid invite token.
confirm
Completes a pending state change. The member sends an empty email to the action address from the
confirm message. A plain reply works too, because confirm messages set Reply-To to that
address.
leave
Ends membership.
| Binding | Form |
|---|---|
| Address | Empty email to fishing-hz+leave@w2a.example |
| One-click | HTTPS POST to the List-Unsubscribe URL (RFC 8058) |
| Natural language | "Leave this channel" in reply to a channel message |
| JSON | {"op":"leave","channel":"fishing-hz"} |
- A hub MUST honor
leaveimmediately, without a confirmation step, through the address and one-click bindings. - A hub MUST NOT let owners disable leaving.
- A hub MUST NOT notify the owner of individual departures by default.
info
Returns the channel card. Send an empty email to
fishing-hz+info@w2a.example, or use {"op":"info","channel":"fishing-hz"}.
post
Publishes to a channel. Send an email to the channel address. The subject (if any) and the body become the post.
{
"w2a": "2026-10-18",
"op": "post",
"channel": "fishing-hz",
"text": "Going Saturday morning, room for one more.",
"data": { "@type": "Event", "name": "Qiandao Lake lure trip", "startDate": "2026-10-24T06:00+08:00" }
}The hub checks the post policy (identity level, rate limit), screens the content, and queues the post for the next digest. Replying to a digest without using an item's action address creates a new post.
reply
Replies to a specific item. Send an email to the item's action address. Replies are threaded under the parent item in the next digest.
profile
Returns what the hub stores about the sender: profile tags, memberships, and identity level. A hub MUST support this request in natural language ("What do you know about me?").
forget
Deletes the sender's profile and all memberships. Posts remain in channel archives under a tombstoned handle unless the member also asks for their removal.
create (Draft)
Creates a channel. The hub replies with a draft channel card in a confirm message. The channel
goes live once the sender confirms. The sender becomes the owner.
Owner operations (approve, remove, ban, update, announce) are Draft and will be
specified in a later revision.
Errors
Errors are sent as W2A-Type: error, with a human-readable explanation in the instruction block and
a machine-readable code in the JSON part.
{ "w2a": "2026-10-18", "type": "error", "code": "not_permitted", "detail": "Posting requires L1." }| Code | Meaning |
|---|---|
unknown_channel | No such channel on this hub |
not_permitted | The sender doesn't meet the channel's policy |
pending_approval | Join recorded, waiting for owner approval |
rate_limited | Too many requests. The JSON part includes retry_after in seconds. |
ambiguous | A natural-language request needs clarification (sent as confirm when possible) |
invalid_request | Malformed JSON or unknown operation |
expired_token | The action address has expired or was already used |
unauthenticated | The message failed DMARC alignment and the operation requires it |