# Fanful Agent Surface

Fanful treats agents as a fourth product surface beside web, iOS, and Android.
The canonical contract is MCP first, then CLI and ChatGPT app layers on the same
tools and resources.

## Available Now

- Developer docs: https://docs.fanful.net
- Developer docs markdown: https://fanful.net/docs.md
- Developers and agents hub: https://fanful.net/developers-and-agents
- Developers and agents hub markdown: https://fanful.net/developers-and-agents.md
- Public overview: https://fanful.net/agents
- Discovery file: https://fanful.net/llms.txt
- Agent SDK starter: https://fanful.net/agent-docs/fanful-agent-sdk-starter.md
- Hosted runtime boundary: https://fanful.net/agent-docs/fanful-hosted-agent-runtime.md
- Agent-ingestion Q&A matrix: https://fanful.net/agent-docs/fanful-agent-ingestion-qa.md
- Community chat manifest: https://fanful.net/api/agent/community-chat
- Embedded-room manifest: https://fanful.net/api/agent/embedded-rooms
- Live-controls manifest: https://fanful.net/api/agent/live-controls
- Live-readiness manifest: https://fanful.net/api/agent/live-readiness
- Creator-commerce manifest: https://fanful.net/api/agent/creator-commerce
- Artist-analytics manifest: https://fanful.net/api/agent/artist-analytics
- Listener-experience manifest: https://fanful.net/api/agent/listener-experience
- Idea-board manifest: https://fanful.net/api/agent/idea-board
- ChatGPT-app readiness manifest: https://fanful.net/api/agent/chatgpt-app
- Action-contracts manifest: https://fanful.net/api/agent/action-contracts
- Workflow-trigger manifest: https://fanful.net/api/agent/workflow-triggers
- Agent-session manifest: https://fanful.net/api/agent/sessions
- Sync-job manifest: https://fanful.net/api/agent/sync-jobs
- Work-log sync feed: https://fanful.net/api/agent/sync-feeds/work-log
- Write-envelope validator: https://fanful.net/api/agent/action-contracts/envelope
- Public MCP endpoint: https://fanful.net/mcp

## Status Glossary

- Manifest-only: Fanful publishes a model-readable HTTP/MCP manifest so agents
  can discover the shape, fields, redactions, and future workflow. It is not an
  executable feature yet.
- Contract-only: Fanful has written down the safety contract for an action,
  including auth, confirmation, audit, idempotency, and redaction rules. The
  action remains blocked until a narrow confirmed write wrapper ships.
- API-only: The server endpoint exists outside the current MCP catalog. Agents
  can use it only with the documented HTTP contract and required scoped
  credentials.

The first runnable MCP server is available locally over stdio and publicly over
stateless Streamable HTTP:

```bash
npm run mcp:server
```

```bash
npm run mcp:smoke:http
```

Smoke it with:

```bash
npm run mcp:smoke
```

The first CLI layer uses the same contracts:

```bash
npm --silent run fanful:cli -- surfaces
```

```bash
npm --silent run fanful:cli -- idea-board
```

```bash
npm --silent run fanful:cli -- action-contracts --audience listener --domain ideas
```

Set `FANFUL_BASE_URL`, `FANFUL_MCP_HTTP_URL`, or pass `--base-url` when testing
against a preview Worker:

```bash
FANFUL_BASE_URL=http://127.0.0.1:8787 npm run mcp:server
```

```bash
FANFUL_MCP_HTTP_URL=http://127.0.0.1:8787/mcp npm run mcp:smoke:http
```

## SDK Starter And Plain HTTP

External agents that do not speak MCP yet can use the provider-neutral
TypeScript example in `examples/fanful-agent-starter/client.ts` or the public
starter at https://fanful.net/agent-docs/fanful-agent-sdk-starter.md. The
starter shows:

- read-only discovery through `/llms.txt`, `/api/agent/listener-experience`, and
  `/api/agent/action-contracts`;
- authenticated creator reads such as `/api/agent/artist-analytics?window=30d`;
- 401 versus 403 handling for missing credentials or missing scopes;
- `agent-write-envelope.v1` validation at
  `/api/agent/action-contracts/envelope` before confirmed write tools;
- workflow-trigger, agent-session, sync-job, ChatGPT-app, MCP, and CLI
  cross-links for clients that need the fuller contract.

Bearer credentials belong in transport headers, environment variables such as
`FANFUL_AGENT_BEARER_TOKEN`, or MCP client config. Do not paste admin tokens,
scoped grants, Stripe ids, checkout URLs, raw media URLs, invite tokens, or raw
private ids into model-visible prompts.

## Hosted Runtime Boundary

The hosted runtime boundary lives at
https://fanful.net/agent-docs/fanful-hosted-agent-runtime.md. Fanful is
external-first today: no arbitrary code or general hosted worker runtime is
enabled. Future hosted workers need a redacted run record, correlation id,
idempotency key, logs, limits, approval state, cancellation, retries, and audit
links before implementation.

## Agent-Ingestion Q&A Matrix

The Q&A smoke matrix lives at
https://fanful.net/agent-docs/fanful-agent-ingestion-qa.md. Use it as the
answer key for what Fanful is, who it is for, how it compares with
Patreon/Circle/Linktree/Shopify, what agents can do, and what remains planned
or blocked.

## Search And Browser-Agent Boundaries

This file, `/llms.txt`, and the markdown mirrors are agent/developer contracts,
not special Google generative-search markup. Google's 2026-05-15 Search
Central guidance says generative AI features still depend on ordinary Search
ranking and quality systems, and that `llms.txt`-style AI text files are not
required for Google Search visibility.

For Google Search, Fanful should keep proving ordinary crawlability,
indexability, page experience, useful non-commodity content, and structured data
where it supports normal rich-result eligibility. #1117, #1131, and #1135 track
that marketing/search evidence.

For browser agents, the public web app still matters. Chrome/web.dev guidance
describes screenshots, raw HTML, and the accessibility tree as the main signals
agents use. Fanful pages should keep actions semantic, labels explicit, layouts
stable, controls visible, and overlays from covering interactive elements.
#1153 completed the first browser-agent UX audit; new regressions should become
focused web/agent issues.

## Agentic Commerce Protocol Watchpoint

Google's Search guidance also points commerce sites toward emerging agentic
experiences such as Universal Commerce Protocol (UCP). Fanful does not expose a
UCP compatibility layer today. Current commerce agent access is through Fanful's
MCP/API manifests, scoped grants, `agent-write-envelope.v1` confirmations,
idempotency, audit correlation, stale-state checks, and redacted responses.

Future UCP/AP2 work should wait until Fanful's own checkout and entitlement
contracts are stable enough to map safely. Track #918 for confirmed
purchase-link checkout intents, #1052 for shared Stripe price and entitlement
management, and #1219 for the UCP documentation watchpoint.

## MCP Tools And Resources

- `fanful_agent_surface_list`: read-only, no-network catalog of current agent
  surfaces and follow-up issues.
- `fanful_agent_manifest_read`: read-only HTTP fetch for the `community-chat`,
  `embedded-rooms`, `live-controls`, `creator-commerce`, `artist-analytics`,
  `listener-experience`, `idea-board`, `chatgpt-app`,
  `action-contracts`, `workflow-triggers`, `agent-sessions`, or `sync-jobs`
  manifest.
- `fanful_listener_community_messages_read`: focused read for the latest
  visible messages in an accessible community channel such as `#general` or
  `#intros`, defaulting to 10 messages.
- `fanful_listener_community_message_post`: confirmed listener write for one
  visible community message or reply after scoped/session listener auth, exact
  public-message confirmation, acknowledged risk, and idempotency checks.
- `fanful_creator_community_channel_create`: confirmed creator/admin write for
  one additional community channel, including optional membership-tier access
  metadata, after exact confirmation, observed channel ids, acknowledged risk,
  idempotency, and audit correlation.
- `fanful_creator_community_channel_update`: confirmed creator/admin write for a
  non-default community channel title, description, archive state, or
  membership-tier access metadata after a fresh channel read and exact
  confirmation.
- `fanful_creator_analytics_read`: focused artist-analytics read. Guest/listener
  calls return `401`/`403`; authorized creator/admin calls include aggregate
  source funnels, top content outcomes, listener cohorts, and recent signal
  types.
- `fanful_agent_action_contracts_read`: read-only HTTP fetch for the #608
  action-contract manifest. Optional `audience` and `domain` filters narrow the
  contract list.
- `fanful_live_readiness_read`: read-only HTTP fetch for listener-safe live
  room, embedded room/webinar, and Listen Along readiness. Optional `eventId`
  and `roomId` focus a specific experience.
- `fanful_live_status_preview`: non-mutating preview for a live-room go-live,
  end, cancel, or scheduled-status transition. It requires environment-gated
  admin credentials and returns readiness, affected surfaces, stale-state guard,
  idempotency, confirmation copy, and audit requirements without updating
  `live_events`, broadcasting sockets, or writing `live_event_admin_actions`.
- `fanful_live_schedule_preview`: non-mutating preview for live-room creates,
  schedule edits, and reschedules. It requires environment-gated admin
  credentials and returns blockers, affected surfaces, stale-state/idempotency
  requirements, confirmation copy, and redacted stream/replay summaries without
  updating `live_events` or writing `live_event_admin_actions`.
- `fanful_creator_live_status_update`: confirmed write for a live-room status
  transition. It requires environment-gated admin credentials and
  `agent-write-envelope.v1` confirmation, idempotency, stale-state, reason, and
  audit correlation before updating `live_events.status`.
- `fanful_listener_entitlements_read`: focused read of a fan's membership tier,
  entitlement flags, purchase summary, and gated experiences. Signed-out calls
  return `sign-in-required`; private reads require a first-party listener
  session or scoped delegated grant with `listener:entitlements:read`.
- `fanful_listener_profile_preferences_read`: focused read of a fan's profile
  basics, email confirmation state, notification channels/categories, and
  community-chat notification routing. Private reads require a first-party
  listener session or scoped delegated grant with both `listener:profile:read`
  and `listener:preferences:read`.
- `fanful_listener_display_name_update`: confirmed write for a fan's visible
  display name. It requires a fresh profile read, exact confirmation text,
  acknowledged risk, idempotency, reason, audit correlation, observed display
  name stale-state guard, and first-party listener session or scoped
  `listener:profile:write` grant.
- `fanful_listener_live_support_preview`: focused read of live-room support
  readiness. It returns `listener.liveSupport`, operation context, principal
  context, and redaction policy so agents can discover a live-room support CTA
  and generic support/donation purchase preview without starting checkout.
- `fanful_member_idea_board_read`: read-only HTTP fetch for visible member
  ideas, signed-in viewer state when available, and admin-redacted review fields
  when authorized.
- `fanful_member_idea_submit`: confirmed listener write for one visible member
  idea. It requires scoped listener auth, exact confirmation, risk
  acknowledgement, idempotency, audit correlation, and reason.
- `fanful_member_idea_vote_toggle`: confirmed listener write for toggling or
  setting the caller's vote on one visible idea.
- `fanful_creator_lesson_price_preview`: non-mutating preview for a lesson or
  coaching price change. It requires environment-gated admin credentials and
  returns service price/policy impact, affected surfaces, Stripe readiness,
  stale-state guard, idempotency, confirmation copy, and audit requirements
  without updating Fanful, Stripe, checkout, or public pages.
- `fanful_creator_lesson_credit_ledger_read`: authorized read-only inspection
  of the redacted lesson-credit ledger health contract through the
  creator-commerce manifest. It returns aggregate credit totals, event-type
  breakdowns, blocked write identifiers, and recent event markers while raw
  student email, user id, booking/purchase ids, Stripe ids, idempotency keys,
  reasons, and metadata stay redacted. Guest and listener callers receive an
  explicit authorization blocker with no partial ledger data.
- `fanful_creator_service_price_policy_update`: confirmed write for a lesson or
  coaching price change. It requires environment-gated admin or scoped creator
  credentials, exact `agent-write-envelope.v1` confirmation, idempotency,
  stale-state, reason, and audit correlation before updating
  `lesson_offerings.price_cents`. It never mutates Stripe directly, and broader
  product, credit, cancellation execution, refund, and entitlement writes remain
  blocked.
- `fanful_creator_shop_product_create`: confirmed write for creating one safe
  shop product. It requires environment-gated admin or scoped creator
  credentials, exact `agent-write-envelope.v1` confirmation, idempotency,
  observed product ids from the latest creator-commerce shop read, reason, and
  audit correlation before inserting one `store_items` row. It can set title,
  description, kind, price cents, active/show-in-shop state, inventory
  tracking/count, public fulfillment note, download display filename/release
  notes, and sort order. It never sets raw download URLs, external URLs, Stripe
  Price ids, checkout sessions, fulfillment execution, orders, refunds, or
  credits.
- `fanful_creator_shop_product_visibility_update`: confirmed write for one
  editable shop product's active/show-in-shop flags. It requires
  environment-gated admin or scoped creator credentials, exact
  `agent-write-envelope.v1` confirmation, idempotency,
  `store_items.updated_at` stale-state guard, reason, and audit correlation
  before mutating only visibility state.
- `fanful_creator_shop_product_details_update`: confirmed write for safe
  existing shop product details. It requires environment-gated admin or scoped
  creator credentials, exact `agent-write-envelope.v1` confirmation,
  idempotency, `store_items.updated_at` stale-state guard, reason, and audit
  correlation before changing title, description, inventory tracking/count,
  fulfillment note, download display filename/release notes, or sort order. It
  never changes price, Stripe mapping, raw download URLs, external URLs,
  product kind/id, checkout sessions, fulfillment execution, orders, or refunds.
- `fanful_creator_shop_product_stripe_price_select`: confirmed write for
  selecting or clearing one compatible app-state Stripe Price mapping on an
  existing shop product. It requires environment-gated admin or scoped creator
  credentials, exact `agent-write-envelope.v1` confirmation, idempotency,
  `store_items.updated_at` stale-state guard, reason, audit correlation, and
  catalog compatibility checks before updating only `store_items.stripe_price_id`.
- `fanful_creator_shop_product_stripe_price_create`: confirmed write for
  creating and selecting one replacement one-time Stripe Price on an existing
  shop product. It requires environment-gated admin or scoped creator
  credentials, exact `agent-write-envelope.v1` confirmation, idempotency,
  `store_items.updated_at` stale-state guard, reason, audit correlation,
  server-side Stripe credentials, and existing Product context before updating
  only `store_items.price_cents` and `store_items.stripe_price_id`.
- `fanful_creator_lesson_policy_update`: confirmed write for one
  artist-default or offering-override lesson policy settings row. It requires
  environment-gated admin or scoped creator credentials, exact
  `agent-write-envelope.v1` confirmation, idempotency,
  `lesson_policy_settings.updated_at` or observed policy id stale-state guard,
  reason, and audit correlation before changing `lesson_policy_settings`. It
  never executes refunds, spends credits, cancels bookings, reopens
  availability, creates bundles, or mutates Stripe.
- `fanful_creator_entitlement_metadata_update`: confirmed write for one
  non-default community channel's tier-access metadata. It requires
  environment-gated admin or scoped creator credentials, exact
  `agent-write-envelope.v1` confirmation, idempotency, a
  `community_chat_channels.updated_at` stale-state guard, reason, and audit
  correlation before changing signed-in or membership-tier access. It never
  creates tiers, changes prices, grants credits, changes paid rooms, resolves
  entitlement groups, revokes memberships, or edits chat messages.
- `fanful://agent/surfaces`: resource form of the surface catalog.
- `fanful://agent/community-chat/manifest`: guest/listener-safe community chat
  manifest.
- `fanful://agent/embedded-rooms/manifest`: guest/listener-safe embedded-room
  manifest.
- `fanful://agent/live-controls/manifest`: guest/listener-safe live-controls
  manifest with admin operation descriptors and non-mutating status previews.
- `fanful://agent/live-readiness/manifest`: listener-safe readiness for live
  rooms, embedded rooms/webinars, and Listen Along, including joinability,
  blockers, next actions, and redacted media/invite handles.
- `fanful://agent/creator-commerce/manifest`: public commerce reads plus
  admin-redacted creator commerce/coaching state, authorized publisher referral
  terms/status, redacted lesson-credit ledger health, and service price/policy
  readiness, including confirmed lesson price, Stripe Price mapping, membership
  tier lifecycle, shop product visibility/details/Stripe Price writes, and
  community channel tier-access metadata descriptors when authorized.
- `fanful://agent/artist-analytics/manifest`: read-only artist analytics
  contract for creator/admin automation clients. Guest calls return `401`,
  listener-only calls return `403`, and authorized clients see aggregate source
  funnels, top content outcomes, listener cohorts, and recent signal types while
  raw listener rows, Better Auth ids, anonymous ids, session ids, device ids,
  raw referrer query strings, and raw event logs stay redacted.
- `fanful://agent/listener-experience/manifest`: public listener/fan state plus
  focused `profilePreferences` and `entitlementStatus`, signed-in account,
  library, playback, notification, and Listen Along summaries with raw listener
  ids, Better Auth user ids, membership ids, media URLs, device ids, push tokens,
  invite tokens, and payment identifiers redacted.
- `fanful://agent/idea-board/manifest`: member idea-board manifest with visible
  ideas, vote counts, signed-in viewer state, admin-redacted review fields, and
  confirmed listener submit/vote operations. Creator review/settings writes
  remain contract-only.
- `fanful://agent/chatgpt-app/manifest`: ChatGPT app readiness manifest. It
  maps the current MCP tools/resources to OpenAI Apps SDK requirements, records
  that Fanful is not yet submitted as a ChatGPT app, and names scoped
  delegated-grant authorization, read-only descriptor metadata,
  profile display-name write readiness, confirmation/audit, and optional widget work
  still needed.
- `fanful://agent/action-contracts/manifest`: action-contract manifest for
  listener, fan, creator, and operator actions. It records auth modes,
  confirmation, audit, idempotency, rate-limit, and redaction expectations.
- `fanful://agent/workflow-triggers/manifest`: signed webhook trigger catalog
  for event-driven agents. It records payload schemas, deterministic samples,
  HMAC signature headers, retry/idempotency guidance, and redaction boundaries.
  The authenticated subscription registry is ready at
  `/api/agent/workflow-triggers/subscriptions`, and trusted callers can send a
  manual signed test delivery to an active subscription. Visible
  `member.idea.submitted` events now fan out automatically to active matching
  subscriptions; other trigger families remain manual-test-only or
  manifest-ready.
- `fanful://agent/sessions/manifest`: external agent run/session contract. It
  records multi-step workflow identity, redacted event replay, pending
  approvals, completed tool calls, cancellation, and the migration path from
  stateless MCP calls to durable session history. Durable storage is not enabled
  yet.
- `fanful://agent/sync-jobs/manifest`: cursor-based sync-job contract. It
  records imported-data sources, target boundaries, opaque cursors, redacted
  checkpoints, duplicate-safe resumes, stats, error shape, and drift-report
  policy. The first authenticated worker now runs Stripe catalog app-reference
  drift checks and persists redacted durable run records; arbitrary hosted
  provider workers remain separate future work. It links the first available
  public feed, `GET /api/agent/sync-feeds/work-log`, for deterministic work-log
  upserts after an opaque cursor.
- Hosted runtime boundary: workflow triggers notify agents, agent sessions
  record redacted run history, sync jobs define checkpoints, MCP and HTTP
  manifests expose capabilities, and action contracts stay mandatory before any
  future Fanful-hosted worker calls a write wrapper.

## ChatGPT App Readiness

The current ChatGPT-app slice is executable as a manifest, not as a submitted
ChatGPT app. OpenAI Apps SDK docs make MCP the required app backbone and the web
component optional. Fanful therefore keeps MCP as the portable contract first:
ChatGPT-specific widgets should layer onto the same tools and resources used by
Codex, Claude Code, CLI, and other MCP clients.

Fanful now serves the MCP server over public HTTPS at `/mcp`. That endpoint is
stateless and starts with the same safe read-only, preview, and confirmed-write
tools as the local stdio server. Private creator/listener reads use the #810 scoped
delegated-grant model: a Better Auth human session approves a named client and
scopes, the client exchanges a one-time code for an opaque bearer token, and the
token travels in transport headers or MCP client config rather than tool input.
Grant storage now exists, `/mcp` plus the agent HTTP manifests can resolve
scoped bearer grants server-side, and first-party approval codes can be
exchanged for bearer credentials. Users can inspect and revoke active grants
from account settings before private ChatGPT/MCP clients are broadly enabled.
The read-only MCP tools also advertise Apps SDK descriptor
`_meta` for no-auth discovery and invocation copy, without claiming widget
templates. Confirmed MCP mutating tools, including listener display-name
updates, consume the shared write envelope; ChatGPT app submission still needs
first-party auth, confirmation widgets, and review assets before exposing them
as public app tools.

## Action Contracts

The #608 action-contract surface is executable as:

```bash
curl https://fanful.net/api/agent/action-contracts
```

or through MCP:

```json
{"name":"fanful_agent_action_contracts_read","arguments":{"audience":"creator","domain":"live"}}
```

Use this before adding mutating tools. It classifies action families as ready,
preview-ready, contract-only, blocked, or deferred, then names the auth,
confirmation, audit, idempotency, rate-limit, and model-visible redaction
requirements that must hold across MCP, CLI, ChatGPT app, web, iOS, and Android.

Validate a proposed write envelope without executing anything:

```bash
curl -X POST https://fanful.net/api/agent/action-contracts/envelope \
  -H 'content-type: application/json' \
  --data '{"contractId":"creator.commerce.preview-and-update","actor":{"role":"artist-admin","id":"artist-admin-laurel","displayName":"Laurel"},"client":{"id":"codex-ax","kind":"codex","name":"Agent Experience (AX)"},"action":{"requested":"creator.commerce.preview-and-update","mode":"validate"},"target":{"type":"lesson-offering","id":"lesson-private-coaching","summary":"Laurel coaching price to $200"},"dryRun":true,"confirmation":{"text":"I confirm creator.commerce.preview-and-update for Laurel coaching price to $200.","acknowledgedRisk":true},"idempotencyKey":"creator-commerce-preview-001","reason":"Validate agent envelope before any commerce write.","auditCorrelationId":"audit-correlation-001"}'
```

The validator returns `executable: false`. It proves the shared
`agent-write-envelope.v1` shape, exact confirmation copy, idempotency key, and
audit correlation before future write tools are enabled.

## Workflow Triggers

The #1112/#1523/#1531/#1537 workflow-trigger surface is executable as a read
manifest plus an authenticated subscription registry, manual signed test
delivery, and `member.idea.submitted` runtime fan-out:

```bash
curl https://fanful.net/api/agent/workflow-triggers
curl https://fanful.net/api/agent/workflow-triggers/subscriptions
```

or through MCP:

```json
{"name":"fanful_agent_manifest_read","arguments":{"surface":"workflow-triggers"}}
```

Use workflow triggers when an authorized external agent should react to Fanful
events without polling, such as live-room readiness changing, support checkout
completion, member idea submission, community moderation escalation, or creator
catalog drift. Use MCP reads when an agent is answering an on-demand question or
needs fresh state before a confirmed write.

Trigger payloads are intentionally compact and redacted. Agents must verify the
signature, use event/delivery ids for retry idempotency, and read the linked
Fanful manifest before acting. A trigger does not authorize a write by itself;
public, destructive, checkout, moderation, creator-speech, and billing-impacting
actions still require a ready action contract and the shared confirmed-write
envelope.

The first runtime trigger records cover live-readiness changes,
support-checkout completion, visible member idea submission, community
moderation escalation, and catalog drift detection. When an admin or confirmed
agent live action creates, schedules, configures, or changes a live event
status, Fanful stores a signed, redacted
`agent-workflow-trigger.live-room-readiness.v1` record on the live-event audit
row. Agents can inspect recent visible-room delivery status through
`GET /api/agent/live-readiness` before reading the linked current-state
manifest. When an agent-started support checkout first reaches a paid Stripe
state, Fanful stores a signed, redacted
`agent-workflow-trigger.support-checkout.v1` record on the existing checkout
intent. Agents can read that status through `listener.purchase-link.status`.
When a verified listener submits a visible idea, Fanful generates a deterministic
signed `agent-workflow-trigger.member-idea.v1` record that creator agents can
inspect through `GET /api/agent/idea-board`. When an admin or approved
automation flags, hides, or restores a community message, Fanful stores a signed
`agent-workflow-trigger.community-escalation.v1` record on the
community-chat audit row. Creator/operator agents can inspect redacted recent
escalation status through `GET /api/agent/community-chat` before reading the
linked current-state manifest. Hidden ideas, raw user ids, voter ids, reviewer
ids, and private admin notes stay out of guest/listener trigger status; raw
community message bodies, moderation notes, admin tokens, and agent bearer
tokens stay out of community-escalation trigger status; stream URLs, provider
tokens, invite tokens, and raw listener ids stay out of live-readiness trigger
status. The first subscription registry is available at
`/api/agent/workflow-triggers/subscriptions` for trusted scoped agents or
operator credentials to list, create, pause, resume, delete webhook
destinations, and send `send_test_delivery` manual signed payloads. Registry
reads redact endpoint paths and never return signing secret material. Manual
test deliveries write redacted `agent-workflow-trigger-deliveries.v1` audit rows
and update subscription last-delivery metadata so agents can verify signature,
idempotency, and retry handling. Active subscriptions that include
`member.idea.submitted` now receive first-attempt signed runtime deliveries when
visible ideas are submitted. Live, checkout, community escalation, and catalog
drift subscriptions remain manual-test-only until future #1223 slices.

## Agent Sessions

The #1113/#1177 agent-session surface is executable as a read-only manifest
with deterministic sample event-log readback:

```bash
curl https://fanful.net/api/agent/sessions
curl https://fanful.net/api/agent/sessions/agent-session-creator-live-0001/events
curl 'https://fanful.net/api/agent/sessions/agent-session-creator-live-0001/events?cursor=agent-session-creator-live-0001:2'
```

or through MCP:

```json
{"name":"fanful_agent_manifest_read","arguments":{"surface":"agent-sessions"}}
```

Use agent sessions when work spans more than one tool call, needs approval
tracking, should survive a client reconnect, or should be inspectable by a
creator, listener, operator, or support UI. Use stateless MCP reads for one-shot
answers. Use workflow triggers to wake an agent, then attach follow-up work to a
session before requesting approvals or writes.

`POST /api/agent/sessions`,
`POST /api/agent/sessions/{sessionId}/messages`,
`PATCH /api/agent/sessions/{sessionId}/approvals/{approvalId}`, and
`POST /api/agent/sessions/{sessionId}/cancel` return structured
`agent_sessions_storage_not_enabled` responses until durable session storage is
enabled. These responses name the expected request contract without echoing
request bodies, bearer tokens, grant ids, Better Auth ids, raw listener ids,
Stripe ids, private message bodies, or admin credentials.

Session events are intentionally redacted. They should carry sequence/cursor
fields, actor kind, summaries, contract ids, idempotency/audit correlation, and
redaction notices. They should not carry raw listener ids, Better Auth ids,
Stripe ids, media URLs, invite tokens, provider secrets, private message bodies,
or admin credentials. A pending approval is not write authorization by itself;
the current action contract and `agent-write-envelope.v1` still need to validate
immediately before any write executes.

## Sync Jobs

The #1114/#1224 sync-job surface is executable as a manifest plus an
authenticated first-party manual worker:

```bash
curl https://fanful.net/api/agent/sync-jobs
```

Run the Stripe catalog app-reference drift worker with creator/admin or
approved automation credentials:

```bash
curl -X POST https://fanful.net/api/agent/sync-jobs \
  -H 'authorization: Bearer <scoped-agent-or-admin-token>' \
  -H 'content-type: application/json' \
  --data '{"action":"run_stripe_catalog_app_reference_sync","jobId":"sync-job-stripe-catalog-app-references-0001","idempotencyKey":"sync-catalog-2026-05-16","auditCorrelationId":"audit-sync-catalog-2026-05-16"}'
```

Read a durable run by idempotency key:

```bash
curl 'https://fanful.net/api/agent/sync-jobs?jobId=sync-job-stripe-catalog-app-references-0001&idempotencyKey=sync-catalog-2026-05-16' \
  -H 'authorization: Bearer <scoped-agent-or-admin-token>'
```

The #1176 work-log feed is the first concrete cursor feed:

```bash
curl 'https://fanful.net/api/agent/sync-feeds/work-log?limit=10'
```

or through MCP:

```json
{"name":"fanful_agent_manifest_read","arguments":{"surface":"sync-jobs"}}
```

```json
{"name":"fanful_sync_job_run","arguments":{"idempotencyKey":"sync-catalog-2026-05-16","auditCorrelationId":"audit-sync-catalog-2026-05-16","useAdminCredential":true}}
```

```json
{"name":"fanful_sync_job_status_read","arguments":{"idempotencyKey":"sync-catalog-2026-05-16","useAdminCredential":true}}
```

Use sync jobs when imported creator/catalog data needs a durable checkpoint,
cursor, drift report, or retry explanation. The first implemented worker is a
Stripe catalog app-reference drift scan that reports redacted checkpoint state
and duplicate-safe resume behavior without accepting provider credentials,
creating Stripe objects, changing entitlements, or exposing raw payment
identifiers from an agent.

Sync output is current-state context, not write authorization. Agents should
store opaque cursors exactly as returned, expect overlapping resume pages, count
duplicate records instead of replaying writes, and read current action contracts
before proposing any billing, entitlement, media, or creator-facing changes.
Catalog drift findings link to `creator.catalog.drift.detected` trigger records,
the current sync-job manifest, and the creator-commerce action contract so an
agent can summarize drift without writing back to Stripe or Fanful state.
For the work-log feed, store `cursor.next`, replay with the same cursor when a
page fails, and skip duplicates by `idempotencyKey`. Deletes are not public sync
events yet, so the feed reports no tombstones.

## Idea Board

The #602/#1702 idea-board surface is executable as:

```bash
curl https://fanful.net/api/agent/idea-board
```

or through MCP:

```json
{"name":"fanful_member_idea_board_read","arguments":{}}
```

Guest reads include visible ideas, public board settings, and vote counts.
Signed-in first-party sessions can add viewer vote and ownership state. Admin
or approved automation credentials can read hidden ideas and review fields, but
raw user ids, voter ids, reviewer ids, and private admin notes stay redacted
from guest/listener output.

Confirmed listener writes are executable through:

```json
{"name":"fanful_member_idea_submit","arguments":{"title":"Add a backstage Q&A","body":"Let members propose questions before a livestream.","targetSummary":"new public idea \"Add a backstage Q&A\"","confirmationText":"I confirm member.ideas.submit-and-vote for new public idea \"Add a backstage Q&A\".","acknowledgedRisk":true,"idempotencyKey":"idea-submit-2026-05-20-001","auditCorrelationId":"audit-idea-submit-2026-05-20-001","reason":"Listener asked the agent to submit this idea."}}
```

```json
{"name":"fanful_member_idea_vote_toggle","arguments":{"ideaId":"<idea-id>","desiredSelected":true,"targetSummary":"upvote idea \"Add a backstage Q&A\"","confirmationText":"I confirm member.ideas.submit-and-vote for upvote idea \"Add a backstage Q&A\".","acknowledgedRisk":true,"idempotencyKey":"idea-vote-2026-05-20-001","auditCorrelationId":"audit-idea-vote-2026-05-20-001","reason":"Listener asked the agent to upvote this idea."}}
```

Creator review/status/visibility/settings changes remain contract-only until
dedicated wrappers consume before/after diffs, confirmation, client
attribution, audit correlation, and idempotency.

## Live Readiness

The #807 live-readiness surface is executable as:

```bash
curl https://fanful.net/api/agent/live-readiness
```

or through MCP:

```json
{"name":"fanful_live_readiness_read","arguments":{"eventId":"optional-live-event-id"}}
```

Preview a creator/admin live status transition without writing:

```json
{"name":"fanful_live_status_preview","arguments":{"eventId":"laurel-studio-room","nextStatus":"live","useAdminCredential":true}}
```

Preview a creator/admin live schedule change without writing:

```json
{"name":"fanful_live_schedule_preview","arguments":{"eventId":"laurel-studio-room","title":"Laurel Studio Room","status":"scheduled","startsAt":"2026-10-07T19:00:00.000Z","streamProvider":"none","chatEnabled":true,"subscriberOnly":false,"useAdminCredential":true}}
```

Execute a confirmed creator/admin live status transition after a fresh preview:

```json
{"name":"fanful_creator_live_status_update","arguments":{"eventId":"laurel-studio-room","nextStatus":"live","observedUpdatedAt":"<preview stateGuard.observedUpdatedAt>","targetSummary":"Laurel Studio Room go-live","confirmationText":"I confirm creator.live.schedule-and-status for Laurel Studio Room go-live.","acknowledgedRisk":true,"idempotencyKey":"live-status-laurel-studio-room-live-2026-05-14","auditCorrelationId":"audit-live-status-laurel-studio-room-live-2026-05-14","reason":"Artist confirmed go-live after preview.","useAdminCredential":true}}
```

Fans can ask whether they can join a live room, webinar-style embedded room, or
Listen Along session. The response names the current status, required access
such as sign-in, confirmed subscriber, membership, purchase, or invite, media
readiness, chat readiness, and the next action. Private draft/cancelled events,
invite-only rooms, stream URLs, RealtimeKit identifiers, media config, attendee
emails, and invite tokens stay redacted unless a separate admin manifest
authorizes them.

## Fan Entitlements

The #805 membership and entitlement surface is executable through the listener
manifest:

```bash
curl https://fanful.net/api/agent/listener-experience
```

or through MCP:

```json
{"name":"fanful_listener_entitlements_read","arguments":{}}
```

Agents should read `listener.entitlementStatus` and branch on `status`:
`sign-in-required`, `email-confirmation-required`, `missing-scope`,
`not-a-member`, `inactive-membership`, or `active-member`. A successful private
read returns membership tier, benefits, renewal/expiration date when known,
purchase summary, entitlement flags, and gated experiences the fan can or
cannot access. It never starts checkout, changes a membership, or exposes raw
membership, purchase, Stripe, listener, media, or offline download identifiers.

For purchase-link previews, read `listener.purchaseLinkPreview` from the same
manifest or filter action contracts with `audience=listener&domain=commerce`.
Statuses are explicit: `sign-in-required`, `email-confirmation-required`,
`missing-scope`, `signed-in-listener-required`, `unavailable-product-price`, or
`preview-ready`. Ready previews show target, buyer mode, price, cadence,
expiration, confirmation copy, blockers, and redacted entitlement outcome. They
do not create checkout, return checkout URLs, persist purchase intent rows, or
grant access. Support/donation previews can include `purchaseAmountCents`, so
agents can show the live-room support amount before confirmed checkout starts;
`docs/agent/link-cli-purchase-contract.md` remains the canonical preview-first
write boundary.

For live-room support, read `listener.liveSupport` from the manifest or call:

```json
{"name":"fanful_listener_live_support_preview","arguments":{}}
```

The response distinguishes generic support/donation checkout preview from the
first-party web checkout path that attributes paid support to a `liveEventId`.
For ChatGPT UI, render `fanful_listener_checkout_confirmation_render` first so
the listener sees the checkout target, amount or terms, affected surfaces, exact
preview confirmation text, idempotency/audit readiness, and write boundary.
Support checkout creation is available through `fanful_listener_support_checkout_start`
or `POST /api/agent/listener-experience` after the listener supplies the exact
preview confirmation, risk acknowledgement, fresh idempotency key, audit
correlation id, and reason. Membership checkout creation is available through
`fanful_listener_membership_checkout_start` with the same confirmed envelope and
an active server-owned Stripe Price mapping. Signed-CD shop checkout creation is
available through `fanful_listener_shop_checkout_start` with the same confirmed
envelope and an active, visible, in-stock shop product. The response contains a
checkout URL plus redacted intent summary; raw Stripe, purchase, membership,
listener, Better Auth, and grant identifiers stay hidden. Lesson and paid-room
checkout starts remain blocked by #918 and target-specific catalog or policy
work.

For profile and notification preferences, use:

```json
{"name":"fanful_listener_profile_preferences_read","arguments":{}}
```

Agents should read `listener.profilePreferences` and branch on `status`:
`sign-in-required`, `email-confirmation-required`, `missing-scope`,
`preferences-unavailable`, or `ready`. A successful private read returns display
name, email confirmation state, notification channel/category summaries, and
community-chat notification routing. It never changes preferences, credentials,
email addresses, or device registrations, and it never exposes raw listener,
Better Auth, device, or push-token identifiers.

For display-name updates, use:

```json
{
  "name": "fanful_listener_display_name_update",
  "arguments": {
    "displayName": "New Fan Name",
    "observedDisplayName": "Current Fan Name",
    "confirmationText": "I confirm listener.profile.display-name.update for display name \"New Fan Name\".",
    "acknowledgedRisk": true,
    "idempotencyKey": "listener-display-name-new-fan-name-2026-05-20",
    "auditCorrelationId": "audit-listener-display-name-new-fan-name-2026-05-20",
    "reason": "Listener asked the agent to update their visible display name."
  }
}
```

## Admin Reads

Admin credentials are environment-gated and are never accepted as tool input.
Use one of these in the MCP server process environment only when the operator
intends to allow admin manifest reads:

```bash
FANFUL_MCP_ALLOW_ADMIN=1 FANFUL_ADMIN_TOKEN=... npm run mcp:server
```

```bash
FANFUL_MCP_ALLOW_ADMIN=1 FANFUL_BEARER_TOKEN=... npm run mcp:server
```

The tool reports whether an admin credential was used, but it does not echo
secrets. This is a dev/operator fallback, not the user-facing private-access
model for ChatGPT, MCP, CLI, or live-room clients.

## Boundaries

- Current write-impacting tools are read-only, preview-only, or explicitly
  confirmed wrappers for live status, lesson price changes, lesson Stripe Price
  mappings, replacement lesson Stripe Price creation, membership tier
  profile/archive/restore changes, shop product creation/visibility/details/
  Stripe Price changes, and community channel tier-access metadata.
- Agents should call server-side manifests and MCP tools, not hidden browser UI.
- Public posts, moderation, creator speech, destructive changes, and
  billing-impacting writes require explicit confirmation and audit behavior
  before they become executable tools.
- Creator service price/policy previews are safe to run with admin credentials.
  Authorized creator-commerce reads include `commerce.creator.publisherReferrals`
  with referral terms, the primary share URL, aggregate claim counts, pending
  reward liability, and recent claim status with referred emails and Stripe
  checkout session ids redacted. They also include
  `commerce.adminLessonCreditLedger`, which exposes aggregate lesson-credit
  ledger health, blocked write identifiers, and recent event markers while
  redacting raw ledger ids, user ids, student emails, booking/purchase ids,
  Stripe ids, idempotency keys, reasons, and metadata. Referral reward credit
  writes remain blocked until #1492 defines the confirmed write contract, and
  credit spend/grant/refund/cancellation writes remain blocked until separate
  confirmed contracts ship.
  Confirmed lesson price writes may update `lesson_offerings.price_cents` after
  exact confirmation and audit checks. Confirmed lesson Stripe Price mapping
  and replacement creation writes may update `lesson_offerings.stripe_price_id`
  and, for replacement creation only, `lesson_offerings.price_cents`.
  Confirmed shop product creation writes may insert one safe `store_items` row
  with catalog metadata only. Confirmed shop product Stripe Price mapping and
  replacement creation writes may update `store_items.stripe_price_id` and, for
  replacement creation only, `store_items.price_cents`.
  Membership tier ids are dynamic; use active ids from the latest creator
  commerce or listener support catalog read for checkout and community channel
  tier access. Confirmed tier creation starts new tiers inactive; scoped Stripe
  Price mapping and restore are separate confirmations before new checkout.
  Service policy execution, raw product URL, fulfillment, checkout/order,
  credit, cancellation, refund, and broader entitlement writes remain
  unavailable. Confirmed community channel
  entitlement metadata writes may update non-default channel active-tier
  metadata only.
- Community-channel reads and confirmed community-message posts are
  agent-executable through the community-chat surface. Other listener/fan
  public writes, reactions, checkout starts, cancellations, support actions,
  and offline download URL reads are not agent-executable yet. They need
  explicit listener confirmation and attribution before they become ready tools.
- ChatGPT app clients should not get a special write path. A ChatGPT app can
  add descriptor metadata or UI widgets, but actual actions must remain the same
  MCP-backed operations available to other agent clients.
- Private agent credentials should be scoped delegated grants, resolved
  server-side into guest, listener, creator admin, owner, or approved automation
  principals before any private manifest or write path runs.
- Raw media tokens, media URLs, private invite links, device ids, listener ids,
  and payment identifiers should stay out of model-visible logs unless a
  contract explicitly redacts or marks them safe.

## Follow-Up Work

- #671 creator coaching and commerce actions.
- #672 live scheduling and go-live controls.
- #673 listener and fan experiences.
- #674 ChatGPT app on top of MCP.
- #608 cross-surface action contracts.
- #611 CLI on shared MCP contracts.
