{"ok":true,"version":"agent-live-controls.v1","generatedAt":"2026-05-30T05:19:56.872Z","surface":{"id":"live-controls","artistId":"laurel","safeForAgent":true,"browserAutomationRequired":false,"relatedIssues":[505,507,524,528,608,609,656,672,800,920,960,998,1012,1028,1549,1657]},"principal":{"source":"guest","role":"guest","signedIn":false,"displayName":"Guest listener","userId":null,"email":null,"adminRole":null,"capabilities":{"readPublicLiveRoom":true,"readLiveControls":false,"scheduleLiveRoom":false,"startLiveRoom":false,"endLiveRoom":false,"linkCommunityChannel":false,"manageStageAccess":false,"moderateLiveChat":false,"postLiveMessage":false,"createSocketToken":true}},"focusEventId":null,"live":{"events":[{"id":"live-with-maya-d454ece6","title":"Live with Maya","description":null,"status":"scheduled","startsAt":"2026-05-14T10:02:56.000Z","endsAt":null,"chatEnabled":true,"subscriberOnly":false,"communityChannelId":null,"communityChannel":null,"stream":{"provider":"none","configured":false,"ingestConfigured":false,"playbackConfigured":false,"replayConfigured":false,"replayPublishedAt":null,"redactedFields":["streamUrl","streamLiveInputId","streamVideoId","streamCustomerCode","streamPlaybackUrl","replayUrl"]},"stats":{"totalMessages":0,"visibleMessages":0,"flaggedMessages":0,"hiddenMessages":0,"pinnedMessages":0},"readiness":{"state":"needs-attention","canStartBroadcast":true,"checks":[{"id":"status-startable","label":"Event can enter or continue a live state","status":"pass","required":true,"message":"Event is in a startable state."},{"id":"starts-at-set","label":"Start time is set","status":"pass","required":false,"message":"Start time exists."},{"id":"stream-configured","label":"Stream source is configured","status":"warn","required":false,"message":"No stream source is configured; this may be fine for a text-first room but should be confirmed before go-live."},{"id":"chat-open","label":"Live chat is open","status":"pass","required":false,"message":"Live notes are enabled."},{"id":"community-channel-linked","label":"Persistent community channel is linked","status":"warn","required":false,"message":"Link a community channel if conversation should persist around the event."},{"id":"moderation-queue-clear","label":"No flagged live notes need moderation","status":"pass","required":false,"message":"No flagged live notes are waiting."}]},"updatedAt":"2026-05-14T09:03:11.000Z"}],"readinessSummary":{"eventId":"live-with-maya-d454ece6","state":"needs-attention","canStartBroadcast":true,"recommendation":"Review readiness checks before confirming go-live, schedule, or channel-link changes."},"recentMessages":[],"redactedFields":["streamUrl","streamLiveInputId","streamVideoId","streamCustomerCode","streamPlaybackUrl","replayUrl","listenerUserId","socketToken"]},"embeddedRooms":{"rooms":[],"relationship":"Use embedded rooms for attendee/co-host/stage access during webinars; use live_events for scheduling, stream state, live notes, and community channel linkage."},"liveSchedulePolicy":{"version":"agent-live-schedule-preview.v1","capability":"live.events.schedule.preview","operationId":"live.events.schedule.preview","safeForAgent":true,"requiredScopes":["creator:laurel:live:write"],"auth":{"source":"guest","role":"guest","canPreview":false,"grant":null},"status":"auth-required","dryRun":{"endpoint":{"href":"https://fanful.net/api/agent/live-controls","method":"POST","auth":"artist-admin-or-approved-automation","description":"Preview live-room create/update scheduling impact and optional fanNotification copy without mutating live_events, live_event_admin_actions, or notification rows."},"supportedActions":["preview_live_event_schedule_change"],"writesState":false},"confirmedWrite":{"status":"auth-required","endpoint":{"href":"https://fanful.net/api/agent/live-controls","method":"POST","auth":"artist-admin-or-approved-automation","description":"Execute confirm_live_event_schedule_create or confirm_live_event_schedule_change with agent-write-envelope.v1 confirmation, idempotency, stale-state when relevant, audit checks, and optional notification-center fan-out."},"supportedActions":["confirm_live_event_schedule_create","confirm_live_event_schedule_change"],"createAction":"confirm_live_event_schedule_create","createToolName":"fanful_creator_live_schedule_create","futureAction":"confirm_live_event_schedule_change","futureToolName":"fanful_creator_live_schedule_update","contractId":"creator.live.schedule-and-status","writesState":true},"confirmedWrites":{"status":"auth-required","shippedFoundationIssues":[672,704,757,786,809,818,819,920,960,998,1012,1549],"requiredBeforeExecutable":["fresh schedule preview","agent-write-envelope.v1 execute payload","artist confirmation text","agent client attribution","idempotency key","audit correlation id","stale updated_at guard for updates","matching fanNotification audience/copy/timezone when notifying followers"],"relatedIssues":[608,672,704,757,800,920,960,998,1012,1549,1657]}},"liveTransitionPolicy":{"version":"agent-live-transition-preview.v1","capability":"live.events.status.preview","operationId":"live.events.status.preview","safeForAgent":true,"requiredScopes":["creator:laurel:live:write"],"auth":{"source":"guest","role":"guest","canPreview":false,"grant":null},"status":"auth-required","dryRun":{"endpoint":{"href":"https://fanful.net/api/agent/live-controls","method":"POST","auth":"artist-admin-or-approved-automation","description":"Preview live-room status transition impact without mutating live_events or live_event_admin_actions."},"supportedActions":["preview_live_event_status_change"],"writesState":false},"confirmedWrite":{"endpoint":{"href":"https://fanful.net/api/agent/live-controls","method":"POST","auth":"artist-admin-or-approved-automation","description":"Execute confirm_live_event_status_change with agent-write-envelope.v1 confirmation, idempotency, stale-state, and audit checks."},"supportedActions":["confirm_live_event_status_change"],"writesState":true,"contractId":"creator.live.schedule-and-status","futureToolName":"fanful_creator_live_status_update"},"supportedTransitions":{"nextStatuses":["scheduled","live","ended","cancelled"],"currentWriteRoute":{"href":"https://fanful.net/api/admin/live-events/status","method":"PATCH","auth":"artist-admin-or-approved-automation","description":"Existing audit-safe status transition route; agent clients should use a confirmed wrapper before writing."}},"confirmedWrites":{"status":"auth-required","shippedFoundationIssues":[672,704,757,786,809,818,819,920],"requiredBeforeExecutable":["fresh status preview with observed updated_at","agent-write-envelope.v1 execute payload","artist confirmation text","agent client attribution","idempotency key","audit correlation id"],"relatedIssues":[608,672,704,757,800,920]}},"operations":[{"id":"live.controls.read","toolName":"live_controls_read","status":"ready","enabled":true,"summary":"Read the agent-safe live controls manifest, public room state, and admin-only go-live readiness when authorized.","endpoint":{"href":"https://fanful.net/api/agent/live-controls","method":"GET","auth":"optional-session","description":"Read caller-safe live scheduling, go-live, moderation, channel-link, and embedded-room operation descriptors.","query":["eventId"]},"confirmation":{"required":false,"kind":"none","reason":null},"audit":{"required":false,"currentRecord":null,"attribution":"Read-only manifest access returns public event state to guests and redacted admin readiness to approved admins/automations."},"input":{"eventId":{"type":"string","required":false,"description":"Optional live event id to focus; private draft/cancelled events still require admin or automation access."}},"boundaries":["Does not expose raw stream URLs, Stream customer codes, socket tokens, admin tokens, private invite links, or media provider config.","Guest/listener reads receive public scheduled/live event state and operation descriptors, not private draft/cancelled scheduling data."]},{"id":"live.events.schedule","toolName":"live_events_schedule","status":"contract-only","enabled":false,"summary":"Create or update a Laurel live room schedule entry through a future confirmation-gated agent write.","endpoint":{"href":"https://fanful.net/api/admin/live-events","method":"POST","auth":"artist-admin-or-approved-automation","description":"Create a live event with title, timing, stream provider, chat policy, subscriber gate, and optional community channel link."},"confirmation":{"required":true,"kind":"live-schedule","reason":"Scheduling creates a creator-managed live surface that may become visible to listeners and native clients."},"audit":{"required":true,"currentRecord":"live_events + live_event_admin_actions","attribution":"Creates a live-event admin action row with the admin or automation identity, client, tool, and redacted next summary."},"input":{"title":{"type":"string","required":true,"minLength":1,"maxLength":180},"description":{"type":"string","required":false,"maxLength":1200},"status":{"type":"enum","required":true,"values":["draft","scheduled","live","ended","cancelled"]},"startsAt":{"type":"string","required":false,"format":"date-time"},"endsAt":{"type":"string","required":false,"format":"date-time"},"streamProvider":{"type":"enum","required":true,"values":["none","cloudflare_stream","external_url"]},"streamUrl":{"type":"string","required":false,"format":"url","description":"Accepted by the admin API for external streams but never echoed by this manifest."},"streamLiveInputId":{"type":"string","required":false,"maxLength":180},"streamVideoId":{"type":"string","required":false,"maxLength":180},"streamCustomerCode":{"type":"string","required":false,"maxLength":80,"description":"Sensitive provider value accepted only by the admin API; do not log in model-visible transcripts."},"streamPlaybackUrl":{"type":"string","required":false,"format":"url","description":"Accepted by the admin API for playback setup but redacted from this manifest."},"replayVideoId":{"type":"string","required":false,"maxLength":180},"replayUrl":{"type":"string","required":false,"format":"url"},"replayPublishedAt":{"type":"string","required":false,"format":"date-time"},"chatEnabled":{"type":"boolean","required":true},"subscriberOnly":{"type":"boolean","required":true},"communityChannelId":{"type":"string","required":false,"nullable":true}},"boundaries":["Agent clients must use live.events.schedule.preview first, then live.events.schedule.confirmed-create or live.events.schedule.confirmed-update for writes.","Use live.events.schedule.confirmed-update for confirmation-gated updates to existing events.","Use live.events.schedule.confirmed-create for confirmation-gated new live-event creation.","Use admin or approved automation credentials only; automation tokens cannot impersonate listeners.","Preserve provider secrets outside model-visible logs. This manifest returns readiness booleans instead of raw stream values.","Prefer linking a persistent community channel so pre/post-event conversation does not disappear with the live note stream."]},{"id":"live.events.schedule.preview","toolName":"live_events_schedule_preview","status":"ready","enabled":false,"summary":"Preview a live-room create, schedule edit, or reschedule payload without mutating live_events or live_event_admin_actions.","endpoint":{"href":"https://fanful.net/api/agent/live-controls","method":"POST","auth":"artist-admin-or-approved-automation","description":"Preview one live-event create/update payload and return affected surfaces, redactions, blockers, stale-state, idempotency, and audit requirements."},"confirmation":{"required":false,"kind":"none","reason":null},"audit":{"required":false,"currentRecord":null,"attribution":"Preview calls are non-mutating. Any later schedule write must carry the admin or automation identity, agent client, confirmation, idempotency key, stale-state guard for updates, and audit metadata."},"input":{"action":{"type":"literal","value":"preview_live_event_schedule_change","required":true},"id":{"type":"string","required":false,"maxLength":180,"description":"Existing live event id. Omit to preview a new scheduled/live event."},"eventId":{"type":"string","required":false,"maxLength":180,"description":"Alias for id for CLI/MCP clients that consistently use eventId."},"title":{"type":"string","required":true,"minLength":1,"maxLength":180},"description":{"type":"string","required":false,"maxLength":1200},"status":{"type":"enum","required":true,"values":["draft","scheduled","live","ended","cancelled"]},"startsAt":{"type":"string","required":false,"format":"date-time"},"endsAt":{"type":"string","required":false,"format":"date-time"},"streamProvider":{"type":"enum","required":true,"values":["none","cloudflare_stream","external_url"]},"streamUrl":{"type":"string","required":false,"format":"url","description":"Accepted by the admin API for external streams but never echoed by this manifest."},"streamLiveInputId":{"type":"string","required":false,"maxLength":180},"streamVideoId":{"type":"string","required":false,"maxLength":180},"streamCustomerCode":{"type":"string","required":false,"maxLength":80,"description":"Sensitive provider value accepted only by the admin API; do not log in model-visible transcripts."},"streamPlaybackUrl":{"type":"string","required":false,"format":"url","description":"Accepted by the admin API for playback setup but redacted from this manifest."},"replayVideoId":{"type":"string","required":false,"maxLength":180},"replayUrl":{"type":"string","required":false,"format":"url"},"replayPublishedAt":{"type":"string","required":false,"format":"date-time"},"chatEnabled":{"type":"boolean","required":true},"subscriberOnly":{"type":"boolean","required":true},"communityChannelId":{"type":"string","required":false,"nullable":true},"fanNotification":{"type":"object","required":false,"description":"Optional follower-notification preview. When enabled, the response previews audience, copy, timezone rendering, and the in-app notification-center write plan.","properties":{"enabled":{"type":"boolean","required":true},"audience":{"type":"enum","required":false,"values":["confirmed_subscribers"],"description":"Current fan-out audience. This slice targets confirmed subscribers with matching Fanful accounts."},"title":{"type":"string","required":false,"minLength":1,"maxLength":140},"body":{"type":"string","required":false,"minLength":1,"maxLength":500},"timeZone":{"type":"string","required":false,"maxLength":80,"description":"IANA timezone used to render the start time in the copy preview, for example America/Los_Angeles."}}},"reason":{"type":"string","required":false,"maxLength":800}},"boundaries":["The preview intentionally cannot create or update live_events, stream setup, community channel links, chat policy, subscriber gates, or live_event_admin_actions.","Raw stream URLs, Cloudflare Stream ids/customer codes/playback URLs, replay URLs, admin ids, and provider config are never echoed in the preview response."]},{"id":"live.events.schedule.confirmed-create","toolName":"fanful_creator_live_schedule_create","status":"ready","enabled":false,"summary":"Create a new live event through the confirmed agent write wrapper after a schedule create preview.","endpoint":{"href":"https://fanful.net/api/agent/live-controls","method":"POST","auth":"artist-admin-or-approved-automation","description":"Consume agent-write-envelope.v1 and create a live event after explicit confirmation, idempotency, blocker, and audit checks."},"confirmation":{"required":true,"kind":"live-schedule","reason":"Creating a live event can publish a new listener-visible room, schedule, chat policy, stream readiness, and linked community context."},"audit":{"required":true,"currentRecord":"live_events + live_event_admin_actions + agent_write_idempotency_keys","attribution":"Records the redacted created-event summary with the admin or automation identity, agent client, idempotency key, and audit correlation id."},"input":{"action":{"type":"literal","value":"confirm_live_event_schedule_create","required":true},"title":{"type":"string","required":true,"minLength":1,"maxLength":180},"description":{"type":"string","required":false,"nullable":true,"maxLength":1200},"status":{"type":"enum","required":false,"values":["draft","scheduled","live","ended","cancelled"],"description":"Defaults to scheduled. Use the status wrapper for later go-live/end/cancel transitions."},"startsAt":{"type":"string","required":false,"nullable":true,"format":"date-time"},"endsAt":{"type":"string","required":false,"nullable":true,"format":"date-time"},"streamProvider":{"type":"enum","required":false,"values":["none","cloudflare_stream","external_url"]},"streamUrl":{"type":"string","required":false,"nullable":true,"format":"url"},"streamLiveInputId":{"type":"string","required":false,"nullable":true,"maxLength":180},"streamVideoId":{"type":"string","required":false,"nullable":true,"maxLength":180},"streamCustomerCode":{"type":"string","required":false,"nullable":true,"maxLength":80},"streamPlaybackUrl":{"type":"string","required":false,"nullable":true,"format":"url"},"replayVideoId":{"type":"string","required":false,"nullable":true,"maxLength":180},"replayUrl":{"type":"string","required":false,"nullable":true,"format":"url"},"replayPublishedAt":{"type":"string","required":false,"nullable":true,"format":"date-time"},"chatEnabled":{"type":"boolean","required":false},"subscriberOnly":{"type":"boolean","required":false},"communityChannelId":{"type":"string","required":false,"nullable":true},"fanNotification":{"type":"object","required":false,"description":"Optional confirmed follower notification. When enabled, audience, title, body, and timezone must be explicit and match the artist-approved copy.","properties":{"enabled":{"type":"boolean","required":true},"audience":{"type":"enum","required":true,"values":["confirmed_subscribers"],"description":"Current fan-out audience. This slice targets confirmed subscribers with matching Fanful accounts."},"title":{"type":"string","required":true,"minLength":1,"maxLength":140},"body":{"type":"string","required":true,"minLength":1,"maxLength":500},"timeZone":{"type":"string","required":true,"maxLength":80,"description":"IANA timezone used to render the start time in the copy preview, for example America/Los_Angeles."}}},"envelope":{"contract":"agent-write-envelope.v1","required":true,"contractId":"creator.live.schedule-and-status","actionMode":"execute","dryRun":false,"requiredFields":["actor","client","action","target","confirmation.text","confirmation.acknowledgedRisk","idempotencyKey","reason","auditCorrelationId"]}},"boundaries":["Use preview_live_event_schedule_change first, then confirm_live_event_schedule_create with the exact shared-envelope confirmation text, idempotency key, audit correlation id, and reason.","This wrapper creates live_events and optional notification-center rows only. Use embedded.room.stage.manage for co-host/stage roster changes; stream provider provisioning remains separate.","Go-live/end/cancel status transitions should continue through live.events.status.confirmed-update after creation."]},{"id":"live.events.schedule.confirmed-update","toolName":"fanful_creator_live_schedule_update","status":"ready","enabled":false,"summary":"Apply a previously-previewed schedule update to an existing live event through the confirmed agent write wrapper.","endpoint":{"href":"https://fanful.net/api/agent/live-controls","method":"POST","auth":"artist-admin-or-approved-automation","description":"Consume agent-write-envelope.v1 and update an existing live event schedule after explicit confirmation, idempotency, stale-state, and audit checks."},"confirmation":{"required":true,"kind":"live-schedule","reason":"Schedule changes can alter public listener visibility, timing, chat policy, stream readiness, and linked community context."},"audit":{"required":true,"currentRecord":"live_events + live_event_admin_actions + agent_write_idempotency_keys","attribution":"Records previous and next redacted event summaries with the admin or automation identity, agent client, idempotency key, and audit correlation id."},"input":{"action":{"type":"literal","value":"confirm_live_event_schedule_change","required":true},"eventId":{"type":"string","required":true,"description":"Existing live event id."},"observedUpdatedAt":{"type":"string","required":true,"format":"date-time","description":"The live_events.updated_at value returned by the latest schedule preview."},"title":{"type":"string","required":true,"minLength":1,"maxLength":180},"description":{"type":"string","required":false,"nullable":true,"maxLength":1200},"status":{"type":"enum","required":false,"values":["draft","scheduled","live","ended","cancelled"],"description":"Must match the current status in this slice; use the status wrapper for go-live/end/cancel transitions."},"startsAt":{"type":"string","required":false,"nullable":true,"format":"date-time"},"endsAt":{"type":"string","required":false,"nullable":true,"format":"date-time"},"streamProvider":{"type":"enum","required":false,"values":["none","cloudflare_stream","external_url"]},"streamUrl":{"type":"string","required":false,"nullable":true,"format":"url"},"streamLiveInputId":{"type":"string","required":false,"nullable":true,"maxLength":180},"streamVideoId":{"type":"string","required":false,"nullable":true,"maxLength":180},"streamCustomerCode":{"type":"string","required":false,"nullable":true,"maxLength":80},"streamPlaybackUrl":{"type":"string","required":false,"nullable":true,"format":"url"},"replayVideoId":{"type":"string","required":false,"nullable":true,"maxLength":180},"replayUrl":{"type":"string","required":false,"nullable":true,"format":"url"},"replayPublishedAt":{"type":"string","required":false,"nullable":true,"format":"date-time"},"chatEnabled":{"type":"boolean","required":false},"subscriberOnly":{"type":"boolean","required":false},"communityChannelId":{"type":"string","required":false,"nullable":true},"fanNotification":{"type":"object","required":false,"description":"Optional confirmed follower notification. When enabled, audience, title, body, and timezone must be explicit and match the artist-approved copy.","properties":{"enabled":{"type":"boolean","required":true},"audience":{"type":"enum","required":true,"values":["confirmed_subscribers"],"description":"Current fan-out audience. This slice targets confirmed subscribers with matching Fanful accounts."},"title":{"type":"string","required":true,"minLength":1,"maxLength":140},"body":{"type":"string","required":true,"minLength":1,"maxLength":500},"timeZone":{"type":"string","required":true,"maxLength":80,"description":"IANA timezone used to render the start time in the copy preview, for example America/Los_Angeles."}}},"envelope":{"contract":"agent-write-envelope.v1","required":true,"contractId":"creator.live.schedule-and-status","actionMode":"execute","dryRun":false,"requiredFields":["actor","client","action","target","confirmation.text","confirmation.acknowledgedRisk","idempotencyKey","reason","auditCorrelationId"]}},"boundaries":["This wrapper only updates existing live events and optional notification-center rows. Use live.events.schedule.confirmed-create for new events and embedded.room.stage.manage for co-host/stage roster changes.","Use preview_live_event_schedule_change first, then confirm_live_event_schedule_change with the exact shared-envelope confirmation text, observed updated_at, idempotency key, audit correlation id, and reason.","Go-live/end/cancel status transitions should continue through live.events.status.confirmed-update."]},{"id":"live.events.status.preview","toolName":"live_events_status_preview","status":"ready","enabled":false,"summary":"Preview a live-room go-live, end, cancel, or scheduled-status transition without mutating live_events or audit logs.","endpoint":{"href":"https://fanful.net/api/agent/live-controls","method":"POST","auth":"artist-admin-or-approved-automation","description":"Preview one live-event status transition and return confirmation, affected surfaces, stale-state, idempotency, and audit requirements."},"confirmation":{"required":false,"kind":"none","reason":null},"audit":{"required":false,"currentRecord":null,"attribution":"Preview calls are non-mutating. Any later write must carry the admin or automation identity, agent client, confirmation, idempotency key, and audit metadata."},"input":{"action":{"type":"literal","value":"preview_live_event_status_change","required":true},"eventId":{"type":"string","required":true,"maxLength":180,"description":"Live event id."},"nextStatus":{"type":"enum","required":true,"values":["scheduled","live","ended","cancelled"]},"reason":{"type":"string","required":false,"maxLength":800}},"boundaries":["The preview intentionally cannot update live_events, open or close chat, broadcast socket events, or write live_event_admin_actions.","Use the returned confirmation, readiness checks, observed updated_at, and audit plan before any future confirmed write wrapper calls the status route."]},{"id":"live.events.status.confirmed-update","toolName":"fanful_creator_live_status_update","status":"ready","enabled":false,"summary":"Start, end, cancel, or restore a scheduled live room through the confirmed agent write wrapper.","endpoint":{"href":"https://fanful.net/api/agent/live-controls","method":"POST","auth":"artist-admin-or-approved-automation","description":"Consume agent-write-envelope.v1 and update only the live event status after explicit confirmation, idempotency, stale-state, and audit checks."},"confirmation":{"required":true,"kind":"go-live","reason":"Go-live and end-room transitions change what listeners see and whether chat is treated as active."},"audit":{"required":true,"currentRecord":"live_event_admin_actions + agent_write_idempotency_keys","attribution":"Records previous and next redacted event summaries with the admin or automation identity, agent client, idempotency key, and audit correlation id."},"input":{"action":{"type":"literal","value":"confirm_live_event_status_change","required":true},"eventId":{"type":"string","required":true,"description":"Live event id."},"nextStatus":{"type":"enum","required":true,"values":["scheduled","live","ended","cancelled"]},"observedUpdatedAt":{"type":"string","required":true,"format":"date-time","description":"The live_events.updated_at value returned by the latest preview."},"envelope":{"contract":"agent-write-envelope.v1","required":true,"contractId":"creator.live.schedule-and-status","actionMode":"execute","dryRun":false,"requiredFields":["actor","client","action","target","confirmation.text","confirmation.acknowledgedRisk","idempotencyKey","reason","auditCorrelationId"]}},"boundaries":["This wrapper preserves title, timing, stream setup, chat policy, subscriber gate, and community channel fields.","Confirm with the exact shared-envelope text before going live, ending, cancelling, or restoring a scheduled status.","The wrapper rejects stale preview state and duplicate idempotency keys before mutating live_events."]},{"id":"live.events.status.update","toolName":"live_events_status_update","status":"ready","enabled":false,"summary":"Start, end, cancel, or restore a scheduled live room through the existing admin status-only route.","endpoint":{"href":"https://fanful.net/api/admin/live-events/status","method":"PATCH","auth":"artist-admin-or-approved-automation","description":"Update only the live event status after explicit confirmation."},"confirmation":{"required":true,"kind":"go-live","reason":"Go-live and end-room transitions change what listeners see and whether chat is treated as active."},"audit":{"required":true,"currentRecord":"live_event_admin_actions","attribution":"Records previous and next redacted event summaries with the admin or automation identity, client, and tool name."},"input":{"id":{"type":"string","required":true,"description":"Live event id."},"status":{"type":"enum","required":true,"values":["scheduled","live","ended","cancelled"]},"confirmed":{"type":"boolean","required":true,"const":true,"description":"Must be true for go-live, end, cancel, or restore-scheduled transitions."},"reason":{"type":"string","required":false,"maxLength":500}},"boundaries":["This status-only route preserves title, timing, stream setup, chat policy, subscriber gate, and community channel fields.","Confirm before going live, ending, cancelling, or restoring a scheduled status.","Agent clients should prefer live.events.status.confirmed-update so shared-envelope confirmation, stale-state, idempotency, and client attribution are enforced."]},{"id":"live.events.audit.read","toolName":"live_events_audit_read","status":"ready","enabled":false,"summary":"Read the live-event admin action log for schedule, status, stream, channel-link, and live-note moderation changes.","endpoint":{"href":"https://fanful.net/api/admin/live-events/audit","method":"GET","auth":"artist-admin-or-approved-automation","description":"Read redacted live-event admin action rows.","query":["eventId","messageId","communityChannelId","action","limit"]},"confirmation":{"required":false,"kind":"none","reason":null},"audit":{"required":false,"currentRecord":"live_event_admin_actions","attribution":"Read-only access requires the same admin or automation identity as write routes."},"input":{"eventId":{"type":"string","required":false},"messageId":{"type":"string","required":false},"communityChannelId":{"type":"string","required":false},"action":{"type":"enum","required":false,"values":["event_create","event_update","status_transition","community_channel_link","community_channel_unlink","stream_setup_update","live_note_moderate"]},"limit":{"type":"number","required":false,"min":1,"max":100}},"boundaries":["Audit summaries expose booleans for stream configuration but not raw stream URLs, customer codes, playback URLs, socket tokens, or media config."]},{"id":"live.community-channel.link","toolName":"live_community_channel_link","status":"ready","enabled":false,"summary":"Attach a live event to a persistent community channel by updating the live event's communityChannelId.","endpoint":{"href":"https://fanful.net/api/admin/live-events","method":"PATCH","auth":"artist-admin-or-approved-automation","description":"Update a live event with a communityChannelId so webinar chat and community conversation share a navigable relationship."},"confirmation":{"required":true,"kind":"live-schedule","reason":"Channel links change where listeners are directed before, during, and after the live event."},"audit":{"required":true,"currentRecord":"live_events.community_channel_id + live_event_admin_actions","attribution":"Records link/unlink changes with before/after redacted live-event summaries and the admin or automation identity."},"input":{"id":{"type":"string","required":true,"description":"Live event id."},"title":{"type":"string","required":true,"minLength":1,"maxLength":180},"description":{"type":"string","required":false,"maxLength":1200},"status":{"type":"enum","required":true,"values":["draft","scheduled","live","ended","cancelled"]},"startsAt":{"type":"string","required":false,"format":"date-time"},"endsAt":{"type":"string","required":false,"format":"date-time"},"streamProvider":{"type":"enum","required":true,"values":["none","cloudflare_stream","external_url"]},"streamUrl":{"type":"string","required":false,"format":"url","description":"Accepted by the admin API for external streams but never echoed by this manifest."},"streamLiveInputId":{"type":"string","required":false,"maxLength":180},"streamVideoId":{"type":"string","required":false,"maxLength":180},"streamCustomerCode":{"type":"string","required":false,"maxLength":80,"description":"Sensitive provider value accepted only by the admin API; do not log in model-visible transcripts."},"streamPlaybackUrl":{"type":"string","required":false,"format":"url","description":"Accepted by the admin API for playback setup but redacted from this manifest."},"replayVideoId":{"type":"string","required":false,"maxLength":180},"replayUrl":{"type":"string","required":false,"format":"url"},"replayPublishedAt":{"type":"string","required":false,"format":"date-time"},"chatEnabled":{"type":"boolean","required":true},"subscriberOnly":{"type":"boolean","required":true},"communityChannelId":{"type":"string","required":true,"description":"Active Laurel community channel id, or null to unlink through the admin API."}},"boundaries":["The admin API validates active Laurel channels and the community-channel unlock gate.","Community channel messages live in community_chat_messages; event-scoped live notes stay in live_chat_messages."]},{"id":"live.chat.messages.read","toolName":"live_chat_messages_read","status":"ready","enabled":true,"summary":"Read visible and flagged live-room notes for one event through the public live chat API.","endpoint":{"href":"https://fanful.net/api/live/messages","method":"GET","auth":"optional-session","description":"Read visible and flagged live-room notes for a selected event.","query":["eventId","after"]},"confirmation":{"required":false,"kind":"none","reason":null},"audit":{"required":false,"currentRecord":null,"attribution":"Read-only live note access returns visible/flagged event notes from the public live room surface."},"input":{"eventId":{"type":"string","required":true},"after":{"type":"string","required":false,"format":"date-time"}},"boundaries":["Hidden notes require the admin live-controls manifest or admin moderation route."]},{"id":"live.chat.messages.post","toolName":"live_chat_messages_post","status":"ready","enabled":false,"summary":"Post a visible live-room note as the signed-in listener when chat is open and subscriber gates allow it.","endpoint":{"href":"https://fanful.net/api/live/messages","method":"POST","auth":"signed-in-listener","description":"Post one visible live-room note."},"confirmation":{"required":true,"kind":"public-message","reason":"Live-room notes are visible to other viewers of the event."},"audit":{"required":true,"currentRecord":"live_chat_messages","attribution":"Stored with the signed-in user's id and display name."},"input":{"eventId":{"type":"string","required":true},"body":{"type":"string","required":true,"minLength":1,"maxLength":600}},"boundaries":["Uses the same signed-in listener checks as web/native live chat.","Automation tokens cannot post live notes as listeners."]},{"id":"live.chat.moderation.manage","toolName":"live_chat_moderation_manage","status":"ready","enabled":false,"summary":"Hide, flag, restore, pin, or unpin one live-room note through the admin moderation endpoint.","endpoint":{"href":"https://fanful.net/api/admin/live-events/messages","method":"PATCH","auth":"artist-admin-or-approved-automation","description":"Moderate one live-room note and broadcast the moderation update."},"confirmation":{"required":true,"kind":"moderation","reason":"Moderation changes alter what viewers can see or what remains pinned during the live event."},"audit":{"required":true,"currentRecord":"live_chat_messages + live_event_admin_actions","attribution":"Stores moderation fields on the note and records a live-event admin action with the admin email/name or Automation token identity."},"input":{"id":{"type":"string","required":true,"description":"Live-room note id."},"status":{"type":"enum","required":false,"values":["visible","hidden","flagged"]},"pinned":{"type":"boolean","required":false}},"boundaries":["Requires Laurel artist-admin, owner, or approved automation access.","Agents should confirm before hiding/restoring notes or pinning a note that will draw public attention."]},{"id":"live.socket-token.create","toolName":"live_socket_token_create","status":"ready","enabled":true,"summary":"Mint a short-lived live-room socket token for presence and realtime notes.","endpoint":{"href":"https://fanful.net/api/live/socket-token","method":"POST","auth":"optional-session","description":"Issue a short-lived live-room WebSocket token."},"confirmation":{"required":false,"kind":"none","reason":null},"audit":{"required":false,"currentRecord":null,"attribution":"Token claims include submitted viewer id and signed-in user when present."},"input":{"eventId":{"type":"string","required":true},"viewerId":{"type":"string","required":true}},"boundaries":["Tokens are short-lived bearer credentials and must not be copied into model-visible logs."]},{"id":"embedded.room.stage.manage","toolName":"fanful_creator_embedded_room_roster_update","status":"ready","enabled":false,"summary":"Execute a confirmed invite, co-host promotion, stage move, removal, or restore for one embedded-room participant.","endpoint":{"href":"https://fanful.net/api/agent/embedded-rooms","method":"POST","auth":"artist-admin-or-approved-automation","description":"Confirmed embedded-room roster write with agent-write-envelope.v1, idempotency, stale-state, and audit attribution."},"confirmation":{"required":true,"kind":"stage-access","reason":"Roster changes alter access, co-host status, and who can appear on stage."},"audit":{"required":true,"currentRecord":"embedded_room_admin_actions + agent_write_idempotency_keys","attribution":"Records the admin or automation identity, target participant, before/after role/status summaries, agent client, tool name, idempotency key, audit correlation id, and reason."},"input":{"action":{"type":"literal","value":"confirm_embedded_room_roster_change","required":true},"roomId":{"type":"string","required":true},"email":{"type":"string","required":true,"format":"email","maxLength":240},"displayName":{"type":"string","required":true,"minLength":1,"maxLength":160},"role":{"type":"enum","required":true,"values":["host","co_host","attendee","stage_guest"]},"status":{"type":"enum","required":true,"values":["invited","joined","left","removed"]},"observedParticipantUpdatedAt":{"type":"string","required":false,"format":"date-time","description":"Required when updating an existing participant; omit only for a new invite."},"envelope":{"type":"agent-write-envelope.v1","required":true}},"boundaries":["This reuses the confirmed embedded-room roster wrapper advertised by agent-embedded-rooms.v1.","The wrapper rejects duplicate idempotency keys, stale existing participant state, and no-op roster changes.","Removed participants are denied even when purchase, membership, invite, or public access would otherwise allow entry."]}],"policy":{"writeConfirmation":"Require explicit user confirmation before scheduling, going live, ending/cancelling, changing community channel links, moderating live notes, or moving people on/off stage.","attribution":"Live-event and moderation writes use the admin or automation identity accepted by existing admin endpoints. Listener live notes use the signed-in listener identity.","secretHandling":"Do not expose raw stream URLs, Cloudflare Stream customer codes, socket tokens, admin tokens, private invite links, external fallback URLs, or raw media config in model-visible logs."},"serverGaps":[{"id":"embedded-room.stage-audit-log","relatedIssue":656,"status":"partial","note":"Stage/co-host roster writes reuse the embedded-room participant endpoint and should share the richer admin action log planned for embedded rooms."},{"id":"live-status.confirmed-agent-wrapper","relatedIssue":920,"status":"ready-for-status-writes","note":"Confirmed status writes now consume the shared write envelope, idempotency key, confirmation, stale-state guard, and live-event audit metadata."},{"id":"live-schedule.confirmed-agent-wrapper","relatedIssue":1012,"status":"ready-for-create-and-existing-updates","note":"Confirmed schedule writes now consume the shared write envelope for new live-event creation and existing live-event updates. Embedded-room/stage writes are ready through embedded.room.stage.manage; stream provider provisioning remains separate."},{"id":"live-schedule.push-delivery","relatedIssue":1657,"status":"ready-when-push-credentials-configured","note":"Confirmed agent schedule writes now attempt APNs/FCM delivery after notification-center rows persist. Production delivery requires APNs and/or FCM server credentials; responses report provider-not-configured instead of exposing raw push tokens."}]}