agentsclimarketplace

Kb fediverse following

Skill reiver/vibefed/skills/kb-fediverse-following

A Fediverse & ActivityPub plugin for those wishing to use LLM coding tools for the Fediverse and the Social Web.

Install
npx -y skills add reiver/vibefed --skill kb-fediverse-following

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 8 stars8 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Background knowledge about how following works on the Fediverse, including at the ActivityPub wire-format level. Load when the user asks about implementing follows, the Follow/Accept/Reject/Undo activity flow, locked vs unlocked accounts, the followers and following collections, shared inboxes, delivery of posts to followers, how follower-only posts work, account migration with the Move activity, the manuallyApprovesFollowers flag, pending follow requests, or unfollowing. Also load when reviewing or writing code that handles any of these activity types, or when debugging federation issues related to follows not working correctly.

SKILL.md

12.7 KB, as published. Nobody here has run it

Fediverse Following — Complete Reference

Overview

Following on the Fediverse is a formal ActivityPub handshake, not a simple database write. It involves activity delivery between servers, an explicit approval step, and ongoing delivery of content. Understanding all the steps — and what can go wrong — is essential for correct implementation.


1. The Actor Object

Before any following can happen, each user is represented as an actor — a JSON-LD object served at a stable URL. The actor contains the endpoints and collections needed for the follow flow:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Person",
  "id": "https://example.com/users/alice",
  "preferredUsername": "alice",
  "inbox": "https://example.com/users/alice/inbox",
  "outbox": "https://example.com/users/alice/outbox",
  "followers": "https://example.com/users/alice/followers",
  "following": "https://example.com/users/alice/following",
  "manuallyApprovesFollowers": false
}

Key properties for following:

  • inbox — the URL where activities are POSTed to reach this actor
  • followers — an OrderedCollection of actors who follow this actor
  • following — an OrderedCollection of actors this actor follows
  • manuallyApprovesFollowersfalse = open/unlocked account (auto-accepts); true = locked account (requires manual approval). Defined in the ActivityPub Miscellaneous Terms as as:manuallyApprovesFollowers.

2. The Follow Handshake — Step by Step

Following is a four-message exchange in the general case. For unlocked accounts it collapses to three (the Accept is sent automatically).

Step 1: Alice sends a Follow activity

Alice's server POSTs a Follow activity to Bob's inbox:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://alice.example/activities/follow-1",
  "type": "Follow",
  "actor": "https://alice.example/users/alice",
  "object": "https://bob.example/users/bob"
}
  • The object is the actor being followed (Bob)
  • The actor is the one initiating the follow (Alice)
  • The id should be a unique, dereferenceable URI on Alice's server (though in practice many implementations use non-dereferenceable UUIDs)
  • At this point, Alice's server may add Bob to Alice's following collection tentatively, or wait until the Accept arrives — implementations differ

Step 2: Bob's server receives the Follow

On receiving the Follow in Bob's inbox, Bob's server:

  1. Validates the HTTP Signature on the request (to confirm it came from Alice's server)
  2. Checks whether Bob has manuallyApprovesFollowers: true or false
  3. Either queues a follow request for Bob to approve (locked account), or automatically proceeds to send an Accept

At this stage the follow is pending — Alice is not yet in Bob's followers collection.

Step 3: Bob's server sends an Accept (or Reject)

For unlocked accountsAccept is sent automatically:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://bob.example/activities/accept-1",
  "type": "Accept",
  "actor": "https://bob.example/users/bob",
  "object": {
    "type": "Follow",
    "actor": "https://alice.example/users/alice",
    "object": "https://bob.example/users/bob"
  }
}

The object of the Accept is the original Follow activity (or just its id URI — either form is acceptable).

For locked accounts — Bob manually approves or denies. If denied, a Reject is sent with the same structure:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://bob.example/activities/reject-1",
  "type": "Reject",
  "actor": "https://bob.example/users/bob",
  "object": "https://alice.example/activities/follow-1"
}

Important spec note: Servers MAY choose to not send a Reject at all (e.g. to protect a user's privacy — not rejecting leaks the fact that the account exists). This means the follow request may be silently ignored, leaving Alice's server in an indefinite pending state. Implementations should handle this gracefully.

Step 4: Alice's server receives the Accept

On receiving the Accept:

  • Alice's server adds Bob to Alice's following collection
  • Bob's server adds Alice to Bob's followers collection
  • The follow relationship is now active

From this point on, when Bob creates a post addressed to his followers, his server will deliver it to Alice's inbox.


3. Unfollowing — The Undo Follow

To unfollow, Alice sends an Undo activity wrapping the original Follow:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://alice.example/activities/undo-follow-1",
  "type": "Undo",
  "actor": "https://alice.example/users/alice",
  "object": {
    "type": "Follow",
    "actor": "https://alice.example/users/alice",
    "object": "https://bob.example/users/bob"
  }
}

This is POSTed to Bob's inbox. On receipt, Bob's server removes Alice from Bob's followers collection. Alice's server removes Bob from Alice's following collection.

The spec requires that the Undo and the activity being undone have the same actor. You cannot undo another actor's Follow.


4. The followers and following Collections

Both are OrderedCollection objects. They may be paginated with OrderedCollectionPage. The actor object contains their URLs; fetching those URLs with Accept: application/activity+json returns the collection.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://bob.example/users/bob/followers",
  "type": "OrderedCollection",
  "totalItems": 412,
  "first": "https://bob.example/users/bob/followers?page=1"
}

Implementations may choose to hide the actual members of these collections for privacy (returning totalItems but an empty items array, or omitting first/next page links). This is valid and common.


5. How Content is Delivered to Followers

When Bob creates a public post, his server must deliver it to all his followers. This is where the follow relationship does its work.

Addressing

A public post addressed to followers is typically addressed as:

{
  "to": ["https://www.w3.org/ns/activitystreams#Public"],
  "cc": ["https://bob.example/users/bob/followers"]
}

A followers-only post omits the public audience:

{
  "to": ["https://bob.example/users/bob/followers"],
  "cc": []
}

Delivery mechanics

Bob's server must POST the Create activity to the inbox of every actor in Bob's followers collection. For followers on many different servers, this can mean hundreds of HTTP POST requests.

Shared inbox optimisation

To avoid sending N requests to the same server (when multiple followers are on the same instance), the actor object may declare a sharedInbox:

{
  "endpoints": {
    "sharedInbox": "https://alice.example/inbox"
  }
}

When a sharedInbox is available, the sending server can POST once to that shared inbox instead of once per follower on that instance. The receiving server then fans out internally to all relevant local followers. Mastodon always provides a shared inbox. Using it is optional but strongly recommended for performance.


6. Visibility Levels and the to/cc Fields

The follow relationship determines what appears in a follower's Home timeline. The to and cc fields on activities determine visibility:

Visibilitytocc
Publicas:Publicfollowers collection
Unlistedfollowers collectionas:Public
Followers-onlyfollowers collection(empty)
Direct (mention-only)mentioned actors(empty)

The special URI https://www.w3.org/ns/activitystreams#Public (often written as as:Public) signals that the post is publicly accessible.

Posts addressed to followers-only are only delivered to followers' inboxes, not crawlable publicly. A server receiving such a post should only show it to users who follow the author.


7. Locked Accounts and Pending Requests

When manuallyApprovesFollowers is true:

  • Incoming Follow activities are queued, not immediately accepted
  • The follower sees a "pending" state in the UI
  • The followed user sees a follow request notification
  • They can Accept (sending an Accept activity) or Reject (sending a Reject activity, or silently ignoring it)
  • Until accepted, the follower does NOT receive the account's posts

There is no standard way for a server to query whether a pending follow request has been accepted or rejected — implementations typically rely on eventually receiving an Accept or Reject, or timing out.


8. Account Migration — The Move Activity

ActivityPub does not natively support moving an account between servers, but a convention has emerged (led by Mastodon) using the Move activity and the alsoKnownAs / movedTo properties.

The process

  1. New account declares alsoKnownAs pointing to the old account:

    {
      "type": "Person",
      "id": "https://new.example/users/alice",
      "alsoKnownAs": ["https://old.example/users/alice"]
    }
    
  2. Old account sends a Move activity to all its followers:

    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Move",
      "actor": "https://old.example/users/alice",
      "object": "https://old.example/users/alice",
      "target": "https://new.example/users/alice"
    }
    
  3. Receiving servers (i.e. servers that have followers of the old account) automatically re-issue a Follow from each of those followers to the new account, effectively migrating the follower list.

Important limitations

  • Only followers are migrated — not posts, likes, bookmarks, or lists
  • The old account's posts remain on the old server (or disappear if the server is shut down)
  • Not all implementations support Move — GotoSocial notably lacked support for a time
  • The alsoKnownAs must be set on the new account before the Move is sent from the old account, or receiving servers may reject it

9. Common Implementation Mistakes

  • Not waiting for Accept before adding to following: Adding the followee to following before the Accept arrives means the collection is inaccurate for locked accounts
  • Not handling silent Reject: If a locked account never sends a Reject, the pending state must time out gracefully
  • Not validating HTTP Signatures on incoming Follow activities: anyone could POST a fake Follow to your inbox
  • Sending Accept to the wrong URL: The Accept must be delivered to the inbox of the Follow's actor, not the object
  • Not using sharedInbox: Sending one request per follower per instance instead of using sharedInbox causes serious performance problems at scale
  • Forgetting to handle Undo Follow: When Alice unfollows Bob, Bob's server must remove Alice from the followers collection, or Alice will keep receiving Bob's posts
  • Exposing full followers list without privacy consideration: Some users expect their followers/following lists to be private; implementations should support hiding collection members while still providing totalItems

10. Summary: The Minimum a Correct Implementation Must Do

DirectionActivityRequired action
Outgoing followSend Follow to target's inboxAdd to local pending state
Incoming AcceptReceive in own inboxMove from pending → active; add to following
Incoming Reject (or silence)Receive in own inbox (or timeout)Remove from pending
Incoming FollowReceive in own inboxQueue or auto-accept; send Accept/Reject
Outgoing AcceptSend to follower's inboxAdd follower to followers collection
Outgoing unfollowSend Undo{Follow} to target's inboxRemove from following
Incoming Undo FollowReceive in own inboxRemove actor from followers collection
Delivering postsPOST Create to each follower's inbox (or sharedInbox)

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.