Lists
FSharp.ATProto provides convenience functions for creating and managing Bluesky lists (moderation, curation, and reference lists) and starter packs.
All examples use taskResult {}. See the Error Handling guide for details.
open FSharp.ATProto.Core
open FSharp.ATProto.Bluesky
open FSharp.ATProto.Syntax
Domain Types
Type |
Fields |
Description |
|---|---|---|
|
|
Reference to a list record |
|
|
Reference to a list item record |
|
|
Reference to a starter pack record |
|
|
Summary of a list |
|
|
A list with its member profiles |
List Purpose
The AppBskyGraph.Defs.ListPurpose DU controls what kind of list you are creating:
Case |
Description |
|---|---|
|
Moderation list -- used to mute or block all members |
|
Curation list -- used for custom feeds and starter packs |
|
General-purpose reference list |
Reading Lists
Function |
Description |
|---|---|
|
Get list details and members |
|
Get lists created by a user (SRTP: |
|
Get posts from a list-based feed |
taskResult {
let! agent = Bluesky.login "https://bsky.social" "handle.bsky.social" "app-password"
// Get lists created by someone
let! page = Bluesky.getLists agent someHandle None None
for list in page.Items do
printfn "%s (%d members)" list.Name list.ListItemCount
// Get a specific list with its members
let! detail = Bluesky.getList agent listUri None None
for m in detail.Items do
printfn " - %s" (Handle.value m.Handle)
}
Managing Lists
Function |
Description |
|---|---|
|
Create a new list (name, purpose, description) |
|
Delete a list |
|
Add a user to a list |
|
Remove a user from a list |
Creating a List and Adding Members
taskResult {
let! agent = Bluesky.login "https://bsky.social" "handle.bsky.social" "app-password"
// Create a curation list
let! listRef =
Bluesky.createList agent
"F# Developers"
AppBskyGraph.Defs.ListPurpose.Curatelist
(Some "People building cool things with F#")
// Add members to the list
let! item1 = Bluesky.addListItem agent listRef.Uri user1Did
let! item2 = Bluesky.addListItem agent listRef.Uri user2Did
// Remove a member later
do! Bluesky.removeListItem agent item1.Uri
// Delete the entire list
do! Bluesky.deleteList agent listRef.Uri
}
List Feed
For curation lists, you can read posts from all list members as a feed:
taskResult {
let! page = Bluesky.getListFeed agent listUri (Some 25L) None
for item in page.Items do
printfn "%s: %s" (Handle.value item.Post.Author.Handle) item.Post.Text
}
Starter Packs
Starter packs are built on top of curation lists. Create a list first, then wrap it in a starter pack:
Function |
Description |
|---|---|
|
Create a starter pack from a list |
|
Delete a starter pack |
taskResult {
let! agent = Bluesky.login "https://bsky.social" "handle.bsky.social" "app-password"
// Create the underlying list first
let! listRef =
Bluesky.createList agent
"Welcome to F# on Bluesky"
AppBskyGraph.Defs.ListPurpose.Curatelist
(Some "Great accounts to follow if you're into F#")
// Add members to the list
let! _ = Bluesky.addListItem agent listRef.Uri user1Did
let! _ = Bluesky.addListItem agent listRef.Uri user2Did
// Create the starter pack wrapping the list
let! starterPackRef =
Bluesky.createStarterPack agent
"F# Starter Pack"
listRef.Uri
(Some "Follow these accounts to get started with F# on Bluesky")
None // optional feed URIs
printfn "Starter pack created: %s" (AtUri.value starterPackRef.Uri)
}
namespace FSharp
--------------------
namespace Microsoft.FSharp
module AtpAgent from FSharp.ATProto.Core
<summary> Functions for creating and authenticating <see cref="AtpAgent" /> instances. </summary>
--------------------
type AtpAgent = { HttpClient: HttpClient mutable BaseUrl: Uri mutable Session: AtpSession option ExtraHeaders: (string * string) list AuthenticateRequest: (HttpRequestMessage -> unit) option RefreshAuthentication: (unit -> Task<Result<unit,XrpcError>>) option OnSessionChanged: (unit -> unit) option }
<summary> Client agent for communicating with an AT Protocol Personal Data Server (PDS). Holds the HTTP client, base URL, optional authenticated session, and extra headers. </summary>
<remarks> Create an agent with <see cref="AtpAgent.create" /> or <see cref="AtpAgent.createWithClient" />, then authenticate with <see cref="AtpAgent.login" />. The agent's <see cref="Session" /> field is mutable: it is updated automatically on login and token refresh. </remarks>
<example><code> let agent = AtpAgent.create "https://bsky.social" let! session = AtpAgent.login "my-handle.bsky.social" "app-password-here" agent </code></example>
module Handle from FSharp.ATProto.Syntax
<summary> Functions for creating, validating, and extracting data from <see cref="Handle" /> values. </summary>
--------------------
type Handle = private | Handle of string override ToString: unit -> string
<summary> A handle (domain name) used as a human-readable identifier in the AT Protocol. Handles are DNS-based names (e.g. <c>my-handle.bsky.social</c>) that resolve to a <see cref="Did" />. They must be valid domain names with at least two segments and a maximum length of 253 characters. </summary>
<remarks> See the AT Protocol specification: https://atproto.com/specs/handle </remarks>
module AtUri from FSharp.ATProto.Syntax
<summary> Functions for creating, validating, and extracting data from <see cref="AtUri" /> values. </summary>
--------------------
type AtUri = private | AtUri of string override ToString: unit -> string
<summary> An AT-URI that identifies a resource in the AT Protocol network. AT-URIs use the scheme <c>at://</c> followed by an authority (DID or handle), an optional collection (NSID), and an optional record key. Format: <c>at://<authority>[/<collection>[/<rkey>]]</c>. Maximum length is 8192 characters. </summary>
<remarks> See the AT Protocol specification: https://atproto.com/specs/at-uri-scheme </remarks>
module Did from FSharp.ATProto.Syntax
<summary> Functions for creating, validating, and extracting data from <see cref="Did" /> values. </summary>
--------------------
type Did = private | Did of string override ToString: unit -> string
<summary> A decentralized identifier (DID) as defined by the AT Protocol. DIDs are the primary stable identifier for accounts. Two methods are currently supported: <c>did:plc:</c> (hosted, managed by PLC directory) and <c>did:web:</c> (self-hosted, DNS-based). </summary>
<remarks> See the AT Protocol specification: https://atproto.com/specs/did and the W3C DID specification: https://www.w3.org/TR/did-core/ </remarks>
<summary> High-level convenience methods for common Bluesky operations: posting, replying, liking, reposting, following, blocking, uploading blobs, and deleting records. All methods require an authenticated <see cref="AtpAgent" />. </summary>
<summary> Get lists created by an actor. Accepts a <see cref="Handle" />, <see cref="Did" />, <see cref="ProfileSummary" />, or <see cref="Profile" />. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="actor">A <see cref="Handle" />, <see cref="Did" />, <see cref="ProfileSummary" />, or <see cref="Profile" />.</param>
<param name="limit">Maximum number of lists to return (optional).</param>
<param name="cursor">Pagination cursor from a previous response (optional).</param>
<returns>A page of <see cref="ListView" /> with an optional cursor, or an <see cref="XrpcError" />.</returns>
val list: ListView
--------------------
type 'T list = List<'T>
<summary> Get a list's details and members. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="listUri">The AT-URI of the list.</param>
<param name="limit">Maximum number of list items to return (optional).</param>
<param name="cursor">Pagination cursor from a previous response (optional).</param>
<returns>A <see cref="ListDetail" /> containing list metadata and member profiles, or an <see cref="XrpcError" />.</returns>
<summary> Extract the string representation of a handle. </summary>
<param name="handle">The handle to extract the value from.</param>
<returns>The full handle string (e.g. <c>"my-handle.bsky.social"</c>).</returns>
<summary> Create a new list. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="name">The name of the list.</param>
<param name="purpose">The list purpose (curate list, mod list, or reference list).</param>
<param name="description">Optional description for the list.</param>
<returns>A <see cref="ListRef" /> on success, or an <see cref="XrpcError" />.</returns>
<summary> Add an account to a list. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="listUri">The AT-URI of the list.</param>
<param name="subject">The DID of the account to add.</param>
<returns>A <see cref="ListItemRef" /> on success, or an <see cref="XrpcError" />.</returns>
<summary>The AT-URI of the list record.</summary>
<summary> Remove an account from a list by deleting the list item record. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="listItemUri">The AT-URI of the list item record to remove.</param>
<returns><c>unit</c> on success, or an <see cref="XrpcError" />.</returns>
<summary>The AT-URI of the list item record.</summary>
<summary> Delete a list. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="listUri">The AT-URI of the list to delete.</param>
<returns><c>unit</c> on success, or an <see cref="XrpcError" />.</returns>
<summary> Get posts from a list feed. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="listUri">The AT-URI of the list.</param>
<param name="limit">Maximum number of posts to return (optional).</param>
<param name="cursor">Pagination cursor from a previous response (optional).</param>
<returns>A page of <see cref="FeedItem" /> with an optional cursor, or an <see cref="XrpcError" />.</returns>
<summary> Create a starter pack. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="name">The name of the starter pack.</param>
<param name="listUri">The AT-URI of the list containing the starter pack members.</param>
<param name="description">Optional description for the starter pack.</param>
<param name="feedUris">Optional list of feed generator URIs to include.</param>
<returns>A <see cref="StarterPackRef" /> on success, or an <see cref="XrpcError" />.</returns>
<summary> Extract the string representation of an AT-URI. </summary>
<param name="atUri">The AT-URI to extract the value from.</param>
<returns>The full AT-URI string (e.g. <c>"at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3k2la3b"</c>).</returns>
<summary>The AT-URI of the starter pack record.</summary>